Skip to content

Commit

Permalink
Address problems reported with the usage of FormatMessage() on Windows
Browse files Browse the repository at this point in the history
(#47).
  • Loading branch information
anthony-tuininga committed Nov 28, 2017
1 parent 6ec1512 commit 0fc9751
Showing 1 changed file with 55 additions and 23 deletions.
78 changes: 55 additions & 23 deletions src/dpiOci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,58 @@ int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month,
}


#ifdef _WIN32
//-----------------------------------------------------------------------------
// dpiOci__getLoadErrorOnWindows() [INTERNAL]
// Get the error message for a load failure on Windows.
//-----------------------------------------------------------------------------
static void dpiOci__getLoadErrorOnWindows(char *loadError,
size_t loadErrorLength)
{
DWORD length = 0, errorNum, status;
wchar_t *wLoadError = NULL;

// get error message in Unicode first
// use English unless English error messages aren't available
errorNum = GetLastError();
status = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, errorNum, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPWSTR) &wLoadError, 0, NULL);
if (!status && GetLastError() == ERROR_MUI_FILE_NOT_FOUND)
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, errorNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &wLoadError, 0, NULL);

if (wLoadError) {

// strip trailing period and carriage return from message, if needed
length = wcslen(wLoadError);
while (length > 0) {
if (wLoadError[length - 1] > 127 ||
wLoadError[length - 1] != L'.' ||
!isspace(wLoadError[length - 1]))
break;

This comment has been minimized.

Copy link
@kubo

kubo Dec 2, 2017

This if-clause is always true. The second || should be &&.

This comment has been minimized.

Copy link
@anthony-tuininga

anthony-tuininga Dec 4, 2017

Author Member

An excellent point. Not sure how I missed that! Corrected now.

length--;
}
wLoadError[length] = L'\0';

// convert to a multi-byte string in UTF-8 encoding
if (length > 0)
length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1, loadError,
loadErrorLength, NULL, NULL);
LocalFree(wLoadError);

}

// fallback in case message cannot be determined
if (length == 0)
sprintf(loadError, "DLL load failed: Windows Error %d", errorNum);
}
#endif


//-----------------------------------------------------------------------------
// dpiOci__loadLib() [INTERNAL]
// Load the OCI library.
Expand All @@ -1360,10 +1412,7 @@ static int dpiOci__loadLib(dpiError *error)
const char *libName;
char loadError[512];
unsigned int i;
#ifdef _WIN32
DWORD length, errorNum;
wchar_t wLoadError[512];
#else
#ifndef _WIN32
char *oracleHome, *oracleHomeLibName;
size_t oracleHomeLibNameLength;
#endif
Expand All @@ -1375,25 +1424,8 @@ static int dpiOci__loadLib(dpiError *error)
break;
#ifdef _WIN32
dpiOciLibHandle = LoadLibrary(libName);
if (!dpiOciLibHandle && i == 0) {

// get error message in Unicode first
errorNum = GetLastError();
wLoadError[0] = L'\0';
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), wLoadError,
sizeof(wLoadError), NULL);

// convert to a multi-byte string in UTF-8 encoding
length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1,
loadError, sizeof(loadError), NULL, NULL);

// strip trailing period and carriage return from message
if (length > 4)
loadError[length - 4] = '\0';
else strcpy(loadError, "DLL load failed");
}
if (!dpiOciLibHandle && i == 0)
dpiOci__getLoadErrorOnWindows(loadError, sizeof(loadError));
#else
dpiOciLibHandle = dlopen(libName, RTLD_LAZY);
if (!dpiOciLibHandle && i == 0) {
Expand Down

0 comments on commit 0fc9751

Please sign in to comment.