Source code of Windows XP (NT5)
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.

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