1371 lines
48 KiB
C
1371 lines
48 KiB
C
|
/*******************************************************************************
|
||
|
* SPUnicode.H *
|
||
|
*--------------*
|
||
|
* Description:
|
||
|
* This is the header file for core helper functions implementation.
|
||
|
* It is internal to Microsoft and is NOT shipped with the SDK since
|
||
|
* many of the functions contatined in this file have not been fully
|
||
|
* tested and therefore should not be exposed in the SDK.
|
||
|
*-------------------------------------------------------------------------------
|
||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
*******************************************************************************/
|
||
|
|
||
|
|
||
|
#ifndef __SPUNICODE_H__
|
||
|
#define __SPUNICODE_H__
|
||
|
|
||
|
#ifndef SPHelper_h
|
||
|
#include <sphelper.h>
|
||
|
#endif
|
||
|
|
||
|
template <const int i = MAX_PATH>
|
||
|
class CSpToAnsiString
|
||
|
{
|
||
|
private:
|
||
|
CHAR * m_pStr;
|
||
|
CHAR m_aString[i];
|
||
|
public:
|
||
|
CSpToAnsiString(const WCHAR * psz)
|
||
|
{
|
||
|
if (psz)
|
||
|
{
|
||
|
m_pStr = m_aString;
|
||
|
::WideCharToMultiByte(CP_ACP, 0, psz, -1, m_aString, i, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pStr = NULL;
|
||
|
}
|
||
|
}
|
||
|
operator CHAR *() { return m_pStr; }
|
||
|
CHAR * operator =(const WCHAR * psz)
|
||
|
{
|
||
|
if (psz)
|
||
|
{
|
||
|
m_pStr = m_aString;
|
||
|
::WideCharToMultiByte(CP_ACP, 0, psz, -1, m_aString, i, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pStr = NULL;
|
||
|
}
|
||
|
return m_pStr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef _WIN32_WCE
|
||
|
|
||
|
//
|
||
|
// The compiler will automatically throw out the inline functions if _UNICODE is defined and simply
|
||
|
// directly call the Win32 function. Unfortunately, this requires two classes since simply defining
|
||
|
// const m_bUnicodeSupport does not force the functions to be inlined when built with _UNICODE.
|
||
|
//
|
||
|
template <BOOL bUnicodeOnly>
|
||
|
class CSpUnicodeSupportT
|
||
|
{
|
||
|
BOOL m_bUnicodeSupport;
|
||
|
public:
|
||
|
CSpUnicodeSupportT()
|
||
|
{
|
||
|
if (!bUnicodeOnly)
|
||
|
{
|
||
|
m_bUnicodeSupport = ::IsWindowUnicode(::GetDesktopWindow());
|
||
|
}
|
||
|
}
|
||
|
CSpUnicodeSupportT(BOOL bUnicodeSupport)
|
||
|
{
|
||
|
if (bUnicodeOnly)
|
||
|
{
|
||
|
SPDBG_ASSERT(bUnicodeSupport);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_bUnicodeSupport = bUnicodeSupport;
|
||
|
}
|
||
|
}
|
||
|
BOOL UnicodeSystem(void) const
|
||
|
{
|
||
|
if (bUnicodeOnly)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return m_bUnicodeSupport;
|
||
|
}
|
||
|
}
|
||
|
HANDLE CreateFile(const WCHAR * lpFileName,
|
||
|
DWORD dwDesiredAccess,
|
||
|
DWORD dwShareMode,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
|
DWORD dwCreationDisposition,
|
||
|
DWORD dwFlagsAndAttributes,
|
||
|
HANDLE hTemplateFile) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||
|
dwFlagsAndAttributes, hTemplateFile);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CreateFileA(CSpToAnsiString<>(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||
|
dwFlagsAndAttributes, hTemplateFile);
|
||
|
}
|
||
|
}
|
||
|
DWORD GetFullPathName(WCHAR *lpFileName, // file name
|
||
|
DWORD nBufferLength, // size of path buffer
|
||
|
WCHAR *lpBuffer, // path buffer
|
||
|
WCHAR **lpFilePart // address of file name in path
|
||
|
)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHAR szTemp[MAX_PATH];
|
||
|
CHAR *szTempFilePart;
|
||
|
DWORD tmp = ::GetFullPathNameA(CSpToAnsiString<>(lpFileName), sp_countof(szTemp), szTemp, &szTempFilePart);
|
||
|
if (tmp)
|
||
|
{
|
||
|
tmp = ::MultiByteToWideChar(CP_ACP, 0, szTemp, -1, lpBuffer, nBufferLength);
|
||
|
lpBuffer[tmp] = 0;
|
||
|
*lpFilePart = lpBuffer + (szTempFilePart - szTemp);
|
||
|
}
|
||
|
return tmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL DeleteFile(LPCWSTR lpFileName)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::DeleteFileW(lpFileName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::DeleteFileA(CSpToAnsiString<>(lpFileName));
|
||
|
}
|
||
|
}
|
||
|
BOOL MoveFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::MoveFileW(lpExistingFileName, lpNewFileName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::MoveFileA(CSpToAnsiString<>(lpExistingFileName), CSpToAnsiString<>(lpNewFileName));
|
||
|
}
|
||
|
}
|
||
|
BOOL CopyFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CopyFileA(CSpToAnsiString<>(lpExistingFileName), CSpToAnsiString<>(lpNewFileName), bFailIfExists);
|
||
|
}
|
||
|
}
|
||
|
BOOL CreateDirectory(const WCHAR * lpPathName,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CreateDirectoryA(CSpToAnsiString<>(lpPathName), lpSecurityAttributes);
|
||
|
}
|
||
|
}
|
||
|
BOOL RemoveDirectory(const WCHAR * lpPathName) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RemoveDirectoryW(lpPathName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RemoveDirectoryA(CSpToAnsiString<>(lpPathName));
|
||
|
}
|
||
|
}
|
||
|
HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect,
|
||
|
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const WCHAR *lpName)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
|
||
|
dwMaximumSizeLow, lpName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
|
||
|
dwMaximumSizeLow, CSpToAnsiString<>(lpName));
|
||
|
}
|
||
|
}
|
||
|
BOOL SetFileAttributes(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::SetFileAttributesW(lpFileName, dwFileAttributes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::SetFileAttributesA(CSpToAnsiString<>(lpFileName), dwFileAttributes);
|
||
|
}
|
||
|
}
|
||
|
DWORD GetFileAttributes(LPCWSTR lpFileName)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::GetFileAttributesW(lpFileName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::GetFileAttributesA(CSpToAnsiString<>(lpFileName));
|
||
|
}
|
||
|
}
|
||
|
LONG RegOpenKeyEx(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegOpenKeyExA(hKey, CSpToAnsiString<>(lpSubKey), ulOptions, samDesired, phkResult);
|
||
|
}
|
||
|
}
|
||
|
LONG RegCreateKeyEx(HKEY hk, LPCWSTR lpSubKey, DWORD dwReserved, LPCWSTR lpClass, DWORD dwOptions,
|
||
|
REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
|
||
|
LPDWORD lpdwDisposition) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegCreateKeyExW(hk, lpSubKey, dwReserved, const_cast<WCHAR *>(lpClass), dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegCreateKeyExA(hk, CSpToAnsiString<>(lpSubKey), dwReserved, CSpToAnsiString<>(lpClass), dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
|
||
|
}
|
||
|
}
|
||
|
LONG RegDeleteKey(HKEY hKey, LPCWSTR lpSubKey) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegDeleteKeyW(hKey, lpSubKey);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegDeleteKeyA(hKey, CSpToAnsiString<>(lpSubKey));
|
||
|
}
|
||
|
}
|
||
|
LONG RegDeleteValue(HKEY hKey, LPCWSTR lpSubKey) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegDeleteValueW(hKey, lpSubKey);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegDeleteValueA(hKey, CSpToAnsiString<>(lpSubKey));
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Use RegQueryStringValue for strings. Use this for binary data.
|
||
|
//
|
||
|
LONG RegQueryValueEx(HKEY hk, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegQueryValueExW(hk, lpValueName, NULL, lpType, lpData, lpcbData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegQueryValueExA(hk, CSpToAnsiString<>(lpValueName), NULL, lpType, lpData, lpcbData);
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// NOTE: The size parameter is in CHARACTERS! Even though the registry API sizes are
|
||
|
// in bytes, this function uses character counts.
|
||
|
//
|
||
|
LONG RegQueryStringValue(HKEY hKey, LPCWSTR lpValueName, LPWSTR lpData, LPDWORD lpcchData) const
|
||
|
{
|
||
|
DWORD dwType;
|
||
|
LONG rr;
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
*lpcchData *= sizeof(WCHAR);
|
||
|
rr = ::RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (BYTE *)lpData, lpcchData);
|
||
|
*lpcchData /= sizeof(WCHAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD dwOrigCharCount = *lpcchData;
|
||
|
char * pszScratch = lpData ? (char *)_alloca(dwOrigCharCount) : NULL;
|
||
|
rr = ::RegQueryValueExA(hKey, CSpToAnsiString<>(lpValueName), NULL, &dwType, (BYTE *)pszScratch, lpcchData);
|
||
|
if (lpData)
|
||
|
{
|
||
|
if (rr == ERROR_SUCCESS)
|
||
|
{
|
||
|
DWORD dwReturnedChars = *lpcchData;
|
||
|
*lpcchData = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, dwReturnedChars, lpData, dwOrigCharCount);
|
||
|
if (*lpcchData == 0)
|
||
|
{
|
||
|
rr = ::GetLastError();
|
||
|
*lpcchData = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, dwReturnedChars, NULL, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (rr == ERROR_SUCCESS && dwType == REG_MULTI_SZ && lpData && *lpcchData)
|
||
|
{
|
||
|
// This is used by Whistler setup to overcome string size limits for REG_SZ.
|
||
|
// Unfortunately, leaves a zero-byte inbetween concatenated strings.
|
||
|
// Must remove these entries. Can do this in situ.
|
||
|
LPWSTR lpTo = lpData;
|
||
|
LPWSTR lpFrom = lpData;
|
||
|
while ( static_cast<UINT>(lpFrom-lpData) < ((*lpcchData)-1) )
|
||
|
{
|
||
|
if ( *lpFrom == 0 )
|
||
|
{
|
||
|
lpFrom ++;
|
||
|
}
|
||
|
// This will copy the 2nd zero of a double null-terminated string.
|
||
|
*lpTo = *lpFrom;
|
||
|
lpTo ++;
|
||
|
lpFrom ++;
|
||
|
}
|
||
|
if ( static_cast<UINT>(lpFrom-lpData) < (*lpcchData) )
|
||
|
{
|
||
|
// This will copy the final null-terminating byte of a single-zero terminated string.
|
||
|
*lpTo = *lpFrom;
|
||
|
}
|
||
|
// Update character count to match new string including null-terminator.
|
||
|
*lpcchData = static_cast<UINT>(lpTo-lpData) + 1;
|
||
|
}
|
||
|
SPDBG_ASSERT((rr != ERROR_SUCCESS) || (dwType == REG_SZ) || (dwType == REG_MULTI_SZ));
|
||
|
return rr;
|
||
|
}
|
||
|
//
|
||
|
// NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumKeyEx, we chose to simply
|
||
|
// implement the ReqEnumKey functionality since the Ex functionality is not used
|
||
|
// by most programs (this saves a bunch of string conversion code).
|
||
|
//
|
||
|
LONG RegEnumKey(HKEY hk, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegEnumKeyExW(hk, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD dwSize = *lpcchName;
|
||
|
char * pszScratch = lpName ? (char *)_alloca(dwSize) : NULL;
|
||
|
LONG rr = ::RegEnumKeyExA(hk, dwIndex, pszScratch, &dwSize, NULL, NULL, NULL, NULL);
|
||
|
if (lpName)
|
||
|
{
|
||
|
if (rr == ERROR_SUCCESS)
|
||
|
{
|
||
|
*lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpName, *lpcchName);
|
||
|
if (*lpcchName == 0)
|
||
|
{
|
||
|
*lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, NULL, 0);
|
||
|
rr = ::GetLastError();
|
||
|
}
|
||
|
*lpcchName *= sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpcchName = dwSize;
|
||
|
}
|
||
|
return rr;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumValue
|
||
|
// it will only return the names, not the data. cbValueName is the count of characters
|
||
|
//
|
||
|
LONG RegEnumValueName(HKEY hk, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegEnumValueW(hk, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD dwSize = *lpcchName;
|
||
|
char * pszScratch = lpName ? (char *)_alloca(dwSize) : NULL;
|
||
|
LONG rr = ::RegEnumValueA(hk, dwIndex, pszScratch, &dwSize, NULL, NULL, NULL, NULL);
|
||
|
if (lpName)
|
||
|
{
|
||
|
if (rr == ERROR_SUCCESS)
|
||
|
{
|
||
|
*lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpName, *lpcchName);
|
||
|
if (*lpcchName == 0)
|
||
|
{
|
||
|
*lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, NULL, 0);
|
||
|
rr = ::GetLastError();
|
||
|
}
|
||
|
*lpcchName *= sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpcchName = dwSize;
|
||
|
}
|
||
|
return rr;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Don't use this for strings. Use RegSetStringValue instead.
|
||
|
//
|
||
|
LONG RegSetValueEx(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE * lpData, DWORD cbData) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::RegSetValueExA(hKey, CSpToAnsiString<>(lpValueName), Reserved, dwType, lpData, cbData);
|
||
|
}
|
||
|
}
|
||
|
LONG RegSetStringValue(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpData) const
|
||
|
{
|
||
|
LONG rr;
|
||
|
DWORD dwSize = (wcslen(lpData)+1) * sizeof(WCHAR);
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
rr = ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char * pszScratch = (char *)_alloca(dwSize);
|
||
|
dwSize = ::WideCharToMultiByte(CP_ACP, 0, lpData, -1, pszScratch, dwSize, NULL, NULL);
|
||
|
rr = ::RegSetValueExA(hKey, CSpToAnsiString<>(lpValueName), NULL, REG_SZ, (BYTE *)pszScratch, dwSize);
|
||
|
}
|
||
|
return rr;
|
||
|
}
|
||
|
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CreateEventA(lpEventAttributes, bManualReset, bInitialState, CSpToAnsiString<>(lpName));
|
||
|
}
|
||
|
}
|
||
|
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CreateMutexA(lpMutexAttributes, bInitialOwner, CSpToAnsiString<>(lpName));
|
||
|
}
|
||
|
}
|
||
|
int LoadString(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBuffer) const
|
||
|
{
|
||
|
if (bUnicodeOnly) // NOTE: If the DLL is built ANSI then use ANSI load!
|
||
|
{
|
||
|
return ::LoadStringW(hInstance, uID, lpBuffer, nBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char * pszScratch = (char *)_alloca(nBuffer * 2);
|
||
|
int r = ::LoadStringA(hInstance, uID, pszScratch, nBuffer * 2);
|
||
|
if (r)
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpBuffer, nBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpBuffer = 0;
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
HMODULE LoadLibrary( LPCWSTR lpLibFileName )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::LoadLibraryW( lpLibFileName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::LoadLibraryA( CSpToAnsiString<>(lpLibFileName) );
|
||
|
}
|
||
|
}
|
||
|
HMODULE LoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::LoadLibraryExW(lpLibFileName, hFile, dwFlags);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::LoadLibraryExA(CSpToAnsiString<>(lpLibFileName), hFile, dwFlags);
|
||
|
}
|
||
|
}
|
||
|
HRSRC FindResourceEx(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::FindResourceExW(hModule, lpType, lpName, wLanguage);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::FindResourceExA(hModule,
|
||
|
HIWORD(lpType) ? CSpToAnsiString<>(lpType) : (const CHAR *) lpType,
|
||
|
HIWORD(lpName) ? CSpToAnsiString<>(lpName) : (const CHAR *) lpName,
|
||
|
wLanguage);
|
||
|
}
|
||
|
}
|
||
|
DWORD GetModuleFileName(HMODULE hModule, LPWSTR lpFileName, DWORD nSize) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::GetModuleFileNameW(hModule, lpFileName, nSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHAR szFileName[MAX_PATH];
|
||
|
DWORD r = ::GetModuleFileNameA(hModule, szFileName, sp_countof(szFileName));
|
||
|
if (r)
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, szFileName, r, lpFileName, nSize - 1);
|
||
|
lpFileName[r] = 0;
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
UINT GetSystemDirectory( LPWSTR lpBuffer, UINT uSize )
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::GetSystemDirectoryW( lpBuffer, uSize );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHAR szSystemDirectory[ MAX_PATH ];
|
||
|
DWORD r = ::GetSystemDirectoryA(szSystemDirectory, sp_countof( szSystemDirectory ));
|
||
|
if ( r )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar( CP_ACP, 0, szSystemDirectory, r, lpBuffer, uSize - 1 );
|
||
|
lpBuffer[r] = 0;
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
DWORD SearchPath( LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR *lpFilePart )
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHAR szFoundFile[ MAX_PATH ];
|
||
|
LPSTR lpaFilePart = NULL;
|
||
|
LPSTR lpaPath = strdup( CSpToAnsiString<>(lpPath) );
|
||
|
LPSTR lpaFileName = strdup( CSpToAnsiString<>(lpFileName) );
|
||
|
|
||
|
DWORD r = ::SearchPathA( CSpToAnsiString<>(lpPath), CSpToAnsiString<>(lpFileName),
|
||
|
CSpToAnsiString<>(lpExtension), sp_countof( szFoundFile ), szFoundFile, &lpaFilePart );
|
||
|
if ( r )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar( CP_ACP, 0, szFoundFile, r, lpBuffer, nBufferLength - 1 );
|
||
|
lpBuffer[r] = 0;
|
||
|
}
|
||
|
if ( r )
|
||
|
{
|
||
|
// Find out how many wide characters are in the file part
|
||
|
int cchFilePartW = ::MultiByteToWideChar( CP_ACP, 0, lpaFilePart,
|
||
|
strlen( szFoundFile ) - (lpaFilePart - szFoundFile),
|
||
|
NULL, 0 );
|
||
|
*lpFilePart = lpBuffer + wcslen( lpBuffer ) - cchFilePartW;
|
||
|
}
|
||
|
|
||
|
if ( lpaPath )
|
||
|
{
|
||
|
free( lpaPath );
|
||
|
}
|
||
|
if ( lpaFileName )
|
||
|
{
|
||
|
free( lpaFileName );
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
int CompareString(LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::CompareStringA(Locale, dwCmpFlags, CSpToAnsiString<>(lpString1), cchCount1,
|
||
|
CSpToAnsiString<>(lpString2), cchCount2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL SetWindowText( HWND hWnd, LPCWSTR lpString )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::SetWindowTextW( hWnd, lpString );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::SetWindowTextA( hWnd, CSpToAnsiString<>(lpString) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL SetDlgItemText(HWND hDlg, int nIDDlgItem, LPCWSTR lpString )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::SetDlgItemTextW( hDlg, nIDDlgItem, lpString );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::SetDlgItemTextA( hDlg, nIDDlgItem, CSpToAnsiString<>(lpString) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int MessageBox( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::MessageBoxW( hWnd, lpText, lpCaption, uType );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::MessageBoxA( hWnd, CSpToAnsiString<>(lpText),
|
||
|
CSpToAnsiString<>(lpCaption), uType );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int GetLocaleInfo( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::GetLocaleInfoW( Locale, LCType, lpLCData, cchData );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int cchNeeded = ::GetLocaleInfoA( Locale, LCType, NULL, 0 );
|
||
|
|
||
|
CHAR *pszLCData = new CHAR[ cchNeeded ];
|
||
|
int r = ::GetLocaleInfoA( Locale, LCType, pszLCData, cchNeeded );
|
||
|
if ( r )
|
||
|
{
|
||
|
if ( lpLCData )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszLCData, r, lpLCData, cchData - 1);
|
||
|
lpLCData[r] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// User wants to know how much space is needed
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszLCData, r, NULL, 0 ) + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] pszLCData;
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int GetTimeFormat( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::GetTimeFormatW( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LPSTR lpaFormat = strdup( CSpToAnsiString<>(lpFormat) );
|
||
|
|
||
|
int cchNeeded = ::GetTimeFormatA( Locale, dwFlags, lpTime, lpaFormat, NULL, 0 );
|
||
|
|
||
|
CHAR *pszTime = new CHAR[ cchNeeded ];
|
||
|
int r = ::GetTimeFormatA( Locale, dwFlags, lpTime, lpaFormat, pszTime, cchNeeded );
|
||
|
if ( r )
|
||
|
{
|
||
|
if ( lpTimeStr )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszTime, r, lpTimeStr, cchTime - 1);
|
||
|
lpTimeStr[r] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// User wants to know how much space is needed
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszTime, r, NULL, 0 ) + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] pszTime;
|
||
|
|
||
|
if ( lpaFormat )
|
||
|
{
|
||
|
free( lpaFormat );
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int GetNumberFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW *lpFormat,
|
||
|
LPWSTR lpNumberStr, int cchNumber )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::GetNumberFormatW( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Convert the NUMBERFMTW into a NUMBERFMTA
|
||
|
NUMBERFMTA nmfmtA;
|
||
|
nmfmtA.NumDigits = lpFormat->NumDigits;
|
||
|
nmfmtA.LeadingZero = lpFormat->LeadingZero;
|
||
|
nmfmtA.Grouping = lpFormat->Grouping;
|
||
|
nmfmtA.NegativeOrder = lpFormat->NegativeOrder;
|
||
|
nmfmtA.lpDecimalSep = strdup( CSpToAnsiString<>(lpFormat->lpDecimalSep) );
|
||
|
nmfmtA.lpThousandSep = strdup( CSpToAnsiString<>(lpFormat->lpThousandSep) );
|
||
|
|
||
|
LPSTR lpaValue = strdup( CSpToAnsiString<>(lpValue) );
|
||
|
|
||
|
int cchNeeded = ::GetNumberFormatA( Locale, dwFlags, lpaValue, &nmfmtA, NULL, 0 );
|
||
|
|
||
|
CHAR *pszNumber = new CHAR[ cchNeeded ];
|
||
|
int r = ::GetNumberFormatA( Locale, dwFlags, lpaValue,
|
||
|
&nmfmtA, pszNumber, cchNeeded );
|
||
|
if ( r )
|
||
|
{
|
||
|
if ( lpNumberStr )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszNumber, r, lpNumberStr, cchNumber - 1);
|
||
|
lpNumberStr[r] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// User wants to know how much space is needed
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszNumber, r, NULL, 0 ) + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] pszNumber;
|
||
|
|
||
|
if ( nmfmtA.lpDecimalSep )
|
||
|
{
|
||
|
free( nmfmtA.lpDecimalSep );
|
||
|
}
|
||
|
if ( nmfmtA.lpThousandSep )
|
||
|
{
|
||
|
free( nmfmtA.lpThousandSep );
|
||
|
}
|
||
|
if ( lpaValue )
|
||
|
{
|
||
|
free( lpaValue );
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int GetCurrencyFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW *lpFormat,
|
||
|
LPWSTR lpCurrencyStr, int cchCurrency )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::GetCurrencyFormatW( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr,
|
||
|
cchCurrency );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Convert the CURRENCYFMTW into a CURRENCYFMTA
|
||
|
CURRENCYFMTA cyfmtA;
|
||
|
cyfmtA.NumDigits = lpFormat->NumDigits;
|
||
|
cyfmtA.LeadingZero = lpFormat->LeadingZero;
|
||
|
cyfmtA.Grouping = lpFormat->Grouping;
|
||
|
cyfmtA.NegativeOrder = lpFormat->NegativeOrder;
|
||
|
cyfmtA.PositiveOrder = lpFormat->PositiveOrder;
|
||
|
cyfmtA.lpDecimalSep = strdup( CSpToAnsiString<>(lpFormat->lpDecimalSep) );
|
||
|
cyfmtA.lpThousandSep = strdup( CSpToAnsiString<>(lpFormat->lpThousandSep) );
|
||
|
cyfmtA.lpCurrencySymbol = strdup( CSpToAnsiString<>(lpFormat->lpCurrencySymbol) );
|
||
|
|
||
|
LPSTR lpaValue = strdup( CSpToAnsiString<>(lpValue) );
|
||
|
|
||
|
int cchNeeded = ::GetCurrencyFormatA( Locale, dwFlags, lpaValue, &cyfmtA, NULL, 0 );
|
||
|
|
||
|
CHAR *pszCurrency = new CHAR[ cchNeeded ];
|
||
|
int r = ::GetCurrencyFormatA( Locale, dwFlags, lpaValue,
|
||
|
&cyfmtA, pszCurrency, cchNeeded );
|
||
|
if ( r )
|
||
|
{
|
||
|
if ( lpCurrencyStr )
|
||
|
{
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszCurrency, r, lpCurrencyStr, cchCurrency - 1);
|
||
|
lpCurrencyStr[r] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// User wants to know how much space is needed
|
||
|
r = ::MultiByteToWideChar(CP_ACP, 0, pszCurrency, r, NULL, 0 ) + 1;
|
||
|
}
|
||
|
}
|
||
|
delete[] pszCurrency;
|
||
|
|
||
|
if ( cyfmtA.lpDecimalSep )
|
||
|
{
|
||
|
free( cyfmtA.lpDecimalSep );
|
||
|
}
|
||
|
if ( cyfmtA.lpThousandSep )
|
||
|
{
|
||
|
free( cyfmtA.lpThousandSep );
|
||
|
}
|
||
|
if ( cyfmtA.lpCurrencySymbol )
|
||
|
{
|
||
|
free( cyfmtA.lpCurrencySymbol );
|
||
|
}
|
||
|
if ( lpaValue )
|
||
|
{
|
||
|
free( lpaValue );
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
LONG_PTR GetWindowLongPtr( HWND hWnd, int nIndex )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::GetWindowLongPtrW( hWnd, nIndex );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::GetWindowLongPtrA( hWnd, nIndex );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::SetWindowLongPtrW( hWnd, nIndex, dwNewLong );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::SetWindowLongPtrA( hWnd, nIndex, dwNewLong );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
INT_PTR DialogBoxParam( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::DialogBoxParamW( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::DialogBoxParamA( hInstance, (LPCTSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LRESULT SendDlgItemMessage(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::SendDlgItemMessageA(hDlg, nIDDlgItem, Msg, wParam, lParam );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef __HTMLHELP_H__
|
||
|
HWND WINAPI HtmlHelp( HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData )
|
||
|
{
|
||
|
if ( UnicodeSystem() )
|
||
|
{
|
||
|
return ::HtmlHelpW( hwndCaller, pszFile, uCommand, dwData );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::HtmlHelpA( hwndCaller, CSpToAnsiString<> (pszFile), uCommand, dwData );
|
||
|
}
|
||
|
}
|
||
|
#endif // __HTMLHELP_H__
|
||
|
|
||
|
BOOL GetUserName(LPWSTR lpBuffer, LPDWORD pnSize)
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::GetUserNameW(lpBuffer, pnSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD cchWideCharBuff = *pnSize;
|
||
|
CHAR * psz = (CHAR *)_alloca(cchWideCharBuff * sizeof(CHAR));
|
||
|
BOOL fWorked = ::GetUserNameA(psz, pnSize);
|
||
|
if (fWorked)
|
||
|
{
|
||
|
*pnSize = ::MultiByteToWideChar(CP_ACP, 0, psz, -1, lpBuffer, cchWideCharBuff);
|
||
|
if (*pnSize == 0)
|
||
|
{
|
||
|
fWorked = FALSE;
|
||
|
*pnSize = ::MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
|
||
|
}
|
||
|
}
|
||
|
return fWorked;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(mmioOpen)
|
||
|
HMMIO mmioOpen(LPCWSTR szFileName, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags) const
|
||
|
{
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
return ::mmioOpenW((WCHAR *)szFileName, lpmmioinfo, dwOpenFlags);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ::mmioOpenA(CSpToAnsiString<>(szFileName), lpmmioinfo, dwOpenFlags);
|
||
|
}
|
||
|
}
|
||
|
MMRESULT waveOutGetDevCaps(UINT uDeviceId, LPWAVEOUTCAPSW pwoc, UINT cbwoc) const
|
||
|
{
|
||
|
// Some drivers overwrite the WAVEINCAPS buffer by a DWORD. So they probably do it for
|
||
|
// WAVEOUTCAPS too
|
||
|
MMRESULT mmr = MMSYSERR_NOERROR;
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
BYTE *pBuffer = new BYTE[sizeof(WAVEOUTCAPSW) + sizeof(DWORD)];
|
||
|
WAVEOUTCAPSW *pwocw = reinterpret_cast<WAVEOUTCAPSW *>(pBuffer);
|
||
|
if (pwocw)
|
||
|
{
|
||
|
mmr = ::waveOutGetDevCapsW(uDeviceId, pwocw, cbwoc);
|
||
|
if (mmr == MMSYSERR_NOERROR)
|
||
|
{
|
||
|
*pwoc = *pwocw;
|
||
|
}
|
||
|
delete [] pBuffer;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = MMSYSERR_ERROR;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BYTE *pBuffer = new BYTE[sizeof(WAVEOUTCAPSA) + sizeof(DWORD)];
|
||
|
WAVEOUTCAPSA *pwoca = reinterpret_cast<WAVEOUTCAPSA *>(pBuffer);
|
||
|
if (pwoca)
|
||
|
{
|
||
|
mmr = ::waveOutGetDevCapsA(uDeviceId, pwoca, sizeof(*pwoca));
|
||
|
if (mmr == MMSYSERR_NOERROR)
|
||
|
{
|
||
|
pwoc->wMid = pwoca->wMid;
|
||
|
pwoc->wPid = pwoca->wPid;
|
||
|
pwoc->vDriverVersion = pwoca->vDriverVersion;
|
||
|
pwoc->dwFormats = pwoca->dwFormats;
|
||
|
pwoc->wChannels = pwoca->wChannels;
|
||
|
pwoc->wReserved1 = pwoca->wReserved1;
|
||
|
pwoc->dwSupport = pwoca->dwSupport;
|
||
|
::MultiByteToWideChar(CP_ACP, 0, pwoca->szPname, -1, pwoc->szPname, sp_countof(pwoc->szPname));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = MMSYSERR_ERROR;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = MMSYSERR_ERROR;
|
||
|
}
|
||
|
}
|
||
|
return mmr;
|
||
|
}
|
||
|
MMRESULT waveInGetDevCaps(UINT uDeviceId, LPWAVEINCAPSW pwic, UINT cbwic) const
|
||
|
{
|
||
|
// Some drivers overwrite the WAVEINCAPS buffer by a DWORD
|
||
|
MMRESULT mmr = MMSYSERR_NOERROR;
|
||
|
if (UnicodeSystem())
|
||
|
{
|
||
|
BYTE *pBuffer = new BYTE[sizeof(WAVEINCAPSW) + sizeof(DWORD)];
|
||
|
WAVEINCAPSW *pwicw = reinterpret_cast<WAVEINCAPSW *>(pBuffer);
|
||
|
if (pwicw)
|
||
|
{
|
||
|
mmr = ::waveInGetDevCapsW(uDeviceId, pwicw, cbwic);
|
||
|
if (mmr == MMSYSERR_NOERROR)
|
||
|
{
|
||
|
*pwic = *pwicw;
|
||
|
}
|
||
|
delete [] pBuffer;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = MMSYSERR_ERROR;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BYTE *pBuffer = new BYTE[sizeof(WAVEINCAPSA) + sizeof(DWORD)];
|
||
|
WAVEINCAPSA *pwica = reinterpret_cast<WAVEINCAPSA *>(pBuffer);
|
||
|
if (pwica)
|
||
|
{
|
||
|
mmr = ::waveInGetDevCapsA(uDeviceId, pwica, sizeof(*pwica));
|
||
|
if (mmr == MMSYSERR_NOERROR)
|
||
|
{
|
||
|
pwic->wMid = pwica->wMid;
|
||
|
pwic->wPid = pwica->wPid;
|
||
|
pwic->vDriverVersion = pwica->vDriverVersion;
|
||
|
pwic->dwFormats = pwica->dwFormats;
|
||
|
pwic->wChannels = pwica->wChannels;
|
||
|
pwic->wReserved1 = pwica->wReserved1;
|
||
|
::MultiByteToWideChar(CP_ACP, 0, pwica->szPname, -1, pwic->szPname, sp_countof(pwic->szPname));
|
||
|
}
|
||
|
delete [] pBuffer;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mmr = MMSYSERR_ERROR;
|
||
|
}
|
||
|
}
|
||
|
return mmr;
|
||
|
}
|
||
|
#endif // defined(mmioOpen)
|
||
|
};
|
||
|
|
||
|
#ifdef _UNICODE
|
||
|
typedef CSpUnicodeSupportT<TRUE> CSpUnicodeSupport;
|
||
|
#else
|
||
|
typedef CSpUnicodeSupportT<FALSE> CSpUnicodeSupport;
|
||
|
#endif
|
||
|
|
||
|
#else //_WIN32_WCE
|
||
|
|
||
|
class CSpUnicodeSupport
|
||
|
{
|
||
|
public:
|
||
|
HANDLE CreateFile(const WCHAR * lpFileName,
|
||
|
DWORD dwDesiredAccess,
|
||
|
DWORD dwShareMode,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
|
DWORD dwCreationDisposition,
|
||
|
DWORD dwFlagsAndAttributes,
|
||
|
HANDLE hTemplateFile) const
|
||
|
{
|
||
|
return ::CreateFile(
|
||
|
lpFileName,
|
||
|
dwDesiredAccess,
|
||
|
dwShareMode,
|
||
|
lpSecurityAttributes,
|
||
|
dwCreationDisposition,
|
||
|
dwFlagsAndAttributes,
|
||
|
hTemplateFile);
|
||
|
}
|
||
|
HANDLE CreateFileForMapping(const WCHAR * lpFileName,
|
||
|
DWORD dwDesiredAccess,
|
||
|
DWORD dwShareMode,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
|
DWORD dwCreationDisposition,
|
||
|
DWORD dwFlagsAndAttributes,
|
||
|
HANDLE hTemplateFile) const
|
||
|
{
|
||
|
return ::CreateFileForMappingW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||
|
dwFlagsAndAttributes, hTemplateFile);
|
||
|
}
|
||
|
DWORD GetFullPathName(WCHAR *lpFileName, // file name
|
||
|
DWORD nBufferLength, // size of path buffer
|
||
|
WCHAR *lpBuffer, // path buffer
|
||
|
WCHAR **lpFilePart // address of file name in path
|
||
|
)
|
||
|
{
|
||
|
return ::GetFullPathName(lpFileName, nBufferLength, lpBuffer, lpFilePart);
|
||
|
}
|
||
|
BOOL DeleteFile(LPCWSTR lpFileName)
|
||
|
{
|
||
|
return ::DeleteFileW(lpFileName);
|
||
|
}
|
||
|
BOOL MoveFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
|
||
|
{
|
||
|
return ::MoveFileW(lpExistingFileName, lpNewFileName);
|
||
|
}
|
||
|
BOOL CopyFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
|
||
|
{
|
||
|
return ::CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
|
||
|
}
|
||
|
BOOL CreateDirectory(const WCHAR * lpPathName,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes) const
|
||
|
{
|
||
|
return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
|
||
|
}
|
||
|
BOOL RemoveDirectory(const WCHAR * lpPathName) const
|
||
|
{
|
||
|
return ::RemoveDirectoryW(lpPathName);
|
||
|
}
|
||
|
HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect,
|
||
|
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const WCHAR *lpName)
|
||
|
{
|
||
|
return ::CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
|
||
|
dwMaximumSizeLow, lpName);
|
||
|
}
|
||
|
BOOL SetFileAttributes(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||
|
{
|
||
|
return ::SetFileAttributesW(lpFileName, dwFileAttributes);
|
||
|
}
|
||
|
DWORD GetFileAttributes(LPCWSTR lpFileName)
|
||
|
{
|
||
|
return ::GetFileAttributesW(lpFileName);
|
||
|
}
|
||
|
LONG RegOpenKeyEx(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && phkResult;
|
||
|
LONG lRet = ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||
|
#endif
|
||
|
}
|
||
|
LONG RegCreateKeyEx(HKEY hk, LPCWSTR lpSubKey, DWORD dwReserved, LPCWSTR lpClass, DWORD dwOptions,
|
||
|
REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
|
||
|
LPDWORD lpdwDisposition) const
|
||
|
{
|
||
|
return ::RegCreateKeyExW(hk, lpSubKey, dwReserved, (WCHAR *)lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
|
||
|
}
|
||
|
LONG RegDeleteKey(HKEY hKey, LPCWSTR lpSubKey) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpSubKey;
|
||
|
LONG lRet = ::RegDeleteKeyW(hKey, lpSubKey);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegDeleteKeyW(hKey, lpSubKey);
|
||
|
#endif
|
||
|
}
|
||
|
LONG RegDeleteValue(HKEY hKey, LPCWSTR lpSubKey) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE);
|
||
|
LONG lRet = ::RegDeleteValueW(hKey, lpSubKey);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegDeleteValueW(hKey, lpSubKey);
|
||
|
#endif
|
||
|
}
|
||
|
LONG RegQueryValueEx(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && ((lpData && lpcbData) || (!lpData && !lpcbData));
|
||
|
LONG lRet = ::RegQueryValueExW(hKey, lpValueName, NULL, lpType, lpData, lpcbData);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegQueryValueExW(hKey, lpValueName, NULL, lpType, lpData, lpcbData);
|
||
|
#endif
|
||
|
}
|
||
|
//
|
||
|
// NOTE: The size parameter is in CHARACTERS! Even though the registry API sizes are
|
||
|
// in bytes, this function uses character counts.
|
||
|
//
|
||
|
LONG RegQueryStringValue(HKEY hKey, LPCWSTR lpValueName, LPWSTR lpData, LPDWORD lpcchData) const
|
||
|
{
|
||
|
DWORD dwType;
|
||
|
*lpcchData *= sizeof(WCHAR);
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
|
||
|
#endif
|
||
|
LONG lRet = ::RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (BYTE *)lpData, lpcchData);
|
||
|
*lpcchData /= sizeof(WCHAR);
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return lRet;
|
||
|
#endif
|
||
|
}
|
||
|
//
|
||
|
// NOTES: Size is in bytes. Although this function uses RegEnumKeyEx, we chose to simply
|
||
|
// implement the ReqEnumKey functionality since the Ex functionality is not used
|
||
|
// by most programs (this saves a bunch of string conversion code).
|
||
|
//
|
||
|
LONG RegEnumKey(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcbName) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpName && lpcbName;
|
||
|
LONG lRet = ::RegEnumKeyExW(hKey, dwIndex, lpName, lpcbName, NULL, NULL, NULL, NULL);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegEnumKeyExW(hKey, dwIndex, lpName, lpcbName, NULL, NULL, NULL, NULL);
|
||
|
#endif
|
||
|
}
|
||
|
//
|
||
|
// NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumValue
|
||
|
// it will only return the names, not the data. cbValueName is the count of characters
|
||
|
//
|
||
|
LONG RegEnumValueName(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpName && lpcchName;
|
||
|
LONG lRet = ::RegEnumValueW(hKey, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegEnumValueW(hKey, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
|
||
|
#endif
|
||
|
}
|
||
|
LONG RegSetValueEx(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE * lpData, DWORD cbData) const
|
||
|
{
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
|
||
|
LONG lRet = ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
|
||
|
#endif
|
||
|
}
|
||
|
LONG RegSetStringValue(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpData) const
|
||
|
{
|
||
|
DWORD dwSize = (wcslen(lpData)+1) * sizeof(WCHAR);
|
||
|
#ifdef _WIN32_WCE_BUG_10655
|
||
|
BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
|
||
|
LONG lRet = ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
|
||
|
return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
|
||
|
#else
|
||
|
return ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
|
||
|
#endif
|
||
|
}
|
||
|
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) const
|
||
|
{
|
||
|
return ::CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
|
||
|
}
|
||
|
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName) const
|
||
|
{
|
||
|
return ::CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
|
||
|
}
|
||
|
int LoadString(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBuffer) const
|
||
|
{
|
||
|
return ::LoadStringW(hInstance, uID, lpBuffer, nBuffer);
|
||
|
}
|
||
|
HMODULE LoadLibrary(LPCWSTR lpLibFileName)
|
||
|
{
|
||
|
return ::LoadLibraryW(lpLibFileName);
|
||
|
}
|
||
|
HMODULE LoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||
|
{
|
||
|
return ::LoadLibraryExW(lpLibFileName, hFile, dwFlags);
|
||
|
}
|
||
|
HRSRC FindResource(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType)
|
||
|
{
|
||
|
return ::FindResource(hModule, lpName, lpType);
|
||
|
}
|
||
|
DWORD GetModuleFileName(HMODULE hModule, LPWSTR lpFileName, DWORD nSize) const
|
||
|
{
|
||
|
return ::GetModuleFileNameW(hModule, lpFileName, nSize);
|
||
|
}
|
||
|
// WCE does not support GetSystemDirectory
|
||
|
#if 0
|
||
|
UINT GetSystemDirectory( LPWSTR lpBuffer, UINT uSize )
|
||
|
{
|
||
|
return ::GetSystemDirectoryW( lpBuffer, uSize );
|
||
|
}
|
||
|
#endif
|
||
|
int CompareString(LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2)
|
||
|
{
|
||
|
return ::CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
|
||
|
}
|
||
|
BOOL SetWindowText( HWND hWnd, LPCWSTR lpString )
|
||
|
{
|
||
|
return ::SetWindowTextW( hWnd, lpString );
|
||
|
}
|
||
|
BOOL SetDlgItemText( HWND hDlg, int nIDDlgItem, LPCWSTR lpString )
|
||
|
{
|
||
|
return ::SetDlgItemTextW( hDlg, nIDDlgItem, lpString );
|
||
|
}
|
||
|
int MessageBox( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType )
|
||
|
{
|
||
|
return ::MessageBoxW( hWnd, lpText, lpCaption, uType );
|
||
|
}
|
||
|
int GetLocaleInfo( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData )
|
||
|
{
|
||
|
return ::GetLocaleInfoW( Locale, LCType, lpLCData, cchData );
|
||
|
}
|
||
|
int GetTimeFormat( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime )
|
||
|
{
|
||
|
return ::GetTimeFormatW( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
|
||
|
}
|
||
|
int GetNumberFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW *lpFormat,
|
||
|
LPWSTR lpNumberStr, int cchNumber )
|
||
|
{
|
||
|
return ::GetNumberFormatW( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
|
||
|
int GetCurrencyFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW *lpFormat,
|
||
|
LPWSTR lpCurrencyStr, int cchCurrency )
|
||
|
{
|
||
|
return ::GetCurrencyFormatW( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency );
|
||
|
}
|
||
|
LONG_PTR GetWindowLongPtr( HWND hWnd, int nIndex )
|
||
|
{
|
||
|
return ::GetWindowLongPtr( hWnd, nIndex );
|
||
|
}
|
||
|
LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
|
||
|
{
|
||
|
return ::SetWindowLongPtr( hWnd, nIndex, dwNewLong );
|
||
|
}
|
||
|
INT_PTR DialogBoxParamCE( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam )
|
||
|
{
|
||
|
return ::DialogBoxParamW( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
|
||
|
}
|
||
|
LRESULT SendDlgItemMessage(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
return ::SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
#ifdef __HTMLHELP_H__
|
||
|
HWND WINAPI HtmlHelp( HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData )
|
||
|
{
|
||
|
return HtmlHelpW( hwndCaller, pszFile, uCommand, dwData );
|
||
|
}
|
||
|
#endif // __HTMLHELP_H__
|
||
|
HMMIO mmioOpen(LPCWSTR szFileName, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags) const
|
||
|
{
|
||
|
return ::mmioOpenW((WCHAR *)szFileName, lpmmioinfo, dwOpenFlags);
|
||
|
}
|
||
|
MMRESULT waveOutGetDevCaps(UINT uDeviceId, LPWAVEOUTCAPS pwoc, UINT cbwoc) const
|
||
|
{
|
||
|
return ::waveOutGetDevCaps(uDeviceId, pwoc, cbwoc);
|
||
|
}
|
||
|
MMRESULT waveInGetDevCaps(UINT uDeviceId, LPWAVEINCAPS pwic, UINT cbwic) const
|
||
|
{
|
||
|
return ::waveInGetDevCaps(uDeviceId, pwic, cbwic);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
//
|
||
|
// Assume a global named g_Unicode
|
||
|
//
|
||
|
extern CSpUnicodeSupport g_Unicode;
|
||
|
|
||
|
|
||
|
#endif // Must be the last line of file. (#ifdef __SPUNICODE_H__)
|