Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1373 lines
49 KiB

  1. /*******************************************************************************
  2. * SPUnicode.H *
  3. *--------------*
  4. * Description:
  5. * This is the header file for core helper functions implementation.
  6. * It is internal to Microsoft and is NOT shipped with the SDK since
  7. * many of the functions contatined in this file have not been fully
  8. * tested and therefore should not be exposed in the SDK.
  9. *-------------------------------------------------------------------------------
  10. * Copyright (c) Microsoft Corporation. All rights reserved.
  11. *******************************************************************************/
  12. #ifndef __SPUNICODE_H__
  13. #define __SPUNICODE_H__
  14. #ifndef SPHelper_h
  15. #include <sphelper.h>
  16. #endif
  17. template <const int i = MAX_PATH>
  18. class CSpToAnsiString
  19. {
  20. private:
  21. CHAR * m_pStr;
  22. CHAR m_aString[i];
  23. public:
  24. CSpToAnsiString(const WCHAR * psz)
  25. {
  26. if (psz)
  27. {
  28. m_pStr = m_aString;
  29. ::WideCharToMultiByte(CP_ACP, 0, psz, -1, m_aString, i, NULL, NULL);
  30. }
  31. else
  32. {
  33. m_pStr = NULL;
  34. }
  35. }
  36. operator CHAR *() { return m_pStr; }
  37. CHAR * operator =(const WCHAR * psz)
  38. {
  39. if (psz)
  40. {
  41. m_pStr = m_aString;
  42. ::WideCharToMultiByte(CP_ACP, 0, psz, -1, m_aString, i, NULL, NULL);
  43. }
  44. else
  45. {
  46. m_pStr = NULL;
  47. }
  48. return m_pStr;
  49. }
  50. };
  51. #ifndef _WIN32_WCE
  52. //
  53. // The compiler will automatically throw out the inline functions if _UNICODE is defined and simply
  54. // directly call the Win32 function. Unfortunately, this requires two classes since simply defining
  55. // const m_bUnicodeSupport does not force the functions to be inlined when built with _UNICODE.
  56. //
  57. template <BOOL bUnicodeOnly>
  58. class CSpUnicodeSupportT
  59. {
  60. BOOL m_bUnicodeSupport;
  61. public:
  62. CSpUnicodeSupportT()
  63. {
  64. if (!bUnicodeOnly)
  65. {
  66. // On NT-based systems, we can always set this to true.
  67. // Thus this whole file becomes a pass through and in post .Net Server branches has been removed.
  68. //m_bUnicodeSupport = ::IsWindowUnicode(::GetDesktopWindow());
  69. m_bUnicodeSupport = TRUE;
  70. }
  71. }
  72. CSpUnicodeSupportT(BOOL bUnicodeSupport)
  73. {
  74. if (bUnicodeOnly)
  75. {
  76. SPDBG_ASSERT(bUnicodeSupport);
  77. }
  78. else
  79. {
  80. m_bUnicodeSupport = bUnicodeSupport;
  81. }
  82. }
  83. BOOL UnicodeSystem(void) const
  84. {
  85. if (bUnicodeOnly)
  86. {
  87. return TRUE;
  88. }
  89. else
  90. {
  91. return m_bUnicodeSupport;
  92. }
  93. }
  94. HANDLE CreateFile(const WCHAR * lpFileName,
  95. DWORD dwDesiredAccess,
  96. DWORD dwShareMode,
  97. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  98. DWORD dwCreationDisposition,
  99. DWORD dwFlagsAndAttributes,
  100. HANDLE hTemplateFile) const
  101. {
  102. if (UnicodeSystem())
  103. {
  104. return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
  105. dwFlagsAndAttributes, hTemplateFile);
  106. }
  107. else
  108. {
  109. return ::CreateFileA(CSpToAnsiString<>(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
  110. dwFlagsAndAttributes, hTemplateFile);
  111. }
  112. }
  113. DWORD GetFullPathName(WCHAR *lpFileName, // file name
  114. DWORD nBufferLength, // size of path buffer
  115. WCHAR *lpBuffer, // path buffer
  116. WCHAR **lpFilePart // address of file name in path
  117. )
  118. {
  119. if (UnicodeSystem())
  120. {
  121. return ::GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
  122. }
  123. else
  124. {
  125. CHAR szTemp[MAX_PATH];
  126. CHAR *szTempFilePart;
  127. DWORD tmp = ::GetFullPathNameA(CSpToAnsiString<>(lpFileName), sp_countof(szTemp), szTemp, &szTempFilePart);
  128. if (tmp)
  129. {
  130. tmp = ::MultiByteToWideChar(CP_ACP, 0, szTemp, -1, lpBuffer, nBufferLength);
  131. lpBuffer[tmp] = 0;
  132. *lpFilePart = lpBuffer + (szTempFilePart - szTemp);
  133. }
  134. return tmp;
  135. }
  136. }
  137. BOOL DeleteFile(LPCWSTR lpFileName)
  138. {
  139. if (UnicodeSystem())
  140. {
  141. return ::DeleteFileW(lpFileName);
  142. }
  143. else
  144. {
  145. return ::DeleteFileA(CSpToAnsiString<>(lpFileName));
  146. }
  147. }
  148. BOOL MoveFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  149. {
  150. if (UnicodeSystem())
  151. {
  152. return ::MoveFileW(lpExistingFileName, lpNewFileName);
  153. }
  154. else
  155. {
  156. return ::MoveFileA(CSpToAnsiString<>(lpExistingFileName), CSpToAnsiString<>(lpNewFileName));
  157. }
  158. }
  159. BOOL CopyFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
  160. {
  161. if (UnicodeSystem())
  162. {
  163. return ::CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
  164. }
  165. else
  166. {
  167. return ::CopyFileA(CSpToAnsiString<>(lpExistingFileName), CSpToAnsiString<>(lpNewFileName), bFailIfExists);
  168. }
  169. }
  170. BOOL CreateDirectory(const WCHAR * lpPathName,
  171. LPSECURITY_ATTRIBUTES lpSecurityAttributes) const
  172. {
  173. if (UnicodeSystem())
  174. {
  175. return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
  176. }
  177. else
  178. {
  179. return ::CreateDirectoryA(CSpToAnsiString<>(lpPathName), lpSecurityAttributes);
  180. }
  181. }
  182. BOOL RemoveDirectory(const WCHAR * lpPathName) const
  183. {
  184. if (UnicodeSystem())
  185. {
  186. return ::RemoveDirectoryW(lpPathName);
  187. }
  188. else
  189. {
  190. return ::RemoveDirectoryA(CSpToAnsiString<>(lpPathName));
  191. }
  192. }
  193. HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect,
  194. DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const WCHAR *lpName)
  195. {
  196. if (UnicodeSystem())
  197. {
  198. return ::CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
  199. dwMaximumSizeLow, lpName);
  200. }
  201. else
  202. {
  203. return ::CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
  204. dwMaximumSizeLow, CSpToAnsiString<>(lpName));
  205. }
  206. }
  207. BOOL SetFileAttributes(LPCWSTR lpFileName, DWORD dwFileAttributes)
  208. {
  209. if (UnicodeSystem())
  210. {
  211. return ::SetFileAttributesW(lpFileName, dwFileAttributes);
  212. }
  213. else
  214. {
  215. return ::SetFileAttributesA(CSpToAnsiString<>(lpFileName), dwFileAttributes);
  216. }
  217. }
  218. DWORD GetFileAttributes(LPCWSTR lpFileName)
  219. {
  220. if (UnicodeSystem())
  221. {
  222. return ::GetFileAttributesW(lpFileName);
  223. }
  224. else
  225. {
  226. return ::GetFileAttributesA(CSpToAnsiString<>(lpFileName));
  227. }
  228. }
  229. LONG RegOpenKeyEx(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) const
  230. {
  231. if (UnicodeSystem())
  232. {
  233. return ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  234. }
  235. else
  236. {
  237. return ::RegOpenKeyExA(hKey, CSpToAnsiString<>(lpSubKey), ulOptions, samDesired, phkResult);
  238. }
  239. }
  240. LONG RegCreateKeyEx(HKEY hk, LPCWSTR lpSubKey, DWORD dwReserved, LPCWSTR lpClass, DWORD dwOptions,
  241. REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
  242. LPDWORD lpdwDisposition) const
  243. {
  244. if (UnicodeSystem())
  245. {
  246. return ::RegCreateKeyExW(hk, lpSubKey, dwReserved, const_cast<WCHAR *>(lpClass), dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  247. }
  248. else
  249. {
  250. return ::RegCreateKeyExA(hk, CSpToAnsiString<>(lpSubKey), dwReserved, CSpToAnsiString<>(lpClass), dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  251. }
  252. }
  253. LONG RegDeleteKey(HKEY hKey, LPCWSTR lpSubKey) const
  254. {
  255. if (UnicodeSystem())
  256. {
  257. return ::RegDeleteKeyW(hKey, lpSubKey);
  258. }
  259. else
  260. {
  261. return ::RegDeleteKeyA(hKey, CSpToAnsiString<>(lpSubKey));
  262. }
  263. }
  264. LONG RegDeleteValue(HKEY hKey, LPCWSTR lpSubKey) const
  265. {
  266. if (UnicodeSystem())
  267. {
  268. return ::RegDeleteValueW(hKey, lpSubKey);
  269. }
  270. else
  271. {
  272. return ::RegDeleteValueA(hKey, CSpToAnsiString<>(lpSubKey));
  273. }
  274. }
  275. //
  276. // Use RegQueryStringValue for strings. Use this for binary data.
  277. //
  278. LONG RegQueryValueEx(HKEY hk, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) const
  279. {
  280. if (UnicodeSystem())
  281. {
  282. return ::RegQueryValueExW(hk, lpValueName, NULL, lpType, lpData, lpcbData);
  283. }
  284. else
  285. {
  286. return ::RegQueryValueExA(hk, CSpToAnsiString<>(lpValueName), NULL, lpType, lpData, lpcbData);
  287. }
  288. }
  289. //
  290. // NOTE: The size parameter is in CHARACTERS! Even though the registry API sizes are
  291. // in bytes, this function uses character counts.
  292. //
  293. LONG RegQueryStringValue(HKEY hKey, LPCWSTR lpValueName, LPWSTR lpData, LPDWORD lpcchData) const
  294. {
  295. DWORD dwType;
  296. LONG rr;
  297. if (UnicodeSystem())
  298. {
  299. *lpcchData *= sizeof(WCHAR);
  300. rr = ::RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (BYTE *)lpData, lpcchData);
  301. *lpcchData /= sizeof(WCHAR);
  302. }
  303. else
  304. {
  305. DWORD dwOrigCharCount = *lpcchData;
  306. char * pszScratch = lpData ? (char *)_alloca(dwOrigCharCount) : NULL;
  307. rr = ::RegQueryValueExA(hKey, CSpToAnsiString<>(lpValueName), NULL, &dwType, (BYTE *)pszScratch, lpcchData);
  308. if (lpData)
  309. {
  310. if (rr == ERROR_SUCCESS)
  311. {
  312. DWORD dwReturnedChars = *lpcchData;
  313. *lpcchData = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, dwReturnedChars, lpData, dwOrigCharCount);
  314. if (*lpcchData == 0)
  315. {
  316. rr = ::GetLastError();
  317. *lpcchData = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, dwReturnedChars, NULL, 0);
  318. }
  319. }
  320. }
  321. }
  322. if (rr == ERROR_SUCCESS && dwType == REG_MULTI_SZ && lpData && *lpcchData)
  323. {
  324. // This is used by Whistler setup to overcome string size limits for REG_SZ.
  325. // Unfortunately, leaves a zero-byte inbetween concatenated strings.
  326. // Must remove these entries. Can do this in situ.
  327. LPWSTR lpTo = lpData;
  328. LPWSTR lpFrom = lpData;
  329. while ( static_cast<UINT>(lpFrom-lpData) < ((*lpcchData)-1) )
  330. {
  331. if ( *lpFrom == 0 )
  332. {
  333. lpFrom ++;
  334. }
  335. // This will copy the 2nd zero of a double null-terminated string.
  336. *lpTo = *lpFrom;
  337. lpTo ++;
  338. lpFrom ++;
  339. }
  340. if ( static_cast<UINT>(lpFrom-lpData) < (*lpcchData) )
  341. {
  342. // This will copy the final null-terminating byte of a single-zero terminated string.
  343. *lpTo = *lpFrom;
  344. }
  345. // Update character count to match new string including null-terminator.
  346. *lpcchData = static_cast<UINT>(lpTo-lpData) + 1;
  347. }
  348. SPDBG_ASSERT((rr != ERROR_SUCCESS) || (dwType == REG_SZ) || (dwType == REG_MULTI_SZ));
  349. return rr;
  350. }
  351. //
  352. // NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumKeyEx, we chose to simply
  353. // implement the ReqEnumKey functionality since the Ex functionality is not used
  354. // by most programs (this saves a bunch of string conversion code).
  355. //
  356. LONG RegEnumKey(HKEY hk, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
  357. {
  358. if (UnicodeSystem())
  359. {
  360. return ::RegEnumKeyExW(hk, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
  361. }
  362. else
  363. {
  364. DWORD dwSize = *lpcchName;
  365. char * pszScratch = lpName ? (char *)_alloca(dwSize) : NULL;
  366. LONG rr = ::RegEnumKeyExA(hk, dwIndex, pszScratch, &dwSize, NULL, NULL, NULL, NULL);
  367. if (lpName)
  368. {
  369. if (rr == ERROR_SUCCESS)
  370. {
  371. *lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpName, *lpcchName);
  372. if (*lpcchName == 0)
  373. {
  374. *lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, NULL, 0);
  375. rr = ::GetLastError();
  376. }
  377. *lpcchName *= sizeof(WCHAR);
  378. }
  379. }
  380. else
  381. {
  382. *lpcchName = dwSize;
  383. }
  384. return rr;
  385. }
  386. }
  387. //
  388. // NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumValue
  389. // it will only return the names, not the data. cbValueName is the count of characters
  390. //
  391. LONG RegEnumValueName(HKEY hk, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
  392. {
  393. if (UnicodeSystem())
  394. {
  395. return ::RegEnumValueW(hk, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
  396. }
  397. else
  398. {
  399. DWORD dwSize = *lpcchName;
  400. char * pszScratch = lpName ? (char *)_alloca(dwSize) : NULL;
  401. LONG rr = ::RegEnumValueA(hk, dwIndex, pszScratch, &dwSize, NULL, NULL, NULL, NULL);
  402. if (lpName)
  403. {
  404. if (rr == ERROR_SUCCESS)
  405. {
  406. *lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpName, *lpcchName);
  407. if (*lpcchName == 0)
  408. {
  409. *lpcchName = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, NULL, 0);
  410. rr = ::GetLastError();
  411. }
  412. *lpcchName *= sizeof(WCHAR);
  413. }
  414. }
  415. else
  416. {
  417. *lpcchName = dwSize;
  418. }
  419. return rr;
  420. }
  421. }
  422. //
  423. // Don't use this for strings. Use RegSetStringValue instead.
  424. //
  425. LONG RegSetValueEx(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE * lpData, DWORD cbData) const
  426. {
  427. if (UnicodeSystem())
  428. {
  429. return ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
  430. }
  431. else
  432. {
  433. return ::RegSetValueExA(hKey, CSpToAnsiString<>(lpValueName), Reserved, dwType, lpData, cbData);
  434. }
  435. }
  436. LONG RegSetStringValue(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpData) const
  437. {
  438. LONG rr;
  439. DWORD dwSize = (wcslen(lpData)+1) * sizeof(WCHAR);
  440. if (UnicodeSystem())
  441. {
  442. rr = ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
  443. }
  444. else
  445. {
  446. char * pszScratch = (char *)_alloca(dwSize);
  447. dwSize = ::WideCharToMultiByte(CP_ACP, 0, lpData, -1, pszScratch, dwSize, NULL, NULL);
  448. rr = ::RegSetValueExA(hKey, CSpToAnsiString<>(lpValueName), NULL, REG_SZ, (BYTE *)pszScratch, dwSize);
  449. }
  450. return rr;
  451. }
  452. HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) const
  453. {
  454. if (UnicodeSystem())
  455. {
  456. return ::CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
  457. }
  458. else
  459. {
  460. return ::CreateEventA(lpEventAttributes, bManualReset, bInitialState, CSpToAnsiString<>(lpName));
  461. }
  462. }
  463. HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName) const
  464. {
  465. if (UnicodeSystem())
  466. {
  467. return ::CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
  468. }
  469. else
  470. {
  471. return ::CreateMutexA(lpMutexAttributes, bInitialOwner, CSpToAnsiString<>(lpName));
  472. }
  473. }
  474. int LoadString(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBuffer) const
  475. {
  476. if (bUnicodeOnly) // NOTE: If the DLL is built ANSI then use ANSI load!
  477. {
  478. return ::LoadStringW(hInstance, uID, lpBuffer, nBuffer);
  479. }
  480. else
  481. {
  482. char * pszScratch = (char *)_alloca(nBuffer * 2);
  483. int r = ::LoadStringA(hInstance, uID, pszScratch, nBuffer * 2);
  484. if (r)
  485. {
  486. r = ::MultiByteToWideChar(CP_ACP, 0, pszScratch, -1, lpBuffer, nBuffer);
  487. }
  488. else
  489. {
  490. *lpBuffer = 0;
  491. }
  492. return r;
  493. }
  494. }
  495. HMODULE LoadLibrary( LPCWSTR lpLibFileName )
  496. {
  497. if ( UnicodeSystem() )
  498. {
  499. return ::LoadLibraryW( lpLibFileName );
  500. }
  501. else
  502. {
  503. return ::LoadLibraryA( CSpToAnsiString<>(lpLibFileName) );
  504. }
  505. }
  506. HMODULE LoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
  507. {
  508. if (UnicodeSystem())
  509. {
  510. return ::LoadLibraryExW(lpLibFileName, hFile, dwFlags);
  511. }
  512. else
  513. {
  514. return ::LoadLibraryExA(CSpToAnsiString<>(lpLibFileName), hFile, dwFlags);
  515. }
  516. }
  517. HRSRC FindResourceEx(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage)
  518. {
  519. if (UnicodeSystem())
  520. {
  521. return ::FindResourceExW(hModule, lpType, lpName, wLanguage);
  522. }
  523. else
  524. {
  525. return ::FindResourceExA(hModule,
  526. HIWORD(lpType) ? CSpToAnsiString<>(lpType) : (const CHAR *) lpType,
  527. HIWORD(lpName) ? CSpToAnsiString<>(lpName) : (const CHAR *) lpName,
  528. wLanguage);
  529. }
  530. }
  531. DWORD GetModuleFileName(HMODULE hModule, LPWSTR lpFileName, DWORD nSize) const
  532. {
  533. if (UnicodeSystem())
  534. {
  535. return ::GetModuleFileNameW(hModule, lpFileName, nSize);
  536. }
  537. else
  538. {
  539. CHAR szFileName[MAX_PATH];
  540. DWORD r = ::GetModuleFileNameA(hModule, szFileName, sp_countof(szFileName));
  541. if (r)
  542. {
  543. r = ::MultiByteToWideChar(CP_ACP, 0, szFileName, r, lpFileName, nSize - 1);
  544. lpFileName[r] = 0;
  545. }
  546. return r;
  547. }
  548. }
  549. UINT GetSystemDirectory( LPWSTR lpBuffer, UINT uSize )
  550. {
  551. if (UnicodeSystem())
  552. {
  553. return ::GetSystemDirectoryW( lpBuffer, uSize );
  554. }
  555. else
  556. {
  557. CHAR szSystemDirectory[ MAX_PATH ];
  558. DWORD r = ::GetSystemDirectoryA(szSystemDirectory, sp_countof( szSystemDirectory ));
  559. if ( r )
  560. {
  561. r = ::MultiByteToWideChar( CP_ACP, 0, szSystemDirectory, r, lpBuffer, uSize - 1 );
  562. lpBuffer[r] = 0;
  563. }
  564. return r;
  565. }
  566. }
  567. DWORD SearchPath( LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR *lpFilePart )
  568. {
  569. if (UnicodeSystem())
  570. {
  571. return ::SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart );
  572. }
  573. else
  574. {
  575. CHAR szFoundFile[ MAX_PATH ];
  576. LPSTR lpaFilePart = NULL;
  577. LPSTR lpaPath = strdup( CSpToAnsiString<>(lpPath) );
  578. LPSTR lpaFileName = strdup( CSpToAnsiString<>(lpFileName) );
  579. DWORD r = ::SearchPathA( CSpToAnsiString<>(lpPath), CSpToAnsiString<>(lpFileName),
  580. CSpToAnsiString<>(lpExtension), sp_countof( szFoundFile ), szFoundFile, &lpaFilePart );
  581. if ( r )
  582. {
  583. r = ::MultiByteToWideChar( CP_ACP, 0, szFoundFile, r, lpBuffer, nBufferLength - 1 );
  584. lpBuffer[r] = 0;
  585. }
  586. if ( r )
  587. {
  588. // Find out how many wide characters are in the file part
  589. int cchFilePartW = ::MultiByteToWideChar( CP_ACP, 0, lpaFilePart,
  590. strlen( szFoundFile ) - (lpaFilePart - szFoundFile),
  591. NULL, 0 );
  592. *lpFilePart = lpBuffer + wcslen( lpBuffer ) - cchFilePartW;
  593. }
  594. if ( lpaPath )
  595. {
  596. free( lpaPath );
  597. }
  598. if ( lpaFileName )
  599. {
  600. free( lpaFileName );
  601. }
  602. return r;
  603. }
  604. }
  605. int CompareString(LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2)
  606. {
  607. if (UnicodeSystem())
  608. {
  609. return ::CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
  610. }
  611. else
  612. {
  613. return ::CompareStringA(Locale, dwCmpFlags, CSpToAnsiString<>(lpString1), cchCount1,
  614. CSpToAnsiString<>(lpString2), cchCount2);
  615. }
  616. }
  617. BOOL SetWindowText( HWND hWnd, LPCWSTR lpString )
  618. {
  619. if ( UnicodeSystem() )
  620. {
  621. return ::SetWindowTextW( hWnd, lpString );
  622. }
  623. else
  624. {
  625. return ::SetWindowTextA( hWnd, CSpToAnsiString<>(lpString) );
  626. }
  627. }
  628. BOOL SetDlgItemText(HWND hDlg, int nIDDlgItem, LPCWSTR lpString )
  629. {
  630. if ( UnicodeSystem() )
  631. {
  632. return ::SetDlgItemTextW( hDlg, nIDDlgItem, lpString );
  633. }
  634. else
  635. {
  636. return ::SetDlgItemTextA( hDlg, nIDDlgItem, CSpToAnsiString<>(lpString) );
  637. }
  638. }
  639. int MessageBox( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType )
  640. {
  641. if ( UnicodeSystem() )
  642. {
  643. return ::MessageBoxW( hWnd, lpText, lpCaption, uType );
  644. }
  645. else
  646. {
  647. return ::MessageBoxA( hWnd, CSpToAnsiString<>(lpText),
  648. CSpToAnsiString<>(lpCaption), uType );
  649. }
  650. }
  651. int GetLocaleInfo( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData )
  652. {
  653. if ( UnicodeSystem() )
  654. {
  655. return ::GetLocaleInfoW( Locale, LCType, lpLCData, cchData );
  656. }
  657. else
  658. {
  659. int cchNeeded = ::GetLocaleInfoA( Locale, LCType, NULL, 0 );
  660. CHAR *pszLCData = new CHAR[ cchNeeded ];
  661. int r = ::GetLocaleInfoA( Locale, LCType, pszLCData, cchNeeded );
  662. if ( r )
  663. {
  664. if ( lpLCData )
  665. {
  666. r = ::MultiByteToWideChar(CP_ACP, 0, pszLCData, r, lpLCData, cchData - 1);
  667. lpLCData[r] = 0;
  668. }
  669. else
  670. {
  671. // User wants to know how much space is needed
  672. r = ::MultiByteToWideChar(CP_ACP, 0, pszLCData, r, NULL, 0 ) + 1;
  673. }
  674. }
  675. delete[] pszLCData;
  676. return r;
  677. }
  678. }
  679. int GetTimeFormat( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime )
  680. {
  681. if ( UnicodeSystem() )
  682. {
  683. return ::GetTimeFormatW( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
  684. }
  685. else
  686. {
  687. LPSTR lpaFormat = strdup( CSpToAnsiString<>(lpFormat) );
  688. int cchNeeded = ::GetTimeFormatA( Locale, dwFlags, lpTime, lpaFormat, NULL, 0 );
  689. CHAR *pszTime = new CHAR[ cchNeeded ];
  690. int r = ::GetTimeFormatA( Locale, dwFlags, lpTime, lpaFormat, pszTime, cchNeeded );
  691. if ( r )
  692. {
  693. if ( lpTimeStr )
  694. {
  695. r = ::MultiByteToWideChar(CP_ACP, 0, pszTime, r, lpTimeStr, cchTime - 1);
  696. lpTimeStr[r] = 0;
  697. }
  698. else
  699. {
  700. // User wants to know how much space is needed
  701. r = ::MultiByteToWideChar(CP_ACP, 0, pszTime, r, NULL, 0 ) + 1;
  702. }
  703. }
  704. delete[] pszTime;
  705. if ( lpaFormat )
  706. {
  707. free( lpaFormat );
  708. }
  709. return r;
  710. }
  711. }
  712. int GetNumberFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW *lpFormat,
  713. LPWSTR lpNumberStr, int cchNumber )
  714. {
  715. if ( UnicodeSystem() )
  716. {
  717. return ::GetNumberFormatW( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
  718. }
  719. else
  720. {
  721. // Convert the NUMBERFMTW into a NUMBERFMTA
  722. NUMBERFMTA nmfmtA;
  723. nmfmtA.NumDigits = lpFormat->NumDigits;
  724. nmfmtA.LeadingZero = lpFormat->LeadingZero;
  725. nmfmtA.Grouping = lpFormat->Grouping;
  726. nmfmtA.NegativeOrder = lpFormat->NegativeOrder;
  727. nmfmtA.lpDecimalSep = strdup( CSpToAnsiString<>(lpFormat->lpDecimalSep) );
  728. nmfmtA.lpThousandSep = strdup( CSpToAnsiString<>(lpFormat->lpThousandSep) );
  729. LPSTR lpaValue = strdup( CSpToAnsiString<>(lpValue) );
  730. int cchNeeded = ::GetNumberFormatA( Locale, dwFlags, lpaValue, &nmfmtA, NULL, 0 );
  731. CHAR *pszNumber = new CHAR[ cchNeeded ];
  732. int r = ::GetNumberFormatA( Locale, dwFlags, lpaValue,
  733. &nmfmtA, pszNumber, cchNeeded );
  734. if ( r )
  735. {
  736. if ( lpNumberStr )
  737. {
  738. r = ::MultiByteToWideChar(CP_ACP, 0, pszNumber, r, lpNumberStr, cchNumber - 1);
  739. lpNumberStr[r] = 0;
  740. }
  741. else
  742. {
  743. // User wants to know how much space is needed
  744. r = ::MultiByteToWideChar(CP_ACP, 0, pszNumber, r, NULL, 0 ) + 1;
  745. }
  746. }
  747. delete[] pszNumber;
  748. if ( nmfmtA.lpDecimalSep )
  749. {
  750. free( nmfmtA.lpDecimalSep );
  751. }
  752. if ( nmfmtA.lpThousandSep )
  753. {
  754. free( nmfmtA.lpThousandSep );
  755. }
  756. if ( lpaValue )
  757. {
  758. free( lpaValue );
  759. }
  760. return r;
  761. }
  762. }
  763. int GetCurrencyFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW *lpFormat,
  764. LPWSTR lpCurrencyStr, int cchCurrency )
  765. {
  766. if ( UnicodeSystem() )
  767. {
  768. return ::GetCurrencyFormatW( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr,
  769. cchCurrency );
  770. }
  771. else
  772. {
  773. // Convert the CURRENCYFMTW into a CURRENCYFMTA
  774. CURRENCYFMTA cyfmtA;
  775. cyfmtA.NumDigits = lpFormat->NumDigits;
  776. cyfmtA.LeadingZero = lpFormat->LeadingZero;
  777. cyfmtA.Grouping = lpFormat->Grouping;
  778. cyfmtA.NegativeOrder = lpFormat->NegativeOrder;
  779. cyfmtA.PositiveOrder = lpFormat->PositiveOrder;
  780. cyfmtA.lpDecimalSep = strdup( CSpToAnsiString<>(lpFormat->lpDecimalSep) );
  781. cyfmtA.lpThousandSep = strdup( CSpToAnsiString<>(lpFormat->lpThousandSep) );
  782. cyfmtA.lpCurrencySymbol = strdup( CSpToAnsiString<>(lpFormat->lpCurrencySymbol) );
  783. LPSTR lpaValue = strdup( CSpToAnsiString<>(lpValue) );
  784. int cchNeeded = ::GetCurrencyFormatA( Locale, dwFlags, lpaValue, &cyfmtA, NULL, 0 );
  785. CHAR *pszCurrency = new CHAR[ cchNeeded ];
  786. int r = ::GetCurrencyFormatA( Locale, dwFlags, lpaValue,
  787. &cyfmtA, pszCurrency, cchNeeded );
  788. if ( r )
  789. {
  790. if ( lpCurrencyStr )
  791. {
  792. r = ::MultiByteToWideChar(CP_ACP, 0, pszCurrency, r, lpCurrencyStr, cchCurrency - 1);
  793. lpCurrencyStr[r] = 0;
  794. }
  795. else
  796. {
  797. // User wants to know how much space is needed
  798. r = ::MultiByteToWideChar(CP_ACP, 0, pszCurrency, r, NULL, 0 ) + 1;
  799. }
  800. }
  801. delete[] pszCurrency;
  802. if ( cyfmtA.lpDecimalSep )
  803. {
  804. free( cyfmtA.lpDecimalSep );
  805. }
  806. if ( cyfmtA.lpThousandSep )
  807. {
  808. free( cyfmtA.lpThousandSep );
  809. }
  810. if ( cyfmtA.lpCurrencySymbol )
  811. {
  812. free( cyfmtA.lpCurrencySymbol );
  813. }
  814. if ( lpaValue )
  815. {
  816. free( lpaValue );
  817. }
  818. return r;
  819. }
  820. }
  821. LONG_PTR GetWindowLongPtr( HWND hWnd, int nIndex )
  822. {
  823. if ( UnicodeSystem() )
  824. {
  825. return ::GetWindowLongPtrW( hWnd, nIndex );
  826. }
  827. else
  828. {
  829. return ::GetWindowLongPtrA( hWnd, nIndex );
  830. }
  831. }
  832. LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
  833. {
  834. if ( UnicodeSystem() )
  835. {
  836. return ::SetWindowLongPtrW( hWnd, nIndex, dwNewLong );
  837. }
  838. else
  839. {
  840. return ::SetWindowLongPtrA( hWnd, nIndex, dwNewLong );
  841. }
  842. }
  843. INT_PTR DialogBoxParam( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam )
  844. {
  845. if ( UnicodeSystem() )
  846. {
  847. return ::DialogBoxParamW( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
  848. }
  849. else
  850. {
  851. return ::DialogBoxParamA( hInstance, (LPCTSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
  852. }
  853. }
  854. LRESULT SendDlgItemMessage(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam )
  855. {
  856. if ( UnicodeSystem() )
  857. {
  858. return ::SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam );
  859. }
  860. else
  861. {
  862. return ::SendDlgItemMessageA(hDlg, nIDDlgItem, Msg, wParam, lParam );
  863. }
  864. }
  865. #ifdef __HTMLHELP_H__
  866. HWND WINAPI HtmlHelp( HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData )
  867. {
  868. if ( UnicodeSystem() )
  869. {
  870. return ::HtmlHelpW( hwndCaller, pszFile, uCommand, dwData );
  871. }
  872. else
  873. {
  874. return ::HtmlHelpA( hwndCaller, CSpToAnsiString<> (pszFile), uCommand, dwData );
  875. }
  876. }
  877. #endif // __HTMLHELP_H__
  878. BOOL GetUserName(LPWSTR lpBuffer, LPDWORD pnSize)
  879. {
  880. if (UnicodeSystem())
  881. {
  882. return ::GetUserNameW(lpBuffer, pnSize);
  883. }
  884. else
  885. {
  886. DWORD cchWideCharBuff = *pnSize;
  887. CHAR * psz = (CHAR *)_alloca(cchWideCharBuff * sizeof(CHAR));
  888. BOOL fWorked = ::GetUserNameA(psz, pnSize);
  889. if (fWorked)
  890. {
  891. *pnSize = ::MultiByteToWideChar(CP_ACP, 0, psz, -1, lpBuffer, cchWideCharBuff);
  892. if (*pnSize == 0)
  893. {
  894. fWorked = FALSE;
  895. *pnSize = ::MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  896. }
  897. }
  898. return fWorked;
  899. }
  900. }
  901. #if defined(mmioOpen)
  902. HMMIO mmioOpen(LPCWSTR szFileName, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags) const
  903. {
  904. if (UnicodeSystem())
  905. {
  906. return ::mmioOpenW((WCHAR *)szFileName, lpmmioinfo, dwOpenFlags);
  907. }
  908. else
  909. {
  910. return ::mmioOpenA(CSpToAnsiString<>(szFileName), lpmmioinfo, dwOpenFlags);
  911. }
  912. }
  913. MMRESULT waveOutGetDevCaps(UINT uDeviceId, LPWAVEOUTCAPSW pwoc, UINT cbwoc) const
  914. {
  915. // Some drivers overwrite the WAVEINCAPS buffer by a DWORD. So they probably do it for
  916. // WAVEOUTCAPS too
  917. MMRESULT mmr = MMSYSERR_NOERROR;
  918. if (UnicodeSystem())
  919. {
  920. BYTE *pBuffer = new BYTE[sizeof(WAVEOUTCAPSW) + sizeof(DWORD)];
  921. WAVEOUTCAPSW *pwocw = reinterpret_cast<WAVEOUTCAPSW *>(pBuffer);
  922. if (pwocw)
  923. {
  924. mmr = ::waveOutGetDevCapsW(uDeviceId, pwocw, cbwoc);
  925. if (mmr == MMSYSERR_NOERROR)
  926. {
  927. *pwoc = *pwocw;
  928. }
  929. delete [] pBuffer;
  930. }
  931. else
  932. {
  933. mmr = MMSYSERR_ERROR;
  934. }
  935. }
  936. else
  937. {
  938. BYTE *pBuffer = new BYTE[sizeof(WAVEOUTCAPSA) + sizeof(DWORD)];
  939. WAVEOUTCAPSA *pwoca = reinterpret_cast<WAVEOUTCAPSA *>(pBuffer);
  940. if (pwoca)
  941. {
  942. mmr = ::waveOutGetDevCapsA(uDeviceId, pwoca, sizeof(*pwoca));
  943. if (mmr == MMSYSERR_NOERROR)
  944. {
  945. pwoc->wMid = pwoca->wMid;
  946. pwoc->wPid = pwoca->wPid;
  947. pwoc->vDriverVersion = pwoca->vDriverVersion;
  948. pwoc->dwFormats = pwoca->dwFormats;
  949. pwoc->wChannels = pwoca->wChannels;
  950. pwoc->wReserved1 = pwoca->wReserved1;
  951. pwoc->dwSupport = pwoca->dwSupport;
  952. ::MultiByteToWideChar(CP_ACP, 0, pwoca->szPname, -1, pwoc->szPname, sp_countof(pwoc->szPname));
  953. }
  954. else
  955. {
  956. mmr = MMSYSERR_ERROR;
  957. }
  958. }
  959. else
  960. {
  961. mmr = MMSYSERR_ERROR;
  962. }
  963. }
  964. return mmr;
  965. }
  966. MMRESULT waveInGetDevCaps(UINT uDeviceId, LPWAVEINCAPSW pwic, UINT cbwic) const
  967. {
  968. // Some drivers overwrite the WAVEINCAPS buffer by a DWORD
  969. MMRESULT mmr = MMSYSERR_NOERROR;
  970. if (UnicodeSystem())
  971. {
  972. BYTE *pBuffer = new BYTE[sizeof(WAVEINCAPSW) + sizeof(DWORD)];
  973. WAVEINCAPSW *pwicw = reinterpret_cast<WAVEINCAPSW *>(pBuffer);
  974. if (pwicw)
  975. {
  976. mmr = ::waveInGetDevCapsW(uDeviceId, pwicw, cbwic);
  977. if (mmr == MMSYSERR_NOERROR)
  978. {
  979. *pwic = *pwicw;
  980. }
  981. delete [] pBuffer;
  982. }
  983. else
  984. {
  985. mmr = MMSYSERR_ERROR;
  986. }
  987. }
  988. else
  989. {
  990. BYTE *pBuffer = new BYTE[sizeof(WAVEINCAPSA) + sizeof(DWORD)];
  991. WAVEINCAPSA *pwica = reinterpret_cast<WAVEINCAPSA *>(pBuffer);
  992. if (pwica)
  993. {
  994. mmr = ::waveInGetDevCapsA(uDeviceId, pwica, sizeof(*pwica));
  995. if (mmr == MMSYSERR_NOERROR)
  996. {
  997. pwic->wMid = pwica->wMid;
  998. pwic->wPid = pwica->wPid;
  999. pwic->vDriverVersion = pwica->vDriverVersion;
  1000. pwic->dwFormats = pwica->dwFormats;
  1001. pwic->wChannels = pwica->wChannels;
  1002. pwic->wReserved1 = pwica->wReserved1;
  1003. ::MultiByteToWideChar(CP_ACP, 0, pwica->szPname, -1, pwic->szPname, sp_countof(pwic->szPname));
  1004. }
  1005. delete [] pBuffer;
  1006. }
  1007. else
  1008. {
  1009. mmr = MMSYSERR_ERROR;
  1010. }
  1011. }
  1012. return mmr;
  1013. }
  1014. #endif // defined(mmioOpen)
  1015. };
  1016. #ifdef _UNICODE
  1017. typedef CSpUnicodeSupportT<TRUE> CSpUnicodeSupport;
  1018. #else
  1019. typedef CSpUnicodeSupportT<FALSE> CSpUnicodeSupport;
  1020. #endif
  1021. #else //_WIN32_WCE
  1022. class CSpUnicodeSupport
  1023. {
  1024. public:
  1025. HANDLE CreateFile(const WCHAR * lpFileName,
  1026. DWORD dwDesiredAccess,
  1027. DWORD dwShareMode,
  1028. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1029. DWORD dwCreationDisposition,
  1030. DWORD dwFlagsAndAttributes,
  1031. HANDLE hTemplateFile) const
  1032. {
  1033. return ::CreateFile(
  1034. lpFileName,
  1035. dwDesiredAccess,
  1036. dwShareMode,
  1037. lpSecurityAttributes,
  1038. dwCreationDisposition,
  1039. dwFlagsAndAttributes,
  1040. hTemplateFile);
  1041. }
  1042. HANDLE CreateFileForMapping(const WCHAR * lpFileName,
  1043. DWORD dwDesiredAccess,
  1044. DWORD dwShareMode,
  1045. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1046. DWORD dwCreationDisposition,
  1047. DWORD dwFlagsAndAttributes,
  1048. HANDLE hTemplateFile) const
  1049. {
  1050. return ::CreateFileForMappingW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
  1051. dwFlagsAndAttributes, hTemplateFile);
  1052. }
  1053. DWORD GetFullPathName(WCHAR *lpFileName, // file name
  1054. DWORD nBufferLength, // size of path buffer
  1055. WCHAR *lpBuffer, // path buffer
  1056. WCHAR **lpFilePart // address of file name in path
  1057. )
  1058. {
  1059. return ::GetFullPathName(lpFileName, nBufferLength, lpBuffer, lpFilePart);
  1060. }
  1061. BOOL DeleteFile(LPCWSTR lpFileName)
  1062. {
  1063. return ::DeleteFileW(lpFileName);
  1064. }
  1065. BOOL MoveFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  1066. {
  1067. return ::MoveFileW(lpExistingFileName, lpNewFileName);
  1068. }
  1069. BOOL CopyFile(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
  1070. {
  1071. return ::CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
  1072. }
  1073. BOOL CreateDirectory(const WCHAR * lpPathName,
  1074. LPSECURITY_ATTRIBUTES lpSecurityAttributes) const
  1075. {
  1076. return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
  1077. }
  1078. BOOL RemoveDirectory(const WCHAR * lpPathName) const
  1079. {
  1080. return ::RemoveDirectoryW(lpPathName);
  1081. }
  1082. HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect,
  1083. DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const WCHAR *lpName)
  1084. {
  1085. return ::CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh,
  1086. dwMaximumSizeLow, lpName);
  1087. }
  1088. BOOL SetFileAttributes(LPCWSTR lpFileName, DWORD dwFileAttributes)
  1089. {
  1090. return ::SetFileAttributesW(lpFileName, dwFileAttributes);
  1091. }
  1092. DWORD GetFileAttributes(LPCWSTR lpFileName)
  1093. {
  1094. return ::GetFileAttributesW(lpFileName);
  1095. }
  1096. LONG RegOpenKeyEx(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) const
  1097. {
  1098. #ifdef _WIN32_WCE_BUG_10655
  1099. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && phkResult;
  1100. LONG lRet = ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  1101. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1102. #else
  1103. return ::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  1104. #endif
  1105. }
  1106. LONG RegCreateKeyEx(HKEY hk, LPCWSTR lpSubKey, DWORD dwReserved, LPCWSTR lpClass, DWORD dwOptions,
  1107. REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
  1108. LPDWORD lpdwDisposition) const
  1109. {
  1110. return ::RegCreateKeyExW(hk, lpSubKey, dwReserved, (WCHAR *)lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  1111. }
  1112. LONG RegDeleteKey(HKEY hKey, LPCWSTR lpSubKey) const
  1113. {
  1114. #ifdef _WIN32_WCE_BUG_10655
  1115. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpSubKey;
  1116. LONG lRet = ::RegDeleteKeyW(hKey, lpSubKey);
  1117. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1118. #else
  1119. return ::RegDeleteKeyW(hKey, lpSubKey);
  1120. #endif
  1121. }
  1122. LONG RegDeleteValue(HKEY hKey, LPCWSTR lpSubKey) const
  1123. {
  1124. #ifdef _WIN32_WCE_BUG_10655
  1125. BOOL bValid = (hKey != INVALID_HANDLE_VALUE);
  1126. LONG lRet = ::RegDeleteValueW(hKey, lpSubKey);
  1127. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1128. #else
  1129. return ::RegDeleteValueW(hKey, lpSubKey);
  1130. #endif
  1131. }
  1132. LONG RegQueryValueEx(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) const
  1133. {
  1134. #ifdef _WIN32_WCE_BUG_10655
  1135. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && ((lpData && lpcbData) || (!lpData && !lpcbData));
  1136. LONG lRet = ::RegQueryValueExW(hKey, lpValueName, NULL, lpType, lpData, lpcbData);
  1137. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1138. #else
  1139. return ::RegQueryValueExW(hKey, lpValueName, NULL, lpType, lpData, lpcbData);
  1140. #endif
  1141. }
  1142. //
  1143. // NOTE: The size parameter is in CHARACTERS! Even though the registry API sizes are
  1144. // in bytes, this function uses character counts.
  1145. //
  1146. LONG RegQueryStringValue(HKEY hKey, LPCWSTR lpValueName, LPWSTR lpData, LPDWORD lpcchData) const
  1147. {
  1148. DWORD dwType;
  1149. *lpcchData *= sizeof(WCHAR);
  1150. #ifdef _WIN32_WCE_BUG_10655
  1151. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
  1152. #endif
  1153. LONG lRet = ::RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (BYTE *)lpData, lpcchData);
  1154. *lpcchData /= sizeof(WCHAR);
  1155. #ifdef _WIN32_WCE_BUG_10655
  1156. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1157. #else
  1158. return lRet;
  1159. #endif
  1160. }
  1161. //
  1162. // NOTES: Size is in bytes. Although this function uses RegEnumKeyEx, we chose to simply
  1163. // implement the ReqEnumKey functionality since the Ex functionality is not used
  1164. // by most programs (this saves a bunch of string conversion code).
  1165. //
  1166. LONG RegEnumKey(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcbName) const
  1167. {
  1168. #ifdef _WIN32_WCE_BUG_10655
  1169. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpName && lpcbName;
  1170. LONG lRet = ::RegEnumKeyExW(hKey, dwIndex, lpName, lpcbName, NULL, NULL, NULL, NULL);
  1171. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1172. #else
  1173. return ::RegEnumKeyExW(hKey, dwIndex, lpName, lpcbName, NULL, NULL, NULL, NULL);
  1174. #endif
  1175. }
  1176. //
  1177. // NOTES: Size is in Characters for lpcchName. Although this function uses RegEnumValue
  1178. // it will only return the names, not the data. cbValueName is the count of characters
  1179. //
  1180. LONG RegEnumValueName(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName) const
  1181. {
  1182. #ifdef _WIN32_WCE_BUG_10655
  1183. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpName && lpcchName;
  1184. LONG lRet = ::RegEnumValueW(hKey, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
  1185. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1186. #else
  1187. return ::RegEnumValueW(hKey, dwIndex, lpName, lpcchName, NULL, NULL, NULL, NULL);
  1188. #endif
  1189. }
  1190. LONG RegSetValueEx(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE * lpData, DWORD cbData) const
  1191. {
  1192. #ifdef _WIN32_WCE_BUG_10655
  1193. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
  1194. LONG lRet = ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
  1195. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1196. #else
  1197. return ::RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
  1198. #endif
  1199. }
  1200. LONG RegSetStringValue(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpData) const
  1201. {
  1202. DWORD dwSize = (wcslen(lpData)+1) * sizeof(WCHAR);
  1203. #ifdef _WIN32_WCE_BUG_10655
  1204. BOOL bValid = (hKey != INVALID_HANDLE_VALUE) && lpData;
  1205. LONG lRet = ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
  1206. return (lRet == ERROR_INVALID_PARAMETER && bValid)? ERROR_FILE_NOT_FOUND : lRet; //WCE bug
  1207. #else
  1208. return ::RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE *)lpData, dwSize);
  1209. #endif
  1210. }
  1211. HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) const
  1212. {
  1213. return ::CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
  1214. }
  1215. HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName) const
  1216. {
  1217. return ::CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
  1218. }
  1219. int LoadString(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBuffer) const
  1220. {
  1221. return ::LoadStringW(hInstance, uID, lpBuffer, nBuffer);
  1222. }
  1223. HMODULE LoadLibrary(LPCWSTR lpLibFileName)
  1224. {
  1225. return ::LoadLibraryW(lpLibFileName);
  1226. }
  1227. HMODULE LoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
  1228. {
  1229. return ::LoadLibraryExW(lpLibFileName, hFile, dwFlags);
  1230. }
  1231. HRSRC FindResource(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType)
  1232. {
  1233. return ::FindResource(hModule, lpName, lpType);
  1234. }
  1235. DWORD GetModuleFileName(HMODULE hModule, LPWSTR lpFileName, DWORD nSize) const
  1236. {
  1237. return ::GetModuleFileNameW(hModule, lpFileName, nSize);
  1238. }
  1239. // WCE does not support GetSystemDirectory
  1240. #if 0
  1241. UINT GetSystemDirectory( LPWSTR lpBuffer, UINT uSize )
  1242. {
  1243. return ::GetSystemDirectoryW( lpBuffer, uSize );
  1244. }
  1245. #endif
  1246. int CompareString(LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2)
  1247. {
  1248. return ::CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
  1249. }
  1250. BOOL SetWindowText( HWND hWnd, LPCWSTR lpString )
  1251. {
  1252. return ::SetWindowTextW( hWnd, lpString );
  1253. }
  1254. BOOL SetDlgItemText( HWND hDlg, int nIDDlgItem, LPCWSTR lpString )
  1255. {
  1256. return ::SetDlgItemTextW( hDlg, nIDDlgItem, lpString );
  1257. }
  1258. int MessageBox( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType )
  1259. {
  1260. return ::MessageBoxW( hWnd, lpText, lpCaption, uType );
  1261. }
  1262. int GetLocaleInfo( LCID Locale, LCTYPE LCType, LPWSTR lpLCData, int cchData )
  1263. {
  1264. return ::GetLocaleInfoW( Locale, LCType, lpLCData, cchData );
  1265. }
  1266. int GetTimeFormat( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime )
  1267. {
  1268. return ::GetTimeFormatW( Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime );
  1269. }
  1270. int GetNumberFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW *lpFormat,
  1271. LPWSTR lpNumberStr, int cchNumber )
  1272. {
  1273. return ::GetNumberFormatW( Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber );
  1274. int GetCurrencyFormat( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST CURRENCYFMTW *lpFormat,
  1275. LPWSTR lpCurrencyStr, int cchCurrency )
  1276. {
  1277. return ::GetCurrencyFormatW( Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency );
  1278. }
  1279. LONG_PTR GetWindowLongPtr( HWND hWnd, int nIndex )
  1280. {
  1281. return ::GetWindowLongPtr( hWnd, nIndex );
  1282. }
  1283. LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
  1284. {
  1285. return ::SetWindowLongPtr( hWnd, nIndex, dwNewLong );
  1286. }
  1287. INT_PTR DialogBoxParamCE( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam )
  1288. {
  1289. return ::DialogBoxParamW( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam );
  1290. }
  1291. LRESULT SendDlgItemMessage(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam )
  1292. {
  1293. return ::SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam );
  1294. }
  1295. #ifdef __HTMLHELP_H__
  1296. HWND WINAPI HtmlHelp( HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData )
  1297. {
  1298. return HtmlHelpW( hwndCaller, pszFile, uCommand, dwData );
  1299. }
  1300. #endif // __HTMLHELP_H__
  1301. HMMIO mmioOpen(LPCWSTR szFileName, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags) const
  1302. {
  1303. return ::mmioOpenW((WCHAR *)szFileName, lpmmioinfo, dwOpenFlags);
  1304. }
  1305. MMRESULT waveOutGetDevCaps(UINT uDeviceId, LPWAVEOUTCAPS pwoc, UINT cbwoc) const
  1306. {
  1307. return ::waveOutGetDevCaps(uDeviceId, pwoc, cbwoc);
  1308. }
  1309. MMRESULT waveInGetDevCaps(UINT uDeviceId, LPWAVEINCAPS pwic, UINT cbwic) const
  1310. {
  1311. return ::waveInGetDevCaps(uDeviceId, pwic, cbwic);
  1312. }
  1313. };
  1314. #endif
  1315. //
  1316. // Assume a global named g_Unicode
  1317. //
  1318. extern CSpUnicodeSupport g_Unicode;
  1319. #endif // Must be the last line of file. (#ifdef __SPUNICODE_H__)