| /**************************************************************************
|
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **************************************************************************/
|
| #include "odbcMsg.h"
|
| #include "nlsfunctions.h"
|
|
|
| #define DRVRMSGDLL_NAME "traf_odbcDrvMsg_intl0100.DLL"
|
| #define SRVRMSGDLL_NAME "traf_odbcSrvrMsg_intl0100.DLL"
|
| #define MSG_NOT_FOUND "Message for ID[%d] not found"
|
| #define MSG_INCOMPLETE "Message for ID[%d] is incomplete"
|
| #define GENERAL_SQLSTATE "HY000"
|
|
|
| OdbcMsg::OdbcMsg()
|
| //************************************************************************
|
| //*
|
| //* Function: OdbcMsg
|
| //*
|
| //* Input Params: None
|
| //*
|
| //* Output Params: None
|
| //*
|
| //* Description: It will load the Server Messages DLL by default
|
| //* and it will use a neutral language (based on system settings)
|
| //*
|
| //************************************************************************
|
| {
|
| OdbcMsg(SRVRMSG_DLL);
|
| }
|
|
|
| OdbcMsg::OdbcMsg(int iDllType)
|
| //************************************************************************
|
| //*
|
| //* Function: OdbcMsg
|
| //*
|
| //* Input Params: type of DLL to load;
|
| //*
|
| //* Output Params: None
|
| //*
|
| //* Description: This function will load the given DLL with a default
|
| //* locale setting for the computer
|
| //*
|
| //************************************************************************
|
| {
|
|
|
| // get locale information for language and code pages
|
| ODBCNLS_GetErrorLanguage (&dwLanguageId);
|
|
|
| // the following is required only when we perform Unicode conversions
|
| ODBCNLS_GetCodePage(&dwACP);
|
|
|
| // load the message DLL
|
| LoadMsgDll(iDllType);
|
| }
|
|
|
| OdbcMsg::OdbcMsg(int iDllType, DWORD dwLangId)
|
| //************************************************************************
|
| //*
|
| //* Function:OdbcMsg
|
| //*
|
| //* Input Params: iDllType - Type of Message Dll to load
|
| //* LanguageId - Language ID definition (from the client)
|
| //*
|
| //* Output Params: None
|
| //*
|
| //* Description: It will try to load the Message DLL store the recommended
|
| //* locale language to be used
|
| //*
|
| //************************************************************************
|
| {
|
| // valid values for the language are generated through the MAKELANGID macro
|
| // and the provided LANG_*, SUBLANG_* literals
|
| dwLanguageId = dwLangId;
|
|
|
| // to get parameters for Unicode conversions
|
| ODBCNLS_GetCodePage(&dwACP);
|
|
|
| LoadMsgDll (iDllType);
|
| }
|
|
|
| OdbcMsg::~OdbcMsg()
|
| //************************************************************************
|
| //*
|
| //* Function: ~OdbcMsg
|
| //*
|
| //* Input Params: None
|
| //*
|
| //* Output Params: None
|
| //*
|
| //* Description: It will try to free the Message Dll if loaded
|
| //*
|
| //************************************************************************
|
| {
|
| // if library was loaded, attempt to free the library
|
| if (hMsgDll)
|
| FreeLibrary(hMsgDll);
|
| }
|
|
|
|
|
| BOOL OdbcMsg::GetOdbcMessage (DWORD dwLangId, DWORD ErrCode, ODBCMXMSG_Def *MsgStruc, ...)
|
| //************************************************************************
|
| //*
|
| //* Function: GetOdbcMessage
|
| //*
|
| //* Input Params: ErrCode - the Message ID to look for in the message file
|
| //*
|
| //* Output Params: MsgStruc - The Message text components
|
| //*
|
| //* Description: It will look for the message in the messages file (if loaded).
|
| //* Valid values for the language are generated through the MAKELANGID
|
| //* macro and the provided LANG_*, SUBLANG_* literals;
|
| //* to use the pre-defined value the user can retrieve it using the
|
| //* GetLanguageId function in this class.
|
| //************************************************************************
|
| {
|
| UINT actual_len;
|
| DWORD error_code;
|
| LPTSTR lpMsgBuf;
|
| va_list Arguments;
|
|
|
| va_start( Arguments, MsgStruc);
|
| lpMsgBuf = NULL;
|
|
|
| // clean up message structure
|
| CleanUpMsgStructure(MsgStruc);
|
| if (bMsgDLLLoaded)
|
| {
|
| // Load string from the DLL
|
| // if the function cannot find a message for the LANGID specified,
|
| // it returns ERROR_RESOURCE_LANG_NOT_FOUND; if we pass 0, it will look for
|
| // a message in te following order:
|
| // 1) Language Neutral
|
| // 2) Thread LANGID
|
| // 3) user default LANGID, based on user locale (be aware that it could be the server)
|
| // 4) system default LANGID
|
| // 5) US English
|
|
|
| actual_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
| FORMAT_MESSAGE_FROM_HMODULE,
|
| hMsgDll,
|
| ErrCode,
|
| LANGIDFROMLCID(dwLangId),
|
| (LPTSTR) &lpMsgBuf,
|
| 0,
|
| &Arguments // va_list
|
| );
|
| error_code = GetLastError();
|
| if ((actual_len == 0) && (error_code == ERROR_RESOURCE_LANG_NOT_FOUND))
|
| {
|
| // deallocate previously allocated buffer
|
| if (lpMsgBuf)
|
| LocalFree( lpMsgBuf );
|
|
|
| // if the specified language is not there, try english as default
|
| actual_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
| FORMAT_MESSAGE_FROM_HMODULE,
|
| hMsgDll,
|
| ErrCode,
|
| MAKELANGID (LANG_ENGLISH, SUBLANG_NEUTRAL),
|
| (LPTSTR) &lpMsgBuf,
|
| 0,
|
| &Arguments // va_list
|
| );
|
| error_code = GetLastError();
|
| if ((actual_len == 0) &&
|
| (error_code == ERROR_RESOURCE_LANG_NOT_FOUND) &&
|
| (dwLangId != 0)) // lang id = 0 already tested before
|
| {
|
| // deallocate previously allocated buffer
|
| if (lpMsgBuf)
|
| LocalFree( lpMsgBuf );
|
|
|
| // try the default option for FormatMessage
|
| actual_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
| FORMAT_MESSAGE_FROM_HMODULE,
|
| hMsgDll,
|
| ErrCode,
|
| 0, // to go through all default four options again
|
| (LPTSTR) &lpMsgBuf,
|
| 0,
|
| &Arguments // va_list
|
| );
|
| if (actual_len == 0) // cannot get the message, maybe is not there
|
| {
|
| ReportError (MsgStruc, ErrCode, GetLastError());
|
| }
|
| else
|
| {
|
| // we got the message finally
|
| FillMsgStructure(ErrCode, (LPSTR)lpMsgBuf, MsgStruc, actual_len);
|
| }
|
| }
|
| else if (actual_len > 0)
|
| {
|
| // we got something, let's return it
|
| FillMsgStructure(ErrCode, (LPSTR)lpMsgBuf, MsgStruc, actual_len);
|
| }
|
| else
|
| {
|
| // this is an error
|
| ReportError (MsgStruc, ErrCode, GetLastError());
|
| }
|
| }
|
| else if (actual_len > 0)
|
| {
|
| // we got a message, return it
|
| FillMsgStructure(ErrCode, (LPSTR)lpMsgBuf, MsgStruc, actual_len);
|
| }
|
| else
|
| {
|
| // it is trully and error
|
| ReportError (MsgStruc, ErrCode, GetLastError());
|
| }
|
| // deallocate previously allocated buffer
|
| if (lpMsgBuf)
|
| LocalFree( lpMsgBuf );
|
| }
|
| else // Message DLL is not loaded
|
| {
|
| ReportError (MsgStruc, ErrCode, 0) ;
|
| return FALSE;
|
| }
|
| // if successfull, return TRUE
|
| return TRUE;
|
| }
|
|
|
| void OdbcMsg::FillMsgStructure (UINT ErrCode,
|
| LPSTR lpMsgBuf,
|
| ODBCMXMSG_Def *MsgStruc,
|
| int actual_len)
|
| //************************************************************************
|
| //*
|
| //* Function: FillMsgStructure
|
| //*
|
| //* Input Params: lpMsgBuf - The original message buffer
|
| //*
|
| //* Output Params: MsgStruc - will contain all message components
|
| //*
|
| //* Description: It will extract the message components based on the
|
| //* columns SQLState, and Message Text.
|
| //* it is assumed that the message structure is already clean
|
| //*
|
| //************************************************************************
|
| {
|
|
|
|
|
| char tempStr[512];
|
| char *szTmp;
|
|
|
| // verify that the message is long enough, otherwise no clean message to return
|
| if (actual_len >= 5)
|
| {
|
|
|
| // from character 1 to character 5 is the SQLCode
|
| strncpy(MsgStruc->lpsSQLState, lpMsgBuf, min(5, sizeof(MsgStruc->lpsSQLState)-1));
|
|
|
| if (actual_len > 13)
|
| {
|
| // then we may have the help ID plus something for message text
|
| // from character 6 to character 10 is the Help ID
|
| // from character 12 on is the message text
|
|
|
| szTmp = &lpMsgBuf[11];
|
| }
|
| else
|
| {
|
| // we don't have enough text to return
|
| sprintf(tempStr, MSG_INCOMPLETE, GetMsgId(ErrCode));
|
| szTmp = tempStr;
|
| }
|
| }
|
| else
|
| {
|
| // return general SQLCode and error message
|
| strcpy(MsgStruc->lpsSQLState, GENERAL_SQLSTATE);
|
| sprintf(tempStr, MSG_INCOMPLETE, GetMsgId(ErrCode));
|
| szTmp = tempStr;
|
| }
|
|
|
| MsgStruc->lpsMsgText = szTmp;
|
|
|
| }
|
|
|
|
|
| //************************************************************************
|
| //*
|
| //* Function: CleanUpMsgStructure
|
| //*
|
| //* Input Params: MsgStruc - The original message structure
|
| //*
|
| //* Output Params: MsgStruc - will contain empty message buffers
|
| //*
|
| //* Description: Empty message buffers
|
| //*
|
| //************************************************************************
|
| void OdbcMsg::CleanUpMsgStructure (ODBCMXMSG_Def * MsgStruc)
|
| {
|
| memset (MsgStruc->lpsSQLState, '\0', sizeof (MsgStruc->lpsSQLState));
|
| }
|
|
|
| //************************************************************************
|
| //*
|
| //* Function: ReportError
|
| //*
|
| //* Input Params: MsgStruc - The original message structure
|
| //*
|
| //* Output Params: MsgStruc - will contain a default error message with data
|
| //*
|
| //* Description: Empty message buffers
|
| //*
|
| //************************************************************************
|
| void OdbcMsg::ReportError (ODBCMXMSG_Def * MsgStruc, UINT MessageId, UINT error_code)
|
| {
|
| char tempStr[512];
|
| #ifdef _DEBUG
|
| LPVOID lpMsgBuf;
|
| FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
| FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
| NULL,
|
| error_code,
|
| MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
| (LPTSTR) &lpMsgBuf,
|
| 0,
|
| NULL);
|
| // printf ("Error:[%s]\n", lpMsgBuf);
|
| LocalFree( lpMsgBuf );
|
| #endif
|
| // use default error message (with message file message ID)
|
| strcpy(MsgStruc->lpsSQLState, GENERAL_SQLSTATE);
|
| sprintf(tempStr, MSG_NOT_FOUND, GetMsgId(MessageId));
|
|
|
| MsgStruc->lpsMsgText = tempStr;
|
| return ;
|
| }
|
|
|
| //************************************************************************
|
| //*
|
| //* Function: LoadMsgDll
|
| //*
|
| //* Input Params: identifier of the MsgDLL to be loaded
|
| //*
|
| //* Output Params: none
|
| //*
|
| //* Description: It loads the specified message DLL and sets the
|
| //* appropriate state variables
|
| //*
|
| //************************************************************************
|
| void OdbcMsg::LoadMsgDll (int iDllType)
|
| {
|
| bMsgDLLLoaded = FALSE;
|
|
|
| // attempt to load the library
|
| switch (iDllType)
|
| {
|
| case DRVRMSG_DLL:
|
| hMsgDll = LoadLibrary(DRVRMSGDLL_NAME);
|
| break;
|
|
|
| case SRVRMSG_DLL:
|
| hMsgDll = LoadLibrary(SRVRMSGDLL_NAME);
|
| break;
|
|
|
| default:
|
| // loads the server DLL by default
|
| hMsgDll = LoadLibrary(SRVRMSGDLL_NAME);
|
|
|
| }
|
| if (hMsgDll != NULL)
|
| {
|
| bMsgDLLLoaded = TRUE;
|
| }
|
| }
|
|
|
| //************************************************************************
|
| //*
|
| //* Function: GetMsgId
|
| //*
|
| //* Input Params: Error code as stored in the message header file
|
| //*
|
| //* Output Params: none
|
| //*
|
| //* Description: It returns the Error code as assigned in the message file
|
| //* (removes application name, flags, etc)
|
| //*
|
| //************************************************************************
|
| DWORD OdbcMsg::GetMsgId (DWORD ErrCode)
|
| {
|
| return ErrCode & 0x0FFFF;
|
| }
|
|
|
|
|
| void OdbcMsg::SetLanguageId (DWORD LanguageId)
|
| {
|
| dwLanguageId = LanguageId;
|
| // set the internal language to something we handle
|
| ODBCNLS_ValidateLanguage (&dwLanguageId);
|
| }
|
|
|
| DWORD OdbcMsg::GetLanguageId ()
|
| {
|
| return dwLanguageId;
|
| }
|