536 lines
15 KiB
C
536 lines
15 KiB
C
|
#include <precomp.h>
|
||
|
#include "wzcsvc.h"
|
||
|
#include "intflist.h"
|
||
|
#include "tracing.h"
|
||
|
|
||
|
// internal-use tracing variables
|
||
|
UINT g_nLineNo;
|
||
|
LPSTR g_szFileName;
|
||
|
|
||
|
// handles for database usage
|
||
|
extern JET_SESID serverSession;
|
||
|
extern JET_DBID databasehandle;
|
||
|
extern JET_TABLEID tablehandle;
|
||
|
extern SESSION_CONTAINER sesscon;
|
||
|
//logging database states
|
||
|
|
||
|
// global buffers to be used when formatting database
|
||
|
// logging message parameters
|
||
|
WCHAR g_wszDbLogBuffer[DBLOG_SZFMT_BUFFS][DBLOG_SZFMT_SIZE];
|
||
|
|
||
|
// global tracing variables
|
||
|
DWORD g_TraceLog;
|
||
|
|
||
|
// debug utility calls
|
||
|
VOID _DebugPrint(DWORD dwFlags, LPCSTR lpFormat, ...)
|
||
|
{
|
||
|
va_list arglist;
|
||
|
va_start(arglist, lpFormat);
|
||
|
|
||
|
TraceVprintfExA(
|
||
|
g_TraceLog,
|
||
|
dwFlags | TRACE_USE_MASK,
|
||
|
lpFormat,
|
||
|
arglist);
|
||
|
}
|
||
|
|
||
|
// if bCheck is not true, print out the assert message & user defined string.
|
||
|
VOID _DebugAssert(BOOL bChecked, LPCSTR lpFormat, ...)
|
||
|
{
|
||
|
if (!bChecked)
|
||
|
{
|
||
|
va_list arglist;
|
||
|
CHAR pBuffer[500];
|
||
|
LPSTR pFileName;
|
||
|
|
||
|
pFileName = strrchr(g_szFileName, '\\');
|
||
|
if (pFileName == NULL)
|
||
|
pFileName = g_szFileName;
|
||
|
else
|
||
|
pFileName++;
|
||
|
sprintf(pBuffer,"##Assert %s:%d## ", pFileName, g_nLineNo);
|
||
|
strcat(pBuffer, lpFormat);
|
||
|
|
||
|
va_start(arglist, lpFormat);
|
||
|
TraceVprintfExA(
|
||
|
g_TraceLog,
|
||
|
TRC_ASSERT | TRACE_USE_MASK,
|
||
|
pBuffer,
|
||
|
arglist);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID _DebugBinary(DWORD dwFlags, LPCSTR lpMessage, LPBYTE pBuffer, UINT nBuffLen)
|
||
|
{
|
||
|
CHAR strHex[128];
|
||
|
UINT nMsgLen = strlen(lpMessage);
|
||
|
|
||
|
if (3*nBuffLen >= 120)
|
||
|
{
|
||
|
strcpy(strHex, "##Binary data too large##");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LPSTR pHexDigit = strHex;
|
||
|
UINT i = nBuffLen;
|
||
|
|
||
|
while(i > 0)
|
||
|
{
|
||
|
sprintf(pHexDigit, "%02x ", *pBuffer);
|
||
|
pHexDigit += 3;
|
||
|
pBuffer++;
|
||
|
i--;
|
||
|
}
|
||
|
*pHexDigit = '\0';
|
||
|
}
|
||
|
|
||
|
TracePrintfExA(
|
||
|
g_TraceLog,
|
||
|
dwFlags | TRACE_USE_MASK,
|
||
|
"%s [%d]:{%s}", lpMessage, nBuffLen, strHex);
|
||
|
}
|
||
|
|
||
|
VOID TrcInitialize()
|
||
|
{
|
||
|
#ifdef DBG
|
||
|
g_TraceLog = TraceRegister(TRC_NAME);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
VOID TrcTerminate()
|
||
|
{
|
||
|
#ifdef DBG
|
||
|
TraceDeregister(g_TraceLog);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//------------- Database Logging functions -------------------
|
||
|
DWORD _DBRecord (
|
||
|
DWORD eventID,
|
||
|
PWZC_DB_RECORD pDbRecord,
|
||
|
va_list *pvaList)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
WCHAR wchBuffer[MAX_RAW_DATA_SIZE/sizeof(WCHAR)];
|
||
|
HINSTANCE hInstance = WZCGetSPResModule();
|
||
|
|
||
|
if (hInstance == NULL)
|
||
|
dwErr = ERROR_DLL_INIT_FAILED;
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
// format the message
|
||
|
if (FormatMessageW(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||
|
hInstance,
|
||
|
eventID,
|
||
|
0, // Default language
|
||
|
wchBuffer,
|
||
|
sizeof(wchBuffer)/sizeof(WCHAR),
|
||
|
pvaList) == 0)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
pDbRecord->message.pData = (LPBYTE)wchBuffer;
|
||
|
pDbRecord->message.dwDataLen = sizeof(WCHAR)*(wcslen(wchBuffer) + 1);
|
||
|
|
||
|
//make a insertion
|
||
|
dwErr = AddWZCDbLogRecord(NULL, 0, pDbRecord, NULL);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD DbLogWzcError (
|
||
|
DWORD eventID,
|
||
|
PINTF_CONTEXT pIntfContext,
|
||
|
...
|
||
|
)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
va_list argList;
|
||
|
WZC_DB_RECORD DbRecord = {0};
|
||
|
BOOL bLogEnabled;
|
||
|
|
||
|
if (!g_wzcInternalCtxt.bValid)
|
||
|
{
|
||
|
dwErr = ERROR_ARENA_TRASHED;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
va_start(argList, pIntfContext);
|
||
|
|
||
|
EnterCriticalSection(&g_wzcInternalCtxt.csContext);
|
||
|
bLogEnabled = ((g_wzcInternalCtxt.wzcContext.dwFlags & WZC_CTXT_LOGGING_ON) != 0);
|
||
|
LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
|
||
|
|
||
|
// If the database is not opened or the logging functionality is disabled,
|
||
|
// do not record any thing
|
||
|
if (!bLogEnabled || !IsDBOpened())
|
||
|
goto exit;
|
||
|
|
||
|
// prepare the info that is about to be logged.
|
||
|
// get the service specific info first (i.e WZC specific part)
|
||
|
// then build up the message.
|
||
|
DbLogInitDbRecord(DBLOG_CATEG_ERR, pIntfContext, &DbRecord);
|
||
|
|
||
|
dwErr = _DBRecord(
|
||
|
eventID,
|
||
|
&DbRecord,
|
||
|
&argList);
|
||
|
exit:
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD DbLogWzcInfo (
|
||
|
DWORD eventID,
|
||
|
PINTF_CONTEXT pIntfContext,
|
||
|
...
|
||
|
)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
va_list argList;
|
||
|
WZC_DB_RECORD DbRecord = {0};
|
||
|
BOOL bLogEnabled;
|
||
|
LPWSTR wszContext = NULL;
|
||
|
DWORD nchContext = 0;
|
||
|
|
||
|
if (!g_wzcInternalCtxt.bValid)
|
||
|
{
|
||
|
dwErr = ERROR_ARENA_TRASHED;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
va_start(argList, pIntfContext);
|
||
|
|
||
|
EnterCriticalSection(&g_wzcInternalCtxt.csContext);
|
||
|
bLogEnabled = ((g_wzcInternalCtxt.wzcContext.dwFlags & WZC_CTXT_LOGGING_ON) != 0);
|
||
|
LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
|
||
|
|
||
|
// If the database is not opened or the logging functionality is disabled,
|
||
|
// do not record any thing
|
||
|
if (!bLogEnabled || !IsDBOpened())
|
||
|
goto exit;
|
||
|
|
||
|
// prepare the info that is about to be logged.
|
||
|
// get the service specific info first (i.e WZC specific part)
|
||
|
// then build up the message.
|
||
|
DbLogInitDbRecord(DBLOG_CATEG_INFO, pIntfContext, &DbRecord);
|
||
|
|
||
|
// if WZCSVC_USR_CFGCHANGE, build the context string
|
||
|
if (eventID == WZCSVC_USR_CFGCHANGE &&
|
||
|
pIntfContext != NULL)
|
||
|
{
|
||
|
DWORD nOffset = 0;
|
||
|
DWORD nchWritten = 0;
|
||
|
nchContext = 64; // large enough for "Flags = 0x00000000"
|
||
|
|
||
|
if (pIntfContext->pwzcPList != NULL)
|
||
|
{
|
||
|
// large enough for "{SSID, Infrastructure, Flags}"
|
||
|
nchContext += pIntfContext->pwzcPList->NumberOfItems * 128;
|
||
|
}
|
||
|
wszContext = (LPWSTR)MemCAlloc(nchContext * sizeof(WCHAR));
|
||
|
if (wszContext == NULL)
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
nchWritten = nchContext;
|
||
|
dwErr = DbLogFmtFlags(
|
||
|
wszContext,
|
||
|
&nchWritten,
|
||
|
pIntfContext->dwCtlFlags);
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
nOffset += nchWritten;
|
||
|
}
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS && pIntfContext->pwzcPList != NULL)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
for (i = 0; i < pIntfContext->pwzcPList->NumberOfItems; i++)
|
||
|
{
|
||
|
nchWritten = nchContext - nOffset;
|
||
|
dwErr = DbLogFmtWConfig(
|
||
|
wszContext + nOffset,
|
||
|
&nchWritten,
|
||
|
&(pIntfContext->pwzcPList->Config[i]));
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
break;
|
||
|
nOffset += nchWritten;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
DbRecord.context.pData = (LPBYTE)wszContext;
|
||
|
DbRecord.context.dwDataLen = (wcslen(wszContext) + 1) * sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
else if (eventID == WZCSVC_BLIST_CHANGED &&
|
||
|
pIntfContext != NULL &&
|
||
|
pIntfContext->pwzcBList != NULL &&
|
||
|
pIntfContext->pwzcBList->NumberOfItems != 0)
|
||
|
{
|
||
|
DWORD nOffset = 0;
|
||
|
DWORD nchWritten = 0;
|
||
|
|
||
|
nchContext = pIntfContext->pwzcBList->NumberOfItems * 128;
|
||
|
wszContext = (LPWSTR)MemCAlloc(nchContext * sizeof(WCHAR));
|
||
|
if (wszContext == NULL)
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
for (i = 0; i < pIntfContext->pwzcBList->NumberOfItems; i++)
|
||
|
{
|
||
|
nchWritten = nchContext - nOffset;
|
||
|
dwErr = DbLogFmtWConfig(
|
||
|
wszContext + nOffset,
|
||
|
&nchWritten,
|
||
|
&(pIntfContext->pwzcBList->Config[i]));
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
break;
|
||
|
nOffset += nchWritten;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
DbRecord.context.pData = (LPBYTE)wszContext;
|
||
|
DbRecord.context.dwDataLen = (wcslen(wszContext) + 1) * sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwErr = _DBRecord(
|
||
|
eventID,
|
||
|
&DbRecord,
|
||
|
&argList);
|
||
|
exit:
|
||
|
|
||
|
MemFree(wszContext);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
// Initializes the WZC_DB_RECORD
|
||
|
DWORD DbLogInitDbRecord(
|
||
|
DWORD dwCategory,
|
||
|
PINTF_CONTEXT pIntfContext,
|
||
|
PWZC_DB_RECORD pDbRecord)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
if (pDbRecord == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ZeroMemory(pDbRecord, sizeof(WZC_DB_RECORD));
|
||
|
pDbRecord->componentid = DBLOG_COMPID_WZCSVC;
|
||
|
pDbRecord->category = dwCategory;
|
||
|
if (pIntfContext != NULL)
|
||
|
{
|
||
|
pDbRecord->ssid.pData = (LPBYTE)DbLogFmtSSID(5,&(pIntfContext->wzcCurrent.Ssid));
|
||
|
pDbRecord->ssid.dwDataLen = sizeof(WCHAR)*(wcslen((LPWSTR)pDbRecord->ssid.pData) + 1);
|
||
|
|
||
|
pDbRecord->localmac.pData = (LPBYTE)DbLogFmtBSSID(6, pIntfContext->ndLocalMac);
|
||
|
pDbRecord->localmac.dwDataLen = sizeof(WCHAR)*(wcslen((LPWSTR)pDbRecord->localmac.pData) + 1);
|
||
|
|
||
|
pDbRecord->remotemac.pData = (LPBYTE)DbLogFmtBSSID(7, pIntfContext->wzcCurrent.MacAddress);
|
||
|
pDbRecord->remotemac.dwDataLen = sizeof(WCHAR)*(wcslen((LPWSTR)pDbRecord->remotemac.pData) + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
// Formats an SSID in the given formatting buffer
|
||
|
LPWSTR DbLogFmtSSID(
|
||
|
UINT nBuff, // index of the format buffer to use (0 .. DBLOG_SZFMT_BUFFS)
|
||
|
PNDIS_802_11_SSID pndSSid)
|
||
|
{
|
||
|
UINT nFmtLen;
|
||
|
|
||
|
DbgAssert((nBuff < DBLOG_SZFMT_SIZE, "Illegal buffer index in DbLogFmtSSID"));
|
||
|
|
||
|
nFmtLen = MultiByteToWideChar(
|
||
|
CP_ACP,
|
||
|
0,
|
||
|
pndSSid->Ssid,
|
||
|
min (pndSSid->SsidLength, DBLOG_SZFMT_SIZE-1),
|
||
|
g_wszDbLogBuffer[nBuff],
|
||
|
DBLOG_SZFMT_SIZE-1);
|
||
|
|
||
|
if (nFmtLen == DBLOG_SZFMT_SIZE-1)
|
||
|
wcscpy(&(g_wszDbLogBuffer[nBuff][DBLOG_SZFMT_SIZE-3]), L"..");
|
||
|
else
|
||
|
g_wszDbLogBuffer[nBuff][nFmtLen] = '\0';
|
||
|
|
||
|
return g_wszDbLogBuffer[nBuff];
|
||
|
}
|
||
|
|
||
|
// Formats a BSSID (MAC address) in the given formatting buffer
|
||
|
LPWSTR DbLogFmtBSSID(
|
||
|
UINT nBuff,
|
||
|
NDIS_802_11_MAC_ADDRESS ndBSSID)
|
||
|
{
|
||
|
UINT i, j;
|
||
|
BOOL bAllZero = TRUE;
|
||
|
|
||
|
DbgAssert((nBuff < DBLOG_SZFMT_SIZE, "Illegal buffer index in DbLogFmtSSID"));
|
||
|
|
||
|
g_wszDbLogBuffer[nBuff][0] = L'\0';
|
||
|
for (j = 0, i = 0; i < sizeof(NDIS_802_11_MAC_ADDRESS); i++)
|
||
|
{
|
||
|
BYTE nHex;
|
||
|
|
||
|
if (ndBSSID[i] != 0)
|
||
|
bAllZero = FALSE;
|
||
|
|
||
|
nHex = (ndBSSID[i] & 0xf0) >> 4;
|
||
|
g_wszDbLogBuffer[nBuff][j++] = HEX2WCHAR(nHex);
|
||
|
nHex = (ndBSSID[i] & 0x0f);
|
||
|
g_wszDbLogBuffer[nBuff][j++] = HEX2WCHAR(nHex);
|
||
|
g_wszDbLogBuffer[nBuff][j++] = MAC_SEPARATOR;
|
||
|
}
|
||
|
|
||
|
if (bAllZero)
|
||
|
g_wszDbLogBuffer[nBuff][0] = L'\0';
|
||
|
else if (j > 0)
|
||
|
g_wszDbLogBuffer[nBuff][j-1] = L'\0';
|
||
|
|
||
|
return g_wszDbLogBuffer[nBuff];
|
||
|
}
|
||
|
|
||
|
// Formats the INTF_CONTEXT::dwCtlFlags field for logging
|
||
|
DWORD DbLogFmtFlags(
|
||
|
LPWSTR wszBuffer, // buffer to place the result into
|
||
|
LPDWORD pnchBuffer, // in: num of chars in the buffer; out: number of chars written to the buffer
|
||
|
DWORD dwFlags) // interface flags to log
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
UINT nchBuffer;
|
||
|
LPVOID pvArgs[5];
|
||
|
WCHAR wszArgs[5][33];
|
||
|
HINSTANCE hInstance = WZCGetSPResModule();
|
||
|
|
||
|
if (pnchBuffer == NULL || *pnchBuffer == 0)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
goto exit;
|
||
|
}
|
||
|
nchBuffer = (*pnchBuffer);
|
||
|
*pnchBuffer = 0;
|
||
|
|
||
|
if (hInstance == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_DLL_INIT_FAILED;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pvArgs[0] = _itow((dwFlags & INTFCTL_ENABLED) != 0, wszArgs[0], 10);
|
||
|
pvArgs[1] = _itow((dwFlags & INTFCTL_FALLBACK) != 0, wszArgs[1], 10);
|
||
|
pvArgs[2] = _itow((dwFlags & INTFCTL_CM_MASK), wszArgs[2], 10);
|
||
|
pvArgs[3] = _itow((dwFlags & INTFCTL_VOLATILE) != 0, wszArgs[3], 10);
|
||
|
pvArgs[4] = _itow((dwFlags & INTFCTL_POLICY) != 0, wszArgs[4], 10);
|
||
|
|
||
|
// format the message
|
||
|
*pnchBuffer = FormatMessageW(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||
|
hInstance,
|
||
|
WZCSVC_DETAILS_FLAGS,
|
||
|
0, // Default language
|
||
|
wszBuffer,
|
||
|
nchBuffer,
|
||
|
(va_list*)pvArgs);
|
||
|
|
||
|
if (*pnchBuffer == 0)
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
exit:
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
// Formats a WZC_WLAN_CONFIG structure for logging
|
||
|
DWORD DbLogFmtWConfig(
|
||
|
LPWSTR wszBuffer, // buffer to place the result into
|
||
|
LPDWORD pnchBuffer, // in: num of chars in the buffer; out: number of chars written to the buffer
|
||
|
PWZC_WLAN_CONFIG pWzcCfg) // WZC_WLAN_CONFIG object to log
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
UINT nchBuffer;
|
||
|
LPVOID pvArgs[5];
|
||
|
WCHAR wszArgs[4][33];
|
||
|
HINSTANCE hInstance = WZCGetSPResModule();
|
||
|
|
||
|
if (pnchBuffer == NULL || *pnchBuffer == 0)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
goto exit;
|
||
|
}
|
||
|
nchBuffer = (*pnchBuffer);
|
||
|
*pnchBuffer = 0;
|
||
|
|
||
|
if (hInstance == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_DLL_INIT_FAILED;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pvArgs[0] = (LPVOID)DbLogFmtSSID(8, &(pWzcCfg->Ssid));
|
||
|
pvArgs[1] = _itow(pWzcCfg->InfrastructureMode, wszArgs[0], 10);
|
||
|
pvArgs[2] = _itow(pWzcCfg->Privacy, wszArgs[1], 10);
|
||
|
pvArgs[3] = _itow((pWzcCfg->dwCtlFlags & WZCCTL_VOLATILE) != 0, wszArgs[2], 10);
|
||
|
pvArgs[4] = _itow((pWzcCfg->dwCtlFlags & WZCCTL_POLICY) != 0, wszArgs[3], 10);
|
||
|
|
||
|
// format the message
|
||
|
*pnchBuffer = FormatMessageW(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||
|
hInstance,
|
||
|
WZCSVC_DETAILS_WCONFIG,
|
||
|
0, // Default language
|
||
|
wszBuffer,
|
||
|
nchBuffer,
|
||
|
(va_list*)pvArgs);
|
||
|
|
||
|
if (*pnchBuffer == 0)
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
exit:
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------
|
||
|
// GetSPResModule: Utility function used to return
|
||
|
// the handle to the module having WZC UI resources
|
||
|
// (needed for XP.QFE & XP.SP1 builds)
|
||
|
HINSTANCE
|
||
|
WZCGetSPResModule()
|
||
|
{
|
||
|
static HINSTANCE st_hModule = NULL;
|
||
|
|
||
|
if (st_hModule == NULL)
|
||
|
{
|
||
|
WCHAR wszFullPath[_MAX_PATH];
|
||
|
|
||
|
if (ExpandEnvironmentStrings(
|
||
|
L"%systemroot%\\system32\\xpsp1res.dll",
|
||
|
wszFullPath,
|
||
|
_MAX_PATH) != 0)
|
||
|
{
|
||
|
st_hModule = LoadLibraryEx(
|
||
|
wszFullPath,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
}
|
||
|
return st_hModule;
|
||
|
}
|