|
|
//+----------------------------------------------------------------------------
//
// File: cmutoa.cpp
//
// Module: CMUTOA.DLL
//
// Synopsis: This dll is a Unicode to Ansi wrapper that exports AU functions
// that have the function header of the W version of a windows API
// but internally do all the conversions necessary so that the Ansi
// version of the API (A version) can be called. This dll was implemented
// so that a Unicode CM could still run on win9x. The idea was borrowed
// from F. Avery Bishop's April 1999 MSJ article "Design a Single Unicode
// App that Runs on Both Windows 98 and Windows 2000"
//
// Copyright (c) 1999 Microsoft Corporation
//
// Author: quintinb Created 04/25/99
//
//+----------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <shlobj.h>
#include <ras.h>
#include <raserror.h>
#include <shellapi.h>
#include "cmutoa.h"
#include "cmdebug.h"
#include "cm_def.h"
#include "cmutil.h"
#include "cmras.h"
#include "raslink.h"
// raslink text constants
#define _CMUTOA_MODULE
#include "raslink.cpp"
//
// Globals
//
DWORD g_dwTlsIndex;
//
// Function Headers
//
LRESULT WINAPI SendMessageAU(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); int WINAPI wvsprintfAU(OUT LPWSTR pszwDest, IN LPCWSTR pszwFmt, IN va_list arglist); int WINAPI lstrlenAU(IN LPCWSTR lpString);
//+----------------------------------------------------------------------------
//
// Function: DllMain
//
// Synopsis: Main Entry point for the DLL, notice that we use thread local
// storage and initialize it here.
//
// Arguments: HANDLE hDll - instance handle to the dll
// DWORD dwReason - reason the function was called
// LPVOID lpReserved -
//
// Returns: BOOL - TRUE on success
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL APIENTRY DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { CMTRACE(TEXT("=====================================================")); CMTRACE1(TEXT(" CMUTOA.DLL - LOADING - Process ID is 0x%x "), GetCurrentProcessId()); CMTRACE(TEXT("====================================================="));
g_dwTlsIndex = TlsAlloc(); if (g_dwTlsIndex == TLS_OUT_OF_INDEXES) { return FALSE; }
DisableThreadLibraryCalls((HMODULE) hDll); } else if (dwReason == DLL_PROCESS_DETACH) { CMTRACE(TEXT("=====================================================")); CMTRACE1(TEXT(" CMUTOA.DLL - UNLOADING - Process ID is 0x%x "), GetCurrentProcessId()); CMTRACE(TEXT("====================================================="));
//
// free the tls index
//
if (g_dwTlsIndex != TLS_OUT_OF_INDEXES) { TlsFree(g_dwTlsIndex); } }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: CharNextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CharNext API.
//
// Arguments: LPCWSTR lpsz - The string to return the next character of
//
// Returns: LPWSTR -- the Next character in the string, unless the current
// char is a NULL terminator and then the input param
// is returned.
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI CharNextAU(IN LPCWSTR lpsz) { LPWSTR pszReturn = (LPWSTR)lpsz;
if (lpsz && (L'\0' != *lpsz)) { pszReturn++; // this is what _wcsinc does
}
return pszReturn;
}
//+----------------------------------------------------------------------------
//
// Function: CharPrevAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CharPrev API.
//
// Arguments: LPCWSTR lpszStart - start of the string
// LPCWSTR lpsz - The current position in the string for which we
// want the previous char of
//
//
// Returns: LPWSTR -- the Previous character in the string, unless the current
// char is less than or equal to the Start of the string or
// a NULL string is passed to the function, then lpszStart
// is returned.
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI CharPrevAU(IN LPCWSTR lpszStart, IN LPCWSTR lpszCurrent) { LPWSTR pszReturn = (LPWSTR)lpszCurrent;
if (lpszStart && lpszCurrent && (lpszCurrent > lpszStart)) { pszReturn--; // this is what _wcsdec does
} else { CMASSERTMSG(FALSE, TEXT("NULL String passed to CharPrevAU")); pszReturn = (LPWSTR)lpszStart; }
return pszReturn; }
typedef WINUSERAPI LPSTR (WINAPI *CharLowerOrUpperA)(LPSTR);
//+----------------------------------------------------------------------------
//
// Function: LowerOrUpperHelper
//
// Synopsis: Helper function called by either CharLowerAU or CharUpperAU which have
// basically the same functionality except for the calling of CharLowerA or
// CharUpperA, respectively.
//
// Arguments: LPWSTR lpsz -- either a pointer to a string to convert to its
// lower/upper character version or a single character stored
// in the low word of the pointer to find the lowercase/uppercase
// character for.
//
// Returns: LPWSTR -- lower/upper case version of the string passed in (same as lpsz
// because it is converted in place) or lower/upper case version
// of the character stored in the Low word of lpsz.
//
// History: quintinb Created 01/03/2000
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI LowerOrUpperHelper(IN OUT LPWSTR lpsz, CharLowerOrUpperA pfnLowerOrUpper) { LPWSTR pszwReturn = lpsz; LPSTR pszAnsiTmp = NULL;
if (lpsz) { //
// CharLower/CharUpper can be used in two ways. There is a Character mode where the Loword of the
// pointer passed in actually stores the numeric value of the character to get the lowercase/uppercase
// value of. There is also the traditional use, where the whole string is passed in. Thus
// we have to detect which mode we are in and handle it accordingly.
//
if (0 == HIWORD(lpsz)) { //
// Character Mode
//
CHAR szAnsiTmp[2]; WCHAR szwWideTmp[2];
szwWideTmp[0] = (WCHAR)LOWORD(lpsz); szwWideTmp[1] = L'\0';
int iChars = WzToSz(szwWideTmp, szAnsiTmp, 2);
if (iChars && (iChars <= 2)) { pfnLowerOrUpper(szAnsiTmp);
iChars = SzToWz(szAnsiTmp, szwWideTmp, 2); if (iChars && (iChars <= 2)) { lpsz = (LPWSTR) ((WORD)szwWideTmp[0]); pszwReturn = lpsz; } else { CMASSERTMSG(FALSE, TEXT("LowerOrUpperHelper-- Failed to convert szAnsiTmp back to szwWideTmp.")); } } else { CMASSERTMSG(FALSE, TEXT("LowerOrUpperHelper -- Failed to convert szwWideTmp to szAnsiTmp.")); } } else { //
// String Mode
//
pszAnsiTmp = WzToSzWithAlloc(lpsz);
if (!pszAnsiTmp) { goto exit; }
pfnLowerOrUpper(pszAnsiTmp);
//
// Convert back into UNICODE chars in lpsz
//
int iCharCount = (lstrlenAU(lpsz) + 1); // include NULL
int iChars = SzToWz(pszAnsiTmp, lpsz, iCharCount);
if (!iChars || (iChars > iCharCount)) { CMASSERTMSG(FALSE, TEXT("LowerOrUpperHelper -- Failed to convert pszAnsiTmp to lpsz.")); goto exit; } } }
exit:
CmFree(pszAnsiTmp);
return pszwReturn; }
//+----------------------------------------------------------------------------
//
// Function: CharLowerAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CharLower API. Notice that
// we support both the string input parameter and the single character
// input method.
//
// Arguments: LPWSTR lpsz -- either a pointer to a string to convert to its
// lower character version or a single character stored
// in the low word of the pointer to find the lowercase
// character for.
//
// Returns: LPWSTR -- lower case version of the string passed in (same as lpsz
// because it is converted in place) or lower case version
// of the character stored in the Low word of lpsz.
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI CharLowerAU(IN OUT LPWSTR lpsz) { return LowerOrUpperHelper(lpsz, CharLowerA); }
//+----------------------------------------------------------------------------
//
// Function: CharUpperAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CharUpper API. Notice that
// we support both the string input parameter and the single character
// input method.
//
// Arguments: LPWSTR lpsz -- either a pointer to a string to convert to its
// upper character version or a single character stored
// in the low word of the pointer to find the uppercase
// character for.
//
// Returns: LPWSTR -- upper case version of the string passed in (same as lpsz
// because it is converted in place) or upper case version
// of the character stored in the Low word of lpsz.
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI CharUpperAU(IN OUT LPWSTR lpsz) { return LowerOrUpperHelper(lpsz, CharUpperA); }
//+----------------------------------------------------------------------------
//
// Function: CreateDialogParamAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateDialogParam API. Notice that
// we support both a full string for the lpTemplateName param or only
// a int from MAKEINTRESOURCE (a resource identifier stored in the string
// pointer var).
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HWND WINAPI CreateDialogParamAU(IN HINSTANCE hInstance, IN LPCWSTR lpTemplateName, IN HWND hWndParent, IN DLGPROC lpDialogFunc, IN LPARAM dwInitParam) { HWND hWndReturn = NULL; CHAR szAnsiTemplateName[MAX_PATH+1]; LPSTR pszAnsiTemplateName;
MYDBGASSERT(hInstance); MYDBGASSERT(lpTemplateName); MYDBGASSERT(lpDialogFunc);
if (hInstance && lpTemplateName && lpDialogFunc) { if (HIWORD(lpTemplateName)) { //
// We have a full template name that we must convert
//
pszAnsiTemplateName = szAnsiTemplateName; int iChars = WzToSz(lpTemplateName, pszAnsiTemplateName, MAX_PATH);
if (!iChars || (MAX_PATH < iChars)) { goto exit; } } else { //
// All we need is a cast
//
pszAnsiTemplateName = (LPSTR)lpTemplateName; }
hWndReturn = CreateDialogParamA(hInstance, pszAnsiTemplateName, hWndParent, lpDialogFunc, dwInitParam); }
exit:
return hWndReturn; }
//+----------------------------------------------------------------------------
//
// Function: CreateDirectoryAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateDirectory API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI CreateDirectoryAU(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE;
LPSTR pszPathName = WzToSzWithAlloc(lpPathName); if (pszPathName) { bRet = CreateDirectoryA(pszPathName, lpSecurityAttributes);
CmFree(pszPathName); }
return bRet; }
//+----------------------------------------------------------------------------
//
// Function: CreateEventAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateEvent API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI CreateEventAU(IN LPSECURITY_ATTRIBUTES lpEventAttributes, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName) { CHAR szAnsiName[MAX_PATH+1]; // lpName is limited to MAX_PATH chars according to the docs.
HANDLE hReturn = NULL; LPSTR pszAnsiName = NULL;
if (lpName) // lpName could be NULL
{ pszAnsiName = szAnsiName; int uNumChars = WzToSz(lpName, pszAnsiName, MAX_PATH);
if (!uNumChars || (MAX_PATH < uNumChars)) { CMTRACE(TEXT("CreateEventAU -- Unable to convert lpName")); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto exit; } }
hReturn = CreateEventA(lpEventAttributes, bManualReset, bInitialState, pszAnsiName);
exit:
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: CreateFileMappingAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateFileMapping API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI CreateFileMappingAU(IN HANDLE hFile, IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, IN DWORD flProtect, IN DWORD dwMaximumSizeHigh, IN DWORD dwMaximumSizeLow, IN LPCWSTR lpName) { HANDLE hHandle = NULL; LPSTR pszName = NULL;
if (lpName) // could be NULL
{ pszName = WzToSzWithAlloc(lpName); }
if (pszName || (NULL == lpName)) { hHandle = CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, pszName);
CmFree(pszName); }
return hHandle; }
//+----------------------------------------------------------------------------
//
// Function: CreateFileAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateFile API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI CreateFileAU(IN LPCWSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile) { HANDLE hHandle = INVALID_HANDLE_VALUE;
LPSTR pszFileName = WzToSzWithAlloc(lpFileName); if (pszFileName) { hHandle = CreateFileA(pszFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
CmFree(pszFileName); }
return hHandle; }
//+----------------------------------------------------------------------------
//
// Function: CreateMutexAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateMutex API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI CreateMutexAU(IN LPSECURITY_ATTRIBUTES lpMutexAttributes, IN BOOL bInitialOwner, IN LPCWSTR lpName) { HANDLE hHandle = NULL; LPSTR pszName = NULL;
if (lpName) // lpName can be NULL, creates an unnamed mutex
{ pszName = WzToSzWithAlloc(lpName); } if (pszName || (NULL == lpName)) { hHandle = CreateMutexA(lpMutexAttributes, bInitialOwner, pszName);
CmFree(pszName); }
return hHandle; }
//+----------------------------------------------------------------------------
//
// Function: CreateProcessAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateProcess API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI CreateProcessAU(IN LPCWSTR lpApplicationName, IN LPWSTR lpCommandLine, IN LPSECURITY_ATTRIBUTES lpProcessAttributes, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN BOOL bInheritHandles, IN DWORD dwCreationFlags, IN LPVOID lpEnvironment, IN LPCWSTR lpCurrentDirectory, IN LPSTARTUPINFOW lpStartupInfo, OUT LPPROCESS_INFORMATION lpProcessInformation) { BOOL bSuccess = FALSE;
//
// Convert the string parameters. Since the environment block is controlled by
// a flag (whether it is Ansi or Unicode) we shouldn't have to touch it here.
//
LPSTR pszAppName = WzToSzWithAlloc(lpApplicationName); // WzToSzWithAlloc will return NULL if the input is NULL
LPSTR pszCmdLine = WzToSzWithAlloc(lpCommandLine); LPSTR pszCurrentDir = WzToSzWithAlloc(lpCurrentDirectory);
//
// Set up the StartUp Info struct. Note that we don't convert it but pass a blank
// structure. If someone needs startupinfo then they will have to write the conversion
// code. We currently don't use it anywhere.
//
STARTUPINFOA StartUpInfoA;
ZeroMemory(&StartUpInfoA, sizeof(STARTUPINFOA)); StartUpInfoA.cb = sizeof(STARTUPINFOA);
#ifdef DEBUG
STARTUPINFOW CompareStartupInfoWStruct; ZeroMemory(&CompareStartupInfoWStruct, sizeof(STARTUPINFOW)); CompareStartupInfoWStruct.cb = sizeof(STARTUPINFOW); CMASSERTMSG((0 == memcmp(lpStartupInfo, &CompareStartupInfoWStruct, sizeof(STARTUPINFOW))), TEXT("CreateProcessAU -- Non-NULL STARTUPINFOW struct passed. Conversion code needs to be written.")); #endif
//
// If we have the Command Line or an App Name go ahead
//
if (pszAppName || pszCmdLine) { bSuccess = CreateProcessA(pszAppName, pszCmdLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, pszCurrentDir, &StartUpInfoA, lpProcessInformation);
}
//
// Cleanup
//
CmFree(pszAppName); CmFree(pszCmdLine); CmFree(pszCurrentDir);
return bSuccess; }
//+----------------------------------------------------------------------------
//
// Function: CreateWindowExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 CreateWindowEx API. Note that
// we only allow MAX_PATH chars for the ClassName and the WindowName
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HWND WINAPI CreateWindowExAU(DWORD dwExStyle, LPCWSTR lpClassNameW, LPCWSTR lpWindowNameW, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { CHAR szClassNameA [MAX_PATH+1]; CHAR szWindowNameA[MAX_PATH+1]; HWND hReturn = NULL;
if (lpClassNameW && lpWindowNameW) { MYDBGASSERT(MAX_PATH >= lstrlenAU(lpClassNameW)); MYDBGASSERT(MAX_PATH >= lstrlenAU(lpWindowNameW));
if (WzToSz(lpClassNameW, szClassNameA, MAX_PATH)) { if (WzToSz(lpWindowNameW, szWindowNameA, MAX_PATH)) { hReturn = CreateWindowExA(dwExStyle, szClassNameA, szWindowNameA, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } } }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: DeleteFileAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 DeleteFile API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI DeleteFileAU(IN LPCWSTR lpFileName) { BOOL bReturn = FALSE; LPSTR pszAnsiFileName = WzToSzWithAlloc(lpFileName); // WzToSzWithAlloc will return NULL if lpFileName is NULL
if (pszAnsiFileName) { DeleteFileA(pszAnsiFileName); CmFree(pszAnsiFileName); }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: DialogBoxParamAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 DialogBoxParam API. Note that
// we don't support the use of a full string name, only ints for the
// lpTemplateName param. We will assert if one is used.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
INT_PTR WINAPI DialogBoxParamAU(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { MYDBGASSERT(0 == HIWORD(lpTemplateName)); // we don't support or use the full string name
return DialogBoxParamA(hInstance, (LPCSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); }
//+----------------------------------------------------------------------------
//
// Function: ExpandEnvironmentStringsAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 ExpandEnvironmentStrings API.
// We support allowing the user to size the string by passing in the
// following Str, NULL, 0 just as the API reference mentions.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
DWORD WINAPI ExpandEnvironmentStringsAU(IN LPCWSTR lpSrc, OUT LPWSTR lpDst, IN DWORD nSize) { DWORD dwReturn = 0;
if (lpSrc) { //
//
// Since the user could pass in 0 for the size and a NULL pszAnsiDst because they
// want to size the destination string, we want to handle that case. However,
// Win98 and Win95 machines (not counting WinME) don't honor sizing the buffer
// using a NULL lpDst. We will "fool" these machines by using a buffer of size 1.
// Thus they could call it with Str, NULL, 0 and then allocate the correct size and
// call again. Note that we will return an error if the user passes Str, NULL, x
// because we have no buffer to copy the data returned from ExpandEnvironmentStringsA
// into.
//
LPSTR pszAnsiSrc = WzToSzWithAlloc(lpSrc); LPSTR pszAnsiDst = (LPSTR)CmMalloc((nSize+1)*sizeof(CHAR));
if (pszAnsiSrc && pszAnsiDst) { dwReturn = ExpandEnvironmentStringsA(pszAnsiSrc, pszAnsiDst, nSize);
if (dwReturn && (dwReturn <= nSize)) { //
// Then the function succeeded and there was sufficient buffer space to hold
// the expanded string. Thus we should convert the results and store it back
// in lpDst.
if (lpDst) { if (!SzToWz(pszAnsiDst, lpDst, nSize)) { CMTRACE(TEXT("ExpandEnvironmentStringsAU -- SzToWz conversion of output param failed.")); dwReturn = 0; } } else { CMTRACE(TEXT("ExpandEnvironmentStringsAU -- NULL pointer passed for lpDst")); dwReturn = 0; SetLastError(ERROR_INVALID_PARAMETER); } } } else { CMTRACE(TEXT("ExpandEnvironmentStringsAU -- NULL pointer returned for pszAnsiSrc or pszAnsiDst")); SetLastError(ERROR_NOT_ENOUGH_MEMORY); }
CmFree(pszAnsiSrc); CmFree(pszAnsiDst); } else { CMTRACE(TEXT("ExpandEnvironmentStringsAU -- NULL pointer passed for lpSrc")); SetLastError(ERROR_INVALID_PARAMETER); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: FindResourceExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 FindResourceEx API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HRSRC WINAPI FindResourceExAU(IN HMODULE hModule, IN LPCWSTR lpType, IN LPCWSTR lpName, IN WORD wLanguage) { HRSRC hReturn = NULL; LPSTR pszType = NULL; LPSTR pszName = NULL;
//
// Check the input parameters
//
if (lpType && lpName) { //
// Two cases for the lpType and the lpName params. These could just be identifiers. We will know
// if the high word is zero. In that case we just need to do a cast and pass it through. If not
// then we need to actually convert the strings.
//
if (0 == HIWORD(lpType)) { pszType = (LPSTR)lpType; } else { pszType = WzToSzWithAlloc(lpType); }
if (0 == HIWORD(lpName)) { pszName = (LPSTR)lpName; } else { pszName = WzToSzWithAlloc(lpName); }
//
// Finally call FindResourceEx
//
if (pszName && pszType) { hReturn = FindResourceExA(hModule, pszType, pszName, wLanguage); } else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } } else { SetLastError(ERROR_INVALID_PARAMETER); }
//
// Clean up
//
if (0 != HIWORD(pszType)) { CmFree(pszType); }
if (0 != HIWORD(pszName)) { CmFree(pszName); }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: FindWindowExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 FindWindowEx API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HWND WINAPI FindWindowExAU(IN HWND hwndParent, IN HWND hwndChildAfter, IN LPCWSTR pszClass, IN LPCWSTR pszWindow) { HWND hReturn = NULL; LPSTR pszAnsiWindow = NULL; LPSTR pszAnsiClass = NULL;
if (pszClass) { //
// We have two cases for pszClass. It can either be a resource ID (high word zero,
// low word contains the ID) in which case we just need to do a cast or
// it could be a NULL terminated string.
//
if (0 == HIWORD(pszClass)) { pszAnsiClass = (LPSTR)pszClass; } else { pszAnsiClass = WzToSzWithAlloc(pszClass); }
//
// pszWindow could be NULL. That will match all Window titles.
//
if (pszWindow) { pszAnsiWindow = WzToSzWithAlloc(pszWindow); } //
// Check our allocations and call FindWindowExA
//
if (pszAnsiClass && (!pszWindow || pszAnsiWindow)) { hReturn = FindWindowExA(hwndParent, hwndChildAfter, pszAnsiClass, pszAnsiWindow); } else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } } else { SetLastError(ERROR_INVALID_PARAMETER); }
//
// Cleanup
//
if (0 != HIWORD(pszAnsiClass)) { CmFree(pszAnsiClass); }
CmFree(pszAnsiWindow);
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetDateFormatAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetDateFormat API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: sumitc Created 11/20/00
//
//+----------------------------------------------------------------------------
int WINAPI GetDateFormatAU(IN LCID Locale, IN DWORD dwFlags, IN CONST SYSTEMTIME *lpDate, IN LPCWSTR lpFormat, OUT LPWSTR lpDateStr, IN int cchDate) { int iReturn = 0; LPSTR pszAnsiFormat = NULL; LPSTR pszAnsiBuffer = NULL;
if (lpFormat) { pszAnsiFormat = WzToSzWithAlloc(lpFormat); if (!pszAnsiFormat) { CMASSERTMSG(FALSE, TEXT("GetDateFormatAU -- Conversion of lpFormat Failed.")); goto exit; } } else { pszAnsiFormat = (LPSTR)lpFormat; // Could be NULL
}
if (lpDateStr && cchDate) { pszAnsiBuffer = (LPSTR) CmMalloc(cchDate * sizeof(CHAR)); }
iReturn = GetDateFormatA(Locale, dwFlags, lpDate, pszAnsiFormat, pszAnsiBuffer, cchDate);
if (iReturn && lpDateStr && cchDate && pszAnsiBuffer) { SzToWz(pszAnsiBuffer, lpDateStr, cchDate); }
exit:
CmFree(pszAnsiFormat); CmFree(pszAnsiBuffer);
return iReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetDlgItemTextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetDlgItemText API. Note that
// this function makes a WM_GETTEXT window message call using GetDlgItem
// and SendMessageAU. This is how the win32 API function is implemented.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
UINT WINAPI GetDlgItemTextAU(IN HWND hDlg, IN int nIDDlgItem, OUT LPWSTR pszwString, IN int nMaxCount) { return (int) SendMessageAU(GetDlgItem(hDlg, nIDDlgItem), WM_GETTEXT, (WPARAM) nMaxCount, (LPARAM) pszwString); }
//+----------------------------------------------------------------------------
//
// Function: GetFileAttributesAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetFileAttributes API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: sumitc Created 11/08/00
//
//+----------------------------------------------------------------------------
DWORD WINAPI GetFileAttributesAU(LPCWSTR lpFileName) { DWORD dwReturn = -1; LPSTR pszAnsiFileName = WzToSzWithAlloc(lpFileName); if (pszAnsiFileName) { dwReturn = GetFileAttributesA(pszAnsiFileName); CmFree(pszAnsiFileName); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetModuleFileNameAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetModuleFileName API.
// Note that we only allow MAX_PATH chars for the module name.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
DWORD WINAPI GetModuleFileNameAU(HMODULE hModule, LPWSTR lpFileName, DWORD nSize) { DWORD dwReturn = 0; CHAR pszAnsiFileName[MAX_PATH] = {'\0'} ;
MYDBGASSERT(MAX_PATH >= nSize);
dwReturn = GetModuleFileNameA(hModule, pszAnsiFileName, __min(nSize, MAX_PATH));
if(dwReturn && lpFileName) { SzToWz(pszAnsiFileName, lpFileName, __min(nSize, MAX_PATH)); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetModuleHandleAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetModuleHandle API.
// Note that we only allow MAX_PATH chars for the module name.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: sumitc Created 10/20/2000
//
//+----------------------------------------------------------------------------
HMODULE WINAPI GetModuleHandleAU(LPCWSTR lpModuleName) { HMODULE hMod = NULL; LPSTR pszAnsiModuleName = WzToSzWithAlloc(lpModuleName);
if (pszAnsiModuleName) { hMod = GetModuleHandleA(pszAnsiModuleName);
CmFree(pszAnsiModuleName); }
return hMod; }
//+----------------------------------------------------------------------------
//
// Function: GetPrivateProfileIntAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetPrivateProfileInt API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
UINT WINAPI GetPrivateProfileIntAU(IN LPCWSTR lpAppName, IN LPCWSTR lpKeyName, IN INT nDefault, IN LPCWSTR lpFileName) { UINT uReturn = nDefault;
if (lpAppName && lpKeyName && lpFileName) { CHAR pszAnsiAppName[MAX_PATH+1]; CHAR pszAnsiKeyName[MAX_PATH+1]; CHAR pszAnsiFileName[MAX_PATH+1];
BOOL bSuccess = TRUE; int nChars; nChars = WzToSz(lpAppName, pszAnsiAppName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars);
nChars = WzToSz(lpKeyName, pszAnsiKeyName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars);
nChars = WzToSz(lpFileName, pszAnsiFileName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars);
if (bSuccess) { uReturn = GetPrivateProfileIntA(pszAnsiAppName, pszAnsiKeyName, nDefault, pszAnsiFileName); }
CMASSERTMSG(bSuccess, TEXT("GetPrivateProfileIntAU -- Failed to convert lpAppName, lpKeyName, or lpFileName")); }
return uReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetPrivateProfileStringAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetPrivateProfileString API.
// Note that either lpAppName or lpKeyName could be NULL. This means
// that our return buffer will contain multiple lines of NULL terminated
// text. We must use MultiByteToWideChar directly with a size param
// to properly convert such a situation.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
DWORD WINAPI GetPrivateProfileStringAU(IN LPCWSTR lpAppName, IN LPCWSTR lpKeyName, IN LPCWSTR lpDefault, OUT LPWSTR lpReturnedString, IN DWORD nSize, IN LPCWSTR lpFileName) { //
// Declare all the temp vars we need
//
LPSTR pszAnsiAppName = NULL; LPSTR pszAnsiKeyName = NULL; LPSTR pszAnsiReturnedString = NULL; CHAR szAnsiAppName[MAX_PATH+1]; CHAR szAnsiKeyName[MAX_PATH+1]; CHAR szAnsiDefault[MAX_PATH+1]; CHAR szAnsiFileName[MAX_PATH+1]; DWORD dwReturn = 0; int nChars;
//
// Check the inputs, note that either lpAppName or lpKeyName may be NULL (or both)
//
if (lpDefault && lpReturnedString && nSize && lpFileName) { if (lpAppName) // pszAnsiAppName already initialized to NULL
{ pszAnsiAppName = szAnsiAppName; nChars = WzToSz(lpAppName, pszAnsiAppName, MAX_PATH); if (!nChars || (MAX_PATH < nChars)) { //
// Conversion failed.
//
goto exit; } }
if (lpKeyName) // pszAnsiKeyName already initialized to NULL
{ pszAnsiKeyName = szAnsiKeyName; nChars = WzToSz(lpKeyName, szAnsiKeyName, MAX_PATH); if (!nChars || (MAX_PATH < nChars)) { //
// Conversion failed.
//
goto exit; } } nChars = WzToSz(lpDefault, szAnsiDefault, MAX_PATH); if (!nChars || (MAX_PATH < nChars)) { goto exit; }
nChars = WzToSz(lpFileName, szAnsiFileName, MAX_PATH); if (!nChars || (MAX_PATH < nChars)) { goto exit; }
//
// Alloc the Ansi return Buffer
//
pszAnsiReturnedString = (LPSTR)CmMalloc(nSize*sizeof(CHAR));
if (pszAnsiReturnedString) { dwReturn = GetPrivateProfileStringA(pszAnsiAppName, pszAnsiKeyName, szAnsiDefault, pszAnsiReturnedString, nSize, szAnsiFileName);
if (dwReturn) { if (pszAnsiAppName && pszAnsiKeyName) { if (!SzToWz(pszAnsiReturnedString, lpReturnedString, nSize)) { dwReturn = 0; } } else { //
// We have multiple lines of text in the return buffer, use MultiByteToWideChar
// with a size specifier
//
if (!MultiByteToWideChar(CP_ACP, 0, pszAnsiReturnedString, dwReturn, lpReturnedString, nSize)) { dwReturn = 0; } } } } }
exit:
CmFree(pszAnsiReturnedString); return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetStringTypeExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetStringTypeEx API. Note
// that because we only use one char at a time with this API, I have
// limited it to a 10 char static buffer to make it faster.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI GetStringTypeExAU(IN LCID Locale, IN DWORD dwInfoType, IN LPCWSTR lpSrcStr, IN int cchSrc, OUT LPWORD lpCharType) { BOOL bReturn = FALSE; CHAR szAnsiString[10]; // We should only be using 1 char at a time with this
if (lpSrcStr && cchSrc) { MYDBGASSERT(cchSrc <= 10);
int nCount = WideCharToMultiByte(CP_ACP, 0, lpSrcStr, cchSrc, szAnsiString, 9, NULL, NULL);
if (nCount) // nCount may not exactly equal cchSrc if DBCS chars were necessary
{ bReturn = GetStringTypeExA(Locale, dwInfoType, szAnsiString, nCount, lpCharType); } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetSystemDirectoryAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetSystemDirectory API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
UINT WINAPI GetSystemDirectoryAU(OUT LPWSTR lpBuffer, IN UINT uSize) { UINT uReturn = 0; LPSTR pszAnsiSystemDir;
pszAnsiSystemDir = uSize ? (LPSTR)CmMalloc(uSize*sizeof(CHAR)) : NULL;
if (pszAnsiSystemDir || (0 == uSize)) { uReturn = GetSystemDirectoryA(pszAnsiSystemDir, uSize); CMASSERTMSG(uReturn, TEXT("GetSystemDirectoryAU -- GetSystemDirectoryAU failed."));
if (uReturn && lpBuffer && (uSize >= uReturn)) { if (!SzToWz(pszAnsiSystemDir, lpBuffer, uSize)) { //
// Conversion failed.
//
CMASSERTMSG(FALSE, TEXT("GetSystemDirectoryAU -- SzToWz conversion failed.")); uReturn = 0; } } }
CmFree(pszAnsiSystemDir);
return uReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetTempFileNameAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetTempFileName API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
UINT WINAPI GetTempFileNameAU(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName) { UINT uReturn = 0;
if (lpPathName && lpPrefixString && lpTempFileName) { CHAR szAnsiTempFileName[MAX_PATH+1]; CHAR szPathName[MAX_PATH+1]; CHAR szPrefixString[MAX_PATH+1]; BOOL bSuccess = TRUE; int nChars; nChars = WzToSz(lpPathName, szPathName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars);
nChars = WzToSz(lpPrefixString, szPrefixString, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars);
if (bSuccess) { uReturn = GetTempFileNameA(szPathName, szPrefixString, uUnique, szAnsiTempFileName); if (uReturn) { if (!SzToWz(szAnsiTempFileName, lpTempFileName, MAX_PATH)) { CMASSERTMSG(FALSE, TEXT("GetTempFileNameAU -- conversion of output buffer failed.")); uReturn = 0; } } } else { CMASSERTMSG(FALSE, TEXT("GetTempFileNameAU -- conversion of inputs failed.")); SetLastError(ERROR_INVALID_PARAMETER); } } else { SetLastError(ERROR_INVALID_PARAMETER); }
return uReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetTempPathAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetTempPath API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
DWORD WINAPI GetTempPathAU(IN DWORD nBufferLength, OUT LPWSTR lpBuffer) { UINT uReturn = 0;
LPSTR pszAnsiBuffer = (LPSTR)CmMalloc(nBufferLength*sizeof(CHAR));
if (pszAnsiBuffer) { uReturn = GetTempPathA(nBufferLength, pszAnsiBuffer); if (uReturn) { if (!SzToWz(pszAnsiBuffer, lpBuffer, nBufferLength)) { CMASSERTMSG(FALSE, TEXT("GetTempPathAU -- conversion of output buffer failed.")); uReturn = 0; } } CmFree(pszAnsiBuffer); }
return uReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetTimeFormatAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetTimeFormat API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: sumitc Created 11/20/00
//
//+----------------------------------------------------------------------------
int WINAPI GetTimeFormatAU(IN LCID Locale, IN DWORD dwFlags, IN CONST SYSTEMTIME *lpTime, IN LPCWSTR lpFormat, OUT LPWSTR lpTimeStr, IN int cchTime) { int iReturn = 0; LPSTR pszAnsiFormat = NULL; LPSTR pszAnsiBuffer = NULL;
if (lpFormat) { pszAnsiFormat = WzToSzWithAlloc(lpFormat); if (!pszAnsiFormat) { CMASSERTMSG(FALSE, TEXT("GetTimeFormatAU -- Conversion of lpFormat Failed.")); goto exit; } } else { pszAnsiFormat = (LPSTR)lpFormat; // Could be NULL
}
if (lpTimeStr && cchTime) { pszAnsiBuffer = (LPSTR) CmMalloc(cchTime * sizeof(CHAR)); }
iReturn = GetTimeFormatA(Locale, dwFlags, lpTime, pszAnsiFormat, pszAnsiBuffer, cchTime);
if (iReturn && lpTimeStr && cchTime && pszAnsiBuffer) { SzToWz(pszAnsiBuffer, lpTimeStr, cchTime); }
exit:
CmFree(pszAnsiFormat); CmFree(pszAnsiBuffer);
return iReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetUserNameAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetUserName API.
// Note that we assume the user name will fit in MAX_PATH chars.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI GetUserNameAU(OUT LPWSTR lpBuffer, IN OUT LPDWORD pdwSize) { BOOL bReturn = FALSE;
if (lpBuffer && pdwSize && *pdwSize) { MYDBGASSERT(MAX_PATH >= *pdwSize); CHAR szAnsiBuffer[MAX_PATH+1]; // API says UNLEN+1 needed but this is less than MAX_PATH
DWORD dwTemp = MAX_PATH;
bReturn = GetUserNameA(szAnsiBuffer, &dwTemp);
if (bReturn) { if (!SzToWz(szAnsiBuffer, lpBuffer, *pdwSize)) { bReturn = FALSE; } else { *pdwSize = lstrlenAU(lpBuffer) + 1; } } } else { SetLastError(ERROR_INVALID_PARAMETER); }
CMASSERTMSG(bReturn, TEXT("GetUserNameAU Failed."));
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetVersionExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetVersionEx API. Note that
// we check to make sure we aren't passed an OSVERSIONINFOEXW struct
// because that struct is currently NT5 only.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI GetVersionExAU(IN OUT LPOSVERSIONINFOW lpVersionInformation) { BOOL bReturn = FALSE;
if (lpVersionInformation) { OSVERSIONINFOA AnsiVersionInfo; //
// Check to make sure we didn't get an OSVERSIONINFOEXW struct instead of a OSVERSIONINFO
// the EX version is NT5 only we shouldn't be calling this on NT5.
//
MYDBGASSERT(lpVersionInformation->dwOSVersionInfoSize != sizeof(_OSVERSIONINFOEXW));
AnsiVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
bReturn = GetVersionExA(&AnsiVersionInfo); if (bReturn) { //lpVersionInformation.dwOSVersionInfoSize; // should be set appropriately already
lpVersionInformation->dwMajorVersion = AnsiVersionInfo.dwMajorVersion; lpVersionInformation->dwMinorVersion = AnsiVersionInfo.dwMinorVersion; lpVersionInformation->dwBuildNumber = AnsiVersionInfo.dwBuildNumber; lpVersionInformation->dwPlatformId = AnsiVersionInfo.dwPlatformId;
if (!SzToWz(AnsiVersionInfo.szCSDVersion, lpVersionInformation->szCSDVersion, 128-1)) { bReturn = FALSE; } } }
CMASSERTMSG(bReturn, TEXT("GetVersionExAU Failed")); return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: GetWindowTextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetWindowText API. This API
// is implemented as a WM_GETTEXT message just as the real windows
// API is.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPI GetWindowTextAU(HWND hWnd, LPWSTR lpStringW, int nMaxChars) { return (int) SendMessageAU(hWnd, WM_GETTEXT, (WPARAM) nMaxChars, (LPARAM) lpStringW); }
//+----------------------------------------------------------------------------
//
// Function: GetWindowTextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 GetWindowText API. This API
// is implemented as a WM_GETTEXT message just as the real windows
// API is. Note that since MF_STRING is 0, we must check to make sure
// that it isn't one of the other menu item choices (MF_OWNERDRAW,
// MF_BITMAP, or MF_SEPARATOR). The other MF_ flags are just modifiers
// for the above basic types.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI InsertMenuAU(IN HMENU hMenu, IN UINT uPosition, IN UINT uFlags, IN UINT_PTR uIDNewItem, IN LPCWSTR lpNewItem) { BOOL bReturn = FALSE; LPSTR pszAnsiNewItem = NULL; BOOL bFreeAnsiNewItem = FALSE;
if (hMenu) { //
// Since MF_STRING == 0, we must check that it is not MF_OWNERDRAW or MF_BITMAP or
// that it is not MF_SEPARATOR
//
if ((0 == (uFlags & MF_BITMAP)) && (0 == (uFlags & MF_OWNERDRAW)) && (0 == (uFlags & MF_SEPARATOR)) && lpNewItem) { //
// Then the menu item actually contains a string and we must convert it.
//
pszAnsiNewItem = WzToSzWithAlloc(lpNewItem);
if (!pszAnsiNewItem) { CMASSERTMSG(FALSE, TEXT("InsertMenuAU -- Conversion of lpNewItem Failed.")); goto exit; } bFreeAnsiNewItem = TRUE; } else { pszAnsiNewItem = (LPSTR)lpNewItem; // Could be NULL
}
bReturn = InsertMenuA(hMenu, uPosition, uFlags, uIDNewItem, pszAnsiNewItem); }
exit:
if (bFreeAnsiNewItem) { CmFree(pszAnsiNewItem); }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadCursorAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadCursor API. Note that
// lpCursorName could be a string or it could be a resource ID from
// MAKEINTRESOURCE. We assume the cursor name will fit in MAX_PATH
// chars if it is a string.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HCURSOR WINAPI LoadCursorAU(IN HINSTANCE hInstance, IN LPCWSTR lpCursorName) { LPSTR pszCursorName; CHAR szCursorName[MAX_PATH+1]; HCURSOR hReturn = NULL;
if (lpCursorName) { BOOL bSuccess = TRUE;
if (0 == HIWORD(lpCursorName)) { pszCursorName = (LPSTR)lpCursorName; } else { int nChars; pszCursorName = szCursorName; nChars = WzToSz(lpCursorName, pszCursorName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars); }
if (bSuccess) { hReturn = LoadCursorA(hInstance, pszCursorName); } } else { SetLastError(ERROR_INVALID_PARAMETER); }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadIconAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadIcon API. Note that
// lpIconName could be a string or it could be a resource ID from
// MAKEINTRESOURCE. We assume the icon name will fit in MAX_PATH
// chars if it is a string.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HICON WINAPI LoadIconAU(IN HINSTANCE hInstance, IN LPCWSTR lpIconName) { LPSTR pszIconName; CHAR szIconName[MAX_PATH+1]; HICON hReturn = NULL;
if (hInstance && lpIconName) { BOOL bSuccess = TRUE;
if (0 == HIWORD(lpIconName)) { pszIconName = (LPSTR)lpIconName; } else { int nChars; pszIconName = szIconName; nChars = WzToSz(lpIconName, pszIconName, MAX_PATH); bSuccess = bSuccess && nChars && (MAX_PATH >= nChars); }
if (bSuccess) { hReturn = LoadIconA(hInstance, pszIconName); } } else { SetLastError(ERROR_INVALID_PARAMETER); }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadImageAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadImage API. Note that
// pszwName could be a string or it could be a resource ID from
// MAKEINTRESOURCE. We assume the image name will fit in MAX_PATH
// chars if it is a string.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI LoadImageAU(IN HINSTANCE hInst, IN LPCWSTR pszwName, IN UINT uType, IN int cxDesired, IN int cyDesired, IN UINT fuLoad) { HANDLE hReturn = NULL;
MYDBGASSERT(hInst || (LR_LOADFROMFILE & fuLoad)); // we don't support loading OEM images -- implement it if you need it.
if (pszwName) { CHAR szAnsiName [MAX_PATH+1]; LPSTR pszAnsiName;
if (0 == HIWORD(pszwName)) { pszAnsiName = LPSTR(pszwName); } else { pszAnsiName = szAnsiName; int iChars = WzToSz(pszwName, pszAnsiName, MAX_PATH);
if (!iChars || (MAX_PATH < iChars)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto exit; } }
hReturn = LoadImageA(hInst, pszAnsiName, uType, cxDesired, cyDesired, fuLoad); }
exit:
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadLibraryExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadLibraryEx API. Note that
// we expect the library name to fit in MAX_PATH ANSI chars.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HMODULE WINAPI LoadLibraryExAU(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { CHAR pszLibFileName[MAX_PATH+1]; HMODULE hReturn = NULL;
if (lpLibFileName && (NULL == hFile)) // hFile is reserved, it must be NULL
{ if(WzToSz(lpLibFileName, pszLibFileName, MAX_PATH)) { hReturn = LoadLibraryExA(pszLibFileName, hFile, dwFlags); } }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadMenuAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadMenu API. Note that
// lpMenuName could be a string or it could be a resource ID from
// MAKEINTRESOURCE. We assume the menu name will fit in MAX_PATH
// chars if it is a string.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HMENU WINAPI LoadMenuAU(IN HINSTANCE hInstance, IN LPCWSTR lpMenuName) { HMENU hMenuReturn = NULL; LPSTR pszAnsiMenuName; CHAR szAnsiMenuName[MAX_PATH+1];
if (hInstance && lpMenuName) { if (HIWORD(lpMenuName)) { pszAnsiMenuName = szAnsiMenuName; int iChars = WzToSz(lpMenuName, pszAnsiMenuName, MAX_PATH); if (!iChars || (MAX_PATH < iChars)) { goto exit; } } else { pszAnsiMenuName = (LPSTR)lpMenuName; }
hMenuReturn = LoadMenuA(hInstance, pszAnsiMenuName); }
exit: return hMenuReturn; }
//+----------------------------------------------------------------------------
//
// Function: LoadStringAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 LoadString API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPI LoadStringAU(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax) { int iReturn = 0;
if (uID && hInstance) // lpBuffer and nBufferMax could be Zero
{ LPSTR pszAnsiBuffer = nBufferMax ? (LPSTR)CmMalloc(nBufferMax*sizeof(CHAR)) : NULL; if (pszAnsiBuffer || (0 == nBufferMax)) { iReturn = LoadStringA(hInstance, uID, pszAnsiBuffer, nBufferMax);
if (lpBuffer && iReturn && (iReturn <= nBufferMax)) { if (!SzToWz(pszAnsiBuffer, lpBuffer, nBufferMax)) { iReturn = 0; } } } CmFree(pszAnsiBuffer); }
CMASSERTMSG(iReturn, TEXT("LoadStringAU Failed."));
return iReturn; }
//+----------------------------------------------------------------------------
//
// Function: lstrcatAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrcat API. Note that we
// use wcscat instead of doing a conversion from Unicode to ANSI,
// then using lstrcatA, and then converting back to Unicode again.
// That seemed like a lot of effort when wcscat should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI lstrcatAU(IN OUT LPWSTR lpString1, IN LPCWSTR lpString2) { if (lpString2 && lpString2) { return wcscat(lpString1, lpString2); } else { CMASSERTMSG(FALSE, TEXT("NULL String passed to lstrcatAU")); return lpString1; } }
//+----------------------------------------------------------------------------
//
// Function: lstrcmpAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrcmp API. Note that we
// use wcscmp instead of doing a conversion from Unicode to ANSI,
// then using lstrcmpA, and then converting back to Unicode again.
// That seemed like a lot of effort when wcscmp should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPI lstrcmpAU(IN LPCWSTR lpString1, IN LPCWSTR lpString2) { if (lpString1 && lpString2) { return wcscmp(lpString1, lpString2); } else { CMASSERTMSG(FALSE, TEXT("NULL String passed to lstrcmpAU")); //
// Wasn't exactly sure what to do on failure since their isn't a failure
// return value from lstrcmp. I looked at the current implementation
// and they do something like the following.
//
if (lpString1) { return 1; } else if (lpString2) { return -1; } else { return 0; } } }
//+----------------------------------------------------------------------------
//
// Function: lstrcmpiAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrcmpi API. Note that we
// use _wcsicmp instead of doing a conversion from Unicode to ANSI,
// then using lstrcmpiA, and then converting back to Unicode again.
// That seemed like a lot of effort when _wcsicmp should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPI lstrcmpiAU(IN LPCWSTR lpString1, IN LPCWSTR lpString2) { if (lpString1 && lpString2) { return _wcsicmp(lpString1, lpString2); } else { CMASSERTMSG(FALSE, TEXT("NULL String passed to lstrcmpiAU")); //
// Wasn't exactly sure what to do on failure since their isn't a failure
// return value from lstrcmp. I looked at the current implementation
// and they do something like the following.
//
if (lpString1) { return 1; } else if (lpString2) { return -1; } else { return 0; } } }
//+----------------------------------------------------------------------------
//
// Function: lstrcpyAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrcpy API. Note that we
// use wcscpy instead of doing a conversion from Unicode to ANSI,
// then using lstrcpyA, and then converting back to Unicode again.
// That seemed like a lot of effort when wcscpy should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI lstrcpyAU(OUT LPWSTR pszDest, IN LPCWSTR pszSource) { if (pszDest && pszSource) { return wcscpy(pszDest, pszSource); } else { CMASSERTMSG(FALSE, TEXT("NULL String passed to lstrcpyAU")); return pszDest; } }
//+----------------------------------------------------------------------------
//
// Function: lstrcpynAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrcpyn API. Note that we
// use wcsncpy instead of doing a conversion from Unicode to ANSI,
// then using lstrcpynA, and then converting back to Unicode again.
// That seemed like a lot of effort when wcsncpy should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LPWSTR WINAPI lstrcpynAU(OUT LPWSTR pszDest, IN LPCWSTR pszSource, IN int iMaxLength) { if (pszDest && pszSource && iMaxLength) { LPWSTR pszReturn = wcsncpy(pszDest, pszSource, iMaxLength);
//
// wcsncpy and lstrcpy behave differently about terminating NULL
// characters. The last char in the lstrcpyn buffer always gets
// a TEXT('\0'), whereas wcsncpy doesn't do this. Thus we must
// NULL the last char before returning.
//
pszDest[iMaxLength-1] = TEXT('\0');
return pszReturn; } else { CMASSERTMSG(FALSE, TEXT("Invalid parameter passed to lstrcpynAU")); return pszDest; } }
//+----------------------------------------------------------------------------
//
// Function: lstrlenAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 lstrlen API. Note that we
// use wcslen instead of doing a conversion from Unicode to ANSI,
// then using lstrlenA, and then converting back to Unicode again.
// That seemed like a lot of effort when wcslen should work just fine.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPI lstrlenAU(IN LPCWSTR lpString) { if (lpString) { return wcslen(lpString); } else { // CMASSERTMSG(FALSE, TEXT("NULL String passed to lstrlenAU"));
return 0; } }
//+----------------------------------------------------------------------------
//
// Function: OpenEventAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 OpenEvent API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI OpenEventAU(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName) { HANDLE hReturn = NULL;
if (lpName) { LPSTR pszAnsiName = WzToSzWithAlloc(lpName); if (pszAnsiName) { hReturn = OpenEventA(dwDesiredAccess, bInheritHandle, pszAnsiName); }
CmFree(pszAnsiName); }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: OpenFileMappingAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 OpenFileMapping API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
HANDLE WINAPI OpenFileMappingAU(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName) { HANDLE hReturn = NULL;
if (lpName) { LPSTR pszAnsiName = WzToSzWithAlloc(lpName); if (pszAnsiName) { hReturn = OpenFileMappingA(dwDesiredAccess, bInheritHandle, pszAnsiName); }
CmFree(pszAnsiName); }
return hReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegCreateKeyExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegCreateKeyEx API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegCreateKeyExAU(IN HKEY hKey, IN LPCWSTR lpSubKey, IN DWORD Reserved, IN LPWSTR lpClass, IN DWORD dwOptions, IN REGSAM samDesired, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, OUT PHKEY phkResult, OUT LPDWORD lpdwDisposition) { LONG lReturn = ERROR_INVALID_PARAMETER; if (lpSubKey) { LPSTR pszAnsiSubKey = WzToSzWithAlloc(lpSubKey); LPSTR pszAnsiClass = lpClass ? WzToSzWithAlloc(lpClass) : NULL;
if (pszAnsiSubKey && (pszAnsiClass || !lpClass)) { lReturn = RegCreateKeyExA(hKey, pszAnsiSubKey, Reserved, pszAnsiClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; }
CmFree(pszAnsiSubKey); CmFree(pszAnsiClass); }
CMASSERTMSG(ERROR_SUCCESS == lReturn, TEXT("RegCreateKeyExAU Failed.")); return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegDeleteKeyAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegDeleteKey API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegDeleteKeyAU(IN HKEY hKey, IN LPCWSTR lpSubKey) { LONG lReturn = ERROR_INVALID_PARAMETER;
if (lpSubKey) { LPSTR pszAnsiSubKey = WzToSzWithAlloc(lpSubKey);
if (pszAnsiSubKey) { lReturn = RegDeleteKeyA(hKey, pszAnsiSubKey); } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; }
CmFree(pszAnsiSubKey); }
CMASSERTMSG(ERROR_SUCCESS == lReturn, TEXT("RegDeleteKeyAU Failed.")); return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegDeleteValueAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegDeleteValue API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegDeleteValueAU(IN HKEY hKey, IN LPCWSTR lpValueName) { LONG lReturn = ERROR_INVALID_PARAMETER;
if (lpValueName) { LPSTR pszAnsiValueName = WzToSzWithAlloc(lpValueName);
if (pszAnsiValueName) { lReturn = RegDeleteValueA(hKey, pszAnsiValueName); CmFree(pszAnsiValueName); } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; } }
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegEnumKeyExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegEnumKeyEx API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG RegEnumKeyExAU(IN HKEY hKey, IN DWORD dwIndex, OUT LPWSTR lpName, IN OUT LPDWORD lpcbName, IN LPDWORD lpReserved, IN OUT LPWSTR lpClass, IN OUT LPDWORD lpcbClass, OUT PFILETIME lpftLastWriteTime) { LONG lReturn = ERROR_INVALID_PARAMETER;
if (lpcbName) { MYDBGASSERT((lpName && *lpcbName) || ((NULL == lpName) && (0 == *lpcbName)));
LPSTR pszAnsiClass = lpClass ? WzToSzWithAlloc(lpClass) : NULL;
LPSTR pszTmpBuffer = lpName ? (LPSTR)CmMalloc(*lpcbName) : NULL;
DWORD dwSizeTmp = lpName ? *lpcbName : 0;
if (pszTmpBuffer || (NULL == lpName)) { lReturn = RegEnumKeyExA(hKey, dwIndex, pszTmpBuffer, &dwSizeTmp, lpReserved, pszAnsiClass, lpcbClass, lpftLastWriteTime);
if ((ERROR_SUCCESS == lReturn) && pszTmpBuffer) { if (!SzToWz(pszTmpBuffer, lpName, (*lpcbName))) { lReturn = ERROR_NOT_ENOUGH_MEMORY; } else { *lpcbName = (lstrlenAU((WCHAR*)lpName) + 1); } } } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; }
CmFree(pszTmpBuffer); }
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegisterClassExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegisterClassEx API. Note
// that we don't deal with the lpszMenuName parameter. If this is
// needed then conversion code will have to be written.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
ATOM WINAPI RegisterClassExAU(CONST WNDCLASSEXW *lpWcw) { WNDCLASSEXA wca; CHAR szClassName[MAX_PATH]; ATOM ReturnAtom = 0;
if (lpWcw->lpszClassName) { if (WzToSz(lpWcw->lpszClassName, szClassName, MAX_PATH)) { wca.cbSize = sizeof(WNDCLASSEXA); wca.lpfnWndProc = lpWcw->lpfnWndProc; wca.style = lpWcw->style; wca.cbClsExtra = lpWcw->cbClsExtra; wca.cbWndExtra = lpWcw->cbWndExtra; wca.hInstance = lpWcw->hInstance; wca.hIcon = lpWcw->hIcon; wca.hCursor = lpWcw->hCursor; wca.hbrBackground = lpWcw->hbrBackground; wca.hIconSm = lpWcw->hIconSm; wca.lpszClassName = szClassName; MYDBGASSERT(NULL == lpWcw->lpszMenuName); wca.lpszMenuName = NULL;
//
// Now register the class.
//
ReturnAtom = RegisterClassExA(&wca); if (0 == ReturnAtom) { //
// We want to assert failure unless we failed because the class
// was already registered. This can happen if something
// calls two CM entry points without exiting first. A prime
// example of this is rasrcise.exe. Unfortunately, GetLastError()
// returns 0 when we try to register the class twice. Thus I
// will only assert if the ReturnAtom is 0 and dwError is non-zero.
//
DWORD dwError = GetLastError(); CMASSERTMSG(!dwError, TEXT("RegisterClassExAU Failed.")); } } }
return ReturnAtom; }
//+----------------------------------------------------------------------------
//
// Function: RegisterWindowMessageAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegisterWindowMessage API. Note
// that we expect the message name to fit within MAX_PATH characters.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
UINT WINAPI RegisterWindowMessageAU(IN LPCWSTR lpString) { UINT uReturn = 0;
if (lpString) { MYDBGASSERT(MAX_PATH > lstrlenAU(lpString)); CHAR szAnsiString [MAX_PATH+1];
if (WzToSz(lpString, szAnsiString, MAX_PATH)) { uReturn = RegisterWindowMessageA(szAnsiString); } }
return uReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegOpenKeyExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegOpenKeyEx API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegOpenKeyExAU(IN HKEY hKey, IN LPCWSTR lpSubKey, IN DWORD ulOptions, IN REGSAM samDesired, OUT PHKEY phkResult) { LONG lReturn = ERROR_INVALID_PARAMETER;
if (lpSubKey) { LPSTR pszAnsiSubKey = WzToSzWithAlloc(lpSubKey);
if (pszAnsiSubKey) { lReturn = RegOpenKeyExA(hKey, pszAnsiSubKey, ulOptions, samDesired, phkResult); } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; }
CmFree(pszAnsiSubKey); }
// CMASSERTMSG(ERROR_SUCCESS == lReturn, TEXT("RegOpenKeyExAU Failed."));
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegQueryValueExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegQueryValueEx API. Note that
// we don't handle the REG_MULTI_SZ type. We would have to have
// special code to handle it and we currently don't need it. Be careful
// modifying this function unless you have read and thoroughly understood
// all of the comments.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegQueryValueExAU(IN HKEY hKey, IN LPCWSTR lpValueName, IN LPDWORD lpReserved, OUT LPDWORD lpType, IN OUT LPBYTE lpData, IN OUT LPDWORD lpcbData) { LONG lReturn = ERROR_NOT_ENOUGH_MEMORY;
//
// lpValueName could be NULL or it could be "". In either case they are after the default
// entry so just pass NULL (don't convert "").
//
LPSTR pszAnsiValueName = (lpValueName && lpValueName[0]) ? WzToSzWithAlloc(lpValueName) : NULL;
if (pszAnsiValueName || !lpValueName || (TEXT('\0') == lpValueName[0])) { //
// lpData could also be NULL, they may not actually want the value just to see if it exists
//
LPSTR pszTmpBuffer = lpData ? (LPSTR)CmMalloc(*lpcbData) : NULL;
if (pszTmpBuffer || !lpData) { DWORD dwTemp = *lpcbData; // we don't want the original value overwritten
lReturn = RegQueryValueExA(hKey, pszAnsiValueName, lpReserved, lpType, (LPBYTE)pszTmpBuffer, &dwTemp);
if ((ERROR_SUCCESS == lReturn) && pszTmpBuffer) { if ((REG_SZ == *lpType) || (REG_EXPAND_SZ == *lpType)) { if (!SzToWz(pszTmpBuffer, (WCHAR*)lpData, (*lpcbData)/sizeof(WCHAR))) { lReturn = ERROR_NOT_ENOUGH_MEMORY; } else { *lpcbData = (lstrlenAU((WCHAR*)lpData) + 1) * sizeof(WCHAR); } } else if (REG_MULTI_SZ == *lpType) { //
// We currently don't have the parsing logic to convert a Multi_SZ.
// Since CM doesn't query any keys that return this type, this shouldn't
// be a problem. However, someday we may need to fill in this code. For
// now, just assert.
//
CMASSERTMSG(FALSE, TEXT("RegQueryValueExAU -- Converion and Parsing code for REG_MULTI_SZ UNIMPLEMENTED.")); lReturn = ERROR_CALL_NOT_IMPLEMENTED; // closest I could find to E_NOTIMPL
} else { //
// Non - text data, nothing to convert so just copy it over
//
*lpcbData = dwTemp; memcpy(lpData, pszTmpBuffer, dwTemp); } } else { *lpcbData = dwTemp; }
CmFree (pszTmpBuffer); } }
CmFree(pszAnsiValueName);
// CMASSERTMSG(ERROR_SUCCESS == lReturn, TEXT("RegOpenKeyExAU Failed."));
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: RegSetValueExAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 RegSetValueEx API. Note that
// this wrapper doesn't support writing REG_MULTI_SZ, this code will
// have to be implemented if we ever need it.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG APIENTRY RegSetValueExAU(IN HKEY hKey, IN LPCWSTR lpValueName, IN DWORD Reserved, IN DWORD dwType, IN CONST BYTE* lpData, IN DWORD cbData) { LONG lReturn = ERROR_INVALID_PARAMETER;
if (lpData) { LPSTR pszAnsiValueName = (lpValueName && lpValueName[0]) ? WzToSzWithAlloc(lpValueName) : NULL; LPSTR pszTmpData = NULL; DWORD dwTmpCbData;
if (pszAnsiValueName || !lpValueName || (TEXT('\0') == lpValueName[0])) { if ((REG_EXPAND_SZ == dwType) || (REG_SZ == dwType)) { pszTmpData = WzToSzWithAlloc((WCHAR*)lpData);
if (pszTmpData) { dwTmpCbData = lstrlenA(pszTmpData) + 1; } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; } } else if (REG_MULTI_SZ == dwType) { // We currently don't have the parsing logic to convert a Multi_SZ.
// Since CM doesn't set any keys that use this type, this shouldn't
// be a problem. However, someday we may need to fill in this code. For
// now, just assert.
//
CMASSERTMSG(FALSE, TEXT("RegSetValueExAU -- Converion and Parsing code for REG_MULTI_SZ UNIMPLEMENTED.")); lReturn = ERROR_CALL_NOT_IMPLEMENTED; // closest I could find to E_NOTIMPL
} else { //
// No text data, leave the buffer alone
//
pszTmpData = (LPSTR)lpData; dwTmpCbData = cbData; }
if (pszTmpData) { lReturn = RegSetValueExA(hKey, pszAnsiValueName, Reserved, dwType, (LPBYTE)pszTmpData, dwTmpCbData);
if ((REG_EXPAND_SZ == dwType) || (REG_SZ == dwType)) { CmFree(pszTmpData); } }
CmFree(pszAnsiValueName); } else { lReturn = ERROR_NOT_ENOUGH_MEMORY; } }
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: SearchPathAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SearchPath API. Note that
// this wrapper uses wcsrchr to fix up the lpFilePart parameter in
// the converted return buffer.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
DWORD WINAPI SearchPathAU(IN LPCWSTR lpPath, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
if (lpFileName && (L'\0' != lpFileName[0])) { CHAR szAnsiPath[MAX_PATH+1]; CHAR szAnsiFileName[MAX_PATH+1]; CHAR szAnsiExt[MAX_PATH+1]; LPSTR pszAnsiPath; LPSTR pszAnsiExt; int iChars; //
// Convert the path if it exists
//
if (lpPath && (L'\0' != lpPath[0])) { pszAnsiPath = szAnsiPath; MYVERIFY(0 != WzToSz(lpPath, pszAnsiPath, MAX_PATH)); } else { pszAnsiPath = NULL; }
//
// Convert the extension if it exists
//
if (lpExtension && (L'\0' != lpExtension[0])) { pszAnsiExt = szAnsiExt; MYVERIFY(0 != WzToSz(lpExtension, pszAnsiExt, MAX_PATH)); } else { pszAnsiExt = NULL; } //
// Convert the file name, which must exist
//
iChars = WzToSz(lpFileName, szAnsiFileName, MAX_PATH);
if (iChars && (MAX_PATH >= iChars)) { LPSTR pszAnsiBuffer = (LPSTR)CmMalloc(nBufferLength);
if (pszAnsiBuffer) { dwReturn = SearchPathA(pszAnsiPath, szAnsiFileName, pszAnsiExt, nBufferLength, pszAnsiBuffer, NULL);
if (dwReturn && lpBuffer) { //
// We have a successful search. Now convert the output buffer
//
iChars = SzToWz(pszAnsiBuffer, lpBuffer, nBufferLength); if (!iChars || (nBufferLength < (DWORD)iChars)) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } else { //
// Fix up lpFilePart
//
if (lpFilePart) { //
// Find the last slash
//
*lpFilePart = wcsrchr(lpBuffer, L'\\'); if (*lpFilePart) { //
// Increment
//
(*lpFilePart)++; } } } } CmFree(pszAnsiBuffer); } } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: SendDlgItemMessageAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SendDlgItemMessage API. Note that
// this wrapper uses GetDlgItem and SendMessage just as the Win32
// implementation of the API does.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LONG_PTR WINAPI SendDlgItemMessageAU(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) { LONG lReturn = 0; HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
if (hWnd) { //
// Rather than going through SendDlgItemMessageA, we just
// do what the system does, i.e., go through
// SendMessage
//
lReturn = SendMessageAU(hWnd, Msg, wParam, lParam); }
return lReturn; }
//+----------------------------------------------------------------------------
//
// Function: SendMessageAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SendMessage API. This
// wrapper attempts to handle all of the Windows Messages that
// need conversion, either before the message is sent or after it
// returns. Obviously this is an inexact science. I have checked
// and tested all of the message types currently in CM but new ones
// may be added at some point. I owe much of this function to
// F. Avery Bishop and his sample code.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
LRESULT WINAPI SendMessageAU(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { LRESULT lResult = 0; LPVOID lpTempBuffer = NULL; int nLength = 0; CHAR cCharA[3] ; WCHAR cCharW[3] ;
//
// Preprocess messages that pass chars and strings via wParam and lParam
//
switch (Msg) { //
// Single Unicode Character in wParam. Convert Unicode character
// to ANSI and pass lParam as is.
//
case EM_SETPASSWORDCHAR: // wParam is char, lParam = 0
case WM_CHAR: //*wParam is char, lParam = key data
case WM_SYSCHAR: // wParam is char, lParam = key data
// Note that we don't handle LeadByte and TrailBytes for
// these two cases. An application should send WM_IME_CHAR
// in these cases anyway
case WM_DEADCHAR: // wParam is char, lParam = key data
case WM_SYSDEADCHAR: // wParam is char, lParam = key data
case WM_IME_CHAR: //*
cCharW[0] = (WCHAR) wParam ; cCharW[1] = L'\0' ;
if (!WzToSz(cCharW, cCharA, 3)) { return FALSE; }
if(Msg == WM_IME_CHAR) { wParam = (cCharA[1] & 0x00FF) | (cCharA[0] << 8); } else { wParam = cCharA[0]; }
wParam &= 0x0000FFFF;
break;
//
// In the following cases, lParam is pointer to an IN buffer containing
// text to send to window.
// Preprocess by converting from Unicode to ANSI
//
case CB_ADDSTRING: // wParam = 0, lParm = lpStr, buffer to add
case LB_ADDSTRING: // wParam = 0, lParm = lpStr, buffer to add
case CB_DIR: // wParam = file attributes, lParam = lpszFileSpec buffer
case LB_DIR: // wParam = file attributes, lParam = lpszFileSpec buffer
case CB_FINDSTRING: // wParam = start index, lParam = lpszFind
case LB_FINDSTRING: // wParam = start index, lParam = lpszFind
case CB_FINDSTRINGEXACT: // wParam = start index, lParam = lpszFind
case LB_FINDSTRINGEXACT: // wParam = start index, lParam = lpszFind
case CB_INSERTSTRING: //*wParam = index, lParam = lpszString to insert
case LB_INSERTSTRING: //*wParam = index, lParam = lpszString to insert
case CB_SELECTSTRING: // wParam = start index, lParam = lpszFind
case LB_SELECTSTRING: // wParam = start index, lParam = lpszFind
case WM_SETTEXT: //*wParam = 0, lParm = lpStr, buffer to set
{ if (NULL != (LPWSTR) lParam) { nLength = 2*lstrlenAU((LPWSTR)lParam) + 1; // Need double length for DBCS characters
lpTempBuffer = (LPVOID)CmMalloc(nLength); }
if (!lpTempBuffer || (!WzToSz((LPWSTR)lParam, (LPSTR)lpTempBuffer, nLength))) { CmFree(lpTempBuffer); return FALSE; }
lParam = (LPARAM) lpTempBuffer;
break ;
} }
// This is where the actual SendMessage takes place
lResult = SendMessageA(hWnd, Msg, wParam, lParam) ;
nLength = 0;
if(lResult > 0) {
switch (Msg) { //
// For these cases, lParam is a pointer to an OUT buffer that received text from
// SendMessageA in ANSI. Convert to Unicode and send back.
//
case WM_GETTEXT: // wParam = numCharacters, lParam = lpBuff to RECEIVE string
case WM_ASKCBFORMATNAME: // wParam = nBufferSize, lParam = lpBuff to RECEIVE string
nLength = (int) wParam;
if(!nLength) { break; }
case CB_GETLBTEXT: // wParam = index, lParam = lpBuff to RECEIVE string
case EM_GETLINE: // wParam = Line no, lParam = lpBuff to RECEIVE string
if(!nLength) { nLength = lstrlenA((LPSTR) lParam) + 1 ; }
lpTempBuffer = (LPVOID) CmMalloc(nLength*sizeof(WCHAR));
if(!lpTempBuffer || (!SzToWz((LPCSTR) lParam, (LPWSTR) lpTempBuffer, nLength))) { *((LPWSTR) lParam) = L'\0'; CmFree(lpTempBuffer); return FALSE; }
lstrcpyAU((LPWSTR) lParam, (LPWSTR) lpTempBuffer) ; } }
if(lpTempBuffer != NULL) { CmFree(lpTempBuffer); }
return lResult; }
//+----------------------------------------------------------------------------
//
// Function: SetCurrentDirectoryAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SetCurrentDirectory API.
// Note that we expect the directory path to fit in MAX_PATH chars.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL SetCurrentDirectoryAU(LPCWSTR pszwPathName) { BOOL bReturn = FALSE;
if (pszwPathName && (L'\0' != pszwPathName[0])) { CHAR szAnsiPath[MAX_PATH+1]; int iChars = WzToSz(pszwPathName, szAnsiPath, MAX_PATH);
if (iChars && (MAX_PATH >= iChars)) { bReturn = SetCurrentDirectoryA(szAnsiPath); } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: SetDlgItemTextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SetDlgItemText API.
// This function calls SendMessageAU with a WM_SETTEXT and the
// appropriate Dialog Item from GetDlgItem.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI SetDlgItemTextAU(IN HWND hDlg, IN int nIDDlgItem, IN LPCWSTR pszwString) { return (BOOL) (0 < SendMessageAU(GetDlgItem(hDlg, nIDDlgItem), WM_SETTEXT, (WPARAM) 0, (LPARAM) pszwString)); }
//+----------------------------------------------------------------------------
//
// Function: SetWindowTextAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 SetWindowText API.
// This function calls SendMessageAU with a WM_SETTEXT.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI SetWindowTextAU(HWND hWnd, LPCWSTR pszwString) { return (BOOL) (0 < SendMessageAU(hWnd, WM_SETTEXT, 0, (LPARAM) pszwString)); }
//+----------------------------------------------------------------------------
//
// Function: UnregisterClassAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 UnregisterClass API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI UnregisterClassAU(IN LPCWSTR lpClassName, IN HINSTANCE hInstance) { BOOL bReturn = FALSE;
if (lpClassName) { LPSTR pszAnsiClassName = WzToSzWithAlloc(lpClassName);
if (pszAnsiClassName) { bReturn = UnregisterClassA(pszAnsiClassName, hInstance); }
CmFree(pszAnsiClassName); }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: WinHelpAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 WinHelp API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI WinHelpAU(IN HWND hWndMain, IN LPCWSTR lpszHelp, IN UINT uCommand, IN ULONG_PTR dwData) { BOOL bReturn = FALSE;
if (lpszHelp) { LPSTR pszAnsiHelp = WzToSzWithAlloc(lpszHelp);
if (pszAnsiHelp) { bReturn = WinHelpA(hWndMain, pszAnsiHelp, uCommand, dwData); }
CmFree(pszAnsiHelp); }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: WritePrivateProfileStringAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 WritePrivateProfileString API.
// Note that we expect lpAppName, lpKeyName, and lpFileName to all
// fit in MAX_PATH chars.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL WINAPI WritePrivateProfileStringAU(IN LPCWSTR lpAppName, IN LPCWSTR lpKeyName, IN LPCWSTR lpString, IN LPCWSTR lpFileName) { BOOL bReturn = FALSE;
//
// Check inputs, but note that either lpKeyName or lpString could be NULL
//
if (lpAppName && lpFileName) { CHAR szAnsiAppName[MAX_PATH+1]; CHAR szAnsiFileName[MAX_PATH+1]; CHAR szAnsiKeyName[MAX_PATH+1]; LPSTR pszAnsiKeyName = NULL; LPSTR pszAnsiString;
if (WzToSz(lpAppName, szAnsiAppName, MAX_PATH)) { if (WzToSz(lpFileName, szAnsiFileName, MAX_PATH)) { if (lpKeyName) { pszAnsiKeyName = szAnsiKeyName; WzToSz(lpKeyName, pszAnsiKeyName, MAX_PATH); } // else pszAnsiKeyName was already init-ed to NULL
if (pszAnsiKeyName || !lpKeyName) { pszAnsiString = lpString ? WzToSzWithAlloc(lpString) : NULL;
if (pszAnsiString || (!lpString)) { bReturn = WritePrivateProfileStringA(szAnsiAppName, pszAnsiKeyName, pszAnsiString, szAnsiFileName);
CmFree(pszAnsiString); } } } } } else { SetLastError(ERROR_INVALID_PARAMETER); }
CMASSERTMSG(bReturn, TEXT("WritePrivateProfileStringAU Failed.")); return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: wsprintfAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 wsprintf API.
// Note that it uses a va_list and calls wvsprintfAU.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
int WINAPIV wsprintfAU(OUT LPWSTR pszwDest, IN LPCWSTR pszwFmt, ...) { va_list arglist; int ret;
va_start(arglist, pszwFmt); ret = wvsprintfAU(pszwDest, pszwFmt, arglist); va_end(arglist); return ret; }
//+----------------------------------------------------------------------------
//
// Function: wvsprintfAU
//
// Synopsis: Unicode to Ansi wrapper for the win32 wvsprintf API. In order to
// avoid parsing the format string to convert the %s to %S and the
// %c to %C and then calling wvsprintfA, which is originally how this
// function was written but which isn't really very safe because
// we don't know the size of the Dest buffer, we will call the
// C runtime function vswprintf to directly handle a Unicode string.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 6/24/99
// quintinb Changed algorithm to use
// the C runtime vswprintf 02/05/00
//
//+----------------------------------------------------------------------------
int WINAPI wvsprintfAU(OUT LPWSTR pszwDest, IN LPCWSTR pszwFmt, IN va_list arglist) {
int iReturn = 0;
if (pszwDest && pszwFmt) { //
// Use the C runtime version of the function
//
iReturn = vswprintf(pszwDest, pszwFmt, arglist); }
return iReturn;
}
//+----------------------------------------------------------------------------
//
// Function: InitCmUToA
//
// Synopsis: This function is called once cmutoa.dll is loaded. It will init
// the passed in UAPIINIT struct with the appropriate function pointers.
//
// Arguments: PUAPIINIT pUAInit -- pointer to a UAInit struct which contains memory
// for all the requested function pointers.
//
// Returns: BOOL -- always returns TRUE
//
// History: quintinb Created 6/24/99
//
//+----------------------------------------------------------------------------
BOOL InitCmUToA(PUAPIINIT pUAInit) { //
// Note that we don't need any translation here, the prototype is the same for A or W
//
*(pUAInit->pCallWindowProcU) = CallWindowProcA; *(pUAInit->pDefWindowProcU) = DefWindowProcA; *(pUAInit->pDispatchMessageU) = DispatchMessageA; *(pUAInit->pGetClassLongU) = GetClassLongA; *(pUAInit->pGetMessageU) = GetMessageA; *(pUAInit->pGetWindowLongU) = GetWindowLongA; *(pUAInit->pGetWindowTextLengthU) = GetWindowTextLengthA; *(pUAInit->pIsDialogMessageU) = IsDialogMessageA; *(pUAInit->pPeekMessageU) = PeekMessageA; *(pUAInit->pPostMessageU) = PostMessageA; *(pUAInit->pPostThreadMessageU) = PostThreadMessageA; *(pUAInit->pSetWindowLongU) = SetWindowLongA;
//
// Whereas we need wrappers here to do parameter conversion here
//
*(pUAInit->pCharLowerU) = CharLowerAU; *(pUAInit->pCharNextU) = CharNextAU; *(pUAInit->pCharPrevU) = CharPrevAU; *(pUAInit->pCharUpperU) = CharUpperAU; *(pUAInit->pCreateDialogParamU) = CreateDialogParamAU; *(pUAInit->pCreateDirectoryU) = CreateDirectoryAU; *(pUAInit->pCreateEventU) = CreateEventAU; *(pUAInit->pCreateFileU) = CreateFileAU; *(pUAInit->pCreateFileMappingU) = CreateFileMappingAU; *(pUAInit->pCreateMutexU) = CreateMutexAU; *(pUAInit->pCreateProcessU) = CreateProcessAU; *(pUAInit->pCreateWindowExU) = CreateWindowExAU; *(pUAInit->pDeleteFileU) = DeleteFileAU; *(pUAInit->pDialogBoxParamU) = DialogBoxParamAU; *(pUAInit->pExpandEnvironmentStringsU) = ExpandEnvironmentStringsAU; *(pUAInit->pFindResourceExU) = FindResourceExAU; *(pUAInit->pFindWindowExU) = FindWindowExAU; *(pUAInit->pGetDateFormatU) = GetDateFormatAU; *(pUAInit->pGetDlgItemTextU) = GetDlgItemTextAU; *(pUAInit->pGetFileAttributesU) = GetFileAttributesAU; *(pUAInit->pGetModuleFileNameU) = GetModuleFileNameAU; *(pUAInit->pGetModuleHandleU) = GetModuleHandleAU; *(pUAInit->pGetPrivateProfileIntU) = GetPrivateProfileIntAU; *(pUAInit->pGetPrivateProfileStringU) = GetPrivateProfileStringAU; *(pUAInit->pGetStringTypeExU) = GetStringTypeExAU; *(pUAInit->pGetSystemDirectoryU) = GetSystemDirectoryAU; *(pUAInit->pGetTempFileNameU) = GetTempFileNameAU; *(pUAInit->pGetTempPathU) = GetTempPathAU; *(pUAInit->pGetTimeFormatU) = GetTimeFormatAU; *(pUAInit->pGetUserNameU) = GetUserNameAU; *(pUAInit->pGetVersionExU) = GetVersionExAU; *(pUAInit->pGetWindowTextU) = GetWindowTextAU; *(pUAInit->pInsertMenuU) = InsertMenuAU; *(pUAInit->pLoadCursorU) = LoadCursorAU; *(pUAInit->pLoadIconU) = LoadIconAU; *(pUAInit->pLoadImageU) = LoadImageAU; *(pUAInit->pLoadLibraryExU) = LoadLibraryExAU; *(pUAInit->pLoadMenuU) = LoadMenuAU; *(pUAInit->pLoadStringU) = LoadStringAU; *(pUAInit->plstrcatU) = lstrcatAU; *(pUAInit->plstrcmpU) = lstrcmpAU; *(pUAInit->plstrcmpiU) = lstrcmpiAU; *(pUAInit->plstrcpyU) = lstrcpyAU; *(pUAInit->plstrcpynU) = lstrcpynAU; *(pUAInit->plstrlenU) = lstrlenAU; *(pUAInit->pOpenEventU) = OpenEventAU; *(pUAInit->pOpenFileMappingU) = OpenFileMappingAU; *(pUAInit->pRegCreateKeyExU) = RegCreateKeyExAU; *(pUAInit->pRegDeleteKeyU) = RegDeleteKeyAU; *(pUAInit->pRegDeleteValueU) = RegDeleteValueAU; *(pUAInit->pRegEnumKeyExU) = RegEnumKeyExAU; *(pUAInit->pRegisterClassExU) = RegisterClassExAU; *(pUAInit->pRegisterWindowMessageU) = RegisterWindowMessageAU; *(pUAInit->pRegOpenKeyExU) = RegOpenKeyExAU; *(pUAInit->pRegQueryValueExU) = RegQueryValueExAU; *(pUAInit->pRegSetValueExU) = RegSetValueExAU; *(pUAInit->pSearchPathU) = SearchPathAU; *(pUAInit->pSendDlgItemMessageU) = SendDlgItemMessageAU; *(pUAInit->pSendMessageU) = SendMessageAU; *(pUAInit->pSetCurrentDirectoryU) = SetCurrentDirectoryAU; *(pUAInit->pSetDlgItemTextU) = SetDlgItemTextAU; *(pUAInit->pSetWindowTextU) = SetWindowTextAU; *(pUAInit->pUnregisterClassU) = UnregisterClassAU; *(pUAInit->pWinHelpU) = WinHelpAU; *(pUAInit->pWritePrivateProfileStringU) = WritePrivateProfileStringAU; *(pUAInit->pwsprintfU) = wsprintfAU; *(pUAInit->pwvsprintfU) = wvsprintfAU;
//
// Currently this always returns TRUE because none of the above can really
// fail. However, in the future we may need more of a meaningful return
// value here.
//
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: RasDeleteEntryUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasDeleteEntry API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasDeleteEntryUA(LPCWSTR pszwPhoneBook, LPCWSTR pszwEntry) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
//
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook);
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex); MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnDeleteEntry);
if (pszwEntry && pAnsiRasLinkage && pAnsiRasLinkage->pfnDeleteEntry) { CHAR szAnsiEntry [RAS_MaxEntryName + 1]; int iChars = WzToSz(pszwEntry, szAnsiEntry, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { dwReturn = pAnsiRasLinkage->pfnDeleteEntry(NULL, szAnsiEntry); } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasGetEntryPropertiesUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasGetEntryProperties API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasGetEntryPropertiesUA(LPCWSTR pszwPhoneBook, LPCWSTR pszwEntry, LPRASENTRYW pRasEntryW, LPDWORD pdwEntryInfoSize, LPBYTE pbDeviceInfo, LPDWORD pdwDeviceInfoSize) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
//
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook); MYDBGASSERT(NULL == pbDeviceInfo); // We don't use or handle this TAPI param. If we need it,
// conversion must be implemented.
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex); MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnGetEntryProperties);
if (pszwEntry && pdwEntryInfoSize && pAnsiRasLinkage && pAnsiRasLinkage->pfnGetEntryProperties) {
CHAR szAnsiEntry [RAS_MaxEntryName + 1]; RASENTRYA RasEntryA; DWORD dwTmpEntrySize = sizeof(RASENTRYA);
ZeroMemory(&RasEntryA, sizeof(RASENTRYA));
int iChars = WzToSz(pszwEntry, szAnsiEntry, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { dwReturn = pAnsiRasLinkage->pfnGetEntryProperties(NULL, szAnsiEntry, &RasEntryA, &dwTmpEntrySize, NULL, NULL);
if ((ERROR_SUCCESS == dwReturn) && pRasEntryW) { //
// Do conversion of RASENTRYA to RASENTRYW
//
// pRasEntryW->dwSize -- this param should already be set
pRasEntryW->dwfOptions = RasEntryA.dwfOptions;
//
// Location/phone number.
//
pRasEntryW->dwCountryID = RasEntryA.dwCountryID; pRasEntryW->dwCountryCode = RasEntryA.dwCountryCode; MYVERIFY(0 != SzToWz(RasEntryA.szAreaCode, pRasEntryW->szAreaCode, RAS_MaxAreaCode)); MYVERIFY(0 != SzToWz(RasEntryA.szLocalPhoneNumber, pRasEntryW->szLocalPhoneNumber, RAS_MaxPhoneNumber)); pRasEntryW->dwAlternateOffset = RasEntryA.dwAlternateOffset; //
// PPP/Ip
//
memcpy(&(pRasEntryW->ipaddr), &(RasEntryA.ipaddr), sizeof(RASIPADDR)); memcpy(&(pRasEntryW->ipaddrDns), &(RasEntryA.ipaddrDns), sizeof(RASIPADDR)); memcpy(&(pRasEntryW->ipaddrDnsAlt), &(RasEntryA.ipaddrDnsAlt), sizeof(RASIPADDR)); memcpy(&(pRasEntryW->ipaddrWins), &(RasEntryA.ipaddrWins), sizeof(RASIPADDR)); memcpy(&(pRasEntryW->ipaddrWinsAlt), &(RasEntryA.ipaddrWinsAlt), sizeof(RASIPADDR)); //
// Framing
//
pRasEntryW->dwFrameSize = RasEntryA.dwFrameSize; pRasEntryW->dwfNetProtocols = RasEntryA.dwfNetProtocols; pRasEntryW->dwFramingProtocol = RasEntryA.dwFramingProtocol; //
// Scripting
//
MYVERIFY(0 != SzToWz(RasEntryA.szScript, pRasEntryW->szScript, MAX_PATH)); //
// AutoDial
//
MYVERIFY(0 != SzToWz(RasEntryA.szAutodialDll, pRasEntryW->szAutodialDll, MAX_PATH)); MYVERIFY(0 != SzToWz(RasEntryA.szAutodialFunc, pRasEntryW->szAutodialFunc, MAX_PATH)); //
// Device
//
MYVERIFY(0 != SzToWz(RasEntryA.szDeviceType, pRasEntryW->szDeviceType, RAS_MaxDeviceType)); MYVERIFY(0 != SzToWz(RasEntryA.szDeviceName, pRasEntryW->szDeviceName, RAS_MaxDeviceName)); //
// X.25 -- we don't use x25
//
pRasEntryW->szX25PadType[0] = L'\0'; pRasEntryW->szX25Address[0] = L'\0'; pRasEntryW->szX25Facilities[0] = L'\0'; pRasEntryW->szX25UserData[0] = L'\0'; pRasEntryW->dwChannels = 0; //
// Reserved
//
pRasEntryW->dwReserved1 = RasEntryA.dwReserved1; pRasEntryW->dwReserved2 = RasEntryA.dwReserved2; } else if ((ERROR_BUFFER_TOO_SMALL == dwReturn) || !pRasEntryW) { //
// We don't know the actual size since we are passing a RASENTRYA, but
// the user only knows about RASENTRYW. Thus double the returned size.
//
*pdwEntryInfoSize = 2*dwTmpEntrySize; } } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasSetEntryPropertiesUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasSetEntryProperties API.
// Note that we do not support the pbDeviceInfo
// parameter, if you need it you will have to implement it.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasSetEntryPropertiesUA(LPCWSTR pszwPhoneBook, LPCWSTR pszwEntry, LPRASENTRYW pRasEntryW, DWORD dwEntryInfoSize, LPBYTE pbDeviceInfo, DWORD dwDeviceInfoSize) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
//
// We don't use or handle this TAPI param. If we need it, conversion must be implemented.
// Note that 1 is a special value for Windows Millennium (see Millennium bug 127371)
//
MYDBGASSERT((NULL == pbDeviceInfo) || ((LPBYTE)1 == pbDeviceInfo));
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnSetEntryProperties);
if (pszwEntry && dwEntryInfoSize && pRasEntryW && pAnsiRasLinkage && pAnsiRasLinkage->pfnSetEntryProperties) { //
// The phonebook should always be NULL on Win9x.
//
MYDBGASSERT(NULL == pszwPhoneBook);
CHAR szAnsiEntry [RAS_MaxEntryName + 1];
int iChars = WzToSz(pszwEntry, szAnsiEntry, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { //
// Figure out the correct size to use
//
MYDBGASSERT((sizeof(RASENTRYW) == pRasEntryW->dwSize) ||(sizeof(RASENTRYW_V401) == pRasEntryW->dwSize)); DWORD dwSize;
if ((sizeof (RASENTRYW_V401) == pRasEntryW->dwSize) && OS_MIL) { //
// Millennium uses the NT4 structure size
//
dwSize = sizeof(RASENTRYA_V401); } else { dwSize = sizeof(RASENTRYA); }
//
// Allocate the RasEntryStructure
//
LPRASENTRYA pAnsiRasEntry = (LPRASENTRYA)CmMalloc(dwSize);
if (pAnsiRasEntry) { //
// Do conversion of RASENTRYA to RASENTRYW
//
pAnsiRasEntry->dwSize = dwSize; pAnsiRasEntry->dwfOptions = pRasEntryW->dwfOptions;
//
// Location/phone number.
//
pAnsiRasEntry->dwCountryID = pRasEntryW->dwCountryID; pAnsiRasEntry->dwCountryCode = pRasEntryW->dwCountryCode; MYVERIFY(0 != WzToSz(pRasEntryW->szAreaCode, pAnsiRasEntry->szAreaCode, RAS_MaxAreaCode)); MYVERIFY(0 != WzToSz(pRasEntryW->szLocalPhoneNumber, pAnsiRasEntry->szLocalPhoneNumber, RAS_MaxPhoneNumber)); CMASSERTMSG(0 == pRasEntryW->dwAlternateOffset, TEXT("RasSetEntryPropertiesUA -- dwAlternateOffset != 0 is not supported. This will need to be implemented if used.")); pAnsiRasEntry->dwAlternateOffset = 0; //
// PPP/Ip
//
memcpy(&(pAnsiRasEntry->ipaddr), &(pRasEntryW->ipaddr), sizeof(RASIPADDR)); memcpy(&(pAnsiRasEntry->ipaddrDns), &(pRasEntryW->ipaddrDns), sizeof(RASIPADDR)); memcpy(&(pAnsiRasEntry->ipaddrDnsAlt), &(pRasEntryW->ipaddrDnsAlt), sizeof(RASIPADDR)); memcpy(&(pAnsiRasEntry->ipaddrWins), &(pRasEntryW->ipaddrWins), sizeof(RASIPADDR)); memcpy(&(pAnsiRasEntry->ipaddrWinsAlt), &(pRasEntryW->ipaddrWinsAlt), sizeof(RASIPADDR)); //
// Framing
//
pAnsiRasEntry->dwFrameSize = pRasEntryW->dwFrameSize; pAnsiRasEntry->dwfNetProtocols = pRasEntryW->dwfNetProtocols; pAnsiRasEntry->dwFramingProtocol = pRasEntryW->dwFramingProtocol; //
// Scripting
//
MYVERIFY(0 != WzToSz(pRasEntryW->szScript, pAnsiRasEntry->szScript, MAX_PATH)); //
// AutoDial
//
MYVERIFY(0 != WzToSz(pRasEntryW->szAutodialDll, pAnsiRasEntry->szAutodialDll, MAX_PATH)); MYVERIFY(0 != WzToSz(pRasEntryW->szAutodialFunc, pAnsiRasEntry->szAutodialFunc, MAX_PATH)); //
// Device
//
MYVERIFY(0 != WzToSz(pRasEntryW->szDeviceType, pAnsiRasEntry->szDeviceType, RAS_MaxDeviceType)); MYVERIFY(0 != WzToSz(pRasEntryW->szDeviceName, pAnsiRasEntry->szDeviceName, RAS_MaxDeviceName)); //
// X.25 -- we don't use x25
//
pAnsiRasEntry->szX25PadType[0] = '\0'; pAnsiRasEntry->szX25Address[0] = '\0'; pAnsiRasEntry->szX25Facilities[0] = '\0'; pAnsiRasEntry->szX25UserData[0] = '\0'; pAnsiRasEntry->dwChannels = 0; //
// Reserved
//
pAnsiRasEntry->dwReserved1 = pRasEntryW->dwReserved1; pAnsiRasEntry->dwReserved2 = pRasEntryW->dwReserved2;
if (sizeof(RASENTRYA_V401) == dwSize) { //
// Copy over the 4.01 data
//
LPRASENTRYA_V401 pAnsi401RasEntry = (LPRASENTRYA_V401)pAnsiRasEntry; LPRASENTRYW_V401 pWide401RasEntry = (LPRASENTRYW_V401)pRasEntryW;
pAnsi401RasEntry->dwSubEntries = pWide401RasEntry->dwSubEntries; pAnsi401RasEntry->dwDialMode = pWide401RasEntry->dwDialMode; pAnsi401RasEntry->dwDialExtraPercent = pWide401RasEntry->dwDialExtraPercent; pAnsi401RasEntry->dwDialExtraSampleSeconds = pWide401RasEntry->dwDialExtraSampleSeconds; pAnsi401RasEntry->dwHangUpExtraPercent = pWide401RasEntry->dwHangUpExtraPercent; pAnsi401RasEntry->dwHangUpExtraSampleSeconds = pWide401RasEntry->dwHangUpExtraSampleSeconds; pAnsi401RasEntry->dwIdleDisconnectSeconds = pWide401RasEntry->dwIdleDisconnectSeconds; }
dwReturn = pAnsiRasLinkage->pfnSetEntryProperties(NULL, szAnsiEntry, pAnsiRasEntry, pAnsiRasEntry->dwSize, pbDeviceInfo, 0);
CmFree(pAnsiRasEntry); } } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasDialParamsWtoRasDialParamsA
//
// Synopsis: Wrapper function to handle converting a RasDialParamsW struct to
// a RasDialParamsA Struct. Used by RasSetEntryDialParamsUA and
// RasDialUA.
//
// Arguments: LPRASDIALPARAMSW pRdpW - pointer to a RasDialParamsW
// LPRASDIALPARAMSA pRdpA - pointer to a RasDialParamsA
//
// Returns: Nothing
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
void RasDialParamsWtoRasDialParamsA (LPRASDIALPARAMSW pRdpW, LPRASDIALPARAMSA pRdpA) { pRdpA->dwSize = sizeof(RASDIALPARAMSA); MYVERIFY(0 != WzToSz(pRdpW->szEntryName, pRdpA->szEntryName, RAS_MaxEntryName)); MYVERIFY(0 != WzToSz(pRdpW->szPhoneNumber, pRdpA->szPhoneNumber, RAS_MaxPhoneNumber)); MYVERIFY(0 != WzToSz(pRdpW->szCallbackNumber, pRdpA->szCallbackNumber, RAS_MaxCallbackNumber)); MYVERIFY(0 != WzToSz(pRdpW->szUserName, pRdpA->szUserName, UNLEN)); MYVERIFY(0 != WzToSz(pRdpW->szPassword, pRdpA->szPassword, PWLEN)); MYVERIFY(0 != WzToSz(pRdpW->szDomain, pRdpA->szDomain, DNLEN)); }
//+----------------------------------------------------------------------------
//
// Function: RasDialParamsAtoRasDialParamsW
//
// Synopsis: Wrapper function to handle converting a RasDialParamsA struct to
// a RasDialParamsW Struct. Used by RasGetEntryDialParamsUA.
//
// Arguments: LPRASDIALPARAMSW pRdpA - pointer to a RasDialParamsA
// LPRASDIALPARAMSA pRdpW - pointer to a RasDialParamsW
//
// Returns: Nothing
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
void RasDialParamsAtoRasDialParamsW (LPRASDIALPARAMSA pRdpA, LPRASDIALPARAMSW pRdpW) { pRdpW->dwSize = sizeof(RASDIALPARAMSW); MYVERIFY(0 != SzToWz(pRdpA->szEntryName, pRdpW->szEntryName, RAS_MaxEntryName)); MYVERIFY(0 != SzToWz(pRdpA->szPhoneNumber, pRdpW->szPhoneNumber, RAS_MaxPhoneNumber)); MYVERIFY(0 != SzToWz(pRdpA->szCallbackNumber, pRdpW->szCallbackNumber, RAS_MaxCallbackNumber)); MYVERIFY(0 != SzToWz(pRdpA->szUserName, pRdpW->szUserName, UNLEN)); MYVERIFY(0 != SzToWz(pRdpA->szPassword, pRdpW->szPassword, PWLEN)); MYVERIFY(0 != SzToWz(pRdpA->szDomain, pRdpW->szDomain, DNLEN)); }
//+----------------------------------------------------------------------------
//
// Function: RasGetEntryDialParamsUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasGetEntryDialParams API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasGetEntryDialParamsUA(LPCWSTR pszwPhoneBook, LPRASDIALPARAMSW pRasDialParamsW, LPBOOL pbPassword) { DWORD dwReturn = ERROR_BUFFER_INVALID;
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnGetEntryDialParams);
if (pRasDialParamsW && pbPassword && pAnsiRasLinkage && pAnsiRasLinkage->pfnGetEntryDialParams) { //
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook);
RASDIALPARAMSA RasDialParamsA; ZeroMemory(&RasDialParamsA, sizeof(RASDIALPARAMSA)); RasDialParamsA.dwSize = sizeof(RASDIALPARAMSA); int iChars = WzToSz(pRasDialParamsW->szEntryName, RasDialParamsA.szEntryName, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { dwReturn = pAnsiRasLinkage->pfnGetEntryDialParams(NULL, &RasDialParamsA, pbPassword);
if (ERROR_SUCCESS == dwReturn) { RasDialParamsAtoRasDialParamsW(&RasDialParamsA, pRasDialParamsW); } } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasSetEntryDialParamsUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasSetEntryDialParams API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasSetEntryDialParamsUA(LPCWSTR pszwPhoneBook, LPRASDIALPARAMSW pRasDialParamsW, BOOL bRemovePassword) { DWORD dwReturn = ERROR_BUFFER_INVALID;
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnSetEntryDialParams);
if (pRasDialParamsW && pAnsiRasLinkage && pAnsiRasLinkage->pfnSetEntryDialParams) { //
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook);
RASDIALPARAMSA RasDialParamsA;
RasDialParamsWtoRasDialParamsA (pRasDialParamsW, &RasDialParamsA);
dwReturn = pAnsiRasLinkage->pfnSetEntryDialParams(NULL, &RasDialParamsA, bRemovePassword); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasEnumDevicesUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasEnumDevices API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD RasEnumDevicesUA(LPRASDEVINFOW pRasDevInfo, LPDWORD pdwCb, LPDWORD pdwDevices) { DWORD dwReturn = ERROR_INVALID_PARAMETER; DWORD dwSize;
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnEnumDevices);
if (pdwCb && pdwDevices && pAnsiRasLinkage && pAnsiRasLinkage->pfnEnumDevices) { LPRASDEVINFOA pAnsiDevInfo;
if ((NULL == pRasDevInfo) && (0 == *pdwCb)) { //
// Then the caller is just trying to size the buffer
//
dwSize = 0; pAnsiDevInfo = NULL; } else { dwSize = ((*pdwCb)/sizeof(RASDEVINFOW))*sizeof(RASDEVINFOA); pAnsiDevInfo = (LPRASDEVINFOA)CmMalloc(dwSize);
if (NULL == pAnsiDevInfo) { return ERROR_NOT_ENOUGH_MEMORY; }
pAnsiDevInfo[0].dwSize = sizeof(RASDEVINFOA); }
dwReturn = pAnsiRasLinkage->pfnEnumDevices(pAnsiDevInfo, &dwSize, pdwDevices); //
// Resize the buffer in terms of RASDEVINFOW structs
//
*pdwCb = ((dwSize)/sizeof(RASDEVINFOA))*sizeof(RASDEVINFOW);
if (ERROR_SUCCESS == dwReturn && pRasDevInfo) { //
// Then we need to convert the returned structs
//
MYDBGASSERT((*pdwDevices)*sizeof(RASDEVINFOW) <= *pdwCb);
for (DWORD dwIndex = 0; dwIndex < *pdwDevices; dwIndex++) { MYVERIFY(0 != SzToWz(pAnsiDevInfo[dwIndex].szDeviceType, pRasDevInfo[dwIndex].szDeviceType, RAS_MaxDeviceType));
MYVERIFY(0 != SzToWz(pAnsiDevInfo[dwIndex].szDeviceName, pRasDevInfo[dwIndex].szDeviceName, RAS_MaxDeviceName)); } }
//
// Free the Ansi buffer
//
CmFree (pAnsiDevInfo); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasDialUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasDial API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasDialUA(LPRASDIALEXTENSIONS pRasDialExt, LPCWSTR pszwPhoneBook, LPRASDIALPARAMSW pRasDialParamsW, DWORD dwNotifierType, LPVOID pvNotifier, LPHRASCONN phRasConn) { DWORD dwReturn = ERROR_INVALID_PARAMETER; MYDBGASSERT(NULL == pszwPhoneBook);
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnDial);
if (pRasDialParamsW && phRasConn && pAnsiRasLinkage && pAnsiRasLinkage->pfnDial) { RASDIALPARAMSA RasDialParamsA;
RasDialParamsWtoRasDialParamsA (pRasDialParamsW, &RasDialParamsA);
dwReturn = pAnsiRasLinkage->pfnDial(pRasDialExt, NULL, &RasDialParamsA, dwNotifierType, pvNotifier, phRasConn); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasHangUpUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasHangUp API. Which for
// some reason has an ANSI and Unicode form, not sure why.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasHangUpUA(HRASCONN hRasConn) { DWORD dwReturn = ERROR_INVALID_PARAMETER; RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnHangUp);
if (hRasConn && pAnsiRasLinkage && pAnsiRasLinkage->pfnHangUp) { dwReturn = pAnsiRasLinkage->pfnHangUp(hRasConn); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasGetErrorStringUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasGetErrorString API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD APIENTRY RasGetErrorStringUA(UINT uErrorValue, LPWSTR pszwOutBuf, DWORD dwBufSize) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnGetErrorString);
if (pszwOutBuf && dwBufSize && pAnsiRasLinkage && pAnsiRasLinkage->pfnGetErrorString) { LPSTR pszAnsiBuf = (LPSTR)CmMalloc(dwBufSize);
if (pszAnsiBuf) { dwReturn = pAnsiRasLinkage->pfnGetErrorString(uErrorValue, pszAnsiBuf, dwBufSize);
if (ERROR_SUCCESS == dwReturn) { int iChars = SzToWz(pszAnsiBuf, pszwOutBuf, dwBufSize); if (!iChars || (dwBufSize < (DWORD)iChars)) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } } }
CmFree(pszAnsiBuf); }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasGetConnectStatusUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasGetConnectStatus API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
DWORD RasGetConnectStatusUA(HRASCONN hRasConn, LPRASCONNSTATUSW pRasConnStatusW) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnGetConnectStatus);
if (pRasConnStatusW && pAnsiRasLinkage && pAnsiRasLinkage->pfnGetConnectStatus) { RASCONNSTATUSA RasConnStatusA; ZeroMemory(&RasConnStatusA, sizeof(RASCONNSTATUSA)); RasConnStatusA.dwSize = sizeof(RASCONNSTATUSA);
dwReturn = pAnsiRasLinkage->pfnGetConnectStatus(hRasConn, &RasConnStatusA);
if (ERROR_SUCCESS == dwReturn) { pRasConnStatusW->rasconnstate = RasConnStatusA.rasconnstate; pRasConnStatusW->dwError = RasConnStatusA.dwError; int iChars = SzToWz(RasConnStatusA.szDeviceType, pRasConnStatusW->szDeviceType, RAS_MaxDeviceType);
if (!iChars || (RAS_MaxDeviceType < iChars)) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } else { iChars = SzToWz(RasConnStatusA.szDeviceName, pRasConnStatusW->szDeviceName, RAS_MaxDeviceName);
if (!iChars || (RAS_MaxDeviceName < iChars)) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } } }
}
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasSetSubEntryPropertiesUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasSetSubEntryProperties API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: SumitC Created 10/26/99
//
//-----------------------------------------------------------------------------
DWORD APIENTRY RasSetSubEntryPropertiesUA(LPCWSTR pszwPhoneBook, LPCWSTR pszwSubEntry, DWORD dwSubEntry, LPRASSUBENTRYW pRasSubEntryW, DWORD dwSubEntryInfoSize, LPBYTE pbDeviceConfig, DWORD dwcbDeviceConfig) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
MYDBGASSERT(NULL == pbDeviceConfig); // must currently be NULL
MYDBGASSERT(0 == dwcbDeviceConfig); // must currently be 0
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnSetEntryProperties);
if (pszwSubEntry && dwSubEntryInfoSize && pRasSubEntryW && pAnsiRasLinkage && pAnsiRasLinkage->pfnSetSubEntryProperties) { //
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook);
CHAR szAnsiSubEntry [RAS_MaxEntryName + 1]; RASSUBENTRYA AnsiRasSubEntry;
ZeroMemory(&AnsiRasSubEntry, sizeof(RASSUBENTRYA)); DWORD dwTmpEntrySize = sizeof(RASSUBENTRYA);
int iChars = WzToSz(pszwSubEntry, szAnsiSubEntry, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { //
// Do conversion of RASSUBENTRYW to RASSUBENTRYA
//
AnsiRasSubEntry.dwSize = sizeof(RASSUBENTRYA); AnsiRasSubEntry.dwfFlags = pRasSubEntryW->dwfFlags; //
// Device
//
MYVERIFY(0 != WzToSz(pRasSubEntryW->szDeviceType, AnsiRasSubEntry.szDeviceType, RAS_MaxDeviceType)); MYVERIFY(0 != WzToSz(pRasSubEntryW->szDeviceName, AnsiRasSubEntry.szDeviceName, RAS_MaxDeviceName)); //
// Location/phone number.
//
MYVERIFY(0 != WzToSz(pRasSubEntryW->szLocalPhoneNumber, AnsiRasSubEntry.szLocalPhoneNumber, RAS_MaxPhoneNumber)); CMASSERTMSG(0 == pRasSubEntryW->dwAlternateOffset, TEXT("RasSetSubEntryPropertiesUA -- dwAlternateOffset != 0 is not supported. This will need to be implemented if used.")); AnsiRasSubEntry.dwAlternateOffset = 0;
dwReturn = pAnsiRasLinkage->pfnSetSubEntryProperties(NULL, szAnsiSubEntry, dwSubEntry, &AnsiRasSubEntry, dwTmpEntrySize, NULL, 0); } }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: RasDeleteSubEntryUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 RasDeleteSubEntryUA API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: SumitC Created 12/14/99
//
//-----------------------------------------------------------------------------
DWORD APIENTRY RasDeleteSubEntryUA(LPCWSTR pszwPhoneBook, LPCWSTR pszwEntry, DWORD dwSubEntryId) { DWORD dwReturn = ERROR_INVALID_PARAMETER;
//
// The phonebook should always be NULL on win9x
//
MYDBGASSERT(NULL == pszwPhoneBook);
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex); MYDBGASSERT(NULL != pAnsiRasLinkage); MYDBGASSERT(NULL != pAnsiRasLinkage->pfnDeleteSubEntry);
if (pszwEntry && pAnsiRasLinkage && pAnsiRasLinkage->pfnDeleteSubEntry) { CHAR szAnsiEntry [RAS_MaxEntryName + 1]; int iChars = WzToSz(pszwEntry, szAnsiEntry, RAS_MaxEntryName);
if (iChars && (RAS_MaxEntryName >= iChars)) { dwReturn = pAnsiRasLinkage->pfnDeleteSubEntry(NULL, szAnsiEntry, dwSubEntryId); } }
return dwReturn;
}
//+----------------------------------------------------------------------------
//
// Function: FreeCmRasUtoA
//
// Synopsis: Unloads the RAS dlls (rasapi32.dll and rnaph.dll) and cleans up
// the RAS linkage structure. To get more details about the cmutoa
// RAS linkage see InitCmRasUtoA and cmdial\ras.cpp\LinkToRas.
//
// Arguments: Nothing
//
// Returns: Nothing
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
void FreeCmRasUtoA() { RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
CMASSERTMSG(pAnsiRasLinkage, TEXT("FreeCmRasUtoA -- RasLinkage hasn't been established yet. Why are we calling FreeCmRasUtoA now?"));
if (pAnsiRasLinkage) { if (pAnsiRasLinkage->hInstRas) { FreeLibrary(pAnsiRasLinkage->hInstRas); }
if (pAnsiRasLinkage->hInstRnaph) { FreeLibrary(pAnsiRasLinkage->hInstRnaph); }
CmFree(pAnsiRasLinkage); TlsSetValue(g_dwTlsIndex, (LPVOID)NULL); } }
//+----------------------------------------------------------------------------
//
// Function: InitCmRasUtoA
//
// Synopsis: Function to Initialize the Unicode to ANSI conversion layer for
// RAS functions. In order to make the LinkToRas stuff work the
// same on win9x and on NT (all come from one dll) we have Cmdial32.dll
// link to cmutoa and get all of the RAS Entry points through Cmutoa.dll.
// In order to make this work, we need to keep function pointers to all of
// the RAS Dll's in memory. In order to prevent two cmdial's on different
// threads from calling InitCmRasUtoA and FreeCmRasUtoA at the wrong times
// (one thread freeing right after another had initialized would leave
// the first thread in a broken state), we usesthread local storage
// to hold a pointer to a RasLinkageStructA. This makes us thread safe
// and allows us to only have to init the RAS pointers once per thread
// (having multiple Cmdials in the same thread is pretty unlikely anyway).
// See cmdial\ras.cpp\LinkToRas for more details on the cmdial side of
// things.
//
// Arguments: Nothing
//
// Returns: BOOL -- TRUE if all of the requested APIs were loaded properly.
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
BOOL InitCmRasUtoA() { BOOL bReturn = TRUE; BOOL bTryRnaph = FALSE;
//
// First Try to get the RasLinkageStruct out of Thread Local Storage, we
// may already be initialized.
//
RasLinkageStructA* pAnsiRasLinkage = (RasLinkageStructA*)TlsGetValue(g_dwTlsIndex);
CMASSERTMSG(NULL == pAnsiRasLinkage, TEXT("InitCmRasUtoA -- RasLinkage Already established. Why are we calling InitCmRasUtoA more than once?"));
if (NULL == pAnsiRasLinkage) { //
// Then we haven't linked to RAS yet, first allocate the struct
//
pAnsiRasLinkage = (RasLinkageStructA*)CmMalloc(sizeof(RasLinkageStructA));
if (!pAnsiRasLinkage) { return FALSE; }
//
// Now that we have a structure, lets start filling it in. Try getting all of
// the entry points out of RasApi32.dll first, then try rnaph.dll if necessary.
//
pAnsiRasLinkage->hInstRas = LoadLibraryExA("rasapi32.dll", NULL, 0);
CMASSERTMSG(NULL != pAnsiRasLinkage->hInstRas, TEXT("InitCmRasUtoA -- Unable to load rasapi32.dll. Failing Ras Link."));
// before doing this, fix up the array based on whether we are on
// Millennium or not. The function below exists only on Millennium
if (!OS_MIL) { c_ArrayOfRasFuncsA[10] = NULL; //RasSetSubEntryProperties
c_ArrayOfRasFuncsA[11] = NULL; //RasDeleteSubEntry
}
if (pAnsiRasLinkage->hInstRas) { for (int i = 0 ; c_ArrayOfRasFuncsA[i] ; i++) { pAnsiRasLinkage->apvPfnRas[i] = GetProcAddress(pAnsiRasLinkage->hInstRas, c_ArrayOfRasFuncsA[i]);
if (!(pAnsiRasLinkage->apvPfnRas[i])) { bTryRnaph = TRUE; } } }
//
// If we missed a few, then we need to get them from rnaph.dll
//
if (bTryRnaph) { pAnsiRasLinkage->hInstRnaph = LoadLibraryExA("rnaph.dll", NULL, 0); CMASSERTMSG(NULL != pAnsiRasLinkage->hInstRnaph, TEXT("InitCmRasUtoA -- Unable to load Rnaph.dll. Failing Ras Link."));
if (pAnsiRasLinkage->hInstRnaph) { for (int i = 0 ; c_ArrayOfRasFuncsA[i] ; i++) { if (NULL == pAnsiRasLinkage->apvPfnRas[i]) { pAnsiRasLinkage->apvPfnRas[i] = GetProcAddress(pAnsiRasLinkage->hInstRnaph, c_ArrayOfRasFuncsA[i]);
if (!(pAnsiRasLinkage->apvPfnRas[i])) { bReturn = FALSE; } } } } }
//
// Always save the pAnsiRasLinkage value to thread local storage, if the linkage wasn't successful
// we will call FreeCmRasUtoA to clean it up. If it was successful we need to maintain it for later
// use. Note that the first thing FreeCmRasUtoA does is get the Ras Linkage struct pointer out of
// thread local storage because that is were it would reside under normal operation.
//
TlsSetValue(g_dwTlsIndex, (LPVOID)pAnsiRasLinkage);
if (!bReturn) { //
// Ras Linkage failed for some reason. We need to free up any resources we
// may have partially filled in.
//
FreeCmRasUtoA(); } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: SHGetPathFromIDListUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 SHGetPathFromIDList API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
BOOL SHGetPathFromIDListUA(LPCITEMIDLIST pidl, LPWSTR pszPath) { BOOL bReturn = FALSE;
if (pidl && pszPath) { CHAR szAnsiPath[MAX_PATH+1];
bReturn = SHGetPathFromIDListA(pidl, szAnsiPath);
if (bReturn) { int iChars = SzToWz(szAnsiPath, pszPath, MAX_PATH); // don't know correct length but
// the API says the path should be at
// least MAX_PATH
if (!iChars || (MAX_PATH < (DWORD)iChars)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); bReturn = FALSE; } } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: SHGetSpecialFolderLocationUA
//
// Synopsis: While the win32 SHGetSpecialFolderLocation API doesn't actually
// require any conversion between Unicode and ANSI, CM's shell dll
// class can only take one dll to take entry points from. Thus I
// was forced to add these here so that the class could get all the
// shell APIs it needed from cmutoa.dll.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
HRESULT SHGetSpecialFolderLocationUA(HWND hwnd, int csidl, LPITEMIDLIST *ppidl) { return SHGetSpecialFolderLocation(hwnd, csidl, ppidl); }
//+----------------------------------------------------------------------------
//
// Function: SHGetMallocUA
//
// Synopsis: While the win32 SHGetMalloc API doesn't actually
// require any conversion between Unicode and ANSI, CM's shell dll
// class can only take one dll to take entry points from. Thus I
// was forced to add these here so that the class could get all the
// shell APIs it needed from cmutoa.dll.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
HRESULT SHGetMallocUA(LPMALLOC * ppMalloc) { return SHGetMalloc(ppMalloc); }
//+----------------------------------------------------------------------------
//
// Function: ShellExecuteExUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 ShellExecuteEx API.
// Note that we do note convert the lpIDList param of the
// SHELLEXECUTEINFOW struct because it is just a binary blob. Thus
// figuring out how to convert it if we don't know what it is. If
// we need this in the future we will have to deal with it on a case
// by case basis.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
BOOL ShellExecuteExUA(LPSHELLEXECUTEINFOW pShellInfoW) { BOOL bReturn = FALSE; SHELLEXECUTEINFOA ShellInfoA; ZeroMemory(&ShellInfoA, sizeof(ShellInfoA));
if (pShellInfoW) { ShellInfoA.cbSize = sizeof(ShellInfoA); ShellInfoA.fMask = pShellInfoW->fMask; ShellInfoA.hwnd = pShellInfoW->hwnd;
if (pShellInfoW->lpVerb) { ShellInfoA.lpVerb = WzToSzWithAlloc(pShellInfoW->lpVerb); if (NULL == ShellInfoA.lpVerb) { goto exit; } }
if (pShellInfoW->lpFile) { ShellInfoA.lpFile = WzToSzWithAlloc(pShellInfoW->lpFile); if (NULL == ShellInfoA.lpFile) { goto exit; } }
if (pShellInfoW->lpParameters) { ShellInfoA.lpParameters = WzToSzWithAlloc(pShellInfoW->lpParameters); if (NULL == ShellInfoA.lpParameters) { goto exit; } }
if (pShellInfoW->lpDirectory) { ShellInfoA.lpDirectory = WzToSzWithAlloc(pShellInfoW->lpDirectory); if (NULL == ShellInfoA.lpDirectory) { goto exit; } }
ShellInfoA.nShow = pShellInfoW->nShow; ShellInfoA.hInstApp = pShellInfoW->hInstApp; //
// Since this is a binary blob conversion could be difficult.
// We also don't currently use it, so I won't spend the cycles implementing it now.
//
MYDBGASSERT(NULL == pShellInfoW->lpIDList); ShellInfoA.lpIDList = NULL;
if (pShellInfoW->lpClass) { ShellInfoA.lpClass = WzToSzWithAlloc(pShellInfoW->lpClass); if (NULL == ShellInfoA.lpClass) { goto exit; } }
ShellInfoA.hkeyClass = pShellInfoW->hkeyClass; ShellInfoA.hIcon = pShellInfoW->hIcon; // hIcon/hMonitor is a union so we only need one of them to get the mem
// HANDLE hProcess this is a return param dealt with below.
//
// Finally call ShellExecuteExA
//
bReturn = ShellExecuteExA(&ShellInfoA);
if (ShellInfoA.hProcess) { //
// The Caller asked for the process handle so send it back.
//
pShellInfoW->hProcess = ShellInfoA.hProcess; } }
exit:
CmFree((void*)ShellInfoA.lpVerb); CmFree((void*)ShellInfoA.lpFile); CmFree((void*)ShellInfoA.lpParameters); CmFree((void*)ShellInfoA.lpDirectory); CmFree((void*)ShellInfoA.lpClass);
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: Shell_NotifyIconUA
//
// Synopsis: Unicode to Ansi wrapper for the win32 Shell_NotifyIcon API.
//
// Arguments: See the win32 API definition
//
// Returns: See the win32 API definition
//
// History: quintinb Created 7/15/99
//
//+----------------------------------------------------------------------------
BOOL Shell_NotifyIconUA (DWORD dwMessage, PNOTIFYICONDATAW pnidW) { BOOL bReturn = FALSE; if (pnidW) { NOTIFYICONDATAA nidA;
ZeroMemory (&nidA, sizeof(NOTIFYICONDATAA)); nidA.cbSize = sizeof(NOTIFYICONDATAA);
nidA.hWnd = pnidW->hWnd; nidA.uID = pnidW->uID; nidA.uFlags = pnidW->uFlags; nidA.uCallbackMessage = pnidW->uCallbackMessage; nidA.hIcon = pnidW->hIcon;
int iChars = WzToSz(pnidW->szTip, nidA.szTip, 64); // 64 is the length of the szTip in the 4.0 struct
if (!iChars || (64 < iChars)) { nidA.szTip[0] = '\0'; }
bReturn = Shell_NotifyIconA(dwMessage, &nidA); }
return bReturn; }
|