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.

9384 lines
252 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation, 1994-1995
  4. //
  5. // File: unicwrap.cpp
  6. //
  7. // Contents: Wrappers for all Unicode functions used in MSHTML.
  8. // Any Unicode parameters/structure fields/buffers are converted
  9. // to ANSI, and then the corresponding ANSI version of the function
  10. // is called.
  11. //
  12. //----------------------------------------------------------------------------
  13. // This file expects to be compiled UNICODE
  14. //----------------------------------------------------------------------------
  15. //
  16. // HOW TO WRITE A WRAPPER
  17. //
  18. //----------------------------------------------------------------------------
  19. //
  20. // Suppose you want to write a wrapper for CreateMutex.
  21. //
  22. // - Look up CreateMutex and see that it is a function in KERNEL32.DLL.
  23. // If your function is in some other DLL, make the appropriate changes
  24. // to the instructions below.
  25. //
  26. // - Write a wrapper for your function, wrapped inside the appropriate
  27. // #ifdef for the DLL being wrapped.
  28. //
  29. // #ifdef NEED_KERNEL32_WRAPPER
  30. // STDAPI_(HANDLE) WINAPI
  31. // CreateMutexWrapW(...)
  32. // {
  33. // VALIDATE_PROTOTYPE(CreateMutex);
  34. // blahblahblah
  35. // }
  36. // #endif // NEED_KERNEL32_WRAPPER
  37. //
  38. // - If your wrapped function is in a DLL other than KERNEL32,
  39. // USER32, GDI32, or ADVAPI32, then you need to write a delay-load
  40. // stub in dllload.c.
  41. //
  42. // Furthermore, if the delay-load stub uses DELAY_MAP instead of
  43. // DELAY_LOAD (SHELL32, WINMM, COMDLG32), then the line
  44. //
  45. // VALIDATE_PROTOTYPE(WrappedFunction)
  46. //
  47. // needs to be changed to
  48. //
  49. // VALIDATE_PROTOTYPE_DELAYLOAD(WrappedFunction, _WrappedFunction)
  50. //
  51. // - Add a line for your function to thunk.h. In our case, we would
  52. // look for the #ifndef NEED_KERNEL32_WRAPPER section and add the
  53. // line
  54. //
  55. // #define CreateMutexWrapW CreateMutexW
  56. //
  57. // (This prevents shlwapi from trying to call a nonexistent wrapper.)
  58. //
  59. // - Add a line for your function to shlwapi.src.
  60. //
  61. // KERNEL32_WRAP(CreateMutexW) @nnn NONAME PRIVATE
  62. //
  63. // - If your wrapper is high-frequency, you may want to use
  64. // FORWARD_AW or THUNK_AW to make it faster on NT.
  65. //
  66. //----------------------------------------------------------------------------
  67. // WARNING: if you add a new call to FORWARD_AW or THUNK_AW (or modify the
  68. // macros), make sure you build this file on both x86 and non-x86 (or
  69. // alternately, build w/ PERF_ASM=0 on x86) to make sure there are no
  70. // syntax errors. the macros are *very* different between x86 and non-x86,
  71. // so successful compilation on one platform in no way guarantees success
  72. // on the other. i speak from experience, not theory...
  73. #include "priv.h"
  74. #define _SHELL32_
  75. #define _SHDOCVW_
  76. #include <shellapi.h>
  77. #include <commctrl.h> // for treeview
  78. #include "unicwrap.h"
  79. #include <wininet.h> // INTERNET_MAX_URL_LENGTH
  80. #include <winnetp.h>
  81. #include "mlui.h"
  82. #include <platform.h>
  83. #include "apithk.h"
  84. #define DM_PERF 0 // perf stats
  85. #ifndef ANSI_SHELL32_ON_UNIX
  86. #define UseUnicodeShell32() ( g_bRunningOnNT )
  87. #else
  88. #define UseUnicodeShell32() ( FALSE )
  89. #endif
  90. //
  91. // Do this in every wrapper function to make sure the wrapper
  92. // prototype matches the function it is intending to replace.
  93. //
  94. #define VALIDATE_PROTOTYPE(f) if (f##W == f##WrapW) 0
  95. #define VALIDATE_PROTOTYPEA(f) if (f##A == f##WrapA) 0
  96. #define VALIDATE_PROTOTYPEX(f) if (f == f##Wrap) 0
  97. #define VALIDATE_PROTOTYPE_DELAYLOAD(fWrap, fDelay) if (fDelay##W == fWrap##WrapW) 0
  98. #define VALIDATE_PROTOTYPE_DELAYLOADX(fWrap, fDelay) if (fDelay == fWrap##Wrap) 0
  99. #define VALIDATE_PROTOTYPE_NO_W(f) if (f## == f##Wrap) 0
  100. //
  101. // Do this in every wrapper function that has an output parameter.
  102. // It raises assertion failures on the main code path so that
  103. // the same assertions are raised on NT and 95. The CStrOut class
  104. // doesn't like it when you say that an output buffer is NULL yet
  105. // has nonzero length. Without this macro, the bug would go undetected
  106. // on NT and appear only on Win95.
  107. //
  108. // FEATURE raymondc - Turn this on after fixing all the RIPs it catches
  109. // (otherwise we assert too much)
  110. #if 0
  111. #define VALIDATE_OUTBUF(s, cch) ASSERT((s) != NULL || (cch) == 0)
  112. #else
  113. #define VALIDATE_OUTBUF(s, cch)
  114. #endif
  115. // compiler should do this opt for us (call-thunk => jmp), but it doesn't
  116. // so we do it ourselves (i raided it and they're adding it to vc6.x so
  117. // hopefully we'll get it someday)
  118. #if _X86_
  119. #define PERF_ASM 1 // turn on inline-asm opts
  120. #endif
  121. // todo??? #ifdef SUNDOWN #undef PERF_ASM
  122. #if PERF_ASM // {
  123. // APPCOMPAT workaround compiler bug
  124. // compiler should know this, but doesn't, so we make it explicit
  125. #define IMPORT_PTR dword ptr // doesn't work for sundown
  126. //*** FORWARD_AW, THUNK_AW -- simple forwarders and thunks
  127. // ENTRY/EXIT
  128. // - declare function w/ FORWARD_API
  129. // - if you're using THUNK_AW, create the 'A' thunk helper
  130. // - make the body FORWARD_AW or THUNK_AW.
  131. // - make sure there's *no* other code in the func. o.w. you'll get bogus
  132. // code.
  133. // EXAMPLE
  134. // int FORWARD_API WINAPI FooWrapW(int i, void *p)
  135. // {
  136. // VALIDATE_PROTOTYPE(Foo);
  137. //
  138. // FORWARD_AW(Foo, (i, p));
  139. // }
  140. //
  141. // int WINAPI BarAThunk(HWND hwnd, WPARAM wParam)
  142. // {
  143. // ... ansi thunk helper ...
  144. // }
  145. //
  146. // int FORWARD_API WINAPI BarWrapW(HWND hwnd, WPARAM wParam)
  147. // {
  148. // VALIDATE_PROTOTYPE(Bar);
  149. //
  150. // THUNK_AW(Bar, (hwnd, wParam));
  151. // }
  152. // NOTES
  153. // - WARNING: can only be used for 'simple' thunks (NAKED => no non-global
  154. // vars, etc.).
  155. // - WARNING: calling func must be declared FORWARD_API. if not you'll
  156. // get bogus code. happily if you forget you get the (obscure) error
  157. // message "error C4035: 'FooW': no return value"
  158. // - note that the macro ends up w/ an extra ";" from the caller, oh well...
  159. // - TODO: perf: better still would be to have a g_pfnCallWndProc, init
  160. // it 1x, and then jmp indirect w/o the test. it would cost us a ptr but
  161. // we only do it for the top-2 funcs (CallWindowProc and SendMessage)
  162. #define FORWARD_API _declspec(naked)
  163. #define FORWARD_AW(_fn, _args) \
  164. if (g_bRunningOnNT) { \
  165. _asm { jmp IMPORT_PTR _fn##W } \
  166. } \
  167. _asm { jmp IMPORT_PTR _fn##A }
  168. #define THUNK_AW(_fn, _args) \
  169. if (g_bRunningOnNT) { \
  170. _asm { jmp IMPORT_PTR _fn##W } \
  171. } \
  172. _asm { jmp _fn##AThunk } // n.b. no IMPORT_PTR
  173. #else // }{
  174. #define FORWARD_API /*NOTHING*/
  175. #define FORWARD_AW(_fn, _args) \
  176. if (g_bRunningOnNT) { \
  177. return _fn##W _args; \
  178. } \
  179. return _fn##A _args;
  180. #define THUNK_AW(_fn, _args) \
  181. if (g_bRunningOnNT) { \
  182. return _fn##W _args; \
  183. } \
  184. return _fn##AThunk _args;
  185. #endif // }
  186. //
  187. // Windows 95 and NT5 do not have the hbmpItem field in their MENUITEMINFO
  188. // structure.
  189. //
  190. #if (_WIN32_WINNT >= 0x0500)
  191. #define MENUITEMINFOSIZE_WIN95 FIELD_OFFSET(MENUITEMINFOW, hbmpItem)
  192. #else
  193. #define MENUITEMINFOSIZE_WIN95 sizeof(MENUITEMINFOW)
  194. #endif
  195. //
  196. // FEATURE - Undefine functions that are defined in thunk.h
  197. // These are duplicates of functions defined here
  198. // and should be deleted from thunk.c.
  199. #undef RegSetValueExW
  200. #undef CompareStringW
  201. #undef GetFileAttributesW
  202. #undef GetFullPathNameW
  203. #undef SearchPathW
  204. #undef GetWindowsDirectoryW
  205. #undef GetSystemDirectoryW
  206. #undef GetEnvironmentVariableW
  207. // Undefine mappings
  208. #undef CharLowerW
  209. //
  210. // FEATURE - There are numerous registry functions that are duplicated
  211. // here and in reg.c
  212. //
  213. //
  214. // Some W functions are implemented on Win95, so complain if anybody
  215. // writes thunks for them.
  216. //
  217. // Though Win95's implementation of TextOutW is incomplete for FE languages.
  218. // Remove this section when we implement FE-aware TextOutW for Win95.
  219. //
  220. #if defined(TextOutWrap)
  221. #error Do not write thunks for TextOutW; Win95 supports it.
  222. #endif
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Member: CConvertStr::Free
  226. //
  227. // Synopsis: Frees string if alloc'd and initializes to NULL.
  228. //
  229. //----------------------------------------------------------------------------
  230. void
  231. CConvertStr::Free()
  232. {
  233. if (_pstr != _ach && HIWORD64(_pstr) != 0 && !IsAtom())
  234. {
  235. delete [] _pstr;
  236. }
  237. _pstr = NULL;
  238. }
  239. //+---------------------------------------------------------------------------
  240. //
  241. // Member: CConvertStrW::Free
  242. //
  243. // Synopsis: Frees string if alloc'd and initializes to NULL.
  244. //
  245. //----------------------------------------------------------------------------
  246. void
  247. CConvertStrW::Free()
  248. {
  249. if (_pwstr != _awch && HIWORD64(_pwstr) != 0)
  250. {
  251. delete [] _pwstr;
  252. }
  253. _pwstr = NULL;
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Member: CStrInW::Init
  258. //
  259. // Synopsis: Converts a LPSTR function argument to a LPWSTR.
  260. //
  261. // Arguments: [pstr] -- The function argument. May be NULL or an atom
  262. // (HIWORD64(pwstr) == 0).
  263. //
  264. // [cch] -- The number of characters in the string to
  265. // convert. If -1, the string is assumed to be
  266. // NULL terminated and its length is calculated.
  267. //
  268. // Modifies: [this]
  269. //
  270. //----------------------------------------------------------------------------
  271. void
  272. CStrInW::Init(LPCSTR pstr, int cch)
  273. {
  274. int cchBufReq;
  275. _cwchLen = 0;
  276. // Check if string is NULL or an atom.
  277. if (HIWORD64(pstr) == 0)
  278. {
  279. _pwstr = (LPWSTR) pstr;
  280. return;
  281. }
  282. ASSERT(cch == -1 || cch > 0);
  283. //
  284. // Convert string to preallocated buffer, and return if successful.
  285. //
  286. // Since the passed in buffer may not be null terminated, we have
  287. // a problem if cch==ARRAYSIZE(_awch), because MultiByteToWideChar
  288. // will succeed, and we won't be able to null terminate the string!
  289. // Decrease our buffer by one for this case.
  290. //
  291. _cwchLen = MultiByteToWideChar(
  292. CP_ACP, 0, pstr, cch, _awch, ARRAYSIZE(_awch)-1);
  293. if (_cwchLen > 0)
  294. {
  295. // Some callers don't NULL terminate.
  296. //
  297. // We could check "if (-1 != cch)" before doing this,
  298. // but always doing the null is less code.
  299. //
  300. _awch[_cwchLen] = 0;
  301. if (0 == _awch[_cwchLen-1]) // account for terminator
  302. _cwchLen--;
  303. _pwstr = _awch;
  304. return;
  305. }
  306. //
  307. // Alloc space on heap for buffer.
  308. //
  309. cchBufReq = MultiByteToWideChar( CP_ACP, 0, pstr, cch, NULL, 0 );
  310. // Again, leave room for null termination
  311. cchBufReq++;
  312. ASSERT(cchBufReq > 0);
  313. _pwstr = new WCHAR[cchBufReq];
  314. if (!_pwstr)
  315. {
  316. // On failure, the argument will point to the empty string.
  317. _awch[0] = 0;
  318. _pwstr = _awch;
  319. return;
  320. }
  321. ASSERT(HIWORD64(_pwstr));
  322. _cwchLen = MultiByteToWideChar(
  323. CP_ACP, 0, pstr, cch, _pwstr, cchBufReq );
  324. #if DBG == 1 /* { */
  325. if (0 == _cwchLen)
  326. {
  327. int errcode = GetLastError();
  328. ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper.");
  329. }
  330. #endif /* } */
  331. // Again, make sure we're always null terminated
  332. ASSERT(_cwchLen < cchBufReq);
  333. _pwstr[_cwchLen] = 0;
  334. if (0 == _pwstr[_cwchLen-1]) // account for terminator
  335. _cwchLen--;
  336. }
  337. //+---------------------------------------------------------------------------
  338. //
  339. // Member: CStrIn::CStrIn
  340. //
  341. // Synopsis: Inits the class.
  342. //
  343. // NOTE: Don't inline this function or you'll increase code size
  344. // by pushing -1 on the stack for each call.
  345. //
  346. //----------------------------------------------------------------------------
  347. CStrIn::CStrIn(LPCWSTR pwstr) : CConvertStr(CP_ACP)
  348. {
  349. Init(pwstr, -1);
  350. }
  351. CStrIn::CStrIn(UINT uCP, LPCWSTR pwstr) : CConvertStr(uCP)
  352. {
  353. Init(pwstr, -1);
  354. }
  355. //+---------------------------------------------------------------------------
  356. //
  357. // Member: CStrIn::Init
  358. //
  359. // Synopsis: Converts a LPWSTR function argument to a LPSTR.
  360. //
  361. // Arguments: [pwstr] -- The function argument. May be NULL or an atom
  362. // (HIWORD(pwstr) == 0).
  363. //
  364. // [cwch] -- The number of characters in the string to
  365. // convert. If -1, the string is assumed to be
  366. // NULL terminated and its length is calculated.
  367. //
  368. // Modifies: [this]
  369. //
  370. // Note: We ignore AreFileApisANSI() and always use CP_ACP.
  371. // The reason is that nobody uses SetFileApisToOEM() except
  372. // console apps, and once you set file APIs to OEM, you
  373. // cannot call shell/user/gdi APIs, since they assume ANSI
  374. // regardless of the FileApis setting. So you end up in
  375. // this horrible messy state where the filename APIs interpret
  376. // the strings as OEM but SHELL32 interprets the strings
  377. // as ANSI and you end up with a big mess.
  378. //
  379. //----------------------------------------------------------------------------
  380. void
  381. CStrIn::Init(LPCWSTR pwstr, int cwch)
  382. {
  383. int cchBufReq;
  384. #if DBG == 1 /* { */
  385. int errcode;
  386. #endif /* } */
  387. _cchLen = 0;
  388. // Check if string is NULL or an atom.
  389. if (HIWORD64(pwstr) == 0 || IsAtom())
  390. {
  391. _pstr = (LPSTR) pwstr;
  392. return;
  393. }
  394. if ( cwch == 0 )
  395. {
  396. *_ach = '\0';
  397. _pstr = _ach;
  398. return;
  399. }
  400. //
  401. // Convert string to preallocated buffer, and return if successful.
  402. //
  403. _cchLen = WideCharToMultiByte(
  404. _uCP, 0, pwstr, cwch, _ach, ARRAYSIZE(_ach)-1, NULL, NULL);
  405. if (_cchLen > 0)
  406. {
  407. // This is DBCS safe since byte before _cchLen is last character
  408. _ach[_cchLen] = 0;
  409. // this may not be safe if the last character
  410. // was a multibyte character...
  411. if (_ach[_cchLen-1]==0)
  412. _cchLen--; // account for terminator
  413. _pstr = _ach;
  414. return;
  415. }
  416. cchBufReq = WideCharToMultiByte(
  417. CP_ACP, 0, pwstr, cwch, NULL, 0, NULL, NULL);
  418. cchBufReq++;
  419. ASSERT(cchBufReq > 0);
  420. _pstr = new char[cchBufReq];
  421. if (!_pstr)
  422. {
  423. // On failure, the argument will point to the empty string.
  424. _ach[0] = 0;
  425. _pstr = _ach;
  426. return;
  427. }
  428. ASSERT(HIWORD64(_pstr));
  429. _cchLen = WideCharToMultiByte(
  430. _uCP, 0, pwstr, cwch, _pstr, cchBufReq, NULL, NULL);
  431. #if DBG == 1 /* { */
  432. if (_cchLen < 0)
  433. {
  434. errcode = GetLastError();
  435. ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper.");
  436. }
  437. #endif /* } */
  438. // Again, make sure we're always null terminated
  439. ASSERT(_cchLen < cchBufReq);
  440. _pstr[_cchLen] = 0;
  441. if (0 == _pstr[_cchLen-1]) // account for terminator
  442. _cchLen--;
  443. }
  444. //+---------------------------------------------------------------------------
  445. //
  446. // Member: CStrInMulti::CStrInMulti
  447. //
  448. // Synopsis: Converts mulitple LPWSTRs to a multiple LPSTRs.
  449. //
  450. // Arguments: [pwstr] -- The strings to convert.
  451. //
  452. // Modifies: [this]
  453. //
  454. //----------------------------------------------------------------------------
  455. CStrInMulti::CStrInMulti(LPCWSTR pwstr)
  456. {
  457. LPCWSTR pwstrT;
  458. // We don't handle atoms because we don't need to.
  459. ASSERT(HIWORD64(pwstr));
  460. //
  461. // Count number of characters to convert.
  462. //
  463. pwstrT = pwstr;
  464. if (pwstr)
  465. {
  466. do {
  467. while (*pwstrT++)
  468. ;
  469. } while (*pwstrT++);
  470. }
  471. Init(pwstr, (int)(pwstrT - pwstr));
  472. }
  473. //+---------------------------------------------------------------------------
  474. //
  475. // Member: CPPFIn::CPPFIn
  476. //
  477. // Synopsis: Inits the class. Truncates the filename to MAX_PATH
  478. // so Win9x DBCS won't fault. Win9x SBCS silently truncates
  479. // to MAX_PATH, so we're bug-for-bug compatible.
  480. //
  481. //----------------------------------------------------------------------------
  482. CPPFIn::CPPFIn(LPCWSTR pwstr)
  483. {
  484. SHUnicodeToAnsi(pwstr, _ach, ARRAYSIZE(_ach));
  485. }
  486. //+---------------------------------------------------------------------------
  487. //
  488. // Member: CStrOut::CStrOut
  489. //
  490. // Synopsis: Allocates enough space for an out buffer.
  491. //
  492. // Arguments: [pwstr] -- The Unicode buffer to convert to when destroyed.
  493. // May be NULL.
  494. //
  495. // [cwchBuf] -- The size of the buffer in characters.
  496. //
  497. // Modifies: [this].
  498. //
  499. //----------------------------------------------------------------------------
  500. CStrOut::CStrOut(LPWSTR pwstr, int cwchBuf) : CConvertStr(CP_ACP)
  501. {
  502. Init(pwstr, cwchBuf);
  503. }
  504. CStrOut::CStrOut(UINT uCP, LPWSTR pwstr, int cwchBuf) : CConvertStr(uCP)
  505. {
  506. Init(pwstr, cwchBuf);
  507. }
  508. void
  509. CStrOut::Init(LPWSTR pwstr, int cwchBuf)
  510. {
  511. ASSERT(cwchBuf >= 0);
  512. _pwstr = pwstr;
  513. _cwchBuf = cwchBuf;
  514. if (!pwstr)
  515. {
  516. // Force cwchBuf = 0 because many callers (in particular, registry
  517. // munging functions) pass garbage as the length because they know
  518. // it will be ignored.
  519. _cwchBuf = 0;
  520. _pstr = NULL;
  521. return;
  522. }
  523. ASSERT(HIWORD64(pwstr));
  524. // Initialize buffer in case Windows API returns an error.
  525. _ach[0] = 0;
  526. // Use preallocated buffer if big enough.
  527. if (cwchBuf * 2 <= ARRAYSIZE(_ach))
  528. {
  529. _pstr = _ach;
  530. return;
  531. }
  532. // Allocate buffer.
  533. _pstr = new char[cwchBuf * 2];
  534. if (!_pstr)
  535. {
  536. //
  537. // On failure, the argument will point to a zero-sized buffer initialized
  538. // to the empty string. This should cause the Windows API to fail.
  539. //
  540. ASSERT(cwchBuf > 0);
  541. _pwstr[0] = 0;
  542. _cwchBuf = 0;
  543. _pstr = _ach;
  544. return;
  545. }
  546. ASSERT(HIWORD64(_pstr));
  547. _pstr[0] = 0;
  548. }
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Member: CStrOutW::CStrOutW
  552. //
  553. // Synopsis: Allocates enough space for an out buffer.
  554. //
  555. // Arguments: [pstr] -- The MBCS buffer to convert to when destroyed.
  556. // May be NULL.
  557. //
  558. // [cchBuf] -- The size of the buffer in characters.
  559. //
  560. // Modifies: [this].
  561. //
  562. //----------------------------------------------------------------------------
  563. CStrOutW::CStrOutW(LPSTR pstr, int cchBuf)
  564. {
  565. ASSERT(cchBuf >= 0);
  566. _pstr = pstr;
  567. _cchBuf = cchBuf;
  568. if (!pstr)
  569. {
  570. // Force cchBuf = 0 because many callers (in particular, registry
  571. // munging functions) pass garbage as the length because they know
  572. // it will be ignored.
  573. _cchBuf = 0;
  574. _pwstr = NULL;
  575. return;
  576. }
  577. ASSERT(HIWORD64(pstr));
  578. // Initialize buffer in case Windows API returns an error.
  579. _awch[0] = 0;
  580. // Use preallocated buffer if big enough.
  581. if (cchBuf <= ARRAYSIZE(_awch))
  582. {
  583. _pwstr = _awch;
  584. return;
  585. }
  586. // Allocate buffer.
  587. _pwstr = new WCHAR[cchBuf];
  588. if (!_pwstr)
  589. {
  590. //
  591. // On failure, the argument will point to a zero-sized buffer initialized
  592. // to the empty string. This should cause the Windows API to fail.
  593. //
  594. ASSERT(cchBuf > 0);
  595. _pstr[0] = 0;
  596. _cchBuf = 0;
  597. _pwstr = _awch;
  598. return;
  599. }
  600. ASSERT(HIWORD64(_pwstr));
  601. _pwstr[0] = 0;
  602. }
  603. //+---------------------------------------------------------------------------
  604. //
  605. // Member: CStrOut::ConvertIncludingNul
  606. //
  607. // Synopsis: Converts the buffer from MBCS to Unicode
  608. //
  609. // Return: Character count INCLUDING the trailing '\0'
  610. //
  611. //----------------------------------------------------------------------------
  612. int
  613. CStrOut::ConvertIncludingNul()
  614. {
  615. int cch;
  616. if (!_pstr)
  617. return 0;
  618. cch = SHAnsiToUnicodeCP(_uCP, _pstr, _pwstr, _cwchBuf);
  619. #if DBG == 1 /* { */
  620. if (cch == 0 && _cwchBuf > 0)
  621. {
  622. int errcode = GetLastError();
  623. ASSERT(0 && "SHAnsiToUnicode failed in unicode wrapper.");
  624. }
  625. #endif /* } */
  626. Free();
  627. return cch;
  628. }
  629. //+---------------------------------------------------------------------------
  630. //
  631. // Member: CStrOutW::ConvertIncludingNul
  632. //
  633. // Synopsis: Converts the buffer from Unicode to MBCS
  634. //
  635. // Return: Character count INCLUDING the trailing '\0'
  636. //
  637. //----------------------------------------------------------------------------
  638. int
  639. CStrOutW::ConvertIncludingNul()
  640. {
  641. int cch;
  642. if (!_pwstr)
  643. return 0;
  644. cch = SHUnicodeToAnsi(_pwstr, _pstr, _cchBuf);
  645. #if DBG == 1 /* { */
  646. if (cch == 0 && _cchBuf > 0)
  647. {
  648. int errcode = GetLastError();
  649. ASSERT(0 && "SHUnicodeToAnsi failed in unicode wrapper.");
  650. }
  651. #endif /* } */
  652. Free();
  653. return cch;
  654. }
  655. //+---------------------------------------------------------------------------
  656. //
  657. // Member: CStrOut::ConvertExcludingNul
  658. //
  659. // Synopsis: Converts the buffer from MBCS to Unicode
  660. //
  661. // Return: Character count EXCLUDING the trailing '\0'
  662. //
  663. //----------------------------------------------------------------------------
  664. int
  665. CStrOut::ConvertExcludingNul()
  666. {
  667. int ret = ConvertIncludingNul();
  668. if (ret > 0)
  669. {
  670. ret -= 1;
  671. }
  672. return ret;
  673. }
  674. //+---------------------------------------------------------------------------
  675. //
  676. // Member: CStrOut::~CStrOut
  677. //
  678. // Synopsis: Converts the buffer from MBCS to Unicode.
  679. //
  680. // Note: Don't inline this function, or you'll increase code size as
  681. // both ConvertIncludingNul() and CConvertStr::~CConvertStr will be
  682. // called inline.
  683. //
  684. //----------------------------------------------------------------------------
  685. CStrOut::~CStrOut()
  686. {
  687. ConvertIncludingNul();
  688. }
  689. //+---------------------------------------------------------------------------
  690. //
  691. // Member: CStrOutW::~CStrOutW
  692. //
  693. // Synopsis: Converts the buffer from Unicode to MBCS.
  694. //
  695. // Note: Don't inline this function, or you'll increase code size as
  696. // both ConvertIncludingNul() and CConvertStr::~CConvertStr will be
  697. // called inline.
  698. //
  699. //----------------------------------------------------------------------------
  700. CStrOutW::~CStrOutW()
  701. {
  702. ConvertIncludingNul();
  703. }
  704. #ifdef NEED_KERNEL32_WRAPPER
  705. //+---------------------------------------------------------------------------
  706. //
  707. // Class: CWin32FindDataInOut
  708. //
  709. // Purpose: Converts WIN32_FIND_DATA structures from UNICODE to ANSI
  710. // on the way in, then ANSI to UNICODE on the way out.
  711. //
  712. //----------------------------------------------------------------------------
  713. class CWin32FindDataInOut
  714. {
  715. public:
  716. operator LPWIN32_FIND_DATAA();
  717. CWin32FindDataInOut(LPWIN32_FIND_DATAW pfdW);
  718. ~CWin32FindDataInOut();
  719. protected:
  720. LPWIN32_FIND_DATAW _pfdW;
  721. WIN32_FIND_DATAA _fdA;
  722. };
  723. //+---------------------------------------------------------------------------
  724. //
  725. // Member: CWin32FindDataInOut::CWin32FindDataInOut
  726. //
  727. // Synopsis: Convert the non-string fields to ANSI. You'd think this
  728. // isn't necessary, but it is, because Win95 puts secret
  729. // goo into the dwReserved fields that must be preserved.
  730. //
  731. //----------------------------------------------------------------------------
  732. inline
  733. CWin32FindDataInOut::CWin32FindDataInOut(LPWIN32_FIND_DATAW pfdW) :
  734. _pfdW(pfdW)
  735. {
  736. memcpy(&_fdA, _pfdW, FIELD_OFFSET(WIN32_FIND_DATA, cFileName));
  737. _fdA.cFileName[0] = '\0';
  738. _fdA.cAlternateFileName[0] = '\0';
  739. }
  740. //+---------------------------------------------------------------------------
  741. //
  742. // Member: CWin32FindDataInOut::~CWin32FindDataInOut
  743. //
  744. // Synopsis: Convert all the fields from ANSI back to UNICODE.
  745. //
  746. //----------------------------------------------------------------------------
  747. inline
  748. CWin32FindDataInOut::~CWin32FindDataInOut()
  749. {
  750. memcpy(_pfdW, &_fdA, FIELD_OFFSET(WIN32_FIND_DATA, cFileName));
  751. SHAnsiToUnicode(_fdA.cFileName, _pfdW->cFileName, ARRAYSIZE(_pfdW->cFileName));
  752. SHAnsiToUnicode(_fdA.cAlternateFileName, _pfdW->cAlternateFileName, ARRAYSIZE(_pfdW->cAlternateFileName));
  753. }
  754. //+---------------------------------------------------------------------------
  755. //
  756. // Member: CWin32FindDataInOut::operator LPWIN32_FIND_DATAA
  757. //
  758. // Synopsis: Returns the WIN32_FIND_DATAA.
  759. //
  760. //----------------------------------------------------------------------------
  761. inline
  762. CWin32FindDataInOut::operator LPWIN32_FIND_DATAA()
  763. {
  764. return &_fdA;
  765. }
  766. #endif // NEED_KERNEL32_WRAPPER
  767. //+------------------------------------------------------------------------
  768. //
  769. // Implementation of the wrapped functions
  770. //
  771. //-------------------------------------------------------------------------
  772. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  773. BOOL WINAPI
  774. AppendMenuWrapW(
  775. HMENU hMenu,
  776. UINT uFlags,
  777. UINT_PTR uIDnewItem,
  778. LPCWSTR lpnewItem)
  779. {
  780. VALIDATE_PROTOTYPE(AppendMenu);
  781. // Make the InsertMenu wrapper do all the work
  782. return InsertMenuWrapW(hMenu, (UINT)-1,
  783. uFlags | MF_BYPOSITION, uIDnewItem, lpnewItem);
  784. }
  785. UINT GetLocaleAnsiCodePage(LCID Locale)
  786. {
  787. WCHAR szCodePage[7];
  788. UINT uiRetVal;
  789. if (0 != GetLocaleInfoWrapW(Locale, LOCALE_IDEFAULTANSICODEPAGE, szCodePage, ARRAYSIZE(szCodePage)))
  790. {
  791. uiRetVal = StrToInt(szCodePage);
  792. }
  793. else
  794. {
  795. uiRetVal = CP_ACP;
  796. }
  797. return uiRetVal;
  798. }
  799. #ifdef NEED_USER32_WRAPPER
  800. LRESULT FORWARD_API WINAPI
  801. CallWindowProcWrapW(
  802. WNDPROC lpPrevWndFunc,
  803. HWND hWnd,
  804. UINT Msg,
  805. WPARAM wParam,
  806. LPARAM lParam)
  807. {
  808. VALIDATE_PROTOTYPE(CallWindowProc);
  809. // perf: better still would be to have a g_pfnCallWndProc, init it 1x,
  810. // and then jmp indirect w/o the test. it would cost us a ptr but we
  811. // only do it for the top-2 funcs (CallWindowProc and SendMessage)
  812. FORWARD_AW(CallWindowProc, (lpPrevWndFunc, hWnd, Msg, wParam, lParam));
  813. }
  814. #endif // NEED_USER32_WRAPPER
  815. #ifdef NEED_USER32_WRAPPER
  816. STDAPI_(BOOL FORWARD_API) CallMsgFilterWrapW(LPMSG lpMsg, int nCode)
  817. {
  818. VALIDATE_PROTOTYPE(CallMsgFilter);
  819. FORWARD_AW(CallMsgFilter, (lpMsg, nCode));
  820. }
  821. #endif // NEED_USER32_WRAPPER
  822. //----------------------------------------------------------------------
  823. //
  824. // function: CharLowerWrapW( LPWSTR pch )
  825. //
  826. // purpose: Converts character to lowercase. Takes either a pointer
  827. // to a string, or a character masquerading as a pointer.
  828. // In the later case, the HIWORD must be zero. This is
  829. // as spec'd for Win32.
  830. //
  831. // returns: Lowercased character or string. In the string case,
  832. // the lowercasing is done inplace.
  833. //
  834. //----------------------------------------------------------------------
  835. #ifdef NEED_USER32_WRAPPER
  836. LPWSTR WINAPI
  837. CharLowerWrapW( LPWSTR pch )
  838. {
  839. VALIDATE_PROTOTYPE(CharLower);
  840. if (g_bRunningOnNT)
  841. {
  842. return CharLowerW( pch );
  843. }
  844. if (!HIWORD64(pch))
  845. {
  846. WCHAR ch = (WCHAR)(LONG_PTR)pch;
  847. CharLowerBuffWrapW( &ch, 1 );
  848. pch = (LPWSTR)MAKEINTATOM(ch);
  849. }
  850. else
  851. {
  852. CharLowerBuffWrapW( pch, lstrlenW(pch) );
  853. }
  854. return pch;
  855. }
  856. #endif // NEED_USER32_WRAPPER
  857. //----------------------------------------------------------------------
  858. //
  859. // function: CharLowerBuffWrapW( LPWSTR pch, DWORD cch )
  860. //
  861. // purpose: Converts a string to lowercase. String must be cch
  862. // characters in length.
  863. //
  864. // returns: Character count (cch). The lowercasing is done inplace.
  865. //
  866. //----------------------------------------------------------------------
  867. #ifdef NEED_USER32_WRAPPER
  868. DWORD WINAPI
  869. CharLowerBuffWrapW( LPWSTR pch, DWORD cchLength )
  870. {
  871. VALIDATE_PROTOTYPE(CharLowerBuff);
  872. if (g_bRunningOnNT)
  873. {
  874. return CharLowerBuffW( pch, cchLength );
  875. }
  876. DWORD cch;
  877. for ( cch = cchLength; cch-- ; pch++ )
  878. {
  879. WCHAR ch = *pch;
  880. if (IsCharUpperWrapW(ch))
  881. {
  882. if (ch < 0x0100)
  883. {
  884. *pch += 32; // Get Latin-1 out of the way first
  885. }
  886. else if (ch < 0x0531)
  887. {
  888. if (ch < 0x0391)
  889. {
  890. if (ch < 0x01cd)
  891. {
  892. if (ch <= 0x178)
  893. {
  894. if (ch < 0x0178)
  895. {
  896. *pch += (ch == 0x0130) ? 0 : 1;
  897. }
  898. else
  899. {
  900. *pch -= 121;
  901. }
  902. }
  903. else
  904. {
  905. static const BYTE abLookup[] =
  906. { // 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
  907. /* 0x0179-0x17f */ 1, 0, 1, 0, 1, 0, 0,
  908. /* 0x0180-0x187 */ 0, 210, 1, 0, 1, 0, 206, 1,
  909. /* 0x0188-0x18f */ 0, 205, 205, 1, 0, 0, 79, 202,
  910. /* 0x0190-0x197 */ 203, 1, 0, 205, 207, 0, 211, 209,
  911. /* 0x0198-0x19f */ 1, 0, 0, 0, 211, 213, 0, 214,
  912. /* 0x01a0-0x1a7 */ 1, 0, 1, 0, 1, 0, 0, 1,
  913. /* 0x01a8-0x1af */ 0, 218, 0, 0, 1, 0, 218, 1,
  914. /* 0x01b0-0x1b7 */ 0, 217, 217, 1, 0, 1, 0, 219,
  915. /* 0x01b8-0x1bf */ 1, 0, 0, 0, 1, 0, 0, 0,
  916. /* 0x01c0-0x1c7 */ 0, 0, 0, 0, 2, 0, 0, 2,
  917. /* 0x01c8-0x1cb */ 0, 0, 2, 0
  918. };
  919. *pch += abLookup[ch-0x0179];
  920. }
  921. }
  922. else if (ch < 0x0386)
  923. {
  924. switch (ch)
  925. {
  926. case 0x01f1: *pch += 2; break;
  927. case 0x01f2: break;
  928. default: *pch += 1;
  929. }
  930. }
  931. else
  932. {
  933. static const BYTE abLookup[] =
  934. { 38, 0, 37, 37, 37, 0, 64, 0, 63, 63 };
  935. *pch += abLookup[ch-0x0386];
  936. }
  937. }
  938. else
  939. {
  940. if (ch < 0x0410)
  941. {
  942. if (ch < 0x0401)
  943. {
  944. if (ch < 0x03e2)
  945. {
  946. if (!InRange(ch, 0x03d2, 0x03d4) &&
  947. !(InRange(ch, 0x3da, 0x03e0) & !(ch & 1)))
  948. {
  949. *pch += 32;
  950. }
  951. }
  952. else
  953. {
  954. *pch += 1;
  955. }
  956. }
  957. else
  958. {
  959. *pch += 80;
  960. }
  961. }
  962. else
  963. {
  964. if (ch < 0x0460)
  965. {
  966. *pch += 32;
  967. }
  968. else
  969. {
  970. *pch += 1;
  971. }
  972. }
  973. }
  974. }
  975. else
  976. {
  977. if (ch < 0x2160)
  978. {
  979. if (ch < 0x1fba)
  980. {
  981. if (ch < 0x1f08)
  982. {
  983. if (ch < 0x1e00)
  984. {
  985. *pch += 48;
  986. }
  987. else
  988. {
  989. *pch += 1;
  990. }
  991. }
  992. else if (!(InRange(ch, 0x1f88, 0x1faf) && (ch & 15)>7))
  993. {
  994. *pch -= 8;
  995. }
  996. }
  997. else
  998. {
  999. static const BYTE abLookup[] =
  1000. { // 8 9 a b c d e f
  1001. 0, 0, 74, 74, 0, 0, 0, 0,
  1002. 86, 86, 86, 86, 0, 0, 0, 0,
  1003. 8, 8, 100, 100, 0, 0, 0, 0,
  1004. 8, 8, 112, 112, 7, 0, 0, 0,
  1005. 128, 128, 126, 126, 0, 0, 0, 0
  1006. };
  1007. int i = (ch-0x1fb0);
  1008. *pch -= (int)abLookup[((i>>1) & ~7) | (i & 7)];
  1009. }
  1010. }
  1011. else
  1012. {
  1013. if (ch < 0xff21)
  1014. {
  1015. if (ch < 0x24b6)
  1016. {
  1017. *pch += 16;
  1018. }
  1019. else
  1020. {
  1021. *pch += 26;
  1022. }
  1023. }
  1024. else
  1025. {
  1026. *pch += 32;
  1027. }
  1028. }
  1029. }
  1030. }
  1031. else
  1032. {
  1033. // These are Unicode Number Forms. They have lowercase counter-
  1034. // parts, but are not considered uppercase. Why, I don't know.
  1035. if (InRange(ch, 0x2160, 0x216f))
  1036. {
  1037. *pch += 16;
  1038. }
  1039. }
  1040. }
  1041. return cchLength;
  1042. }
  1043. #endif // NEED_USER32_WRAPPER
  1044. //
  1045. // REARCHITECT - Do CharNextWrap and CharPrevWrap need to call the
  1046. // CharNextW, CharPrevW on WinNT? Couldn't these be MACROS?
  1047. //
  1048. LPWSTR WINAPI
  1049. CharNextWrapW(LPCWSTR lpszCurrent)
  1050. {
  1051. VALIDATE_PROTOTYPE(CharNext);
  1052. if (*lpszCurrent)
  1053. {
  1054. return (LPWSTR) lpszCurrent + 1;
  1055. }
  1056. else
  1057. {
  1058. return (LPWSTR) lpszCurrent;
  1059. }
  1060. }
  1061. LPWSTR WINAPI
  1062. CharPrevWrapW(LPCWSTR lpszStart, LPCWSTR lpszCurrent)
  1063. {
  1064. VALIDATE_PROTOTYPE(CharPrev);
  1065. if (lpszCurrent == lpszStart)
  1066. {
  1067. return (LPWSTR) lpszStart;
  1068. }
  1069. else
  1070. {
  1071. return (LPWSTR) lpszCurrent - 1;
  1072. }
  1073. }
  1074. #ifdef NEED_USER32_WRAPPER
  1075. BOOL WINAPI
  1076. CharToOemWrapW(LPCWSTR lpszSrc, LPSTR lpszDst)
  1077. {
  1078. VALIDATE_PROTOTYPE(CharToOem);
  1079. if (g_bRunningOnNT)
  1080. {
  1081. CharToOemW(lpszSrc, lpszDst);
  1082. }
  1083. CStrIn str(lpszSrc);
  1084. return CharToOemA(str, lpszDst);
  1085. }
  1086. #endif // NEED_USER32_WRAPPER
  1087. //----------------------------------------------------------------------
  1088. //
  1089. // function: CharUpperWrapW( LPWSTR pch )
  1090. //
  1091. // purpose: Converts character to uppercase. Takes either a pointer
  1092. // to a string, or a character masquerading as a pointer.
  1093. // In the later case, the HIWORD must be zero. This is
  1094. // as spec'd for Win32.
  1095. //
  1096. // returns: Uppercased character or string. In the string case,
  1097. // the uppercasing is done inplace.
  1098. //
  1099. //----------------------------------------------------------------------
  1100. #ifdef NEED_USER32_WRAPPER
  1101. LPWSTR WINAPI
  1102. CharUpperWrapW( LPWSTR pch )
  1103. {
  1104. VALIDATE_PROTOTYPE(CharUpper);
  1105. if (g_bRunningOnNT)
  1106. {
  1107. return CharUpperW( pch );
  1108. }
  1109. if (!HIWORD64(pch))
  1110. {
  1111. WCHAR ch = (WCHAR)(LONG_PTR)pch;
  1112. CharUpperBuffWrapW( &ch, 1 );
  1113. pch = (LPWSTR)MAKEINTATOM(ch);
  1114. }
  1115. else
  1116. {
  1117. CharUpperBuffWrapW( pch, lstrlenW(pch) );
  1118. }
  1119. return pch;
  1120. }
  1121. #endif // NEED_USER32_WRAPPER
  1122. //----------------------------------------------------------------------
  1123. //
  1124. // function: CharUpperBuffWrapW( LPWSTR pch, DWORD cch )
  1125. //
  1126. // purpose: Converts a string to uppercase. String must be cch
  1127. // characters in length. Note that this function is
  1128. // is messier that CharLowerBuffWrap, and the reason for
  1129. // this is many Unicode characters are considered uppercase,
  1130. // even when they don't have an uppercase counterpart.
  1131. //
  1132. // returns: Character count (cch). The uppercasing is done inplace.
  1133. //
  1134. //----------------------------------------------------------------------
  1135. #ifdef NEED_USER32_WRAPPER
  1136. DWORD WINAPI
  1137. CharUpperBuffWrapW( LPWSTR pch, DWORD cchLength )
  1138. {
  1139. VALIDATE_PROTOTYPE(CharUpperBuff);
  1140. if (g_bRunningOnNT)
  1141. {
  1142. return CharUpperBuffW( pch, cchLength );
  1143. }
  1144. DWORD cch;
  1145. for ( cch = cchLength; cch-- ; pch++ )
  1146. {
  1147. WCHAR ch = *pch;
  1148. if (IsCharLowerWrapW(ch))
  1149. {
  1150. if (ch < 0x00ff)
  1151. {
  1152. *pch -= ((ch != 0xdf) << 5);
  1153. }
  1154. else if (ch < 0x03b1)
  1155. {
  1156. if (ch < 0x01f5)
  1157. {
  1158. if (ch < 0x01ce)
  1159. {
  1160. if (ch < 0x017f)
  1161. {
  1162. if (ch < 0x0101)
  1163. {
  1164. *pch += 121;
  1165. }
  1166. else
  1167. {
  1168. *pch -= (ch != 0x0131 &&
  1169. ch != 0x0138 &&
  1170. ch != 0x0149);
  1171. }
  1172. }
  1173. else if (ch < 0x01c9)
  1174. {
  1175. static const BYTE abMask[] =
  1176. { // 6543210f edcba987
  1177. 0xfc, 0xbf, // 11111100 10111111
  1178. 0xbf, 0x67, // 10111111 01100111
  1179. 0xff, 0xef, // 11111111 11101111
  1180. 0xff, 0xf7, // 11111111 11110111
  1181. 0xbf, 0xfd // 10111111 11111101
  1182. };
  1183. int i = ch - 0x017f;
  1184. *pch -= ((abMask[i>>3] >> (i&7)) & 1) +
  1185. (ch == 0x01c6);
  1186. }
  1187. else
  1188. {
  1189. *pch -= ((ch != 0x01cb)<<1);
  1190. }
  1191. }
  1192. else
  1193. {
  1194. if (ch < 0x01df)
  1195. {
  1196. if (ch < 0x01dd)
  1197. {
  1198. *pch -= 1;
  1199. }
  1200. else
  1201. {
  1202. *pch -= 79;
  1203. }
  1204. }
  1205. else
  1206. {
  1207. *pch -= 1 + (ch == 0x01f3) -
  1208. InRange(ch,0x01f0,0x01f2);
  1209. }
  1210. }
  1211. }
  1212. else if (ch < 0x0253)
  1213. {
  1214. *pch -= (ch < 0x0250);
  1215. }
  1216. else if (ch < 0x03ac)
  1217. {
  1218. static const BYTE abLookup[] =
  1219. {// 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
  1220. /* 0x0253-0x0257 */ 210, 206, 0, 205, 205,
  1221. /* 0x0258-0x025f */ 0, 202, 0, 203, 0, 0, 0, 0,
  1222. /* 0x0260-0x0267 */ 205, 0, 0, 207, 0, 0, 0, 0,
  1223. /* 0x0268-0x026f */ 209, 211, 0, 0, 0, 0, 0, 211,
  1224. /* 0x0270-0x0277 */ 0, 0, 213, 0, 0, 214, 0, 0,
  1225. /* 0x0278-0x027f */ 0, 0, 0, 0, 0, 0, 0, 0,
  1226. /* 0x0280-0x0287 */ 0, 0, 0, 218, 0, 0, 0, 0,
  1227. /* 0x0288-0x028f */ 218, 0, 217, 217, 0, 0, 0, 0,
  1228. /* 0x0290-0x0297 */ 0, 0, 219
  1229. };
  1230. if (ch <= 0x0292)
  1231. {
  1232. *pch -= abLookup[ch - 0x0253];
  1233. }
  1234. }
  1235. else
  1236. {
  1237. *pch -= (ch == 0x03b0) ? 0 : (37 + (ch == 0x03ac));
  1238. }
  1239. }
  1240. else
  1241. {
  1242. if (ch < 0x0561)
  1243. {
  1244. if (ch < 0x0451)
  1245. {
  1246. if (ch < 0x03e3)
  1247. {
  1248. if (ch < 0x03cc)
  1249. {
  1250. *pch -= 32 - (ch == 0x03c2);
  1251. }
  1252. else
  1253. {
  1254. int i = (ch < 0x03d0);
  1255. *pch -= (i<<6) - i + (ch == 0x03cc);
  1256. }
  1257. }
  1258. else if (ch < 0x0430)
  1259. {
  1260. *pch -= (ch < 0x03f0);
  1261. }
  1262. else
  1263. {
  1264. *pch -= 32;
  1265. }
  1266. }
  1267. else if (ch < 0x0461)
  1268. {
  1269. *pch -= 80;
  1270. }
  1271. else
  1272. {
  1273. *pch -= 1;
  1274. }
  1275. }
  1276. else
  1277. {
  1278. if (ch < 0x1fb0)
  1279. {
  1280. if (ch < 0x1f70)
  1281. {
  1282. if (ch < 0x1e01)
  1283. {
  1284. int i = ch != 0x0587 && ch < 0x10d0;
  1285. *pch -= ((i<<5)+(i<<4)); /* 48 */
  1286. }
  1287. else if (ch < 0x1f00)
  1288. {
  1289. *pch -= !InRange(ch, 0x1e96, 0x1e9a);
  1290. }
  1291. else
  1292. {
  1293. int i = !InRange(ch, 0x1f50, 0x1f56)||(ch & 1);
  1294. *pch += (i<<3);
  1295. }
  1296. }
  1297. else
  1298. {
  1299. static const BYTE abLookup[] =
  1300. { 74, 86, 86, 100, 128, 112, 126 };
  1301. if ( ch <= 0x1f7d )
  1302. {
  1303. *pch += abLookup[(ch-0x1f70)>>1];
  1304. }
  1305. }
  1306. }
  1307. else
  1308. {
  1309. if (ch < 0x24d0)
  1310. {
  1311. if (ch < 0x1fe5)
  1312. {
  1313. *pch += (0x0023 & (1<<(ch&15))) ? 8 : 0;
  1314. }
  1315. else if (ch < 0x2170)
  1316. {
  1317. *pch += (0x0023 & (1<<(ch&15))) ? 7 : 0;
  1318. }
  1319. else
  1320. {
  1321. *pch -= ((ch > 0x24b5)<<4);
  1322. }
  1323. }
  1324. else if (ch < 0xff41)
  1325. {
  1326. int i = !InRange(ch, 0xfb00, 0xfb17);
  1327. *pch -= (i<<4)+(i<<3)+(i<<1); /* 26 */
  1328. }
  1329. else
  1330. {
  1331. *pch -= 32;
  1332. }
  1333. }
  1334. }
  1335. }
  1336. }
  1337. else
  1338. {
  1339. int i = InRange(ch, 0x2170, 0x217f);
  1340. *pch -= (i<<4);
  1341. }
  1342. }
  1343. return cchLength;
  1344. }
  1345. #endif // NEED_USER32_WRAPPER
  1346. #ifdef NEED_USER32_WRAPPER
  1347. int FORWARD_API WINAPI
  1348. CopyAcceleratorTableWrapW(
  1349. HACCEL hAccelSrc,
  1350. LPACCEL lpAccelDst,
  1351. int cAccelEntries)
  1352. {
  1353. VALIDATE_PROTOTYPE(CopyAcceleratorTable);
  1354. FORWARD_AW(CopyAcceleratorTable, (hAccelSrc, lpAccelDst, cAccelEntries));
  1355. }
  1356. #endif // NEED_USER32_WRAPPER
  1357. #ifdef NEED_USER32_WRAPPER
  1358. HACCEL FORWARD_API WINAPI
  1359. CreateAcceleratorTableWrapW(LPACCEL lpAccel, int cEntries)
  1360. {
  1361. VALIDATE_PROTOTYPE(CreateAcceleratorTable);
  1362. FORWARD_AW(CreateAcceleratorTable, (lpAccel, cEntries));
  1363. }
  1364. #endif // NEED_USER32_WRAPPER
  1365. #ifdef NEED_GDI32_WRAPPER
  1366. typedef HDC (*FnCreateHDCA)(LPCSTR, LPCSTR, LPCSTR, CONST DEVMODEA *);
  1367. HDC WINAPI
  1368. CreateHDCWrapW(
  1369. LPCWSTR lpszDriver,
  1370. LPCWSTR lpszDevice,
  1371. LPCWSTR lpszOutput,
  1372. CONST DEVMODEW * lpInitData,
  1373. FnCreateHDCA pfn)
  1374. {
  1375. DEVMODEA * pdevmode = NULL;
  1376. CStrIn strDriver(lpszDriver);
  1377. CStrIn strDevice(lpszDevice);
  1378. CStrIn strOutput(lpszOutput);
  1379. HDC hdcReturn = 0;
  1380. if (lpInitData)
  1381. {
  1382. pdevmode = (DEVMODEA *) LocalAlloc( LPTR, lpInitData->dmSize + lpInitData->dmDriverExtra );
  1383. if (pdevmode)
  1384. {
  1385. // LPBYTE->LPSTR casts below
  1386. SHUnicodeToAnsi(lpInitData->dmDeviceName, (LPSTR)pdevmode->dmDeviceName, ARRAYSIZE(pdevmode->dmDeviceName));
  1387. memcpy(&pdevmode->dmSpecVersion,
  1388. &lpInitData->dmSpecVersion,
  1389. FIELD_OFFSET(DEVMODEW,dmFormName) - FIELD_OFFSET(DEVMODEW,dmSpecVersion));
  1390. SHUnicodeToAnsi(lpInitData->dmFormName, (LPSTR)pdevmode->dmFormName, ARRAYSIZE(pdevmode->dmFormName));
  1391. memcpy(&pdevmode->dmLogPixels,
  1392. &lpInitData->dmLogPixels,
  1393. lpInitData->dmDriverExtra + lpInitData->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
  1394. pdevmode->dmSize -= (sizeof(BCHAR) - sizeof(char)) * (CCHDEVICENAME + CCHFORMNAME);
  1395. }
  1396. }
  1397. hdcReturn = (*pfn)(strDriver, strDevice, strOutput, pdevmode);
  1398. if (pdevmode)
  1399. {
  1400. LocalFree(pdevmode);
  1401. }
  1402. return hdcReturn;
  1403. }
  1404. #endif // NEED_GDI32_WRAPPER
  1405. #ifdef NEED_GDI32_WRAPPER
  1406. HDC WINAPI
  1407. CreateDCWrapW(
  1408. LPCWSTR lpszDriver,
  1409. LPCWSTR lpszDevice,
  1410. LPCWSTR lpszOutput,
  1411. CONST DEVMODEW * lpInitData)
  1412. {
  1413. VALIDATE_PROTOTYPE(CreateDC);
  1414. if (g_bRunningOnNT)
  1415. {
  1416. return CreateDCW(lpszDriver, lpszDevice, lpszOutput, lpInitData);
  1417. }
  1418. return CreateHDCWrapW(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateDCA);
  1419. }
  1420. #endif // NEED_GDI32_WRAPPER
  1421. #ifdef NEED_GDI32_WRAPPER
  1422. HDC WINAPI
  1423. CreateICWrapW(
  1424. LPCWSTR lpszDriver,
  1425. LPCWSTR lpszDevice,
  1426. LPCWSTR lpszOutput,
  1427. CONST DEVMODEW * lpInitData)
  1428. {
  1429. VALIDATE_PROTOTYPE(CreateIC);
  1430. if (g_bRunningOnNT)
  1431. {
  1432. return CreateICW(lpszDriver, lpszDevice, lpszOutput, lpInitData);
  1433. }
  1434. return CreateHDCWrapW(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateICA);
  1435. }
  1436. #endif // NEED_GDI32_WRAPPER
  1437. #undef CreateDialogIndirectParamW
  1438. HWND WINAPI
  1439. CreateDialogIndirectParamWrapW(
  1440. HINSTANCE hInstance,
  1441. LPCDLGTEMPLATEW hDialogTemplate,
  1442. HWND hWndParent,
  1443. DLGPROC lpDialogFunc,
  1444. LPARAM dwInitParam)
  1445. {
  1446. VALIDATE_PROTOTYPE(CreateDialogIndirectParam);
  1447. if (fDoMungeUI(hInstance))
  1448. {
  1449. return MLCreateDialogIndirectParamI(
  1450. hInstance,
  1451. hDialogTemplate,
  1452. hWndParent,
  1453. lpDialogFunc,
  1454. dwInitParam);
  1455. }
  1456. if (g_bRunningOnNT)
  1457. {
  1458. return CreateDialogIndirectParamW(
  1459. hInstance,
  1460. hDialogTemplate,
  1461. hWndParent,
  1462. lpDialogFunc,
  1463. dwInitParam);
  1464. }
  1465. return CreateDialogIndirectParamA(
  1466. hInstance,
  1467. hDialogTemplate,
  1468. hWndParent,
  1469. lpDialogFunc,
  1470. dwInitParam);
  1471. }
  1472. #undef CreateDialogParamW
  1473. HWND WINAPI
  1474. CreateDialogParamWrapW(
  1475. HINSTANCE hInstance,
  1476. LPCWSTR lpTemplateName,
  1477. HWND hWndParent,
  1478. DLGPROC lpDialogFunc,
  1479. LPARAM dwInitParam)
  1480. {
  1481. VALIDATE_PROTOTYPE(CreateDialogParam);
  1482. ASSERT(HIWORD64(lpTemplateName) == 0);
  1483. if (fDoMungeUI(hInstance))
  1484. return MLCreateDialogParamI(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
  1485. if (g_bRunningOnNT)
  1486. {
  1487. return CreateDialogParamW(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
  1488. }
  1489. return CreateDialogParamA(hInstance, (LPSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
  1490. }
  1491. #ifdef NEED_KERNEL32_WRAPPER
  1492. BOOL WINAPI
  1493. CreateDirectoryWrapW(
  1494. LPCWSTR lpPathName,
  1495. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  1496. {
  1497. VALIDATE_PROTOTYPE(CreateDirectory);
  1498. if (g_bRunningOnNT)
  1499. {
  1500. return CreateDirectoryW(lpPathName, lpSecurityAttributes);
  1501. }
  1502. CStrIn str(lpPathName);
  1503. ASSERT(!lpSecurityAttributes);
  1504. return CreateDirectoryA(str, lpSecurityAttributes);
  1505. }
  1506. #endif // NEED_KERNEL32_WRAPPER
  1507. #ifdef NEED_KERNEL32_WRAPPER
  1508. HANDLE WINAPI
  1509. CreateEventWrapW(
  1510. LPSECURITY_ATTRIBUTES lpEventAttributes,
  1511. BOOL bManualReset,
  1512. BOOL bInitialState,
  1513. LPCWSTR lpName)
  1514. {
  1515. VALIDATE_PROTOTYPE(CreateEvent);
  1516. //Totally bogus assert.
  1517. //ASSERT(!lpName);
  1518. // cast means we can't use FORWARD_AW
  1519. if (g_bRunningOnNT)
  1520. {
  1521. return CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
  1522. }
  1523. return CreateEventA(lpEventAttributes, bManualReset, bInitialState, (LPCSTR)lpName);
  1524. }
  1525. #endif // NEED_KERNEL32_WRAPPER
  1526. #ifdef NEED_KERNEL32_WRAPPER
  1527. HANDLE WINAPI
  1528. CreateFileWrapW(
  1529. LPCWSTR lpFileName,
  1530. DWORD dwDesiredAccess,
  1531. DWORD dwShareMode,
  1532. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1533. DWORD dwCreationDisposition,
  1534. DWORD dwFlagsAndAttributes,
  1535. HANDLE hTemplateFile)
  1536. {
  1537. VALIDATE_PROTOTYPE(CreateFile);
  1538. if (g_bRunningOnNT)
  1539. {
  1540. return CreateFileW(
  1541. lpFileName,
  1542. dwDesiredAccess,
  1543. dwShareMode,
  1544. lpSecurityAttributes,
  1545. dwCreationDisposition,
  1546. dwFlagsAndAttributes,
  1547. hTemplateFile);
  1548. }
  1549. CStrIn str(lpFileName);
  1550. return CreateFileA(
  1551. str,
  1552. dwDesiredAccess,
  1553. dwShareMode,
  1554. lpSecurityAttributes,
  1555. dwCreationDisposition,
  1556. dwFlagsAndAttributes,
  1557. hTemplateFile);
  1558. }
  1559. #endif // NEED_KERNEL32_WRAPPER
  1560. #ifdef NEED_GDI32_WRAPPER
  1561. HFONT WINAPI
  1562. CreateFontIndirectWrapW(CONST LOGFONTW * plfw)
  1563. {
  1564. VALIDATE_PROTOTYPE(CreateFontIndirect);
  1565. if (g_bRunningOnNT)
  1566. {
  1567. return CreateFontIndirectW(plfw);
  1568. }
  1569. LOGFONTA lfa;
  1570. HFONT hFont;
  1571. memcpy(&lfa, plfw, FIELD_OFFSET(LOGFONTA, lfFaceName));
  1572. SHUnicodeToAnsi(plfw->lfFaceName, lfa.lfFaceName, ARRAYSIZE(lfa.lfFaceName));
  1573. hFont = CreateFontIndirectA(&lfa);
  1574. return hFont;
  1575. }
  1576. #endif // NEED_GDI32_WRAPPER
  1577. #ifdef NEED_USER32_WRAPPER
  1578. HWND WINAPI
  1579. CreateWindowExWrapW(
  1580. DWORD dwExStyle,
  1581. LPCWSTR lpClassName,
  1582. LPCWSTR lpWindowName,
  1583. DWORD dwStyle,
  1584. int X,
  1585. int Y,
  1586. int nWidth,
  1587. int nHeight,
  1588. HWND hWndParent,
  1589. HMENU hMenu,
  1590. HINSTANCE hInstance,
  1591. LPVOID lpParam)
  1592. {
  1593. VALIDATE_PROTOTYPE(CreateWindowEx);
  1594. if (g_bRunningOnNT)
  1595. {
  1596. return CreateWindowExW(
  1597. dwExStyle,
  1598. lpClassName,
  1599. lpWindowName,
  1600. dwStyle,
  1601. X,
  1602. Y,
  1603. nWidth,
  1604. nHeight,
  1605. hWndParent,
  1606. hMenu,
  1607. hInstance,
  1608. lpParam);
  1609. }
  1610. CStrIn strClass(lpClassName);
  1611. CStrIn strWindow(lpWindowName);
  1612. return CreateWindowExA(
  1613. dwExStyle,
  1614. strClass,
  1615. strWindow,
  1616. dwStyle,
  1617. X,
  1618. Y,
  1619. nWidth,
  1620. nHeight,
  1621. hWndParent,
  1622. hMenu,
  1623. hInstance,
  1624. lpParam);
  1625. }
  1626. #endif // NEED_USER32_WRAPPER
  1627. #ifdef NEED_USER32_WRAPPER
  1628. LRESULT FORWARD_API WINAPI DefWindowProcWrapW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1629. {
  1630. VALIDATE_PROTOTYPE(DefWindowProc);
  1631. FORWARD_AW(DefWindowProc, (hWnd, msg, wParam, lParam));
  1632. }
  1633. #endif // NEED_USER32_WRAPPER
  1634. #ifdef NEED_KERNEL32_WRAPPER
  1635. BOOL WINAPI DeleteFileWrapW(LPCWSTR pwsz)
  1636. {
  1637. VALIDATE_PROTOTYPE(DeleteFile);
  1638. if (g_bRunningOnNT)
  1639. {
  1640. return DeleteFileW(pwsz);
  1641. }
  1642. CStrIn str(pwsz);
  1643. return DeleteFileA(str);
  1644. }
  1645. #endif // NEED_KERNEL32_WRAPPER
  1646. #undef DialogBoxIndirectParamW
  1647. INT_PTR WINAPI
  1648. DialogBoxIndirectParamWrapW(
  1649. HINSTANCE hInstance,
  1650. LPCDLGTEMPLATEW hDialogTemplate,
  1651. HWND hWndParent,
  1652. DLGPROC lpDialogFunc,
  1653. LPARAM dwInitParam)
  1654. {
  1655. VALIDATE_PROTOTYPE(DialogBoxIndirectParam);
  1656. if (fDoMungeUI(hInstance))
  1657. return MLDialogBoxIndirectParamI(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
  1658. if (g_bRunningOnNT)
  1659. {
  1660. return DialogBoxIndirectParamW(
  1661. hInstance,
  1662. hDialogTemplate,
  1663. hWndParent,
  1664. lpDialogFunc,
  1665. dwInitParam);
  1666. }
  1667. return DialogBoxIndirectParamA(
  1668. hInstance,
  1669. hDialogTemplate,
  1670. hWndParent,
  1671. lpDialogFunc,
  1672. dwInitParam);
  1673. }
  1674. #undef DialogBoxParamW
  1675. INT_PTR WINAPI
  1676. DialogBoxParamWrapW(
  1677. HINSTANCE hInstance,
  1678. LPCWSTR lpszTemplate,
  1679. HWND hWndParent,
  1680. DLGPROC lpDialogFunc,
  1681. LPARAM dwInitParam)
  1682. {
  1683. VALIDATE_PROTOTYPE(DialogBoxParam);
  1684. ASSERT(HIWORD64(lpszTemplate) == 0);
  1685. if (fDoMungeUI(hInstance))
  1686. return MLDialogBoxParamI(hInstance, lpszTemplate, hWndParent, lpDialogFunc, dwInitParam);
  1687. if (g_bRunningOnNT)
  1688. {
  1689. return DialogBoxParamW(
  1690. hInstance,
  1691. lpszTemplate,
  1692. hWndParent,
  1693. lpDialogFunc,
  1694. dwInitParam);
  1695. }
  1696. return DialogBoxParamA(hInstance, (LPCSTR) lpszTemplate, hWndParent, lpDialogFunc, dwInitParam);
  1697. }
  1698. #ifdef NEED_USER32_WRAPPER
  1699. LRESULT FORWARD_API WINAPI
  1700. DispatchMessageWrapW(CONST MSG * lpMsg)
  1701. {
  1702. VALIDATE_PROTOTYPE(DispatchMessage);
  1703. FORWARD_AW(DispatchMessage, (lpMsg));
  1704. }
  1705. #endif // NEED_USER32_WRAPPER
  1706. BOOL _MayNeedFontLinking(LPCWSTR lpStr, UINT cch)
  1707. {
  1708. #ifndef UNIX
  1709. //
  1710. // Scan the string to see if we might need to use font linking to draw it.
  1711. // If you've got a better way of doing this, I'd love to hear it.
  1712. //
  1713. BOOL fRet = FALSE;
  1714. int cChars = ((cch == -1) ? lstrlenW(lpStr) : cch);
  1715. for (int i=0; i < cChars; i++)
  1716. {
  1717. if (lpStr[i] > 127)
  1718. {
  1719. fRet = TRUE;
  1720. break;
  1721. }
  1722. }
  1723. return fRet;
  1724. #else
  1725. return FALSE;
  1726. #endif
  1727. }
  1728. #ifdef NEED_USER32_WRAPPER
  1729. int WINAPI
  1730. DrawTextWrapW(
  1731. HDC hDC,
  1732. LPCWSTR lpString,
  1733. int nCount,
  1734. LPRECT lpRect,
  1735. UINT uFormat)
  1736. {
  1737. VALIDATE_PROTOTYPE(DrawText);
  1738. if (_MayNeedFontLinking(lpString, nCount))
  1739. {
  1740. return DrawTextFLW(hDC, lpString, nCount, lpRect, uFormat);
  1741. }
  1742. else if (g_bRunningOnNT)
  1743. {
  1744. return DrawTextW(hDC, lpString, nCount, lpRect, uFormat);
  1745. }
  1746. CStrIn str(lpString, nCount);
  1747. return DrawTextA(hDC, str, str.strlen(), lpRect, uFormat);
  1748. }
  1749. #endif // NEED_USER32_WRAPPER
  1750. #ifdef NEED_GDI32_WRAPPER
  1751. struct EFFSTAT
  1752. {
  1753. LPARAM lParam;
  1754. FONTENUMPROC lpEnumFontProc;
  1755. BOOL fFamilySpecified;
  1756. };
  1757. int CALLBACK
  1758. EnumFontFamiliesCallbackWrap(
  1759. ENUMLOGFONTA * lpelf,
  1760. NEWTEXTMETRIC * lpntm,
  1761. DWORD FontType,
  1762. LPARAM lParam)
  1763. {
  1764. ENUMLOGFONTW elf;
  1765. // Convert strings from ANSI to Unicode
  1766. if (((EFFSTAT *)lParam)->fFamilySpecified && (FontType & TRUETYPE_FONTTYPE) )
  1767. {
  1768. // LPBYTE->LPCSTR cast below
  1769. SHAnsiToUnicode((LPCSTR)lpelf->elfFullName, elf.elfFullName, ARRAYSIZE(elf.elfFullName));
  1770. SHAnsiToUnicode((LPCSTR)lpelf->elfStyle, elf.elfStyle, ARRAYSIZE(elf.elfStyle));
  1771. }
  1772. else
  1773. {
  1774. elf.elfStyle[0] = L'\0';
  1775. elf.elfFullName[0] = L'\0';
  1776. }
  1777. SHAnsiToUnicode(lpelf->elfLogFont.lfFaceName, elf.elfLogFont.lfFaceName, ARRAYSIZE(elf.elfLogFont.lfFaceName));
  1778. // Copy the non-string data
  1779. memcpy(
  1780. &elf.elfLogFont,
  1781. &lpelf->elfLogFont,
  1782. FIELD_OFFSET(LOGFONTA, lfFaceName));
  1783. // Chain to the original callback function
  1784. return (*((EFFSTAT *) lParam)->lpEnumFontProc)(
  1785. (const LOGFONTW *)&elf,
  1786. (const TEXTMETRICW *) lpntm,
  1787. FontType,
  1788. ((EFFSTAT *) lParam)->lParam);
  1789. }
  1790. #endif // NEED_GDI32_WRAPPER
  1791. #ifdef NEED_GDI32_WRAPPER
  1792. int WINAPI
  1793. EnumFontFamiliesWrapW(
  1794. HDC hdc,
  1795. LPCWSTR lpszFamily,
  1796. FONTENUMPROC lpEnumFontProc,
  1797. LPARAM lParam)
  1798. {
  1799. VALIDATE_PROTOTYPE(EnumFontFamilies);
  1800. if (g_bRunningOnNT)
  1801. {
  1802. return EnumFontFamiliesW(
  1803. hdc,
  1804. lpszFamily,
  1805. lpEnumFontProc,
  1806. lParam);
  1807. }
  1808. CStrIn str(lpszFamily);
  1809. EFFSTAT effstat;
  1810. effstat.lParam = lParam;
  1811. effstat.lpEnumFontProc = lpEnumFontProc;
  1812. effstat.fFamilySpecified = lpszFamily != NULL;
  1813. return EnumFontFamiliesA(
  1814. hdc,
  1815. str,
  1816. (FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
  1817. (LPARAM) &effstat);
  1818. }
  1819. #endif // NEED_GDI32_WRAPPER
  1820. #ifdef NEED_GDI32_WRAPPER
  1821. int WINAPI
  1822. EnumFontFamiliesExWrapW(
  1823. HDC hdc,
  1824. LPLOGFONTW lplfw,
  1825. FONTENUMPROC lpEnumFontProc,
  1826. LPARAM lParam,
  1827. DWORD dwFlags )
  1828. {
  1829. VALIDATE_PROTOTYPE(EnumFontFamiliesEx);
  1830. if (g_bRunningOnNT)
  1831. {
  1832. return EnumFontFamiliesExW(
  1833. hdc,
  1834. lplfw,
  1835. lpEnumFontProc,
  1836. lParam,
  1837. dwFlags);
  1838. }
  1839. LOGFONTA lfa;
  1840. CStrIn str(lplfw->lfFaceName);
  1841. EFFSTAT effstat;
  1842. ASSERT( FIELD_OFFSET(LOGFONTW, lfFaceName) == FIELD_OFFSET(LOGFONTA, lfFaceName) );
  1843. memcpy( &lfa, lplfw, sizeof(LOGFONTA) - FIELD_OFFSET(LOGFONTA, lfFaceName) );
  1844. memcpy( lfa.lfFaceName, str, LF_FACESIZE );
  1845. lfa.lfFaceName[LF_FACESIZE - 1] = 0x00;
  1846. effstat.lParam = lParam;
  1847. effstat.lpEnumFontProc = lpEnumFontProc;
  1848. effstat.fFamilySpecified = lplfw->lfFaceName != NULL;
  1849. return EnumFontFamiliesExA(
  1850. hdc,
  1851. &lfa,
  1852. (FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
  1853. (LPARAM) &effstat,
  1854. dwFlags );
  1855. }
  1856. #endif // NEED_GDI32_WRAPPER
  1857. #ifdef NEED_KERNEL32_WRAPPER
  1858. BOOL WINAPI
  1859. EnumResourceNamesWrapW(
  1860. HINSTANCE hModule,
  1861. LPCWSTR lpType,
  1862. ENUMRESNAMEPROCW lpEnumFunc,
  1863. LPARAM lParam)
  1864. {
  1865. VALIDATE_PROTOTYPE(EnumResourceNames);
  1866. ASSERT(HIWORD64(lpType) == 0);
  1867. if (g_bRunningOnNT)
  1868. {
  1869. return EnumResourceNamesW(hModule, lpType, lpEnumFunc, lParam);
  1870. }
  1871. return EnumResourceNamesA(hModule, (LPCSTR) lpType, (ENUMRESNAMEPROCA)lpEnumFunc, lParam);
  1872. }
  1873. #endif // NEED_KERNEL32_WRAPPER
  1874. #ifdef NEED_KERNEL32_WRAPPER
  1875. HANDLE WINAPI
  1876. FindFirstFileWrapW(
  1877. LPCWSTR lpFileName,
  1878. LPWIN32_FIND_DATAW pwszFd)
  1879. {
  1880. VALIDATE_PROTOTYPE(FindFirstFile);
  1881. if (g_bRunningOnNT)
  1882. {
  1883. return FindFirstFileW(lpFileName, pwszFd);
  1884. }
  1885. CStrIn str(lpFileName);
  1886. CWin32FindDataInOut fd(pwszFd);
  1887. return FindFirstFileA(str, fd);
  1888. }
  1889. #endif // NEED_KERNEL32_WRAPPER
  1890. #ifdef NEED_KERNEL32_WRAPPER
  1891. HRSRC WINAPI
  1892. FindResourceWrapW(HINSTANCE hModule, LPCWSTR lpName, LPCWSTR lpType)
  1893. {
  1894. VALIDATE_PROTOTYPE(FindResource);
  1895. if (g_bRunningOnNT)
  1896. {
  1897. return FindResourceW(hModule, lpName, lpType);
  1898. }
  1899. // NOTE: The FindResourceW exists on Win9x, but Win95 and Win98
  1900. // have a bug where they make two bogus call to LocalFree to try
  1901. // to free up the passed-in buffers that they did not allocate.
  1902. //
  1903. // We work around by always wrapping. Another solution that Godot uses:
  1904. //
  1905. // For win95/98 only:
  1906. // 1) Copy the two params to stack-alloc'ed variables
  1907. // 2) Call the "W" function with the variables from step #1
  1908. // 3) Clear out last error when it is ERROR_INVALID_HANDLE (the error that the
  1909. // bogus LocalFree call in the OS will cause
  1910. // This gives proper Unicode behavior to both functions on all Win9x platforms.
  1911. CStrIn strName(lpName);
  1912. CStrIn strType(lpType);
  1913. return FindResourceA(hModule, strName, strType);
  1914. }
  1915. #endif // NEED_KERNEL32_WRAPPER
  1916. #ifdef NEED_USER32_WRAPPER
  1917. HWND WINAPI
  1918. FindWindowWrapW(LPCWSTR lpClassName, LPCWSTR lpWindowName)
  1919. {
  1920. VALIDATE_PROTOTYPE(FindWindow);
  1921. if (g_bRunningOnNT)
  1922. {
  1923. return FindWindowW(lpClassName, lpWindowName);
  1924. }
  1925. // Let FindWindowExWrapW do the thunking
  1926. return FindWindowExWrapW(NULL, NULL, lpClassName, lpWindowName);
  1927. }
  1928. #endif // NEED_USER32_WRAPPER
  1929. #ifdef NEED_USER32_WRAPPER
  1930. HWND WINAPI
  1931. FindWindowExWrapW(HWND hwndParent, HWND hwndChildAfter, LPCWSTR pwzClassName, LPCWSTR pwzWindowName)
  1932. {
  1933. VALIDATE_PROTOTYPE(FindWindowEx);
  1934. if (g_bRunningOnNT)
  1935. return FindWindowExW(hwndParent, hwndChildAfter, pwzClassName, pwzWindowName);
  1936. CStrIn strClass(pwzClassName);
  1937. CStrIn strWindow(pwzWindowName);
  1938. return FindWindowExA(hwndParent, hwndChildAfter, strClass, strWindow);
  1939. }
  1940. #endif // NEED_USER32_WRAPPER
  1941. #ifdef NEED_KERNEL32_WRAPPER
  1942. //
  1943. // FindNextArgInfo - Finds the argument format and argument number from a FormatMessage like template
  1944. //
  1945. // Returns - True if arg is wide string, False if other
  1946. //
  1947. BOOL FindNextArgInfo(LPCWSTR *pszTemplate, UINT *puiNum, LPWSTR pszFormat, UINT cchFormat)
  1948. {
  1949. BOOL fRet = FALSE;
  1950. if(*pszTemplate == NULL)
  1951. return(FALSE);
  1952. LPCWSTR psz = *pszTemplate;
  1953. LPCWSTR pszT1 = NULL;
  1954. LPCWSTR pszT2 = NULL;
  1955. LPWSTR pszFmt = pszFormat;
  1956. BOOL fHaveStart = FALSE;
  1957. UINT cchFmt;
  1958. *puiNum = 0;
  1959. if(cchFormat > 0)
  1960. {
  1961. *pszFmt = TEXT('%');
  1962. pszFmt++;
  1963. cchFormat--;
  1964. }
  1965. if(*psz >= TEXT('1') && *psz <= TEXT('9'))
  1966. {
  1967. for(; *psz; psz++)
  1968. {
  1969. if(*psz == TEXT('!'))
  1970. {
  1971. if(fHaveStart) // Done
  1972. {
  1973. pszT2 = ++psz; // Mark end of type
  1974. break;
  1975. }
  1976. else
  1977. {
  1978. fHaveStart = TRUE;
  1979. psz++;
  1980. if(pszT1 == NULL)
  1981. pszT1 = psz; // Mark start of arg format string
  1982. }
  1983. }
  1984. if(!fHaveStart) // Get arg number
  1985. {
  1986. if(*psz >= TEXT('0') && *psz <= TEXT('9'))
  1987. *puiNum = (*puiNum * 10) + (*psz - TEXT('0'));
  1988. else
  1989. break;
  1990. }
  1991. }
  1992. if(*puiNum == 0)
  1993. return(FALSE);
  1994. }
  1995. else // Special format specifier
  1996. {
  1997. pszT1 = psz;
  1998. pszT2 = psz+1;
  1999. }
  2000. if(pszT1 != NULL) // We have an arg format string
  2001. {
  2002. cchFmt = cchFormat;
  2003. if(cchFmt > (UINT)(pszT2 - pszT1))
  2004. cchFmt = (pszT2 - pszT1);
  2005. StrCpyN(pszFmt, pszT1, cchFmt);
  2006. // Is argument type a string
  2007. if(StrChrI(pszFormat, TEXT('s')))
  2008. {
  2009. fRet = TRUE;
  2010. }
  2011. else
  2012. {
  2013. cchFmt = cchFormat;
  2014. if(cchFmt > (UINT)(pszT2 - *pszTemplate)+1)
  2015. cchFmt = (pszT2 - *pszTemplate)+1;
  2016. StrCpyN(pszFmt, *pszTemplate, cchFmt);
  2017. }
  2018. }
  2019. else // No arg format string, FormatMessage default is !s!
  2020. {
  2021. pszT2 = psz;
  2022. fRet = TRUE;
  2023. cchFmt = cchFormat;
  2024. if(cchFmt > 3)
  2025. cchFmt = 3;
  2026. StrCpyN(pszFmt, TEXT("ws"), cchFmt);
  2027. }
  2028. *pszTemplate = pszT2; // Move template string beyond this format specifier
  2029. return(fRet);
  2030. }
  2031. //
  2032. // The following is used to work around Win9x FormatMessage problems related to converting
  2033. // DBCS strings to Unicode.
  2034. //
  2035. #define FML_BUFFER_SIZE 1024
  2036. #define FML_BUFFER_INC 256
  2037. DWORD
  2038. FormatMessageLiteW(
  2039. DWORD dwFlags,
  2040. LPCWSTR lpSource,
  2041. PVOID * pDest,
  2042. DWORD nSize,
  2043. va_list * Arguments)
  2044. {
  2045. BOOL fIsStr;
  2046. UINT uiNum;
  2047. UINT uiDataCnt = 0;
  2048. va_list pArgList = *Arguments;
  2049. va_list pArgList2;
  2050. WCHAR *pszBuf2;
  2051. WCHAR szFmt[256];
  2052. VOID *pData[10];
  2053. LPCWSTR psz = lpSource;
  2054. LPCWSTR psz1 = NULL;
  2055. LPWSTR lpBuffer;
  2056. INT cchBufUsed = 0;
  2057. INT cchBuf2;
  2058. INT cch;
  2059. if(lpSource == NULL || pDest == NULL || Arguments == NULL)
  2060. return(0);
  2061. if(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  2062. {
  2063. nSize = max(nSize, FML_BUFFER_SIZE);
  2064. if((lpBuffer = (WCHAR *)LocalAlloc(LPTR, nSize * sizeof(WCHAR))) == NULL)
  2065. return(0);
  2066. }
  2067. else
  2068. {
  2069. if(nSize == 0)
  2070. return(0);
  2071. lpBuffer = (LPWSTR)pDest;
  2072. }
  2073. cchBuf2 = nSize + lstrlen(lpSource);
  2074. if((pszBuf2 = (WCHAR *)LocalAlloc(LPTR, cchBuf2 * sizeof(WCHAR))) != NULL)
  2075. {
  2076. *lpBuffer = TEXT('\0');
  2077. while(*psz)
  2078. {
  2079. if(*psz == TEXT('%'))
  2080. {
  2081. psz++;
  2082. if(psz1 != NULL) // Copy any previous text to the buffer
  2083. {
  2084. if((cch = psz - psz1) > (INT)(nSize - cchBufUsed))
  2085. {
  2086. if(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  2087. {
  2088. LPWSTR lpRealloc;
  2089. nSize = max(FML_BUFFER_INC, cch);
  2090. if((lpRealloc = (WCHAR *)LocalReAlloc(lpBuffer, nSize * sizeof(WCHAR), LMEM_ZEROINIT | LMEM_MOVEABLE)) == NULL)
  2091. {
  2092. LocalFree(lpBuffer);
  2093. LocalFree(pszBuf2);
  2094. return(0);
  2095. }
  2096. lpBuffer = lpRealloc;
  2097. }
  2098. else
  2099. {
  2100. RIPMSG(FALSE, "Output buffer not large enough. Truncating.");
  2101. cch = nSize - cchBufUsed;
  2102. }
  2103. }
  2104. StrCpyNW(lpBuffer+cchBufUsed, psz1, cch);
  2105. cchBufUsed += cch-1;
  2106. psz1 = NULL;
  2107. }
  2108. fIsStr = FindNextArgInfo(&psz, &uiNum, szFmt, ARRAYSIZE(szFmt));
  2109. if(fIsStr)
  2110. {
  2111. if(uiNum > uiDataCnt)
  2112. {
  2113. for(UINT i = uiDataCnt; i < uiNum; i++) // Find the iTH argument
  2114. {
  2115. pData[i] = va_arg(pArgList, VOID *);
  2116. uiDataCnt++;
  2117. }
  2118. }
  2119. cch = wnsprintfW(pszBuf2, cchBuf2, szFmt, pData[uiNum-1]);
  2120. if(cch == cchBuf2)
  2121. {
  2122. RIPMSG(FALSE, "Param buffer may be too small. Output string may be truncated.");
  2123. }
  2124. }
  2125. else
  2126. {
  2127. // Call FormatMessage on non-string arguments
  2128. pArgList2 = *Arguments;
  2129. CStrIn strSource(CP_ACP, (LPCWSTR)szFmt, -1);
  2130. CStrOut str(pszBuf2, cchBuf2);
  2131. FormatMessageA(FORMAT_MESSAGE_FROM_STRING, strSource, 0, 0, str, str.BufSize(), &pArgList2);
  2132. cch = str.ConvertExcludingNul();
  2133. }
  2134. if(cch > 0)
  2135. {
  2136. if(cch > (INT)(nSize - cchBufUsed))
  2137. {
  2138. if(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  2139. {
  2140. LPWSTR lpRealloc;
  2141. nSize += max(FML_BUFFER_INC, cch);
  2142. if((lpRealloc = (WCHAR *)LocalReAlloc(lpBuffer, nSize * sizeof(WCHAR), LMEM_ZEROINIT | LMEM_MOVEABLE)) == NULL)
  2143. {
  2144. LocalFree(lpBuffer);
  2145. LocalFree(pszBuf2);
  2146. return(0);
  2147. }
  2148. lpBuffer = lpRealloc;
  2149. }
  2150. else
  2151. {
  2152. RIPMSG(FALSE, "Output buffer not large enough. Truncating.");
  2153. cch = nSize - cchBufUsed;
  2154. }
  2155. }
  2156. StrCpyW(lpBuffer+cchBufUsed, pszBuf2);
  2157. cchBufUsed += cch;
  2158. }
  2159. else
  2160. {
  2161. RIPMSG(FALSE, "Argument string conversion failed. Argument not copied to output buffer");
  2162. }
  2163. continue;
  2164. }
  2165. if(psz1 == NULL)
  2166. psz1 = psz; // Start of text block
  2167. psz++;
  2168. }
  2169. if(psz1) // Copy any remaining text to the output buffer
  2170. {
  2171. if((cch = (psz - psz1)+1) > (INT)(nSize - cchBufUsed))
  2172. {
  2173. if(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  2174. {
  2175. LPWSTR lpRealloc;
  2176. nSize = max(FML_BUFFER_INC, cch);
  2177. if((lpRealloc = (WCHAR *)LocalReAlloc(lpBuffer, nSize * sizeof(WCHAR), LMEM_ZEROINIT | LMEM_MOVEABLE)) == NULL)
  2178. {
  2179. LocalFree(lpBuffer);
  2180. LocalFree(pszBuf2);
  2181. return(0);
  2182. }
  2183. lpBuffer = lpRealloc;
  2184. }
  2185. else
  2186. {
  2187. RIPMSG(FALSE, "Output buffer not large enough. Truncating.");
  2188. cch = nSize - cchBufUsed;
  2189. }
  2190. }
  2191. StrCpyNW(lpBuffer+cchBufUsed, psz1, cch);
  2192. cchBufUsed += cch - 1; // substract the null from the count
  2193. }
  2194. LocalFree(pszBuf2);
  2195. pszBuf2 = NULL;
  2196. }
  2197. if(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  2198. {
  2199. *pDest = (PVOID *)lpBuffer;
  2200. }
  2201. return((DWORD)cchBufUsed);
  2202. }
  2203. DWORD WINAPI
  2204. FormatMessageWrapW(
  2205. DWORD dwFlags,
  2206. LPCVOID lpSource,
  2207. DWORD dwMessageId,
  2208. DWORD dwLanguageId,
  2209. LPWSTR lpBuffer,
  2210. DWORD nSize,
  2211. va_list * Arguments)
  2212. {
  2213. VALIDATE_PROTOTYPE(FormatMessage);
  2214. if (!(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER))
  2215. {
  2216. VALIDATE_OUTBUF(lpBuffer, nSize);
  2217. }
  2218. DWORD dwResult;
  2219. if (g_bRunningOnNT)
  2220. {
  2221. dwResult = FormatMessageW(
  2222. dwFlags,
  2223. lpSource,
  2224. dwMessageId,
  2225. dwLanguageId,
  2226. lpBuffer,
  2227. nSize,
  2228. Arguments);
  2229. }
  2230. else
  2231. {
  2232. #ifdef DEBUG
  2233. // If a source string is passed, make sure that all string insertions
  2234. // have explicit character set markers. Otherwise, you get random
  2235. // behavior depending on whether we need to thunk to ANSI or not.
  2236. // (We are not clever enough to thunk the inserts; that's the caller's
  2237. // responsibility.)
  2238. //
  2239. if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
  2240. {
  2241. LPCWSTR pwsz;
  2242. for (pwsz = (LPCWSTR)lpSource; *pwsz; pwsz++)
  2243. {
  2244. if (*pwsz == L'%')
  2245. {
  2246. pwsz++;
  2247. // Found an insertion. Get the digit or two.
  2248. if (*pwsz == L'0')
  2249. continue; // "%0" is special
  2250. if (*pwsz < L'0' || *pwsz > L'9')
  2251. continue; // skip % followed by nondigit
  2252. pwsz++; // Skip the digit
  2253. if (*pwsz >= L'0' && *pwsz <= L'9')
  2254. pwsz++; // Skip the optional second digit
  2255. // The next character MUST be an exclamation point!
  2256. ASSERT(*pwsz == L'!' &&
  2257. "FormatMessageWrapW: All string insertions must have explicit character sets.");
  2258. // I'm not going to validate that the insertion contains
  2259. // an explicit character set override because if you went
  2260. // so far as to do a %n!...!, you'll get the last bit right too.
  2261. }
  2262. }
  2263. }
  2264. #endif
  2265. //
  2266. // FORMAT_MESSAGE_FROM_STRING means that the source is a string.
  2267. // Otherwise, it's an opaque LPVOID (aka, an atom).
  2268. //
  2269. if(((dwFlags == FORMAT_MESSAGE_FROM_STRING) ||
  2270. (dwFlags == (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER))) &&
  2271. (dwMessageId == 0) && (dwLanguageId == 0))
  2272. {
  2273. TraceMsg(TF_WARNING, "This is a lite version of FormatMessage. It may not act as you expect.");
  2274. dwResult = FormatMessageLiteW(dwFlags, (LPCWSTR)lpSource, (PVOID *)lpBuffer, nSize, Arguments);
  2275. }
  2276. else
  2277. {
  2278. CStrIn strSource((dwFlags & FORMAT_MESSAGE_FROM_STRING) ? CP_ACP : CP_ATOM,
  2279. (LPCWSTR)lpSource, -1);
  2280. if (!(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER))
  2281. {
  2282. CStrOut str(lpBuffer, nSize);
  2283. FormatMessageA(
  2284. dwFlags,
  2285. strSource,
  2286. dwMessageId,
  2287. dwLanguageId,
  2288. str,
  2289. str.BufSize(),
  2290. Arguments); // We don't handle Arguments != NULL
  2291. dwResult = str.ConvertExcludingNul();
  2292. }
  2293. else
  2294. {
  2295. LPSTR pszBuffer = NULL;
  2296. LPWSTR * ppwzOut = (LPWSTR *)lpBuffer;
  2297. *ppwzOut = NULL;
  2298. FormatMessageA(
  2299. dwFlags,
  2300. strSource,
  2301. dwMessageId,
  2302. dwLanguageId,
  2303. (LPSTR)&pszBuffer,
  2304. 0,
  2305. Arguments);
  2306. if (pszBuffer)
  2307. {
  2308. DWORD cchSize = (lstrlenA(pszBuffer) + 1);
  2309. LPWSTR pszThunkedBuffer;
  2310. if (cchSize < nSize)
  2311. cchSize = nSize;
  2312. pszThunkedBuffer = (LPWSTR) LocalAlloc(LPTR, cchSize * sizeof(WCHAR));
  2313. if (pszThunkedBuffer)
  2314. {
  2315. *ppwzOut = pszThunkedBuffer;
  2316. SHAnsiToUnicode(pszBuffer, pszThunkedBuffer, cchSize);
  2317. }
  2318. LocalFree(pszBuffer);
  2319. }
  2320. dwResult = (*ppwzOut ? lstrlenW(*ppwzOut) : 0);
  2321. }
  2322. }
  2323. }
  2324. return dwResult;
  2325. }
  2326. #endif // NEED_KERNEL32_WRAPPER
  2327. #ifdef NEED_USER32_WRAPPER
  2328. BOOL WINAPI
  2329. GetClassInfoWrapW(HINSTANCE hModule, LPCWSTR lpClassName, LPWNDCLASSW lpWndClassW)
  2330. {
  2331. VALIDATE_PROTOTYPE(GetClassInfo);
  2332. if (g_bRunningOnNT)
  2333. {
  2334. return GetClassInfoW(hModule, lpClassName, lpWndClassW);
  2335. }
  2336. BOOL ret;
  2337. CStrIn strClassName(lpClassName);
  2338. ASSERT(sizeof(WNDCLASSA) == sizeof(WNDCLASSW));
  2339. ret = GetClassInfoA(hModule, strClassName, (LPWNDCLASSA) lpWndClassW);
  2340. lpWndClassW->lpszMenuName = NULL;
  2341. lpWndClassW->lpszClassName = NULL;
  2342. return ret;
  2343. }
  2344. #endif // NEED_USER32_WRAPPER
  2345. #ifdef NEED_USER32_WRAPPER
  2346. DWORD FORWARD_API WINAPI
  2347. GetClassLongWrapW(HWND hWnd, int nIndex)
  2348. {
  2349. VALIDATE_PROTOTYPE(GetClassLong);
  2350. FORWARD_AW(GetClassLong, (hWnd, nIndex));
  2351. }
  2352. #endif // NEED_USER32_WRAPPER
  2353. #ifdef NEED_USER32_WRAPPER
  2354. int WINAPI
  2355. GetClassNameWrapW(HWND hWnd, LPWSTR lpClassName, int nMaxCount)
  2356. {
  2357. VALIDATE_PROTOTYPE(GetClassName);
  2358. VALIDATE_OUTBUF(lpClassName, nMaxCount);
  2359. if (g_bRunningOnNT)
  2360. {
  2361. return GetClassNameW(hWnd, lpClassName, nMaxCount);
  2362. }
  2363. CStrOut strClassName(lpClassName, nMaxCount);
  2364. GetClassNameA(hWnd, strClassName, strClassName.BufSize());
  2365. return strClassName.ConvertIncludingNul();
  2366. }
  2367. #endif // NEED_USER32_WRAPPER
  2368. #ifdef NEED_USER32_WRAPPER
  2369. int WINAPI
  2370. GetClipboardFormatNameWrapW(UINT format, LPWSTR lpFormatName, int cchFormatName)
  2371. {
  2372. VALIDATE_PROTOTYPE(GetClipboardFormatName);
  2373. VALIDATE_OUTBUF(lpFormatName, cchFormatName);
  2374. if (g_bRunningOnNT)
  2375. {
  2376. return GetClipboardFormatNameW(format, lpFormatName, cchFormatName);
  2377. }
  2378. CStrOut strFormatName(lpFormatName, cchFormatName);
  2379. GetClipboardFormatNameA(format, strFormatName, strFormatName.BufSize());
  2380. return strFormatName.ConvertIncludingNul();
  2381. }
  2382. #endif // NEED_USER32_WRAPPER
  2383. #ifdef NEED_KERNEL32_WRAPPER
  2384. DWORD WINAPI
  2385. GetCurrentDirectoryWrapW(DWORD nBufferLength, LPWSTR lpBuffer)
  2386. {
  2387. VALIDATE_PROTOTYPE(GetCurrentDirectory);
  2388. VALIDATE_OUTBUF(lpBuffer, nBufferLength);
  2389. if (g_bRunningOnNT)
  2390. {
  2391. return GetCurrentDirectoryW(nBufferLength, lpBuffer);
  2392. }
  2393. CStrOut str(lpBuffer, nBufferLength);
  2394. GetCurrentDirectoryA(str.BufSize(), str);
  2395. return str.ConvertExcludingNul();
  2396. }
  2397. #endif // NEED_KERNEL32_WRAPPER
  2398. #ifdef NEED_USER32_WRAPPER
  2399. UINT WINAPI
  2400. GetDlgItemTextWrapW(
  2401. HWND hWndDlg,
  2402. int idControl,
  2403. LPWSTR lpsz,
  2404. int cchMax)
  2405. {
  2406. VALIDATE_PROTOTYPE(GetDlgItemText);
  2407. VALIDATE_OUTBUF(lpsz, cchMax);
  2408. HWND hWnd = GetDlgItem(hWndDlg, idControl);
  2409. if (hWnd)
  2410. return GetWindowTextWrapW(hWnd, lpsz, cchMax);
  2411. /*
  2412. * If we couldn't find the window, just null terminate lpch so that the
  2413. * app doesn't gp fault if it tries to run through the text.
  2414. */
  2415. if (cchMax)
  2416. *lpsz = (WCHAR)0;
  2417. return 0;
  2418. }
  2419. #endif // NEED_USER32_WRAPPER
  2420. #ifdef NEED_KERNEL32_WRAPPER
  2421. DWORD WINAPI
  2422. GetFileAttributesWrapW(LPCWSTR lpFileName)
  2423. {
  2424. VALIDATE_PROTOTYPE(GetFileAttributes);
  2425. if (g_bRunningOnNT)
  2426. {
  2427. return GetFileAttributesW(lpFileName);
  2428. }
  2429. CStrIn str(lpFileName);
  2430. return GetFileAttributesA(str);
  2431. }
  2432. #endif // NEED_KERNEL32_WRAPPER
  2433. #ifdef NEED_KERNEL32_WRAPPER
  2434. int WINAPI
  2435. GetLocaleInfoWrapW(LCID Locale, LCTYPE LCType, LPWSTR lpsz, int cchData)
  2436. {
  2437. VALIDATE_PROTOTYPE(GetLocaleInfo);
  2438. VALIDATE_OUTBUF(lpsz, cchData);
  2439. if (g_bRunningOnNT)
  2440. {
  2441. return GetLocaleInfoW(Locale, LCType, lpsz, cchData);
  2442. }
  2443. CStrOut str(lpsz, cchData);
  2444. GetLocaleInfoA(Locale, LCType, str, str.BufSize());
  2445. return str.ConvertIncludingNul();
  2446. }
  2447. #endif // NEED_KERNEL32_WRAPPER
  2448. #ifdef NEED_USER32_WRAPPER
  2449. BOOL FORWARD_API WINAPI
  2450. GetMessageWrapW(
  2451. LPMSG lpMsg,
  2452. HWND hWnd,
  2453. UINT wMsgFilterMin,
  2454. UINT wMsgFilterMax)
  2455. {
  2456. VALIDATE_PROTOTYPE(GetMessage);
  2457. FORWARD_AW(GetMessage, (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax));
  2458. }
  2459. #endif // NEED_USER32_WRAPPER
  2460. #ifdef NEED_KERNEL32_WRAPPER
  2461. DWORD WINAPI
  2462. GetModuleFileNameWrapW(HINSTANCE hModule, LPWSTR pwszFilename, DWORD nSize)
  2463. {
  2464. VALIDATE_PROTOTYPE(GetModuleFileName);
  2465. VALIDATE_OUTBUF(pwszFilename, nSize);
  2466. if (g_bRunningOnNT)
  2467. {
  2468. return GetModuleFileNameW(hModule, pwszFilename, nSize);
  2469. }
  2470. CStrOut str(pwszFilename, nSize);
  2471. GetModuleFileNameA(hModule, str, str.BufSize());
  2472. return str.ConvertIncludingNul();
  2473. }
  2474. #endif // NEED_KERNEL32_WRAPPER
  2475. #ifdef NEED_KERNEL32_WRAPPER
  2476. UINT WINAPI
  2477. GetSystemDirectoryWrapW(LPWSTR lpBuffer, UINT uSize)
  2478. {
  2479. VALIDATE_PROTOTYPE(GetSystemDirectory);
  2480. VALIDATE_OUTBUF(lpBuffer, uSize);
  2481. if (g_bRunningOnNT)
  2482. {
  2483. return GetSystemDirectoryW(lpBuffer, uSize);
  2484. }
  2485. CStrOut str(lpBuffer, uSize);
  2486. GetSystemDirectoryA(str, str.BufSize());
  2487. return str.ConvertExcludingNul();
  2488. }
  2489. #endif // NEED_KERNEL32_WRAPPER
  2490. #ifdef NEED_KERNEL32_WRAPPER
  2491. DWORD WINAPI
  2492. SearchPathWrapW(
  2493. LPCWSTR lpPathName,
  2494. LPCWSTR lpFileName,
  2495. LPCWSTR lpExtension,
  2496. DWORD cchReturnBuffer,
  2497. LPWSTR lpReturnBuffer,
  2498. LPWSTR * plpfilePart)
  2499. {
  2500. VALIDATE_PROTOTYPE(SearchPath);
  2501. VALIDATE_OUTBUF(lpReturnBuffer, cchReturnBuffer);
  2502. if (g_bRunningOnNT)
  2503. {
  2504. return SearchPathW(
  2505. lpPathName,
  2506. lpFileName,
  2507. lpExtension,
  2508. cchReturnBuffer,
  2509. lpReturnBuffer,
  2510. plpfilePart);
  2511. }
  2512. CStrIn strPath(lpPathName);
  2513. CStrIn strFile(lpFileName);
  2514. CStrIn strExtension(lpExtension);
  2515. CStrOut strReturnBuffer(lpReturnBuffer, cchReturnBuffer);
  2516. DWORD dwLen = SearchPathA(
  2517. strPath,
  2518. strFile,
  2519. strExtension,
  2520. strReturnBuffer.BufSize(),
  2521. strReturnBuffer,
  2522. (LPSTR *)plpfilePart);
  2523. //
  2524. // Getting the correct value for plpfilePart requires
  2525. // a strrchr on the converted string. If this value
  2526. // is needed, just add the code to do it here.
  2527. //
  2528. *plpfilePart = NULL;
  2529. if (cchReturnBuffer == 0)
  2530. dwLen = 2*dwLen;
  2531. else
  2532. dwLen = strReturnBuffer.ConvertExcludingNul();
  2533. return dwLen;
  2534. }
  2535. #endif // NEED_KERNEL32_WRAPPER
  2536. #ifdef NEED_KERNEL32_WRAPPER
  2537. HMODULE WINAPI
  2538. GetModuleHandleWrapW(LPCWSTR lpModuleName)
  2539. {
  2540. VALIDATE_PROTOTYPE(GetModuleHandle);
  2541. if (g_bRunningOnNT)
  2542. {
  2543. return GetModuleHandleW(lpModuleName);
  2544. }
  2545. CStrIn str(lpModuleName);
  2546. return GetModuleHandleA(str);
  2547. }
  2548. #endif // NEED_KERNEL32_WRAPPER
  2549. #ifdef NEED_GDI32_WRAPPER
  2550. int WINAPI
  2551. GetObjectWrapW(HGDIOBJ hgdiObj, int cbBuffer, LPVOID lpvObj)
  2552. {
  2553. VALIDATE_PROTOTYPE(GetObject);
  2554. if (g_bRunningOnNT)
  2555. {
  2556. return GetObjectW(hgdiObj, cbBuffer, lpvObj);
  2557. }
  2558. int nRet;
  2559. if(cbBuffer != sizeof(LOGFONTW))
  2560. {
  2561. nRet = GetObjectA(hgdiObj, cbBuffer, lpvObj);
  2562. }
  2563. else
  2564. {
  2565. LOGFONTA lfa;
  2566. nRet = GetObjectA(hgdiObj, sizeof(lfa), &lfa);
  2567. if (nRet > 0)
  2568. {
  2569. memcpy(lpvObj, &lfa, FIELD_OFFSET(LOGFONTW, lfFaceName));
  2570. SHAnsiToUnicode(lfa.lfFaceName, ((LOGFONTW*)lpvObj)->lfFaceName, ARRAYSIZE(((LOGFONTW*)lpvObj)->lfFaceName));
  2571. nRet = sizeof(LOGFONTW);
  2572. }
  2573. }
  2574. return nRet;
  2575. }
  2576. #endif // NEED_GDI32_WRAPPER
  2577. #ifdef NEED_SHELL32_WRAPPER
  2578. LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW pbiW)
  2579. {
  2580. if (UseUnicodeShell32())
  2581. {
  2582. return SHBrowseForFolderW(pbiW);
  2583. }
  2584. LPITEMIDLIST pidl = NULL;
  2585. ASSERT(pbiW);
  2586. if (pbiW)
  2587. {
  2588. CStrIn strTitle(pbiW->lpszTitle);
  2589. CStrOut strDisplayName(pbiW->pszDisplayName, MAX_PATH);
  2590. BROWSEINFOA biA;
  2591. biA = * (LPBROWSEINFOA) pbiW;
  2592. biA.lpszTitle = strTitle;
  2593. biA.pszDisplayName = strDisplayName;
  2594. pidl = SHBrowseForFolderA(&biA);
  2595. if (pidl)
  2596. {
  2597. strDisplayName.ConvertIncludingNul();
  2598. }
  2599. }
  2600. return pidl;
  2601. }
  2602. #endif // NEED_SHELL32_WRAPPER
  2603. #ifdef NEED_SHELL32_WRAPPER
  2604. BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl, LPWSTR pwzPath)
  2605. {
  2606. if (UseUnicodeShell32())
  2607. {
  2608. return SHGetPathFromIDListW(pidl, pwzPath);
  2609. }
  2610. CStrOut strPathOut(pwzPath, MAX_PATH);
  2611. BOOL fResult = SHGetPathFromIDListA(pidl, strPathOut);
  2612. if (fResult)
  2613. {
  2614. strPathOut.ConvertIncludingNul();
  2615. }
  2616. return fResult;
  2617. }
  2618. #endif // NEED_SHELL32_WRAPPER
  2619. #ifdef NEED_SHELL32_WRAPPER
  2620. BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW pExecInfoW)
  2621. {
  2622. if (g_bRunningOnNT)
  2623. {
  2624. return ShellExecuteExW(pExecInfoW);
  2625. }
  2626. BOOL fResult = FALSE;
  2627. ASSERT(pExecInfoW);
  2628. if (pExecInfoW)
  2629. {
  2630. SHELLEXECUTEINFOA ExecInfoA;
  2631. CStrIn strVerb(pExecInfoW->lpVerb);
  2632. CStrIn strParameters(pExecInfoW->lpParameters);
  2633. CStrIn strDirectory(pExecInfoW->lpDirectory);
  2634. CStrIn strClass(pExecInfoW->lpClass);
  2635. CHAR szFile[MAX_PATH + INTERNET_MAX_URL_LENGTH + 2];
  2636. ExecInfoA = *(LPSHELLEXECUTEINFOA) pExecInfoW;
  2637. ExecInfoA.lpVerb = strVerb;
  2638. ExecInfoA.lpParameters = strParameters;
  2639. ExecInfoA.lpDirectory = strDirectory;
  2640. ExecInfoA.lpClass = strClass;
  2641. if (pExecInfoW->lpFile)
  2642. {
  2643. ExecInfoA.lpFile = szFile;
  2644. SHUnicodeToAnsi(pExecInfoW->lpFile, szFile, ARRAYSIZE(szFile));
  2645. // SEE_MASK_FILEANDURL passes "file\0url". What a hack!
  2646. if (pExecInfoW->fMask & SEE_MASK_FILEANDURL)
  2647. {
  2648. // We are so lucky that Win9x implements lstrlenW
  2649. int cch = lstrlenW(pExecInfoW->lpFile) + 1;
  2650. cch += lstrlenW(pExecInfoW->lpFile + cch) + 1;
  2651. if (!WideCharToMultiByte(CP_ACP, 0, pExecInfoW->lpFile, cch, szFile, ARRAYSIZE(szFile), NULL, NULL))
  2652. {
  2653. // Return a completely random error code
  2654. pExecInfoW->hInstApp = (HINSTANCE)SE_ERR_OOM;
  2655. SetLastError(ERROR_INVALID_PARAMETER);
  2656. return FALSE;
  2657. }
  2658. }
  2659. }
  2660. fResult = ShellExecuteExA(&ExecInfoA);
  2661. // Out parameters
  2662. pExecInfoW->hInstApp = ExecInfoA.hInstApp;
  2663. pExecInfoW->hProcess = ExecInfoA.hProcess;
  2664. }
  2665. else
  2666. {
  2667. SetLastError(ERROR_INVALID_PARAMETER);
  2668. }
  2669. return fResult;
  2670. }
  2671. #endif // NEED_SHELL32_WRAPPER
  2672. #ifdef NEED_SHELL32_WRAPPER
  2673. int WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW pFileOpW)
  2674. {
  2675. // We don't thunk multiple files.
  2676. ASSERT(pFileOpW);
  2677. ASSERT(!(pFileOpW->fFlags & FOF_MULTIDESTFILES));
  2678. if (UseUnicodeShell32())
  2679. {
  2680. return SHFileOperationW(pFileOpW);
  2681. }
  2682. int nResult = 1; // non-Zero is failure.
  2683. if (pFileOpW)
  2684. {
  2685. SHFILEOPSTRUCTA FileOpA;
  2686. CStrIn strTo(pFileOpW->pTo);
  2687. CStrIn strFrom(pFileOpW->pFrom);
  2688. CStrIn strProgressTitle(pFileOpW->lpszProgressTitle);
  2689. FileOpA = *(LPSHFILEOPSTRUCTA) pFileOpW;
  2690. FileOpA.pFrom = strFrom;
  2691. FileOpA.pTo = strTo;
  2692. FileOpA.lpszProgressTitle = strProgressTitle;
  2693. nResult = SHFileOperationA(&FileOpA);
  2694. }
  2695. return nResult;
  2696. }
  2697. #endif // NEED_SHELL32_WRAPPER
  2698. #ifdef NEED_SHELL32_WRAPPER
  2699. UINT WINAPI ExtractIconExWrapW(LPCWSTR pwzFile, int nIconIndex, HICON FAR *phiconLarge, HICON FAR *phiconSmall, UINT nIcons)
  2700. {
  2701. if (UseUnicodeShell32())
  2702. {
  2703. return ExtractIconExW(pwzFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
  2704. }
  2705. CStrIn str(pwzFile);
  2706. return ExtractIconExA(str, nIconIndex, phiconLarge, phiconSmall, nIcons);
  2707. }
  2708. #endif // NEED_SHELL32_WRAPPER
  2709. #ifdef NEED_SHELL32_WRAPPER
  2710. //
  2711. // Shell_GetCachedImageIndexWrapA/W are exported from shlwapi.
  2712. // Only the W version should be in NEED_SHELL32_WRAPPER
  2713. int WINAPI Shell_GetCachedImageIndexWrapW(LPCWSTR pszIconPath, int iIconIndex, UINT uIconFlags)
  2714. {
  2715. if (UseUnicodeShell32())
  2716. {
  2717. return Shell_GetCachedImageIndex(pszIconPath, iIconIndex, uIconFlags);
  2718. }
  2719. CStrIn strIconPath(pszIconPath);
  2720. return Shell_GetCachedImageIndex((LPCWSTR)((void*)(strIconPath)), iIconIndex, uIconFlags);
  2721. }
  2722. #endif // NEED_SHELL32_WRAPPER
  2723. int WINAPI Shell_GetCachedImageIndexWrapA(LPCSTR pszIconPath, int iIconIndex, UINT uIconFlags)
  2724. {
  2725. if (UseUnicodeShell32())
  2726. {
  2727. WCHAR szIconPath[MAX_PATH];
  2728. SHAnsiToUnicode(pszIconPath, szIconPath, ARRAYSIZE(szIconPath));
  2729. return Shell_GetCachedImageIndex(szIconPath, iIconIndex, uIconFlags);
  2730. }
  2731. return Shell_GetCachedImageIndex((LPCWSTR)((void*)(pszIconPath)), iIconIndex, uIconFlags);
  2732. }
  2733. #ifdef NEED_KERNEL32_WRAPPER
  2734. BOOL WINAPI SetFileAttributesWrapW(LPCWSTR pwzFile, DWORD dwFileAttributes)
  2735. {
  2736. VALIDATE_PROTOTYPE(SetFileAttributes);
  2737. if (g_bRunningOnNT)
  2738. return SetFileAttributesW(pwzFile, dwFileAttributes);
  2739. CStrIn str(pwzFile);
  2740. return SetFileAttributesA(str, dwFileAttributes);
  2741. }
  2742. #endif // NEED_KERNEL32_WRAPPER
  2743. #ifdef NEED_KERNEL32_WRAPPER
  2744. int WINAPI GetNumberFormatWrapW(LCID Locale, DWORD dwFlags, LPCWSTR pwzValue, CONST NUMBERFMTW * pFormatW, LPWSTR pwzNumberStr, int cchNumber)
  2745. {
  2746. VALIDATE_PROTOTYPE(GetNumberFormat);
  2747. if (g_bRunningOnNT)
  2748. return GetNumberFormatW(Locale, dwFlags, pwzValue, pFormatW, pwzNumberStr, cchNumber);
  2749. int nResult;
  2750. NUMBERFMTA FormatA;
  2751. CStrIn strValue(pwzValue);
  2752. CStrIn strDecimalSep(pFormatW ? pFormatW->lpDecimalSep : NULL);
  2753. CStrIn strThousandSep(pFormatW ? pFormatW->lpThousandSep : NULL);
  2754. CStrOut strNumberStr(pwzNumberStr, cchNumber);
  2755. if (pFormatW)
  2756. {
  2757. FormatA = *(NUMBERFMTA *) pFormatW;
  2758. FormatA.lpDecimalSep = strDecimalSep;
  2759. FormatA.lpThousandSep = strThousandSep;
  2760. }
  2761. nResult = GetNumberFormatA(Locale, dwFlags, strValue, (pFormatW ? &FormatA : NULL), strNumberStr, strNumberStr.BufSize());
  2762. if (ERROR_SUCCESS == nResult)
  2763. strNumberStr.ConvertIncludingNul();
  2764. return nResult;
  2765. }
  2766. #endif // NEED_KERNEL32_WRAPPER
  2767. #ifdef NEED_USER32_WRAPPER
  2768. int WINAPI MessageBoxWrapW(HWND hwnd, LPCWSTR pwzText, LPCWSTR pwzCaption, UINT uType)
  2769. {
  2770. VALIDATE_PROTOTYPE(MessageBox);
  2771. if (g_bRunningOnNT)
  2772. return MessageBoxW(hwnd, pwzText, pwzCaption, uType);
  2773. CStrIn strCaption(pwzCaption);
  2774. CStrIn strText(pwzText);
  2775. return MessageBoxA(hwnd, strText, strCaption, uType);
  2776. }
  2777. #endif // NEED_USER32_WRAPPER
  2778. #ifdef NEED_KERNEL32_WRAPPER
  2779. BOOL WINAPI FindNextFileWrapW(HANDLE hSearchHandle, LPWIN32_FIND_DATAW pFindFileDataW)
  2780. {
  2781. VALIDATE_PROTOTYPE(FindNextFile);
  2782. if (g_bRunningOnNT)
  2783. return FindNextFileW(hSearchHandle, pFindFileDataW);
  2784. CWin32FindDataInOut fd(pFindFileDataW);
  2785. return FindNextFileA(hSearchHandle, fd);
  2786. }
  2787. #endif // NEED_KERNEL32_WRAPPER
  2788. #ifdef NEED_KERNEL32_WRAPPER
  2789. //--------------------------------------------------------------
  2790. // GetFullPathNameWrap
  2791. //--------------------------------------------------------------
  2792. DWORD
  2793. WINAPI
  2794. GetFullPathNameWrapW( LPCWSTR lpFileName,
  2795. DWORD nBufferLength,
  2796. LPWSTR lpBuffer,
  2797. LPWSTR *lpFilePart)
  2798. {
  2799. VALIDATE_PROTOTYPE(GetFullPathName);
  2800. VALIDATE_OUTBUF(lpBuffer, nBufferLength);
  2801. if (g_bRunningOnNT)
  2802. {
  2803. return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
  2804. }
  2805. CStrIn strIn(lpFileName);
  2806. CStrOut strOut(lpBuffer,nBufferLength);
  2807. LPSTR pFile;
  2808. DWORD dwRet;
  2809. dwRet = GetFullPathNameA(strIn, nBufferLength, strOut, &pFile);
  2810. strOut.ConvertIncludingNul();
  2811. // REARCHITECT raymondc - This is wrong if we had to do DBCS or related goo
  2812. *lpFilePart = lpBuffer + (pFile - strOut);
  2813. return dwRet;
  2814. }
  2815. #endif // NEED_KERNEL32_WRAPPER
  2816. #ifdef NEED_KERNEL32_WRAPPER
  2817. DWORD WINAPI
  2818. GetShortPathNameWrapW(
  2819. LPCWSTR lpszLongPath,
  2820. LPWSTR lpszShortPath,
  2821. DWORD cchBuffer)
  2822. {
  2823. VALIDATE_PROTOTYPE(GetShortPathName);
  2824. if (g_bRunningOnNT)
  2825. {
  2826. return GetShortPathNameW(lpszLongPath, lpszShortPath, cchBuffer);
  2827. }
  2828. CStrIn strLongPath(lpszLongPath);
  2829. CStrOut strShortPath(lpszShortPath, cchBuffer);
  2830. return GetShortPathNameA(strLongPath, strShortPath, strShortPath.BufSize());
  2831. }
  2832. #endif // NEED_KERNEL32_WRAPPER
  2833. #ifdef NEED_KERNEL32_WRAPPER
  2834. BOOL WINAPI
  2835. GetStringTypeExWrapW(LCID lcid, DWORD dwInfoType, LPCTSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
  2836. {
  2837. VALIDATE_PROTOTYPE(GetStringTypeEx);
  2838. if (g_bRunningOnNT)
  2839. {
  2840. return GetStringTypeExW(lcid, dwInfoType, lpSrcStr, cchSrc, lpCharType);
  2841. }
  2842. CStrIn str(lpSrcStr, cchSrc);
  2843. return GetStringTypeExA(lcid, dwInfoType, str, str.strlen(), lpCharType);
  2844. }
  2845. #endif // NEED_KERNEL32_WRAPPER
  2846. #ifdef NEED_KERNEL32_WRAPPER
  2847. UINT WINAPI
  2848. GetPrivateProfileIntWrapW(
  2849. LPCWSTR lpAppName,
  2850. LPCWSTR lpKeyName,
  2851. INT nDefault,
  2852. LPCWSTR lpFileName)
  2853. {
  2854. VALIDATE_PROTOTYPE(GetPrivateProfileInt);
  2855. if (g_bRunningOnNT)
  2856. {
  2857. return GetPrivateProfileIntW(lpAppName, lpKeyName, nDefault, lpFileName);
  2858. }
  2859. CStrIn strApp(lpAppName);
  2860. CStrIn strKey(lpKeyName);
  2861. CPPFIn strFile(lpFileName); // PrivateProfile filename needs special class
  2862. return GetPrivateProfileIntA(strApp, strKey, nDefault, strFile);
  2863. }
  2864. #endif // NEED_KERNEL32_WRAPPER
  2865. #ifdef NEED_KERNEL32_WRAPPER
  2866. DWORD WINAPI
  2867. GetProfileStringWrapW(
  2868. LPCWSTR lpAppName,
  2869. LPCWSTR lpKeyName,
  2870. LPCWSTR lpDefault,
  2871. LPWSTR lpBuffer,
  2872. DWORD dwBuffersize)
  2873. {
  2874. VALIDATE_PROTOTYPE(GetProfileString);
  2875. VALIDATE_OUTBUF(lpBuffer, dwBuffersize);
  2876. if (g_bRunningOnNT)
  2877. {
  2878. return GetProfileStringW(lpAppName, lpKeyName, lpDefault, lpBuffer, dwBuffersize);
  2879. }
  2880. CStrIn strApp(lpAppName);
  2881. CStrIn strKey(lpKeyName);
  2882. CStrIn strDefault(lpDefault);
  2883. CStrOut strBuffer(lpBuffer, dwBuffersize);
  2884. GetProfileStringA(strApp, strKey, strDefault, strBuffer, dwBuffersize);
  2885. return strBuffer.ConvertIncludingNul();
  2886. }
  2887. #endif // NEED_KERNEL32_WRAPPER
  2888. #ifdef NEED_USER32_WRAPPER
  2889. HANDLE WINAPI
  2890. GetPropWrapW(HWND hWnd, LPCWSTR lpString)
  2891. {
  2892. VALIDATE_PROTOTYPE(GetProp);
  2893. if (g_bRunningOnNT)
  2894. {
  2895. return GetPropW(hWnd, lpString);
  2896. }
  2897. CStrIn str(lpString);
  2898. return GetPropA(hWnd, str);
  2899. }
  2900. #endif // NEED_USER32_WRAPPER
  2901. #ifdef NEED_KERNEL32_WRAPPER
  2902. UINT WINAPI
  2903. GetTempFileNameWrapW(
  2904. LPCWSTR lpPathName,
  2905. LPCWSTR lpPrefixString,
  2906. UINT uUnique,
  2907. LPWSTR lpTempFileName)
  2908. {
  2909. VALIDATE_PROTOTYPE(GetTempFileName);
  2910. VALIDATE_OUTBUF(lpTempFileName, MAX_PATH);
  2911. if (g_bRunningOnNT)
  2912. {
  2913. return GetTempFileNameW(lpPathName, lpPrefixString, uUnique, lpTempFileName);
  2914. }
  2915. CStrIn strPath(lpPathName);
  2916. CStrIn strPrefix(lpPrefixString);
  2917. CStrOut strFileName(lpTempFileName, MAX_PATH);
  2918. return GetTempFileNameA(strPath, strPrefix, uUnique, strFileName);
  2919. }
  2920. #endif // NEED_KERNEL32_WRAPPER
  2921. #ifdef NEED_KERNEL32_WRAPPER
  2922. DWORD WINAPI
  2923. GetTempPathWrapW(DWORD nBufferLength, LPWSTR lpBuffer)
  2924. {
  2925. VALIDATE_PROTOTYPE(GetTempPath);
  2926. VALIDATE_OUTBUF(lpBuffer, nBufferLength);
  2927. if (g_bRunningOnNT)
  2928. {
  2929. return GetTempPathW(nBufferLength, lpBuffer);
  2930. }
  2931. CStrOut str(lpBuffer, nBufferLength);
  2932. GetTempPathA(str.BufSize(), str);
  2933. return str.ConvertExcludingNul();
  2934. }
  2935. #endif // NEED_KERNEL32_WRAPPER
  2936. #ifdef NEED_GDI32_WRAPPER
  2937. BOOL APIENTRY
  2938. GetTextExtentPoint32WrapW(
  2939. HDC hdc,
  2940. LPCWSTR pwsz,
  2941. int cb,
  2942. LPSIZE pSize)
  2943. {
  2944. VALIDATE_PROTOTYPE(GetTextExtentPoint32);
  2945. if (_MayNeedFontLinking(pwsz, cb))
  2946. {
  2947. return GetTextExtentPointFLW(hdc, pwsz, cb, pSize);
  2948. }
  2949. else if (g_bRunningOnNT)
  2950. {
  2951. return GetTextExtentPoint32W(hdc, pwsz, cb, pSize);
  2952. }
  2953. CStrIn str(pwsz,cb);
  2954. return GetTextExtentPoint32A(hdc, str, str.strlen(), pSize);
  2955. }
  2956. #endif // NEED_GDI32_WRAPPER
  2957. #ifdef NEED_GDI32_WRAPPER
  2958. int WINAPI
  2959. GetTextFaceWrapW(
  2960. HDC hdc,
  2961. int cch,
  2962. LPWSTR lpFaceName)
  2963. {
  2964. VALIDATE_PROTOTYPE(GetTextFace);
  2965. VALIDATE_OUTBUF(lpFaceName, cch);
  2966. if (g_bRunningOnNT)
  2967. {
  2968. return GetTextFaceW(hdc, cch, lpFaceName);
  2969. }
  2970. CStrOut str(lpFaceName, cch);
  2971. GetTextFaceA(hdc, str.BufSize(), str);
  2972. return str.ConvertIncludingNul();
  2973. }
  2974. #endif // NEED_GDI32_WRAPPER
  2975. #ifdef NEED_GDI32_WRAPPER
  2976. BOOL WINAPI
  2977. GetTextMetricsWrapW(HDC hdc, LPTEXTMETRICW lptm)
  2978. {
  2979. VALIDATE_PROTOTYPE(GetTextMetrics);
  2980. if (g_bRunningOnNT)
  2981. {
  2982. return GetTextMetricsW(hdc, lptm);
  2983. }
  2984. BOOL ret;
  2985. TEXTMETRICA tm;
  2986. ret = GetTextMetricsA(hdc, &tm);
  2987. if (ret)
  2988. {
  2989. lptm->tmHeight = tm.tmHeight;
  2990. lptm->tmAscent = tm.tmAscent;
  2991. lptm->tmDescent = tm.tmDescent;
  2992. lptm->tmInternalLeading = tm.tmInternalLeading;
  2993. lptm->tmExternalLeading = tm.tmExternalLeading;
  2994. lptm->tmAveCharWidth = tm.tmAveCharWidth;
  2995. lptm->tmMaxCharWidth = tm.tmMaxCharWidth;
  2996. lptm->tmWeight = tm.tmWeight;
  2997. lptm->tmOverhang = tm.tmOverhang;
  2998. lptm->tmDigitizedAspectX = tm.tmDigitizedAspectX;
  2999. lptm->tmDigitizedAspectY = tm.tmDigitizedAspectY;
  3000. lptm->tmItalic = tm.tmItalic;
  3001. lptm->tmUnderlined = tm.tmUnderlined;
  3002. lptm->tmStruckOut = tm.tmStruckOut;
  3003. lptm->tmPitchAndFamily = tm.tmPitchAndFamily;
  3004. lptm->tmCharSet = tm.tmCharSet;
  3005. // LPBYTE -> LPCSTR casts below
  3006. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&tm.tmFirstChar, 1, &lptm->tmFirstChar, 1);
  3007. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&tm.tmLastChar, 1, &lptm->tmLastChar, 1);
  3008. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&tm.tmDefaultChar, 1, &lptm->tmDefaultChar, 1);
  3009. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&tm.tmBreakChar, 1, &lptm->tmBreakChar, 1);
  3010. }
  3011. return ret;
  3012. }
  3013. #endif // NEED_GDI32_WRAPPER
  3014. #ifdef NEED_ADVAPI32_WRAPPER
  3015. BOOL WINAPI GetUserNameWrapW(LPWSTR pszBuffer, LPDWORD pcch)
  3016. {
  3017. VALIDATE_PROTOTYPE(GetUserName);
  3018. BOOL fRet;
  3019. if (UseUnicodeShell32())
  3020. {
  3021. fRet = GetUserNameW(pszBuffer, pcch);
  3022. }
  3023. else
  3024. {
  3025. CStrOut stroBuffer(pszBuffer, *pcch);
  3026. fRet = GetUserNameA(stroBuffer, pcch);
  3027. if (fRet)
  3028. *pcch = stroBuffer.ConvertIncludingNul();
  3029. }
  3030. return fRet;
  3031. }
  3032. #endif // NEED_ADVAPI32_WRAPPER
  3033. #ifdef NEED_USER32_WRAPPER
  3034. LONG FORWARD_API WINAPI
  3035. GetWindowLongWrapW(HWND hWnd, int nIndex)
  3036. {
  3037. VALIDATE_PROTOTYPE(GetWindowLong);
  3038. FORWARD_AW(GetWindowLong, (hWnd, nIndex));
  3039. }
  3040. #endif // NEED_USER32_WRAPPER
  3041. #ifdef NEED_USER32_WRAPPER
  3042. int WINAPI
  3043. GetWindowTextWrapW(HWND hWnd, LPWSTR lpString, int nMaxCount)
  3044. {
  3045. VALIDATE_PROTOTYPE(GetWindowText);
  3046. VALIDATE_OUTBUF(lpString, nMaxCount);
  3047. if (MLIsEnabled(hWnd))
  3048. return MLGetControlTextI(hWnd, lpString, nMaxCount);
  3049. if (g_bRunningOnNT)
  3050. {
  3051. return GetWindowTextW(hWnd, lpString, nMaxCount);
  3052. }
  3053. CStrOut str(lpString, nMaxCount);
  3054. GetWindowTextA(hWnd, str, str.BufSize());
  3055. return str.ConvertExcludingNul();
  3056. }
  3057. #endif // NEED_USER32_WRAPPER
  3058. #ifdef NEED_USER32_WRAPPER
  3059. int WINAPI
  3060. GetWindowTextLengthWrapW(HWND hWnd)
  3061. {
  3062. VALIDATE_PROTOTYPE(GetWindowTextLength);
  3063. if (g_bRunningOnNT)
  3064. {
  3065. return GetWindowTextLengthW(hWnd);
  3066. }
  3067. return GetWindowTextLengthA(hWnd);
  3068. }
  3069. #endif // NEED_USER32_WRAPPER
  3070. #ifdef NEED_KERNEL32_WRAPPER
  3071. UINT WINAPI
  3072. GetWindowsDirectoryWrapW(LPWSTR lpWinPath, UINT cch)
  3073. {
  3074. VALIDATE_PROTOTYPE(GetWindowsDirectory);
  3075. VALIDATE_OUTBUF(lpWinPath, cch);
  3076. if (g_bRunningOnNT)
  3077. {
  3078. return GetWindowsDirectoryW(lpWinPath, cch);
  3079. }
  3080. CStrOut str(lpWinPath, cch);
  3081. GetWindowsDirectoryA(str, str.BufSize());
  3082. return str.ConvertExcludingNul();
  3083. }
  3084. #endif // NEED_USER32_WRAPPER
  3085. #ifdef NEED_KERNEL32_WRAPPER
  3086. STDAPI_(DWORD) WINAPI
  3087. GetEnvironmentVariableWrapW(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize)
  3088. {
  3089. VALIDATE_PROTOTYPE(GetEnvironmentVariable);
  3090. VALIDATE_OUTBUF(lpBuffer, nSize);
  3091. if (g_bRunningOnNT)
  3092. {
  3093. return GetEnvironmentVariableW(lpName,lpBuffer, nSize);
  3094. }
  3095. CStrOut str(lpBuffer, nSize);
  3096. CStrIn strName(lpName);
  3097. GetEnvironmentVariableA(strName, str, str.BufSize());
  3098. return str.ConvertExcludingNul();
  3099. }
  3100. #endif // NEED_KERNEL32_WRAPPER
  3101. #ifdef NEED_USER32_WRAPPER
  3102. BOOL FORWARD_API WINAPI
  3103. IsDialogMessageWrapW(HWND hWndDlg, LPMSG lpMsg)
  3104. {
  3105. VALIDATE_PROTOTYPE(IsDialogMessage);
  3106. FORWARD_AW(IsDialogMessage, (hWndDlg, lpMsg));
  3107. }
  3108. #endif // NEED_USER32_WRAPPER
  3109. #ifdef NEED_USER32_WRAPPER
  3110. HACCEL WINAPI
  3111. LoadAcceleratorsWrapW(HINSTANCE hInstance, LPCWSTR lpTableName)
  3112. {
  3113. VALIDATE_PROTOTYPE(LoadAccelerators);
  3114. ASSERT(HIWORD64(lpTableName) == 0);
  3115. if (g_bRunningOnNT)
  3116. {
  3117. return LoadAcceleratorsW(hInstance, lpTableName);
  3118. }
  3119. return LoadAcceleratorsA(hInstance, (LPCSTR) lpTableName);
  3120. }
  3121. #endif // NEED_USER32_WRAPPER
  3122. #ifdef NEED_USER32_WRAPPER
  3123. HBITMAP WINAPI
  3124. LoadBitmapWrapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
  3125. {
  3126. VALIDATE_PROTOTYPE(LoadBitmap);
  3127. ASSERT(HIWORD64(lpBitmapName) == 0);
  3128. if (g_bRunningOnNT)
  3129. {
  3130. return LoadBitmapW(hInstance, lpBitmapName);
  3131. }
  3132. return LoadBitmapA(hInstance, (LPCSTR) lpBitmapName);
  3133. }
  3134. #endif // NEED_USER32_WRAPPER
  3135. #ifdef NEED_USER32_WRAPPER
  3136. HCURSOR WINAPI
  3137. LoadCursorWrapW(HINSTANCE hInstance, LPCWSTR lpCursorName)
  3138. {
  3139. VALIDATE_PROTOTYPE(LoadCursor);
  3140. ASSERT(HIWORD64(lpCursorName) == 0);
  3141. if (g_bRunningOnNT)
  3142. {
  3143. return LoadCursorW(hInstance, lpCursorName);
  3144. }
  3145. return LoadCursorA(hInstance, (LPCSTR) lpCursorName);
  3146. }
  3147. #endif // NEED_USER32_WRAPPER
  3148. #ifdef NEED_USER32_WRAPPER
  3149. HICON WINAPI
  3150. LoadIconWrapW(HINSTANCE hInstance, LPCWSTR lpIconName)
  3151. {
  3152. VALIDATE_PROTOTYPE(LoadIcon);
  3153. ASSERT(HIWORD64(lpIconName) == 0);
  3154. if (g_bRunningOnNT)
  3155. {
  3156. return LoadIconW(hInstance, lpIconName);
  3157. }
  3158. return LoadIconA(hInstance, (LPCSTR) lpIconName);
  3159. }
  3160. #endif // NEED_USER32_WRAPPER
  3161. #ifdef NEED_USER32_WRAPPER
  3162. //+-------------------------------------------------------------------------
  3163. // Returns an icon from a dll/exe loaded as a datafile. Note that this is
  3164. // very similar to the standard LoadImage API. However, LoadImage does
  3165. // not work properly (returns bogus icons) on win95/98 when the dll is
  3166. // loaded as a datafile. (Stevepro 18-Sept-98)
  3167. //--------------------------------------------------------------------------
  3168. HICON _LoadIconFromInstanceA
  3169. (
  3170. HINSTANCE hInstance, // instance containing the icon
  3171. LPCSTR pszName, // name or id of icon
  3172. int cxDesired,
  3173. int cyDesired,
  3174. UINT fuLoad // load flags, LR_DEFAULTCOLOR | LR_MONOCHROME
  3175. )
  3176. {
  3177. HICON hIcon;
  3178. UINT fUnsupportedFlags = ~(LR_DEFAULTCOLOR | LR_MONOCHROME);
  3179. if (fuLoad & fUnsupportedFlags)
  3180. {
  3181. // We saw a flag that we don't support, so default to the standard API
  3182. hIcon = (HICON)LoadImageA(hInstance, pszName, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
  3183. }
  3184. else
  3185. {
  3186. // Find the group icon
  3187. HRSRC hRsrc;
  3188. HGLOBAL hGlobal;
  3189. PBYTE pIconDir;
  3190. if ((hRsrc = FindResourceA(hInstance, pszName, (LPCSTR)RT_GROUP_ICON)) == NULL ||
  3191. (hGlobal = LoadResource(hInstance, hRsrc)) == NULL ||
  3192. (pIconDir = (PBYTE)LockResource(hGlobal)) == NULL)
  3193. {
  3194. // Note that FreeResource and UnlockResource are obsolete APIs, so we just exit.
  3195. return NULL;
  3196. }
  3197. // Find the icon that best matches the desired size
  3198. int nID = LookupIconIdFromDirectoryEx(pIconDir, TRUE, cxDesired, cyDesired, fuLoad);
  3199. PBYTE pbRes;
  3200. if (0 == nID ||
  3201. (hRsrc = FindResourceA(hInstance, MAKEINTRESOURCEA(nID), (LPCSTR)RT_ICON)) == NULL ||
  3202. (hGlobal = LoadResource(hInstance, hRsrc)) == NULL ||
  3203. (pbRes = (PBYTE)LockResource(hGlobal)) == NULL)
  3204. {
  3205. return NULL;
  3206. }
  3207. // Let the OS make us an icon
  3208. LPBITMAPINFOHEADER pbmh = (LPBITMAPINFOHEADER)pbRes;
  3209. hIcon = CreateIconFromResourceEx(pbRes, SizeofResource(hInstance, hRsrc), TRUE, 0x00030000,
  3210. pbmh->biWidth, pbmh->biHeight/2, fuLoad);
  3211. // It failed, odds are good we're on NT so try the non-Ex way
  3212. if (hIcon == NULL)
  3213. {
  3214. // We would break on NT if we try with a 16bpp image
  3215. if(pbmh->biBitCount != 16)
  3216. {
  3217. hIcon = CreateIconFromResource(pbRes, SizeofResource(hInstance, hRsrc), TRUE, 0x00030000);
  3218. }
  3219. }
  3220. }
  3221. return hIcon;
  3222. }
  3223. HANDLE WINAPI
  3224. LoadImageWrapA(
  3225. HINSTANCE hInstance,
  3226. LPCSTR lpName,
  3227. UINT uType,
  3228. int cxDesired,
  3229. int cyDesired,
  3230. UINT fuLoad)
  3231. {
  3232. VALIDATE_PROTOTYPE(LoadImage);
  3233. //
  3234. // If the hInstance is loaded as a datafile, LoadImage returns the
  3235. // wrong icons on win95/98. (Kernel can't find the datafile and uses
  3236. // null instead)
  3237. //
  3238. // APPCOMPAT: Should also fix loading other resource types from datafiles
  3239. //
  3240. if (!g_bRunningOnNT && uType == IMAGE_ICON)
  3241. {
  3242. return _LoadIconFromInstanceA(
  3243. hInstance,
  3244. lpName,
  3245. cxDesired,
  3246. cyDesired,
  3247. fuLoad);
  3248. }
  3249. return LoadImageA(
  3250. hInstance,
  3251. lpName,
  3252. uType,
  3253. cxDesired,
  3254. cyDesired,
  3255. fuLoad);
  3256. }
  3257. HANDLE WINAPI
  3258. LoadImageWrapW(
  3259. HINSTANCE hInstance,
  3260. LPCWSTR lpName,
  3261. UINT uType,
  3262. int cxDesired,
  3263. int cyDesired,
  3264. UINT fuLoad)
  3265. {
  3266. VALIDATE_PROTOTYPE(LoadImage);
  3267. if (g_bRunningOnNT)
  3268. {
  3269. return LoadImageW(
  3270. hInstance,
  3271. lpName,
  3272. uType,
  3273. cxDesired,
  3274. cyDesired,
  3275. fuLoad);
  3276. }
  3277. CStrIn str(lpName);
  3278. return LoadImageWrapA(
  3279. hInstance,
  3280. str,
  3281. uType,
  3282. cxDesired,
  3283. cyDesired,
  3284. fuLoad);
  3285. }
  3286. #endif // NEED_USER32_WRAPPER
  3287. #ifdef NEED_KERNEL32_WRAPPER
  3288. HINSTANCE WINAPI
  3289. LoadLibraryExWrapW(
  3290. LPCWSTR lpLibFileName,
  3291. HANDLE hFile,
  3292. DWORD dwFlags)
  3293. {
  3294. VALIDATE_PROTOTYPE(LoadLibraryEx);
  3295. if (g_bRunningOnNT)
  3296. return LoadLibraryExW(lpLibFileName, hFile, dwFlags);
  3297. CStrIn str(lpLibFileName);
  3298. // Win9X will crash if the pathname is longer than MAX_PATH bytes.
  3299. if (str.strlen() >= MAX_PATH)
  3300. {
  3301. SetLastError( ERROR_BAD_PATHNAME );
  3302. return NULL;
  3303. }
  3304. else
  3305. {
  3306. return LoadLibraryExA(str, hFile, dwFlags);
  3307. }
  3308. }
  3309. #endif // NEED_KERNEL32_WRAPPER
  3310. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3311. BOOL fDoMungeLangId(LANGID lidUI);
  3312. BOOL NeedMenuOwnerDraw(void)
  3313. {
  3314. // FEATURE: need to be improved
  3315. // It checks whether current UI language is cross codepage or not
  3316. if (g_bRunningOnNT5OrHigher)
  3317. return FALSE;
  3318. return fDoMungeLangId(MLGetUILanguage());
  3319. }
  3320. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3321. #define PUI_OWNERDRAW_SIG 0xFFFF0000
  3322. // NOTE: This structure is only visible from subclassed OwnerDrawSubclassProc
  3323. // with WM_DRAWITEM and WM_MEASUREITEM. All other places won't see this
  3324. // structure. We restore original format MENUITEMINFO structure without
  3325. // MFT_OWNERDRAW flag unless it's a real owner draw item.
  3326. // For this, we do/undo munge in Get/SetMenuItemInfo and InsertMenuItem.
  3327. typedef struct tagPUIMENUITEM
  3328. {
  3329. DWORD dwSig; // signature for this structure
  3330. HMENU hmenu; // menu handle
  3331. UINT fMask; // original MENUITEMINFO fMask value
  3332. UINT fType; // original MENUITEMINFO fType value
  3333. DWORD_PTR dwItemData; // original MENUITEMINFO dwItemData value
  3334. LPWSTR lpwz; // unicode menu string
  3335. UINT cch; // number of character for menu string
  3336. UINT iTabLength;
  3337. } PUIMENUITEM, *LPPUIMENUITEM;
  3338. void MungeMenuItem(HMENU hMenu, LPCMENUITEMINFOW lpmiiW, LPMENUITEMINFOW lpmiiNewW)
  3339. {
  3340. if (lpmiiW && lpmiiNewW)
  3341. {
  3342. *lpmiiNewW = *lpmiiW;
  3343. if ((MIIM_TYPE & lpmiiW->fMask) && !(MFT_NONSTRING & lpmiiW->fType))
  3344. {
  3345. LPWSTR lpmenuText = (LPWSTR)lpmiiW->dwTypeData;
  3346. if (lpmenuText)
  3347. {
  3348. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)LocalAlloc(LPTR, sizeof(PUIMENUITEM));
  3349. if (lpItem)
  3350. {
  3351. lpItem->dwSig = PUI_OWNERDRAW_SIG;
  3352. lpItem->hmenu = hMenu;
  3353. lpItem->fMask = lpmiiW->fMask;
  3354. lpItem->fType = lpmiiW->fType;
  3355. lpItem->dwItemData = lpmiiW->dwItemData;
  3356. lpItem->cch = lstrlenW(lpmenuText);
  3357. lpItem->lpwz = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * (lpItem->cch + 1));
  3358. if (lpItem->lpwz)
  3359. StrCpyNW(lpItem->lpwz, lpmenuText, lpItem->cch + 1);
  3360. else
  3361. lpItem->cch = 0;
  3362. lpmiiNewW->fType |= MFT_OWNERDRAW;
  3363. lpmiiNewW->fMask |= MIIM_DATA;
  3364. lpmiiNewW->dwItemData = (ULONG_PTR)lpItem;
  3365. lpmiiNewW->dwTypeData = 0;
  3366. lpmiiNewW->cch = 0;
  3367. }
  3368. }
  3369. }
  3370. }
  3371. }
  3372. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3373. void DeleteOwnerDrawMenuItem(HMENU hMenu, UINT uItem, BOOL fByPosition);
  3374. void DeleteOwnerDrawMenu(HMENU hMenu)
  3375. {
  3376. int i, nItem = GetMenuItemCount(hMenu);
  3377. for (i = 0; i < nItem; i++)
  3378. DeleteOwnerDrawMenuItem(hMenu, i, TRUE);
  3379. }
  3380. void DeleteOwnerDrawMenuItem(HMENU hMenu, UINT uItem, BOOL fByPosition)
  3381. {
  3382. MENUITEMINFOA miiA;
  3383. miiA.cbSize = sizeof(miiA);
  3384. miiA.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
  3385. miiA.cch = 0;
  3386. if (GetMenuItemInfoA(hMenu, uItem, fByPosition, &miiA))
  3387. {
  3388. if (miiA.hSubMenu)
  3389. DeleteOwnerDrawMenu(miiA.hSubMenu);
  3390. else
  3391. {
  3392. if ((MIIM_TYPE & miiA.fMask) && (MFT_OWNERDRAW & miiA.fType))
  3393. {
  3394. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)miiA.dwItemData;
  3395. if (!IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig && !(MFT_OWNERDRAW & lpItem->fType))
  3396. {
  3397. if (lpItem->lpwz && lpItem->cch)
  3398. LocalFree(lpItem->lpwz);
  3399. LocalFree(lpItem);
  3400. }
  3401. }
  3402. }
  3403. }
  3404. }
  3405. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3406. BOOL WINAPI
  3407. DeleteMenuWrap(HMENU hMenu, UINT uPosition, UINT uFlags)
  3408. {
  3409. VALIDATE_PROTOTYPEX(DeleteMenu);
  3410. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  3411. if (bOwnerDraw)
  3412. DeleteOwnerDrawMenuItem(hMenu, uPosition, (MF_BYPOSITION & uFlags)? TRUE: FALSE);
  3413. return DeleteMenu(hMenu, uPosition, uFlags);
  3414. }
  3415. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3416. BOOL WINAPI
  3417. DestroyMenuWrap(HMENU hMenu)
  3418. {
  3419. VALIDATE_PROTOTYPEX(DestroyMenu);
  3420. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  3421. if (bOwnerDraw)
  3422. DeleteOwnerDrawMenu(hMenu);
  3423. return DestroyMenu(hMenu);
  3424. }
  3425. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3426. LPBYTE MenuLoadMENUTemplates(LPBYTE lpMenuTemplate, HMENU *phMenu)
  3427. {
  3428. HMENU hMenu;
  3429. UINT menuFlags = 0;
  3430. ULONG_PTR menuId = 0;
  3431. LPWSTR lpmenuText;
  3432. MENUITEMINFO mii;
  3433. if (!(hMenu = CreateMenu()))
  3434. goto memoryerror;
  3435. do
  3436. {
  3437. // Get the menu flags.
  3438. menuFlags = (UINT)(*(WORD *)lpMenuTemplate);
  3439. lpMenuTemplate += 2;
  3440. if (menuFlags & ~MF_VALID) {
  3441. goto memoryerror;
  3442. }
  3443. if (!(menuFlags & MF_POPUP))
  3444. {
  3445. menuId = *(WORD *)lpMenuTemplate;
  3446. lpMenuTemplate += 2;
  3447. }
  3448. lpmenuText = (LPWSTR)lpMenuTemplate;
  3449. if (*lpmenuText) // If a string exists, then skip to the end of it.
  3450. lpMenuTemplate += lstrlenW(lpmenuText) * sizeof(WCHAR);
  3451. else
  3452. lpmenuText = NULL;
  3453. // Skip over terminating NULL of the string (or the single NULL if empty string).
  3454. lpMenuTemplate += sizeof(WCHAR);
  3455. lpMenuTemplate = (BYTE *)(((ULONG_PTR)lpMenuTemplate + 1) & ~1); // word align
  3456. ZeroMemory(&mii, sizeof(mii));
  3457. mii.cbSize = sizeof(MENUITEMINFO);
  3458. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  3459. if (menuFlags & MF_POPUP)
  3460. {
  3461. mii.fMask |= MIIM_SUBMENU;
  3462. lpMenuTemplate = MenuLoadMENUTemplates(lpMenuTemplate, (HMENU *)&menuId);
  3463. if (!lpMenuTemplate)
  3464. goto memoryerror;
  3465. mii.hSubMenu = (HMENU)menuId;
  3466. }
  3467. // Don't allow bitmaps from the resource file.
  3468. if (menuFlags & MF_BITMAP)
  3469. menuFlags = (UINT)((menuFlags | MFT_RIGHTJUSTIFY) & ~MF_BITMAP);
  3470. // We have to take out MFS_HILITE since that bit marks the end of a menu in
  3471. // a resource file. Since we shouldn't have any pre hilited items in the
  3472. // menu anyway, this is no big deal.
  3473. mii.fState = (menuFlags & MFS_OLDAPI_MASK) & ~MFS_HILITE;
  3474. mii.fType = (menuFlags & MFT_OLDAPI_MASK);
  3475. if (menuFlags & MFT_OWNERDRAW)
  3476. {
  3477. mii.fMask |= MIIM_DATA;
  3478. mii.dwItemData = (ULONG_PTR) lpmenuText;
  3479. lpmenuText = 0;
  3480. }
  3481. mii.dwTypeData = (LPTSTR)lpmenuText;
  3482. mii.cch = (UINT)-1;
  3483. mii.wID = (UINT)menuId;
  3484. if (!InsertMenuItemWrapW(hMenu, 0xFFFFFFFF, TRUE, &mii))
  3485. {
  3486. if (menuFlags & MF_POPUP)
  3487. DestroyMenuWrap(mii.hSubMenu);
  3488. goto memoryerror;
  3489. }
  3490. } while (!(menuFlags & MF_END));
  3491. *phMenu = hMenu;
  3492. return lpMenuTemplate;
  3493. memoryerror:
  3494. if (hMenu != NULL)
  3495. DestroyMenuWrap(hMenu);
  3496. *phMenu = NULL;
  3497. return NULL;
  3498. }
  3499. PMENUITEMTEMPLATE2 MenuLoadMENUEXTemplates(PMENUITEMTEMPLATE2 lpMenuTemplate, HMENU *phMenu, WORD wResInfo)
  3500. {
  3501. HMENU hMenu;
  3502. HMENU hSubMenu;
  3503. long menuId = 0;
  3504. LPWSTR lpmenuText;
  3505. MENUITEMINFO mii;
  3506. UINT cch = 0;
  3507. DWORD dwHelpID;
  3508. if (!(hMenu = CreateMenu()))
  3509. goto memoryerror;
  3510. do
  3511. {
  3512. if (!(wResInfo & MFR_POPUP))
  3513. {
  3514. // If the PREVIOUS wResInfo field was not a POPUP, the
  3515. // dwHelpID field is not there. Back up so things fit.
  3516. lpMenuTemplate = (PMENUITEMTEMPLATE2)(((LPBYTE)lpMenuTemplate) - sizeof(lpMenuTemplate->dwHelpID));
  3517. dwHelpID = 0;
  3518. }
  3519. else
  3520. dwHelpID = lpMenuTemplate->dwHelpID;
  3521. menuId = lpMenuTemplate->menuId;
  3522. ZeroMemory(&mii, sizeof(mii));
  3523. mii.cbSize = sizeof(MENUITEMINFO);
  3524. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  3525. mii.fType = lpMenuTemplate->fType;
  3526. if (mii.fType & ~MFT_MASK)
  3527. goto memoryerror;
  3528. mii.fState = lpMenuTemplate->fState;
  3529. if (mii.fState & ~MFS_MASK)
  3530. goto memoryerror;
  3531. wResInfo = lpMenuTemplate->wResInfo;
  3532. if (wResInfo & ~(MF_END | MFR_POPUP))
  3533. goto memoryerror;
  3534. if (dwHelpID)
  3535. SetMenuContextHelpId(hMenu,dwHelpID);
  3536. if (lpMenuTemplate->mtString[0])
  3537. lpmenuText = lpMenuTemplate->mtString;
  3538. else
  3539. lpmenuText = NULL;
  3540. cch = lstrlenW(lpmenuText);
  3541. mii.dwTypeData = (LPTSTR) lpmenuText;
  3542. // skip to next menu item template (DWORD boundary)
  3543. lpMenuTemplate = (PMENUITEMTEMPLATE2)
  3544. (((LPBYTE)lpMenuTemplate) +
  3545. sizeof(MENUITEMTEMPLATE2) +
  3546. ((cch * sizeof(WCHAR) + 3) & ~3));
  3547. if (mii.fType & MFT_OWNERDRAW)
  3548. {
  3549. mii.fMask |= MIIM_DATA;
  3550. mii.dwItemData = (ULONG_PTR) mii.dwTypeData;
  3551. mii.dwTypeData = 0;
  3552. }
  3553. if (wResInfo & MFR_POPUP)
  3554. {
  3555. mii.fMask |= MIIM_SUBMENU;
  3556. lpMenuTemplate = MenuLoadMENUEXTemplates(lpMenuTemplate, &hSubMenu, MFR_POPUP);
  3557. if (lpMenuTemplate == NULL)
  3558. goto memoryerror;
  3559. mii.hSubMenu = hSubMenu;
  3560. }
  3561. // Don't allow bitmaps from the resource file.
  3562. if (mii.fType & MFT_BITMAP)
  3563. mii.fType = (mii.fType | MFT_RIGHTJUSTIFY) & ~MFT_BITMAP;
  3564. mii.cch = (UINT)-1;
  3565. mii.wID = menuId;
  3566. if (!InsertMenuItemWrapW(hMenu, 0xFFFFFFFF, TRUE, &mii))
  3567. {
  3568. if (wResInfo & MFR_POPUP)
  3569. DestroyMenuWrap(mii.hSubMenu);
  3570. goto memoryerror;
  3571. }
  3572. wResInfo &= ~MFR_POPUP;
  3573. } while (!(wResInfo & MFR_END));
  3574. *phMenu = hMenu;
  3575. return lpMenuTemplate;
  3576. memoryerror:
  3577. if (hMenu != NULL)
  3578. DestroyMenuWrap(hMenu);
  3579. *phMenu = NULL;
  3580. return NULL;
  3581. }
  3582. HMENU CreateMenuFromResource(LPBYTE lpMenuTemplate)
  3583. {
  3584. HMENU hMenu = NULL;
  3585. UINT menuTemplateVersion;
  3586. UINT menuTemplateHeaderSize;
  3587. // menu resource: First, strip version number word out of the menu
  3588. // template. This value should be 0 for MENU, 1 for MENUEX.
  3589. menuTemplateVersion = *(WORD *)lpMenuTemplate;
  3590. lpMenuTemplate += 2;
  3591. if (menuTemplateVersion > 1)
  3592. return NULL;
  3593. menuTemplateHeaderSize = *(WORD *)lpMenuTemplate;
  3594. lpMenuTemplate += 2;
  3595. lpMenuTemplate += menuTemplateHeaderSize;
  3596. switch (menuTemplateVersion)
  3597. {
  3598. case 0:
  3599. MenuLoadMENUTemplates(lpMenuTemplate, &hMenu);
  3600. break;
  3601. case 1:
  3602. MenuLoadMENUEXTemplates((PMENUITEMTEMPLATE2)lpMenuTemplate, &hMenu, 0);
  3603. break;
  3604. }
  3605. return hMenu;
  3606. }
  3607. HMENU WINAPI
  3608. LoadMenuWrapW(HINSTANCE hInstance, LPCWSTR lpMenuName)
  3609. {
  3610. VALIDATE_PROTOTYPE(LoadMenu);
  3611. ASSERT(HIWORD64(lpMenuName) == 0);
  3612. if (NeedMenuOwnerDraw() && MLIsMLHInstance(hInstance))
  3613. {
  3614. HRSRC hRes;
  3615. if (hRes = FindResourceWrapW(hInstance, lpMenuName, RT_MENU))
  3616. {
  3617. LPBYTE lpMenuTemplate = (LPBYTE)LoadResource(hInstance, hRes);
  3618. if (lpMenuTemplate)
  3619. {
  3620. HMENU hmenu = CreateMenuFromResource(lpMenuTemplate);
  3621. if (hmenu)
  3622. return hmenu;
  3623. }
  3624. }
  3625. }
  3626. if (g_bRunningOnNT)
  3627. {
  3628. return LoadMenuW(hInstance, lpMenuName);
  3629. }
  3630. return LoadMenuA(hInstance, (LPCSTR) lpMenuName);
  3631. }
  3632. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3633. #define CX_MENUCHECK 8
  3634. #define CY_MENUCHECK 8
  3635. #define CHK_RADIO 0x006C
  3636. #define CHK_NORMAL 0x00FC
  3637. int FindCharPosition(LPCWSTR lpwStr, WCHAR wch)
  3638. {
  3639. int iPos;
  3640. int iLength = lstrlenW(lpwStr);
  3641. for (iPos = 0; iPos < iLength; iPos++)
  3642. {
  3643. if (lpwStr[iPos] == wch)
  3644. break;
  3645. }
  3646. return (iPos < iLength) ? iPos : -1;
  3647. }
  3648. int CalculateMenuTabString(HWND hWnd, HMENU hMenu)
  3649. {
  3650. int i;
  3651. int iMenuCount = GetMenuItemCount(hMenu);
  3652. int iLength;
  3653. int iTabPos = 0;
  3654. int iMaxTabLength = 0;
  3655. RECT rc;
  3656. HDC hdc;
  3657. HFONT hfont, hfontSav;
  3658. NONCLIENTMETRICSA ncm;
  3659. MENUITEMINFOA miiA;
  3660. ncm.cbSize = sizeof(ncm);
  3661. if (!SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
  3662. return 0;
  3663. hfont = CreateFontIndirectA(&ncm.lfMenuFont);
  3664. if (NULL == hfont)
  3665. return 0;
  3666. hdc = GetDC(hWnd);
  3667. hfontSav = (HFONT)SelectObject(hdc, hfont);
  3668. for (i = 0; i < iMenuCount; i++)
  3669. {
  3670. miiA.cbSize = sizeof(miiA);
  3671. miiA.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
  3672. miiA.cch = 0;
  3673. if (GetMenuItemInfoA(hMenu, i, MF_BYPOSITION, &miiA))
  3674. {
  3675. if (miiA.hSubMenu)
  3676. CalculateMenuTabString(hWnd, miiA.hSubMenu);
  3677. if ((MIIM_TYPE & miiA.fMask) && (MFT_OWNERDRAW & miiA.fType))
  3678. {
  3679. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)miiA.dwItemData;
  3680. if (!IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig && !(MFT_OWNERDRAW & lpItem->fType))
  3681. {
  3682. if (lpItem->lpwz && lpItem->cch)
  3683. {
  3684. iTabPos = FindCharPosition(lpItem->lpwz, L'\t');
  3685. if (iTabPos >= 0)
  3686. {
  3687. DrawTextFLW(hdc, lpItem->lpwz + iTabPos + 1,
  3688. lstrlenW(lpItem->lpwz) - iTabPos - 1, &rc, DT_SINGLELINE | DT_CALCRECT);
  3689. iLength = rc.right - rc.left;
  3690. if (iLength > iMaxTabLength)
  3691. iMaxTabLength = iLength;
  3692. }
  3693. }
  3694. }
  3695. }
  3696. }
  3697. }
  3698. for (i = 0; i < iMenuCount; i++)
  3699. {
  3700. miiA.cbSize = sizeof(miiA);
  3701. miiA.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
  3702. miiA.cch = 0;
  3703. if (GetMenuItemInfoA(hMenu, i, MF_BYPOSITION, &miiA))
  3704. {
  3705. if ((MIIM_TYPE & miiA.fMask) && (MFT_OWNERDRAW & miiA.fType))
  3706. {
  3707. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)miiA.dwItemData;
  3708. if (!IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig && !(MFT_OWNERDRAW & lpItem->fType))
  3709. {
  3710. if (lpItem->lpwz && lpItem->cch)
  3711. {
  3712. lpItem->iTabLength = iMaxTabLength;
  3713. }
  3714. }
  3715. }
  3716. }
  3717. }
  3718. SelectObject(hdc, hfontSav);
  3719. DeleteObject(hfont);
  3720. ReleaseDC(hWnd, hdc);
  3721. return iMaxTabLength;
  3722. }
  3723. void DrawMenuItemCheckMark(HDC hdc, LPCSTR lpChkSym, LPRECT lprc, UINT uFormat)
  3724. {
  3725. HFONT hFont, hFontSave;
  3726. NONCLIENTMETRICSA ncm;
  3727. ncm.cbSize = sizeof(ncm);
  3728. if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
  3729. {
  3730. StrCpyNA(ncm.lfMenuFont.lfFaceName, "Wingdings", LF_FACESIZE);
  3731. ncm.lfMenuFont.lfCharSet = SYMBOL_CHARSET;
  3732. hFont = CreateFontIndirectA(&ncm.lfMenuFont);
  3733. if ( hFont == NULL )
  3734. return;
  3735. hFontSave = (HFONT)SelectObject(hdc, hFont);
  3736. DrawTextA(hdc, lpChkSym, 1, lprc, uFormat);
  3737. hFont = (HFONT)SelectObject(hdc, hFontSave);
  3738. DeleteObject(hFont);
  3739. }
  3740. }
  3741. void DrawMenuItemText(HDC hdc, LPCWSTR lpwMenuStr, LPRECT lprc, UINT uiRefData)
  3742. {
  3743. UINT uFormat = DT_VCENTER | DT_SINGLELINE | DT_LEFT | DT_EXPANDTABS;
  3744. int iTabPos;
  3745. iTabPos = FindCharPosition(lpwMenuStr, L'\t');
  3746. if(iTabPos < 0)
  3747. {
  3748. // No TAB string is in the menu string
  3749. DrawTextFLW(hdc, lpwMenuStr, lstrlenW(lpwMenuStr), lprc, uFormat);
  3750. }
  3751. else
  3752. {
  3753. RECT rc;
  3754. // Draw Text before TAB
  3755. DrawTextFLW(hdc, lpwMenuStr, iTabPos, lprc, uFormat);
  3756. // Adjust RC for after TAB string.
  3757. CopyRect(&rc, lprc);
  3758. rc.left = rc.right - uiRefData - GetSystemMetrics(SM_CXMENUCHECK);
  3759. DrawTextFLW(hdc, lpwMenuStr + iTabPos + 1, lstrlenW(lpwMenuStr) - iTabPos - 1, &rc, uFormat);
  3760. }
  3761. }
  3762. void DrawMenuItem(LPDRAWITEMSTRUCT lpdis, LPRECT lprc)
  3763. {
  3764. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)lpdis->itemData;
  3765. if (lpItem && lpItem->lpwz)
  3766. {
  3767. HDC hdc = lpdis->hDC;
  3768. UINT uFormat = DT_VCENTER | DT_SINGLELINE | DT_LEFT | DT_EXPANDTABS;
  3769. CHAR ChkSym[2] = {(CHAR)CHK_NORMAL, 0x00};
  3770. COLORREF clrTxt;
  3771. int iBkMode;
  3772. RECT rc;
  3773. if (ODS_CHECKED & lpdis->itemState)
  3774. {
  3775. MENUITEMINFOA miiA;
  3776. miiA.cbSize = sizeof(miiA);
  3777. miiA.fMask = MIIM_TYPE;
  3778. miiA.cch = 0;
  3779. if (GetMenuItemInfoA(lpItem->hmenu, lpdis->itemID, FALSE, &miiA))
  3780. {
  3781. if (MFT_RADIOCHECK & miiA.fType)
  3782. ChkSym[0] = CHK_RADIO;
  3783. }
  3784. }
  3785. iBkMode = SetBkMode(hdc, TRANSPARENT);
  3786. if (ODS_GRAYED & lpdis->itemState)
  3787. {
  3788. clrTxt = SetTextColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
  3789. if (ODS_CHECKED & lpdis->itemState)
  3790. {
  3791. CopyRect(&rc, &(lpdis->rcItem));
  3792. OffsetRect(&rc, 1, 1);
  3793. DrawMenuItemCheckMark(hdc, ChkSym, &rc, uFormat);
  3794. }
  3795. CopyRect(&rc, lprc);
  3796. OffsetRect(&rc, 1, 1);
  3797. DrawMenuItemText(hdc, lpItem->lpwz, &rc, lpItem->iTabLength);
  3798. SetTextColor(hdc, GetSysColor(COLOR_BTNSHADOW));
  3799. }
  3800. if (ODS_CHECKED & lpdis->itemState)
  3801. DrawMenuItemCheckMark(hdc, ChkSym, &(lpdis->rcItem), uFormat);
  3802. DrawMenuItemText(hdc, lpItem->lpwz, lprc, lpItem->iTabLength);
  3803. if (ODS_GRAYED & lpdis->itemState)
  3804. SetTextColor(hdc, clrTxt);
  3805. SetBkMode(hdc, iBkMode);
  3806. }
  3807. }
  3808. LRESULT OwnerDrawSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  3809. {
  3810. switch (uMsg)
  3811. {
  3812. case WM_DRAWITEM:
  3813. if (0 == wParam) // This is a menu
  3814. {
  3815. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  3816. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)lpdis->itemData;
  3817. if (lpdis->CtlType == ODT_MENU
  3818. && !IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig
  3819. && !(MFT_OWNERDRAW & lpItem->fType))
  3820. {
  3821. int cyTemp;
  3822. RECT rc;
  3823. HDC hdc = lpdis->hDC;
  3824. HFONT hfont, hfontSav;
  3825. TEXTMETRICA tm;
  3826. NONCLIENTMETRICSA ncm;
  3827. ncm.cbSize = sizeof(ncm);
  3828. if (!SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
  3829. break;
  3830. hfont = CreateFontIndirectA(&ncm.lfMenuFont);
  3831. if (NULL == hfont)
  3832. break;
  3833. hfontSav = (HFONT)SelectObject(hdc, hfont);
  3834. GetTextMetricsA(hdc, &tm);
  3835. CopyRect(&rc, &lpdis->rcItem);
  3836. rc.left += GetSystemMetrics(SM_CXMENUCHECK);
  3837. rc.top += tm.tmExternalLeading;
  3838. cyTemp = (lpdis->rcItem.bottom - lpdis->rcItem.top) - (tm.tmHeight + tm.tmExternalLeading + GetSystemMetrics(SM_CYBORDER));
  3839. if (cyTemp > 0)
  3840. rc.top += (cyTemp / 2);
  3841. switch (lpdis->itemAction)
  3842. {
  3843. case ODA_DRAWENTIRE:
  3844. DrawMenuItem(lpdis, &rc);
  3845. break;
  3846. case ODA_FOCUS:
  3847. break;
  3848. case ODA_SELECT:
  3849. {
  3850. COLORREF clrTxt, clrBk, clrTxtSav, clrBkSav;
  3851. if (ODS_SELECTED & lpdis->itemState)
  3852. {
  3853. clrTxt = GetSysColor(COLOR_HIGHLIGHTTEXT);
  3854. clrBk = GetSysColor(COLOR_HIGHLIGHT);
  3855. }
  3856. else
  3857. {
  3858. clrTxt = GetSysColor(COLOR_MENUTEXT);
  3859. clrBk = GetSysColor(COLOR_MENU);
  3860. }
  3861. clrTxtSav = SetTextColor(hdc, clrTxt);
  3862. clrBkSav = SetBkColor(hdc, clrBk);
  3863. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &lpdis->rcItem, TEXT(""), 0, NULL);
  3864. DrawMenuItem(lpdis, &rc);
  3865. SetTextColor(hdc, clrTxtSav);
  3866. SetBkColor(hdc, clrBkSav);
  3867. break;
  3868. }
  3869. }
  3870. SelectObject(hdc, hfontSav);
  3871. DeleteObject(hfont);
  3872. return TRUE;
  3873. }
  3874. }
  3875. break;
  3876. case WM_MEASUREITEM:
  3877. if (0 == wParam) // This is a menu
  3878. {
  3879. LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
  3880. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)lpmis->itemData;
  3881. if (lpmis->CtlType == ODT_MENU
  3882. && !IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig
  3883. && !(MFT_OWNERDRAW & lpItem->fType) && lpItem->lpwz)
  3884. {
  3885. RECT rc;
  3886. HDC hdc;
  3887. HFONT hfont, hfontSav;
  3888. NONCLIENTMETRICSA ncm;
  3889. int iTabPos;
  3890. ncm.cbSize = sizeof(ncm);
  3891. if (!SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
  3892. break;
  3893. hfont = CreateFontIndirectA(&ncm.lfMenuFont);
  3894. if (NULL == hfont)
  3895. break;
  3896. hdc = GetDC(hWnd);
  3897. hfontSav = (HFONT)SelectObject(hdc, hfont);
  3898. iTabPos = FindCharPosition(lpItem->lpwz, L'\t');
  3899. if (iTabPos < 0)
  3900. iTabPos = lstrlenW(lpItem->lpwz);
  3901. DrawTextFLW(hdc, lpItem->lpwz, iTabPos, &rc, DT_SINGLELINE | DT_CALCRECT | DT_EXPANDTABS);
  3902. SelectObject(hdc, hfontSav);
  3903. DeleteObject(hfont);
  3904. ReleaseDC(hWnd, hdc);
  3905. lpmis->itemWidth = rc.right - rc.left + GetSystemMetrics(SM_CXMENUCHECK) +
  3906. GetSystemMetrics(SM_CXEDGE) * 2 + lpItem->iTabLength;
  3907. lpmis->itemHeight = rc.bottom - rc.top + GetSystemMetrics(SM_CYEDGE) * 2;
  3908. return TRUE;
  3909. }
  3910. }
  3911. break;
  3912. case WM_MENUCHAR:
  3913. // FEATURE: need to be implemented
  3914. break;
  3915. }
  3916. return DefSubclassProc(hWnd, uMsg, wParam, lParam);
  3917. }
  3918. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3919. int WINAPI
  3920. GetMenuStringWrapW(
  3921. HMENU hMenu,
  3922. UINT uIDItem,
  3923. LPWSTR lpString,
  3924. int nMaxCount,
  3925. UINT uFlag)
  3926. {
  3927. VALIDATE_PROTOTYPE(GetMenuString);
  3928. VALIDATE_OUTBUF(lpString, nMaxCount);
  3929. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  3930. if (bOwnerDraw)
  3931. {
  3932. MENUITEMINFOA miiA;
  3933. miiA.cbSize = sizeof(miiA);
  3934. miiA.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
  3935. miiA.cch = 0;
  3936. if (GetMenuItemInfoA(hMenu, uIDItem, (uFlag & MF_BYPOSITION)? TRUE: FALSE, &miiA))
  3937. {
  3938. if ((MIIM_TYPE & miiA.fMask) && (MFT_OWNERDRAW & miiA.fType))
  3939. {
  3940. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)miiA.dwItemData;
  3941. if (!IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig && !(MFT_OWNERDRAW & lpItem->fType))
  3942. {
  3943. if (lpItem->lpwz && lpItem->cch)
  3944. {
  3945. StrCpyNW(lpString, lpItem->lpwz, nMaxCount);
  3946. return min((UINT)(nMaxCount - 1), lpItem->cch);
  3947. }
  3948. }
  3949. }
  3950. }
  3951. }
  3952. if (g_bRunningOnNT)
  3953. {
  3954. return GetMenuStringW(hMenu, uIDItem, lpString, nMaxCount, uFlag);
  3955. }
  3956. CStrOut str(lpString, nMaxCount);
  3957. GetMenuStringA(hMenu, uIDItem, str, str.BufSize(), uFlag);
  3958. return str.ConvertExcludingNul();
  3959. }
  3960. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  3961. BOOL WINAPI
  3962. InsertMenuWrapW(
  3963. HMENU hMenu,
  3964. UINT uPosition,
  3965. UINT uFlags,
  3966. UINT_PTR uIDNewItem,
  3967. LPCWSTR lpNewItem)
  3968. {
  3969. VALIDATE_PROTOTYPE(InsertMenu);
  3970. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  3971. if (bOwnerDraw)
  3972. {
  3973. if (!((MF_BITMAP | MF_OWNERDRAW) & uFlags)) // if MF_STRING is set. MF_STRING is 0
  3974. {
  3975. MENUITEMINFOW miiW;
  3976. miiW.cbSize = sizeof(miiW);
  3977. miiW.fMask = MIIM_TYPE | MIIM_STATE;
  3978. miiW.fType = MFT_STRING;
  3979. miiW.fState = uFlags & (MF_DEFAULT | MF_CHECKED | MF_UNCHECKED | MF_HILITE | MF_UNHILITE| MF_ENABLED | MF_DISABLED | MF_GRAYED);
  3980. if (uFlags & (MF_GRAYED | MF_DISABLED))
  3981. miiW.fState |= MFS_GRAYED;
  3982. if (MF_POPUP & uFlags)
  3983. {
  3984. miiW.fMask |= MIIM_SUBMENU;
  3985. miiW.hSubMenu = (HMENU)uIDNewItem;
  3986. }
  3987. else
  3988. {
  3989. miiW.fMask |= MIIM_ID;
  3990. miiW.wID = (UINT)uIDNewItem;
  3991. }
  3992. miiW.dwTypeData = (LPWSTR)lpNewItem;
  3993. miiW.cch = lstrlenW(lpNewItem);
  3994. return InsertMenuItemWrapW(hMenu, uPosition, (MF_BYPOSITION & uFlags)? TRUE: FALSE, &miiW);
  3995. }
  3996. }
  3997. if (g_bRunningOnNT)
  3998. {
  3999. return InsertMenuW(hMenu, uPosition, uFlags, uIDNewItem, lpNewItem);
  4000. }
  4001. //
  4002. // You can't test for MFT_STRING because MFT_STRING is zero!
  4003. // So instead you have to check for everything *other* than
  4004. // a string.
  4005. //
  4006. // The presence of any non-string menu type turns lpnewItem into
  4007. // an atom.
  4008. //
  4009. CStrIn str((uFlags & MFT_NONSTRING) ? CP_ATOM : CP_ACP, lpNewItem);
  4010. return InsertMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
  4011. }
  4012. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  4013. BOOL IsWindowOnCurrentThread(HWND hWnd)
  4014. {
  4015. DWORD foo;
  4016. if (!IsWindow(hWnd))
  4017. // bail if the window is dead so we dont bogusly rip
  4018. return TRUE;
  4019. if (GetCurrentThreadId() != GetWindowThreadProcessId(hWnd, &foo))
  4020. return FALSE;
  4021. else
  4022. return TRUE;
  4023. }
  4024. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  4025. BOOL WINAPI
  4026. TrackPopupMenuWrap(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT *prcRect)
  4027. {
  4028. VALIDATE_PROTOTYPEX(TrackPopupMenu);
  4029. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  4030. BOOL bIsWindowOnCurrentThread, bRet;
  4031. if (bOwnerDraw && (bIsWindowOnCurrentThread = IsWindowOnCurrentThread(hWnd)))
  4032. {
  4033. CalculateMenuTabString(hWnd, hMenu);
  4034. SetWindowSubclass(hWnd, OwnerDrawSubclassProc, 0, (DWORD_PTR)NULL);
  4035. }
  4036. bRet = TrackPopupMenu(hMenu, uFlags, x, y, nReserved, hWnd, prcRect);
  4037. if (bOwnerDraw && bIsWindowOnCurrentThread)
  4038. RemoveWindowSubclass(hWnd, OwnerDrawSubclassProc, 0);
  4039. return bRet;
  4040. }
  4041. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  4042. BOOL WINAPI
  4043. TrackPopupMenuExWrap(HMENU hMenu, UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpm)
  4044. {
  4045. VALIDATE_PROTOTYPEX(TrackPopupMenuEx);
  4046. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  4047. BOOL bIsWindowOnCurrentThread, bRet;
  4048. if (bOwnerDraw && (bIsWindowOnCurrentThread = IsWindowOnCurrentThread(hWnd)))
  4049. {
  4050. CalculateMenuTabString(hWnd, hMenu);
  4051. SetWindowSubclass(hWnd, OwnerDrawSubclassProc, 0, (DWORD_PTR)NULL);
  4052. }
  4053. bRet = TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
  4054. if (bOwnerDraw && bIsWindowOnCurrentThread)
  4055. RemoveWindowSubclass(hWnd, OwnerDrawSubclassProc, 0);
  4056. return bRet;
  4057. }
  4058. #ifdef NEED_USER32_WRAPPER
  4059. int WINAPI
  4060. LoadStringWrapW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax)
  4061. {
  4062. VALIDATE_PROTOTYPE(LoadString);
  4063. if (g_bRunningOnNT)
  4064. {
  4065. return LoadStringW(hInstance, uID, lpBuffer, nBufferMax);
  4066. }
  4067. //
  4068. // Do it manually. The old code used to call LoadStringA and then
  4069. // convert it up to unicode, which is bad, since resources are
  4070. // physically already Unicode! Just copy it out directly.
  4071. //
  4072. // The old code was also buggy in the case where the loaded string
  4073. // contains embedded NULLs.
  4074. //
  4075. if (nBufferMax <= 0) return 0; // sanity check
  4076. PWCHAR pwch;
  4077. /*
  4078. * String tables are broken up into "bundles" of 16 strings each.
  4079. */
  4080. HRSRC hrsrc;
  4081. int cwch = 0;
  4082. hrsrc = FindResourceA(hInstance, (LPSTR)(LONG_PTR)(1 + uID / 16), (LPSTR)RT_STRING);
  4083. if (hrsrc) {
  4084. pwch = (PWCHAR)LoadResource(hInstance, hrsrc);
  4085. if (pwch) {
  4086. /*
  4087. * Now skip over the strings in the resource until we
  4088. * hit the one we want. Each entry is a counted string,
  4089. * just like Pascal.
  4090. */
  4091. for (uID %= 16; uID; uID--) {
  4092. pwch += *pwch + 1;
  4093. }
  4094. cwch = min(*pwch, nBufferMax - 1);
  4095. memcpy(lpBuffer, pwch+1, cwch * sizeof(WCHAR)); /* Copy the goo */
  4096. }
  4097. }
  4098. lpBuffer[cwch] = L'\0'; /* Terminate the string */
  4099. return cwch;
  4100. }
  4101. #endif // NEED_USER32_WRAPPER
  4102. //----------------------------------------------------------------------
  4103. //
  4104. // function: TransformCharNoOp1( WCHAR **ppch )
  4105. //
  4106. // purpose: Stand-in for TransformCharWidth. Used by the function
  4107. // CompareStringString.
  4108. //
  4109. // returns: Character at *ppch. The value *ppch is incremented.
  4110. //
  4111. //----------------------------------------------------------------------
  4112. static WCHAR
  4113. TransformCharNoOp1( LPCWSTR *ppch, int )
  4114. {
  4115. WCHAR ch = **ppch;
  4116. (*ppch)++;
  4117. return ch;
  4118. }
  4119. //----------------------------------------------------------------------
  4120. //
  4121. // function: TransformCharWidth( WCHAR **ppch, cchRemaining )
  4122. //
  4123. // purpose: Converts halfwidth characters to fullwidth characters.
  4124. // Also combines voiced (dakuon) and semi-voiced (handakuon)
  4125. // characters. *pch is advanced by one, unless there is a
  4126. // (semi)voiced character, in which case it is advanced by
  4127. // two characters.
  4128. //
  4129. // Note that unlike the full widechar version, we do not
  4130. // combine other characters, notably the combining Hiragana
  4131. // characters (U+3099 and U+309A.) This is to keep the
  4132. // tables from getting unnecessarily large.
  4133. //
  4134. // cchRemaining is passed so as to not include the voiced
  4135. // marks if it's passed the end of the specified buffer.
  4136. //
  4137. // returns: Full width character. *pch is incremented.
  4138. //
  4139. //----------------------------------------------------------------------
  4140. static WCHAR
  4141. TransformCharWidth( LPCWSTR *ppch, int cchRemaining )
  4142. {
  4143. WCHAR ch = **ppch;
  4144. (*ppch)++;
  4145. if (ch == 0x0020)
  4146. {
  4147. ch = 0x3000;
  4148. }
  4149. else if (ch == 0x005c)
  4150. {
  4151. // REVERSE SOLIDUS (aka BACKSLASH) maps to itself
  4152. }
  4153. else if (InRange(ch, 0x0021, 0x07e))
  4154. {
  4155. ch += 65248;
  4156. }
  4157. else if (InRange(ch, 0x00a2, 0x00af))
  4158. {
  4159. static const WCHAR achFull[] =
  4160. {
  4161. 0xffe0, 0xffe1, 0x00a4, 0xffe5, 0xffe4, 0x00a7, 0x00a8, // 0xa2-0xa8
  4162. 0x00a9, 0x00aa, 0x00ab, 0xffe2, 0x00ad, 0x00ae, 0xffe3 // 0xa9-0xaf
  4163. };
  4164. ch = achFull[ch - 0x00a2];
  4165. }
  4166. else if (ch == 0x20a9) // WON SIGN
  4167. {
  4168. ch = 0xffe6;
  4169. }
  4170. else if (InRange(ch, 0xff61, 0xffdc))
  4171. {
  4172. WCHAR chNext = (cchRemaining > 1) ? **ppch : 0;
  4173. if (chNext == 0xff9e && InRange(ch, 0xff73, 0xff8e))
  4174. {
  4175. if (cchRemaining != 1)
  4176. {
  4177. static const WCHAR achFull[] =
  4178. {
  4179. /* 0xff73-0xff79 */ 0xb0f4, 0x30a8, 0x30aa, 0xb0ac, 0xb0ae, 0xb0b0, 0xb0b2,
  4180. /* 0xff7a-0xff80 */ 0xb0b4, 0xb0b6, 0xb0b8, 0xb0ba, 0xb0bc, 0xb0be, 0xb0c0,
  4181. /* 0xff81-0xff87 */ 0xb0c2, 0xb0c5, 0xb0c7, 0xb0c9, 0x30ca, 0x30cb, 0x30cc,
  4182. /* 0xff88-0xff8e */ 0x30cd, 0x30ce, 0xb0d0, 0xb0d3, 0xb0d6, 0xb0d9, 0xb0dc
  4183. };
  4184. // HALFWIDTH KATAKANA VOICED SOUND MARK
  4185. WCHAR chTemp = achFull[ch - 0xff73];
  4186. // Some in the range absorb the sound mark.
  4187. // These are indicated by the set high-bit.
  4188. ch = chTemp & 0x7fff;
  4189. if (chTemp & 0x8000)
  4190. {
  4191. (*ppch)++;
  4192. }
  4193. }
  4194. }
  4195. else if (chNext == 0xff9f && InRange(ch, 0xff8a, 0xff8e))
  4196. {
  4197. // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
  4198. ch = 0x30d1 + (ch - 0xff8a) * 3;
  4199. (*ppch)++;
  4200. }
  4201. else
  4202. {
  4203. static const WCHAR achMapFullFFxx[] =
  4204. {
  4205. 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1, // 0xff61-0xff67
  4206. 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, // 0xff68-0xff6e
  4207. 0x30c3, 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, // 0xff6f-0xff75
  4208. 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, // 0xff76-0xff7c
  4209. 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c4, 0x30c6, // 0xff7d-0xff83
  4210. 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, // 0xff84-0xff8a
  4211. 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, // 0xff8b-0xff91
  4212. 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, 0x30ea, // 0xff92-0xff98
  4213. 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c, // 0xff99-0xff9f
  4214. 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, // 0xffa0-0xffa6
  4215. 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, // 0xffa7-0xffad
  4216. 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, // 0xffae-0xffb4
  4217. 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, // 0xffb5-0xffbb
  4218. 0x314c, 0x314d, 0x314e, 0xffbf, 0xffc0, 0xffc1, 0x314f, // 0xffbc-0xffc2
  4219. 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0xffc8, 0xffc9, // 0xffc3-0xffc9
  4220. 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0xffd0, // 0xffca-0xffd0
  4221. 0xffd1, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, // 0xffd1-0xffd7
  4222. 0xffd8, 0xffd9, 0x3161, 0x3162, 0x3163 // 0xffd8-0xffac
  4223. };
  4224. ch = achMapFullFFxx[ch - 0xff61];
  4225. }
  4226. }
  4227. return ch;
  4228. }
  4229. //----------------------------------------------------------------------
  4230. //
  4231. // function: TransformaCharNoOp2( WCHAR ch )
  4232. //
  4233. // purpose: Stand-in for CharLowerBuffWrap. Used by the function
  4234. // CompareStringString.
  4235. //
  4236. // returns: Original character
  4237. //
  4238. //----------------------------------------------------------------------
  4239. static WCHAR
  4240. TransformCharNoOp2( WCHAR ch )
  4241. {
  4242. return ch;
  4243. }
  4244. //----------------------------------------------------------------------
  4245. //
  4246. // function: TransformaCharKana( WCHAR ch )
  4247. //
  4248. // purpose: Converts Hiragana characters to Katakana characters
  4249. //
  4250. // returns: Original character if not Hiragana,
  4251. // Katanaka character if Hiragana
  4252. //
  4253. //----------------------------------------------------------------------
  4254. static WCHAR
  4255. TransformCharKana( WCHAR ch )
  4256. {
  4257. if (((ch & 0xff00) == 0x3000) &&
  4258. (InRange(ch, 0x3041, 0x3094) || InRange(ch, 0x309d, 0x309e)))
  4259. {
  4260. ch += 0x060;
  4261. }
  4262. return ch;
  4263. }
  4264. //----------------------------------------------------------------------
  4265. //
  4266. // function: TransformCharNoOp3( LPWSTR pch, DWORD cch )
  4267. //
  4268. // purpose: Stand-in for CharLowerBuffWrap. Used by the function
  4269. // CompareStringString.
  4270. //
  4271. // returns: Character count (cch).
  4272. //
  4273. //----------------------------------------------------------------------
  4274. static DWORD
  4275. TransformCharNoOp3( LPWSTR, DWORD cch )
  4276. {
  4277. return cch;
  4278. }
  4279. //----------------------------------------------------------------------
  4280. //
  4281. // function: TransformaCharFinal( WCHAR ch )
  4282. //
  4283. // purpose: Converts "final" forms to regular forms
  4284. //
  4285. // returns: Original character if not Hiragana,
  4286. // Katanaka character if Hiragana
  4287. //
  4288. //----------------------------------------------------------------------
  4289. // REARCHITECT (cthrash) We do not fold Presentation Forms (Alphabetic or Arabic)
  4290. static WCHAR
  4291. TransformCharFinal( WCHAR ch )
  4292. {
  4293. WCHAR chRet = ch;
  4294. if (ch >= 0x3c2) // short-circuit ASCII +
  4295. {
  4296. switch (ch)
  4297. {
  4298. case 0x03c2: // GREEK SMALL LETTER FINAL SIGMA
  4299. case 0x05da: // HEBREW LETTER FINAL KAF
  4300. case 0x05dd: // HEBREW LETTER FINAL MEM
  4301. case 0x05df: // HEBREW LETTER FINAL NUN
  4302. case 0x05e3: // HEBREW LETTER FINAL PE
  4303. case 0x05e5: // HEBREW LETTER FINAL TSADI
  4304. case 0xfb26: // HEBREW LETTER WIDE FINAL MEM
  4305. case 0xfb3a: // HEBREW LETTER FINAL KAF WITH DAGESH
  4306. case 0xfb43: // HEBREW LETTER FINAL PE WITH DAGESH
  4307. chRet++;
  4308. break;
  4309. }
  4310. }
  4311. return ch;
  4312. }
  4313. //----------------------------------------------------------------------
  4314. //
  4315. // function: CompareStringString( ... )
  4316. //
  4317. // purpose: Helper for CompareStringWrap.
  4318. //
  4319. // We handle the string comparsion for CompareStringWrap.
  4320. // We can convert each character to (1) fullwidth,
  4321. // (2) Katakana, and (3) lowercase, as necessary.
  4322. //
  4323. // returns: 1 - string A is less in lexical value as string B
  4324. // 2 - string B is equal in lexical value as string B
  4325. // 3 - string B is greater in lexical value as string B
  4326. //
  4327. //----------------------------------------------------------------------
  4328. static int
  4329. CompareStringString(
  4330. DWORD dwFlags,
  4331. LPCWSTR lpA,
  4332. int cchA,
  4333. LPCWSTR lpB,
  4334. int cchB )
  4335. {
  4336. int nRet = 0;
  4337. WCHAR wchIgnoreNulA = cchA == -1 ? 0 : -1;
  4338. WCHAR wchIgnoreNulB = cchB == -1 ? 0 : -1;
  4339. WCHAR (*pfnTransformWidth)(LPCWSTR *, int);
  4340. WCHAR (*pfnTransformKana)(WCHAR);
  4341. DWORD (*pfnTransformLower)(LPWSTR, DWORD);
  4342. WCHAR (*pfnTransformFinal)(WCHAR);
  4343. pfnTransformWidth = (dwFlags & NORM_IGNOREWIDTH)
  4344. ? TransformCharWidth : TransformCharNoOp1;
  4345. pfnTransformKana = (dwFlags & NORM_IGNOREKANATYPE)
  4346. ? TransformCharKana : TransformCharNoOp2;
  4347. pfnTransformLower = (dwFlags & NORM_IGNORECASE)
  4348. ? CharLowerBuffWrap : TransformCharNoOp3;
  4349. pfnTransformFinal = (dwFlags & NORM_IGNORECASE)
  4350. ? TransformCharFinal : TransformCharNoOp2;
  4351. while ( !nRet
  4352. && cchA
  4353. && cchB
  4354. && (*lpA | wchIgnoreNulA)
  4355. && (*lpB | wchIgnoreNulB) )
  4356. {
  4357. WCHAR chA, chB;
  4358. LPCWSTR lpAOld = lpA;
  4359. LPCWSTR lpBOld = lpB;
  4360. chA = (*pfnTransformWidth)(&lpA, cchA);
  4361. chA = (*pfnTransformKana)(chA);
  4362. (*pfnTransformLower)(&chA, 1);
  4363. chA = (*pfnTransformFinal)(chA);
  4364. chB = (*pfnTransformWidth)(&lpB, cchB);
  4365. chB = (*pfnTransformKana)(chB);
  4366. (*pfnTransformLower)(&chB, 1);
  4367. chB = (*pfnTransformFinal)(chB);
  4368. nRet = (int)chA - (int)chB;
  4369. cchA -= (int) (lpA - lpAOld);
  4370. cchB -= (int) (lpB - lpBOld);
  4371. }
  4372. if (!nRet)
  4373. {
  4374. nRet = cchA - cchB;
  4375. }
  4376. if (nRet)
  4377. {
  4378. nRet = nRet > 0 ? 1 : -1;
  4379. }
  4380. return nRet + 2;
  4381. }
  4382. //----------------------------------------------------------------------
  4383. //
  4384. // function: CompareStringWord( ... )
  4385. //
  4386. // purpose: Helper for CompareStringWrap.
  4387. //
  4388. // We handle the word comparsion for CompareStringWrap.
  4389. //
  4390. // returns: 1 - string A is less in lexical value as string B
  4391. // 2 - string B is equal in lexical value as string B
  4392. // 3 - string B is greater in lexical value as string B
  4393. //
  4394. //----------------------------------------------------------------------
  4395. static int
  4396. CompareStringWord(
  4397. LCID lcid,
  4398. DWORD dwFlags,
  4399. LPCWSTR lpA,
  4400. int cchA,
  4401. LPCWSTR lpB,
  4402. int cchB )
  4403. {
  4404. // FEATURE (cthrash) We won't properly support word compare for the
  4405. // time being. Do the same old CP_ACP trick, which should cover
  4406. // enough cases.
  4407. // fail if either string is NULL, as it causes assert on debug windows
  4408. if (!lpA || !lpB)
  4409. return 0;
  4410. CStrIn strA(lpA, cchA);
  4411. CStrIn strB(lpB, cchB);
  4412. cchA = strA.strlen();
  4413. cchB = strB.strlen();
  4414. return CompareStringA(lcid, dwFlags, strA, cchA, strB, cchB);
  4415. }
  4416. //----------------------------------------------------------------------
  4417. //
  4418. // function: CompareStringWrapW( ... )
  4419. //
  4420. // purpose: Unicode wrapper of CompareString for Win95.
  4421. //
  4422. // Note not all bits in dwFlags are honored; specifically,
  4423. // since we don't do a true widechar word compare, we
  4424. // won't properly handle NORM_IGNORENONSPACE or
  4425. // NORM_IGNORESYMBOLS for arbitrary widechar strings.
  4426. //
  4427. // returns: 1 - string A is less in lexical value as string B
  4428. // 2 - string B is equal in lexical value as string B
  4429. // 3 - string B is greater in lexical value as string B
  4430. //
  4431. //----------------------------------------------------------------------
  4432. LWSTDAPI_(int)
  4433. CompareStringAltW(
  4434. LCID lcid,
  4435. DWORD dwFlags,
  4436. LPCWSTR lpA,
  4437. int cchA,
  4438. LPCWSTR lpB,
  4439. int cchB )
  4440. {
  4441. if (g_bRunningOnNT)
  4442. {
  4443. return CompareStringW(lcid, dwFlags, lpA, cchA, lpB, cchB);
  4444. }
  4445. int nRet;
  4446. if (dwFlags & SORT_STRINGSORT)
  4447. {
  4448. nRet = CompareStringString(dwFlags, lpA, cchA, lpB, cchB);
  4449. }
  4450. else
  4451. {
  4452. nRet = CompareStringWord(lcid, dwFlags, lpA, cchA, lpB, cchB);
  4453. }
  4454. return nRet;
  4455. }
  4456. #ifdef NEED_KERNEL32_WRAPPER
  4457. int StrLenN(LPCWSTR psz, int cchMin)
  4458. {
  4459. LPCWSTR pszEnd = psz;
  4460. while (((pszEnd - psz) < cchMin) && *pszEnd)
  4461. {
  4462. pszEnd++;
  4463. }
  4464. return pszEnd - psz;
  4465. }
  4466. int WINAPI CompareStringWrapW(LCID Locale, DWORD dwFlags,
  4467. LPCWSTR psz1, int cch1,
  4468. LPCWSTR psz2, int cch2)
  4469. {
  4470. VALIDATE_PROTOTYPE(CompareString);
  4471. if (g_bRunningOnNT)
  4472. {
  4473. return CompareStringW(Locale, dwFlags, psz1, cch1, psz2, cch2);
  4474. }
  4475. else if (psz1 && psz2)
  4476. {
  4477. if (dwFlags & NORM_STOP_ON_NULL)
  4478. {
  4479. cch1 = StrLenN(psz1, cch1);
  4480. cch2 = StrLenN(psz2, cch2);
  4481. dwFlags &= ~NORM_STOP_ON_NULL;
  4482. }
  4483. CStrIn strString1(psz1, cch1);
  4484. CStrIn strString2(psz2, cch2);
  4485. cch1 = strString1.strlen();
  4486. cch2 = strString2.strlen();
  4487. return CompareStringA(Locale, dwFlags, strString1, cch1, strString2, cch2);
  4488. }
  4489. else
  4490. return 0; // fail if either string is NULL, as it causes assert on debug windows
  4491. }
  4492. #endif // NEED_KERNEL32_WRAPPER
  4493. #ifdef NEED_USER32_WRAPPER
  4494. #ifndef UNIX
  4495. BOOL WINAPI
  4496. MessageBoxIndirectWrapW(CONST MSGBOXPARAMS *pmbp)
  4497. #else
  4498. int WINAPI
  4499. MessageBoxIndirectWrapW(LPMSGBOXPARAMS pmbp)
  4500. #endif /* UNIX */
  4501. {
  4502. VALIDATE_PROTOTYPE(MessageBoxIndirect);
  4503. ASSERT(HIWORD64(pmbp->lpszIcon) == 0);
  4504. if (g_bRunningOnNT)
  4505. {
  4506. return MessageBoxIndirectW(pmbp);
  4507. }
  4508. CStrIn strText(pmbp->lpszText);
  4509. CStrIn strCaption(pmbp->lpszCaption);
  4510. MSGBOXPARAMSA mbp;
  4511. memcpy(&mbp, pmbp, sizeof(mbp));
  4512. mbp.lpszText = strText;
  4513. mbp.lpszCaption = strCaption;
  4514. return MessageBoxIndirectA(&mbp);
  4515. }
  4516. #endif // NEED_USER32_WRAPPER
  4517. #ifdef NEED_GDI32_WRAPPER
  4518. DWORD GetCharacterPlacementWrapW(
  4519. HDC hdc, // handle to device context
  4520. LPCTSTR lpString, // pointer to string
  4521. int nCount, // number of characters in string
  4522. int nMaxExtent, // maximum extent for displayed string
  4523. LPGCP_RESULTS lpResults, // pointer to buffer for placement result
  4524. DWORD dwFlags // placement flags
  4525. )
  4526. {
  4527. VALIDATE_PROTOTYPE(GetCharacterPlacement);
  4528. // Leave for someone else.
  4529. ASSERT (lpResults->lpOutString == NULL);
  4530. ASSERT (lpResults->lpClass == NULL);
  4531. if (g_bRunningOnNT)
  4532. {
  4533. return GetCharacterPlacementW (hdc,
  4534. lpString,
  4535. nCount,
  4536. nMaxExtent,
  4537. lpResults,
  4538. dwFlags);
  4539. }
  4540. CStrIn strText(lpString);
  4541. DWORD dwRet;
  4542. dwRet = GetCharacterPlacementA (hdc, strText, nCount, nMaxExtent,
  4543. (LPGCP_RESULTSA)lpResults,
  4544. dwFlags);
  4545. return dwRet;
  4546. }
  4547. #endif // NEED_GDI32_WRAPPER
  4548. #ifdef NEED_GDI32_WRAPPER
  4549. //
  4550. // Note that we're calling get GetCharWidthA instead of GetCharWidth32A
  4551. // because the 32 version doesn't exist under Win95.
  4552. BOOL WINAPI GetCharWidth32WrapW(
  4553. HDC hdc,
  4554. UINT iFirstChar,
  4555. UINT iLastChar,
  4556. LPINT lpBuffer)
  4557. {
  4558. VALIDATE_PROTOTYPE(GetCharWidth32);
  4559. if (g_bRunningOnNT)
  4560. {
  4561. return GetCharWidth32W (hdc, iFirstChar, iLastChar, lpBuffer);
  4562. }
  4563. // Note that we expect to do only one character at a time for anything but
  4564. // ISO Latin 1.
  4565. if (iFirstChar > 255)
  4566. {
  4567. UINT mbChar=0;
  4568. WCHAR ch;
  4569. // Convert string
  4570. ch = (WCHAR)iFirstChar;
  4571. WideCharToMultiByte(CP_ACP, 0, &ch, 1,
  4572. (char *)&mbChar, 2, NULL, NULL);
  4573. }
  4574. return (GetCharWidthA (hdc, iFirstChar, iLastChar, lpBuffer));
  4575. }
  4576. #endif // NEED_GDI32_WRAPPER
  4577. #ifdef NEED_GDI32_WRAPPER
  4578. //
  4579. // Note: Win95 does support ExtTextOutW. This thunk is not for
  4580. // ANSI/UNICODE wrapping. It's to work around an ISV app bug.
  4581. //
  4582. // Y'see, there's an app that patches Win95 GDI and their ExtTextOutW handler
  4583. // is broken. It always dereferences the lpStr parameter, even if
  4584. // cch is zero. Consequently, any time we are about to pass NULL as
  4585. // the lpStr, we have to change our mind and pass a null UNICODE string
  4586. // instead.
  4587. //
  4588. // The name of this app: Lotus SmartSuite ScreenCam 97.
  4589. //
  4590. LWSTDAPI_(BOOL)
  4591. ExtTextOutWrapW(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx)
  4592. {
  4593. VALIDATE_PROTOTYPE(ExtTextOut);
  4594. if (lpStr == NULL) // workaround
  4595. lpStr = L""; // for ScreenCam 97
  4596. if (_MayNeedFontLinking(lpStr, cch))
  4597. {
  4598. return ExtTextOutFLW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
  4599. }
  4600. return ExtTextOutW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
  4601. }
  4602. #endif // NEED_GDI32_WRAPPER
  4603. #ifdef NEED_USER32_WRAPPER
  4604. BOOL WINAPI
  4605. ModifyMenuWrapW(
  4606. HMENU hMenu,
  4607. UINT uPosition,
  4608. UINT uFlags,
  4609. UINT_PTR uIDNewItem,
  4610. LPCWSTR lpNewItem)
  4611. {
  4612. VALIDATE_PROTOTYPE(ModifyMenu);
  4613. ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW));
  4614. if (g_bRunningOnNT)
  4615. {
  4616. return ModifyMenuW(hMenu, uPosition, uFlags, uIDNewItem, lpNewItem);
  4617. }
  4618. CStrIn str(lpNewItem);
  4619. return ModifyMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
  4620. }
  4621. #endif // NEED_USER32_WRAPPER
  4622. #ifdef NEED_KERNEL32_WRAPPER
  4623. BOOL WINAPI
  4624. CopyFileWrapW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
  4625. {
  4626. VALIDATE_PROTOTYPE(CopyFile);
  4627. if (g_bRunningOnNT)
  4628. {
  4629. return CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
  4630. }
  4631. CStrIn strOld(lpExistingFileName);
  4632. CStrIn strNew(lpNewFileName);
  4633. return CopyFileA(strOld, strNew, bFailIfExists);
  4634. }
  4635. #endif // NEED_KERNEL32_WRAPPER
  4636. #ifdef NEED_KERNEL32_WRAPPER
  4637. BOOL WINAPI
  4638. MoveFileWrapW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  4639. {
  4640. VALIDATE_PROTOTYPE(MoveFile);
  4641. if (g_bRunningOnNT)
  4642. {
  4643. return MoveFileW(lpExistingFileName, lpNewFileName);
  4644. }
  4645. CStrIn strOld(lpExistingFileName);
  4646. CStrIn strNew(lpNewFileName);
  4647. return MoveFileA(strOld, strNew);
  4648. }
  4649. #endif // NEED_KERNEL32_WRAPPER
  4650. #ifdef NEED_USER32_WRAPPER
  4651. BOOL WINAPI
  4652. OemToCharWrapW(LPCSTR lpszSrc, LPWSTR lpszDst)
  4653. {
  4654. VALIDATE_PROTOTYPE(OemToChar);
  4655. VALIDATE_OUTBUF(lpszDst, lstrlenA(lpszSrc));
  4656. if (g_bRunningOnNT)
  4657. {
  4658. return OemToCharW(lpszSrc, lpszDst);
  4659. }
  4660. CStrOut strDst(lpszDst, lstrlenA(lpszSrc));
  4661. return OemToCharA(lpszSrc, strDst);
  4662. }
  4663. #endif // NEED_USER32_WRAPPER
  4664. #ifdef NEED_KERNEL32_WRAPPER
  4665. HANDLE WINAPI
  4666. OpenEventWrapW(
  4667. DWORD fdwAccess,
  4668. BOOL fInherit,
  4669. LPCWSTR lpszEventName)
  4670. {
  4671. VALIDATE_PROTOTYPE(OpenEvent);
  4672. if (g_bRunningOnNT)
  4673. {
  4674. return OpenEventW(fdwAccess, fInherit, lpszEventName);
  4675. }
  4676. CStrIn strEventName(lpszEventName);
  4677. return OpenEventA(fdwAccess, fInherit, strEventName);
  4678. }
  4679. #endif // NEED_KERNEL32_WRAPPER
  4680. #ifdef NEED_KERNEL32_WRAPPER
  4681. VOID WINAPI
  4682. OutputDebugStringWrapW(LPCWSTR lpOutputString)
  4683. {
  4684. VALIDATE_PROTOTYPE(OutputDebugString);
  4685. if (g_bRunningOnNT)
  4686. {
  4687. OutputDebugStringW(lpOutputString);
  4688. return;
  4689. }
  4690. CStrIn str(lpOutputString);
  4691. OutputDebugStringA(str);
  4692. }
  4693. #endif // NEED_KERNEL32_WRAPPER
  4694. #ifdef NEED_USER32_WRAPPER
  4695. BOOL FORWARD_API WINAPI
  4696. PeekMessageWrapW(
  4697. LPMSG lpMsg,
  4698. HWND hWnd,
  4699. UINT wMsgFilterMin,
  4700. UINT wMsgFilterMax,
  4701. UINT wRemoveMsg)
  4702. {
  4703. VALIDATE_PROTOTYPE(PeekMessage);
  4704. FORWARD_AW(PeekMessage, (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg));
  4705. }
  4706. #endif // NEED_USER32_WRAPPER
  4707. #ifdef NEED_WINMM_WRAPPER
  4708. LWSTDAPI_(BOOL)
  4709. PlaySoundWrapW(
  4710. LPCWSTR pszSound,
  4711. HMODULE hmod,
  4712. DWORD fdwSound)
  4713. {
  4714. if (g_bRunningOnNT)
  4715. {
  4716. return PlaySoundW(pszSound, hmod, fdwSound);
  4717. }
  4718. CStrIn strSound(pszSound);
  4719. return PlaySoundA(strSound, hmod, fdwSound);
  4720. }
  4721. #endif // NEED_WINMM_WRAPPER
  4722. #ifdef NEED_USER32_WRAPPER
  4723. BOOL FORWARD_API WINAPI
  4724. PostMessageWrapW(
  4725. HWND hWnd,
  4726. UINT Msg,
  4727. WPARAM wParam,
  4728. LPARAM lParam)
  4729. {
  4730. VALIDATE_PROTOTYPE(PostMessage);
  4731. FORWARD_AW(PostMessage, (hWnd, Msg, wParam, lParam));
  4732. }
  4733. #endif // NEED_USER32_WRAPPER
  4734. #ifdef NEED_USER32_WRAPPER
  4735. BOOL FORWARD_API WINAPI
  4736. PostThreadMessageWrapW(
  4737. DWORD idThread,
  4738. UINT Msg,
  4739. WPARAM wParam,
  4740. LPARAM lParam)
  4741. {
  4742. VALIDATE_PROTOTYPE(PostThreadMessage);
  4743. FORWARD_AW(PostThreadMessage, (idThread, Msg, wParam, lParam));
  4744. }
  4745. #endif // NEED_USER32_WRAPPER
  4746. #ifdef NEED_ADVAPI32_WRAPPER
  4747. LONG APIENTRY
  4748. RegCreateKeyWrapW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
  4749. {
  4750. VALIDATE_PROTOTYPE(RegCreateKey);
  4751. if (g_bRunningOnNT)
  4752. {
  4753. return RegCreateKeyW(hKey, lpSubKey, phkResult);
  4754. }
  4755. CStrIn str(lpSubKey);
  4756. return RegCreateKeyA(hKey, str, phkResult);
  4757. }
  4758. #endif // NEED_ADVAPI32_WRAPPER
  4759. #ifdef NEED_ADVAPI32_WRAPPER
  4760. LONG APIENTRY
  4761. RegCreateKeyExWrapW(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
  4762. {
  4763. VALIDATE_PROTOTYPE(RegCreateKeyEx);
  4764. if (g_bRunningOnNT)
  4765. {
  4766. return RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  4767. }
  4768. CStrIn strSubKey(lpSubKey);
  4769. CStrIn strClass(lpClass);
  4770. return RegCreateKeyExA(hKey, strSubKey, Reserved, strClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  4771. }
  4772. #endif // NEED_ADVAPI32_WRAPPER
  4773. #ifdef NEED_ADVAPI32_WRAPPER
  4774. //
  4775. // Subtle difference: RegDeleteKey on Win9x will recursively delete subkeys.
  4776. // On NT, it fails if the key being deleted has subkeys. If you need to
  4777. // force NT-style behavior, use SHDeleteEmptyKey. To force 95-style
  4778. // behavior, use SHDeleteKey.
  4779. //
  4780. LONG APIENTRY
  4781. RegDeleteKeyWrapW(HKEY hKey, LPCWSTR pwszSubKey)
  4782. {
  4783. VALIDATE_PROTOTYPE(RegDeleteKey);
  4784. if (g_bRunningOnNT)
  4785. {
  4786. return RegDeleteKeyW(hKey, pwszSubKey);
  4787. }
  4788. CStrIn str(pwszSubKey);
  4789. return RegDeleteKeyA(hKey, str);
  4790. }
  4791. #endif // NEED_ADVAPI32_WRAPPER
  4792. #ifdef NEED_ADVAPI32_WRAPPER
  4793. LONG APIENTRY
  4794. RegDeleteValueWrapW(HKEY hKey, LPCWSTR pwszSubKey)
  4795. {
  4796. VALIDATE_PROTOTYPE(RegDeleteValue);
  4797. if (g_bRunningOnNT)
  4798. {
  4799. return RegDeleteValueW(hKey, pwszSubKey);
  4800. }
  4801. CStrIn str(pwszSubKey);
  4802. return RegDeleteValueA(hKey, str);
  4803. }
  4804. #endif // NEED_ADVAPI32_WRAPPER
  4805. #ifdef NEED_ADVAPI32_WRAPPER
  4806. LONG APIENTRY
  4807. RegEnumKeyWrapW(
  4808. HKEY hKey,
  4809. DWORD dwIndex,
  4810. LPWSTR lpName,
  4811. DWORD cbName)
  4812. {
  4813. VALIDATE_PROTOTYPE(RegEnumKey);
  4814. VALIDATE_OUTBUF(lpName, cbName);
  4815. if (g_bRunningOnNT)
  4816. {
  4817. return RegEnumKeyW(hKey, dwIndex, lpName, cbName);
  4818. }
  4819. CStrOut str(lpName, cbName);
  4820. return RegEnumKeyA(hKey, dwIndex, str, str.BufSize());
  4821. }
  4822. #endif // NEED_ADVAPI32_WRAPPER
  4823. #ifdef NEED_ADVAPI32_WRAPPER
  4824. LONG APIENTRY
  4825. RegEnumKeyExWrapW(
  4826. HKEY hKey,
  4827. DWORD dwIndex,
  4828. LPWSTR lpName,
  4829. LPDWORD lpcbName,
  4830. LPDWORD lpReserved,
  4831. LPWSTR lpClass,
  4832. LPDWORD lpcbClass,
  4833. PFILETIME lpftLastWriteTime)
  4834. {
  4835. VALIDATE_PROTOTYPE(RegEnumKeyEx);
  4836. if (lpcbName) {VALIDATE_OUTBUF(lpName, *lpcbName);}
  4837. if (lpcbClass) {VALIDATE_OUTBUF(lpClass, *lpcbClass);}
  4838. if (g_bRunningOnNT)
  4839. {
  4840. return RegEnumKeyExW(
  4841. hKey,
  4842. dwIndex,
  4843. lpName,
  4844. lpcbName,
  4845. lpReserved,
  4846. lpClass,
  4847. lpcbClass,
  4848. lpftLastWriteTime);
  4849. }
  4850. long ret;
  4851. DWORD dwClass = 0;
  4852. if (!lpcbClass)
  4853. {
  4854. lpcbClass = &dwClass;
  4855. }
  4856. CStrOut strName(lpName, *lpcbName);
  4857. CStrOut strClass(lpClass, *lpcbClass);
  4858. ret = RegEnumKeyExA(
  4859. hKey,
  4860. dwIndex,
  4861. strName,
  4862. lpcbName,
  4863. lpReserved,
  4864. strClass,
  4865. lpcbClass,
  4866. lpftLastWriteTime);
  4867. *lpcbName = strName.ConvertExcludingNul();
  4868. *lpcbClass = strClass.ConvertExcludingNul();
  4869. return ret;
  4870. }
  4871. #endif // NEED_ADVAPI32_WRAPPER
  4872. #ifdef NEED_ADVAPI32_WRAPPER
  4873. LONG APIENTRY
  4874. RegOpenKeyWrapW(HKEY hKey, LPCWSTR pwszSubKey, PHKEY phkResult)
  4875. {
  4876. VALIDATE_PROTOTYPE(RegOpenKey);
  4877. if (g_bRunningOnNT)
  4878. {
  4879. return RegOpenKeyW(hKey, pwszSubKey, phkResult);
  4880. }
  4881. CStrIn str(pwszSubKey);
  4882. return RegOpenKeyA(hKey, str, phkResult);
  4883. }
  4884. #endif // NEED_ADVAPI32_WRAPPER
  4885. #ifdef NEED_ADVAPI32_WRAPPER
  4886. LONG APIENTRY
  4887. RegOpenKeyExWrapW(
  4888. HKEY hKey,
  4889. LPCWSTR lpSubKey,
  4890. DWORD ulOptions,
  4891. REGSAM samDesired,
  4892. PHKEY phkResult)
  4893. {
  4894. VALIDATE_PROTOTYPE(RegOpenKeyEx);
  4895. if (g_bRunningOnNT)
  4896. {
  4897. return RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  4898. }
  4899. CStrIn str(lpSubKey);
  4900. return RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
  4901. }
  4902. #endif // NEED_ADVAPI32_WRAPPER
  4903. #ifdef NEED_ADVAPI32_WRAPPER
  4904. LONG APIENTRY
  4905. RegQueryInfoKeyWrapW(
  4906. HKEY hKey,
  4907. LPWSTR lpClass,
  4908. LPDWORD lpcbClass,
  4909. LPDWORD lpReserved,
  4910. LPDWORD lpcSubKeys,
  4911. LPDWORD lpcbMaxSubKeyLen,
  4912. LPDWORD lpcbMaxClassLen,
  4913. LPDWORD lpcValues,
  4914. LPDWORD lpcbMaxValueNameLen,
  4915. LPDWORD lpcbMaxValueLen,
  4916. LPDWORD lpcbSecurityDescriptor,
  4917. PFILETIME lpftLastWriteTime)
  4918. {
  4919. VALIDATE_PROTOTYPE(RegQueryInfoKey);
  4920. if (g_bRunningOnNT)
  4921. {
  4922. return RegQueryInfoKeyW(
  4923. hKey,
  4924. lpClass,
  4925. lpcbClass,
  4926. lpReserved,
  4927. lpcSubKeys,
  4928. lpcbMaxSubKeyLen,
  4929. lpcbMaxClassLen,
  4930. lpcValues,
  4931. lpcbMaxValueNameLen,
  4932. lpcbMaxValueLen,
  4933. lpcbSecurityDescriptor,
  4934. lpftLastWriteTime);
  4935. }
  4936. CStrIn str(lpClass);
  4937. return RegQueryInfoKeyA(
  4938. hKey,
  4939. str,
  4940. lpcbClass,
  4941. lpReserved,
  4942. lpcSubKeys,
  4943. lpcbMaxSubKeyLen,
  4944. lpcbMaxClassLen,
  4945. lpcValues,
  4946. lpcbMaxValueNameLen,
  4947. lpcbMaxValueLen,
  4948. lpcbSecurityDescriptor,
  4949. lpftLastWriteTime);
  4950. }
  4951. #endif // NEED_ADVAPI32_WRAPPER
  4952. #ifdef NEED_ADVAPI32_WRAPPER
  4953. LONG APIENTRY
  4954. RegQueryValueWrapW(
  4955. HKEY hKey,
  4956. LPCWSTR pwszSubKey,
  4957. LPWSTR pwszValue,
  4958. PLONG lpcbValue)
  4959. {
  4960. VALIDATE_PROTOTYPE(RegQueryValue);
  4961. if (lpcbValue) {VALIDATE_OUTBUF(pwszValue, *lpcbValue);}
  4962. if (g_bRunningOnNT)
  4963. {
  4964. return RegQueryValueW(hKey, pwszSubKey, pwszValue, lpcbValue);
  4965. }
  4966. long ret;
  4967. long cb;
  4968. CStrIn strKey(pwszSubKey);
  4969. CStrOut strValue(pwszValue, (lpcbValue ? ((*lpcbValue) / sizeof(WCHAR)) : 0));
  4970. cb = strValue.BufSize();
  4971. ret = RegQueryValueA(hKey, strKey, strValue, (lpcbValue ? &cb : NULL));
  4972. if (ret != ERROR_SUCCESS)
  4973. goto Cleanup;
  4974. if (strValue)
  4975. {
  4976. cb = strValue.ConvertIncludingNul();
  4977. }
  4978. if (lpcbValue)
  4979. *lpcbValue = cb * sizeof(WCHAR);
  4980. Cleanup:
  4981. return ret;
  4982. }
  4983. #endif // NEED_ADVAPI32_WRAPPER
  4984. #ifdef NEED_ADVAPI32_WRAPPER
  4985. LONG APIENTRY
  4986. RegQueryValueExWrapW(
  4987. HKEY hKey,
  4988. LPCWSTR lpValueName,
  4989. LPDWORD lpReserved,
  4990. LPDWORD lpType,
  4991. LPBYTE lpData,
  4992. LPDWORD lpcbData)
  4993. {
  4994. VALIDATE_PROTOTYPE(RegQueryValueEx);
  4995. if (lpcbData) {VALIDATE_OUTBUF(lpData, *lpcbData);}
  4996. LONG ret;
  4997. DWORD dwTempType;
  4998. if (g_bRunningOnNT)
  4999. {
  5000. #ifdef DEBUG
  5001. if (lpType == NULL)
  5002. lpType = &dwTempType;
  5003. #endif
  5004. ret = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
  5005. return ret;
  5006. }
  5007. CStrIn strValueName(lpValueName);
  5008. DWORD cb;
  5009. //
  5010. // Determine the type of buffer needed
  5011. //
  5012. ret = RegQueryValueExA(hKey, strValueName, lpReserved, &dwTempType, NULL, (lpcbData ? &cb : NULL));
  5013. if (ret != ERROR_SUCCESS)
  5014. goto Cleanup;
  5015. ASSERT(dwTempType != REG_MULTI_SZ);
  5016. switch (dwTempType)
  5017. {
  5018. case REG_EXPAND_SZ:
  5019. case REG_SZ:
  5020. {
  5021. CStrOut strData((LPWSTR) lpData, (lpcbData ? ((*lpcbData) / sizeof(WCHAR)) : 0));
  5022. cb = strData.BufSize();
  5023. ret = RegQueryValueExA(hKey, strValueName, lpReserved, lpType, (LPBYTE)(LPSTR)strData, (lpcbData ? &cb : NULL));
  5024. if (ret != ERROR_SUCCESS)
  5025. break;
  5026. if (strData)
  5027. {
  5028. cb = strData.ConvertIncludingNul();
  5029. }
  5030. if (lpcbData)
  5031. *lpcbData = cb * sizeof(WCHAR);
  5032. break;
  5033. }
  5034. default:
  5035. {
  5036. ret = RegQueryValueExA(
  5037. hKey,
  5038. strValueName,
  5039. lpReserved,
  5040. lpType,
  5041. lpData,
  5042. lpcbData);
  5043. break;
  5044. }
  5045. }
  5046. Cleanup:
  5047. return ret;
  5048. }
  5049. #endif // NEED_ADVAPI32_WRAPPER
  5050. #ifdef NEED_ADVAPI32_WRAPPER
  5051. LONG APIENTRY
  5052. RegSetValueWrapW(
  5053. HKEY hKey,
  5054. LPCWSTR lpSubKey,
  5055. DWORD dwType,
  5056. LPCWSTR lpData,
  5057. DWORD cbData)
  5058. {
  5059. VALIDATE_PROTOTYPE(RegSetValue);
  5060. if (g_bRunningOnNT)
  5061. {
  5062. return RegSetValueW(hKey, lpSubKey, dwType, lpData, cbData);
  5063. }
  5064. CStrIn strKey(lpSubKey);
  5065. CStrIn strValue(lpData);
  5066. return RegSetValueA(hKey, strKey, dwType, strValue, cbData);
  5067. }
  5068. #endif // NEED_ADVAPI32_WRAPPER
  5069. #ifdef NEED_ADVAPI32_WRAPPER
  5070. LONG APIENTRY
  5071. RegSetValueExWrapW(
  5072. HKEY hKey,
  5073. LPCWSTR lpValueName,
  5074. DWORD Reserved,
  5075. DWORD dwType,
  5076. CONST BYTE* lpData,
  5077. DWORD cbData)
  5078. {
  5079. VALIDATE_PROTOTYPE(RegSetValueEx);
  5080. ASSERT(dwType != REG_MULTI_SZ);
  5081. if (g_bRunningOnNT)
  5082. {
  5083. return RegSetValueExW(
  5084. hKey,
  5085. lpValueName,
  5086. Reserved,
  5087. dwType,
  5088. lpData,
  5089. cbData);
  5090. }
  5091. CStrIn strKey(lpValueName);
  5092. CStrIn strSZ((dwType == REG_SZ || dwType == REG_EXPAND_SZ) ? (LPCWSTR) lpData : NULL);
  5093. if (strSZ)
  5094. {
  5095. lpData = (LPBYTE) (LPSTR) strSZ;
  5096. cbData = strSZ.strlen() + 1;
  5097. }
  5098. return RegSetValueExA(
  5099. hKey,
  5100. strKey,
  5101. Reserved,
  5102. dwType,
  5103. lpData,
  5104. cbData);
  5105. }
  5106. #endif // NEED_ADVAPI32_WRAPPER
  5107. #ifdef NEED_USER32_WRAPPER
  5108. ATOM WINAPI
  5109. RegisterClassWrapW(CONST WNDCLASSW * lpWndClass)
  5110. {
  5111. VALIDATE_PROTOTYPE(RegisterClass);
  5112. if (g_bRunningOnNT)
  5113. {
  5114. return RegisterClassW(lpWndClass);
  5115. }
  5116. WNDCLASSA wc;
  5117. CStrIn strMenuName(lpWndClass->lpszMenuName);
  5118. CStrIn strClassName(lpWndClass->lpszClassName);
  5119. ASSERT(sizeof(wc) == sizeof(*lpWndClass));
  5120. memcpy(&wc, lpWndClass, sizeof(wc));
  5121. wc.lpszMenuName = strMenuName;
  5122. wc.lpszClassName = strClassName;
  5123. return RegisterClassA(&wc);
  5124. }
  5125. #endif // NEED_USER32_WRAPPER
  5126. #ifdef NEED_USER32_WRAPPER
  5127. UINT WINAPI
  5128. RegisterClipboardFormatWrapW(LPCWSTR lpString)
  5129. {
  5130. VALIDATE_PROTOTYPE(RegisterClipboardFormat);
  5131. if (g_bRunningOnNT)
  5132. {
  5133. return RegisterClipboardFormatW(lpString);
  5134. }
  5135. CStrIn str(lpString);
  5136. return RegisterClipboardFormatA(str);
  5137. }
  5138. #endif // NEED_USER32_WRAPPER
  5139. #ifdef NEED_USER32_WRAPPER
  5140. UINT WINAPI
  5141. RegisterWindowMessageWrapW(LPCWSTR lpString)
  5142. {
  5143. VALIDATE_PROTOTYPE(RegisterWindowMessage);
  5144. if (g_bRunningOnNT)
  5145. {
  5146. return RegisterWindowMessageW(lpString);
  5147. }
  5148. CStrIn str(lpString);
  5149. return RegisterWindowMessageA(str);
  5150. }
  5151. #endif // NEED_USER32_WRAPPER
  5152. #ifdef NEED_KERNEL32_WRAPPER
  5153. BOOL WINAPI
  5154. RemoveDirectoryWrapW(LPCWSTR lpszDir)
  5155. {
  5156. VALIDATE_PROTOTYPE(RemoveDirectory);
  5157. if (g_bRunningOnNT)
  5158. {
  5159. return RemoveDirectoryW(lpszDir);
  5160. }
  5161. CStrIn strDir(lpszDir);
  5162. return RemoveDirectoryA(strDir);
  5163. }
  5164. #endif // NEED_KERNEL32_WRAPPER
  5165. #ifdef NEED_USER32_WRAPPER
  5166. HANDLE WINAPI
  5167. RemovePropWrapW(
  5168. HWND hWnd,
  5169. LPCWSTR lpString)
  5170. {
  5171. VALIDATE_PROTOTYPE(RemoveProp);
  5172. if (g_bRunningOnNT)
  5173. {
  5174. return RemovePropW(hWnd, lpString);
  5175. }
  5176. CStrIn str(lpString);
  5177. return RemovePropA(hWnd, str);
  5178. }
  5179. #endif // NEED_USER32_WRAPPER
  5180. #ifdef NEED_USER32_WRAPPER
  5181. LRESULT WINAPI SendMessageWrapW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  5182. // NOTE (SumitC) Instead of calling SendDlgItemMessageA below, I'm forwarding to
  5183. // SendMessageWrap so as not to have to re-do the special-case processing.
  5184. LRESULT WINAPI
  5185. SendDlgItemMessageWrapW(
  5186. HWND hDlg,
  5187. int nIDDlgItem,
  5188. UINT Msg,
  5189. WPARAM wParam,
  5190. LPARAM lParam)
  5191. {
  5192. VALIDATE_PROTOTYPE(SendDlgItemMessage);
  5193. if (g_bRunningOnNT)
  5194. {
  5195. return SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam);
  5196. }
  5197. HWND hWnd;
  5198. hWnd = GetDlgItem(hDlg, nIDDlgItem);
  5199. return SendMessageWrapW(hWnd, Msg, wParam, lParam);
  5200. }
  5201. #endif // NEED_USER32_WRAPPER
  5202. #ifdef NEED_USER32_WRAPPER
  5203. int CharIndexToByteIndex(LPCSTR psz, int cch)
  5204. {
  5205. if (cch <= 0)
  5206. return cch;
  5207. LPCSTR pszTemp = psz;
  5208. while (*pszTemp && cch-- > 0)
  5209. {
  5210. pszTemp = CharNextA(pszTemp);
  5211. }
  5212. return (int)(pszTemp - psz);
  5213. }
  5214. int ByteIndexToCharIndex(LPCSTR psz, int cb)
  5215. {
  5216. if (cb <=0)
  5217. return cb;
  5218. LPCSTR pszTemp = psz;
  5219. LPCSTR pszEnd = &psz[cb];
  5220. int cch = 0;
  5221. while (*pszTemp && pszTemp < pszEnd)
  5222. {
  5223. pszTemp = CharNextA(pszTemp);
  5224. ++cch;
  5225. }
  5226. return cch;
  5227. }
  5228. //
  5229. // Translate between byte positions and "character" positions
  5230. //
  5231. void TranslateCharPos(HWND hwnd, BOOL fByteIndexToCharIndex, DWORD* pdwPos, int cPos)
  5232. {
  5233. int cch = GetWindowTextLengthA(hwnd);
  5234. if (cch > 0)
  5235. {
  5236. char szBuf[MAX_PATH];
  5237. LPSTR pszBuf = szBuf;
  5238. if (cch >= ARRAYSIZE(szBuf))
  5239. {
  5240. pszBuf = new char[cch + 1];
  5241. }
  5242. if (pszBuf)
  5243. {
  5244. GetWindowTextA(hwnd, (LPSTR)pszBuf, cch+1);
  5245. // Translate Each value passed in
  5246. while (cPos--)
  5247. {
  5248. if (fByteIndexToCharIndex)
  5249. {
  5250. *pdwPos = (DWORD)ByteIndexToCharIndex(pszBuf, (int)*pdwPos);
  5251. }
  5252. else
  5253. {
  5254. *pdwPos = (DWORD)CharIndexToByteIndex(pszBuf, (int)*pdwPos);
  5255. }
  5256. ++pdwPos;
  5257. }
  5258. if (pszBuf != szBuf)
  5259. {
  5260. delete [] pszBuf;
  5261. }
  5262. }
  5263. }
  5264. }
  5265. //
  5266. // There is no WM_GETOBJECT/OBJID_QUERYCLASSNAMEIDX code for comboex,
  5267. // so we will just send CCM_GETUNICODEFORMAT and hope for the best.
  5268. // We are relying on the fact that Win95's combo box returns 0 in response
  5269. // to messages it doesn't understand (like CCM_GETUNICODEFORMAT).
  5270. //
  5271. #define IsUnicodeComboEx(hWnd) SendMessageA(hWnd, CCM_GETUNICODEFORMAT, 0, 0)
  5272. #ifdef DEBUG
  5273. int g_cSMTot, g_cSMHit;
  5274. int g_cSMMod = 100;
  5275. #endif
  5276. LRESULT WINAPI
  5277. SendMessageAThunk(
  5278. HWND hWnd,
  5279. UINT Msg,
  5280. WPARAM wParam,
  5281. LPARAM lParam)
  5282. {
  5283. #ifdef DEBUG
  5284. if ((g_cSMTot % g_cSMMod) == 0)
  5285. TraceMsg(DM_PERF, "sm: tot=%d hit=%d", g_cSMTot, g_cSMHit);
  5286. #endif
  5287. DBEXEC(TRUE, g_cSMTot++);
  5288. // todo: perf? seems to be pretty common case, at least for now...
  5289. DBEXEC(Msg > WM_USER, g_cSMHit++);
  5290. #if 0
  5291. if (Msg > WM_USER)
  5292. goto Ldef;
  5293. #endif
  5294. switch (Msg)
  5295. {
  5296. case EM_GETLINE:
  5297. {
  5298. LRESULT nLen;
  5299. CStrOut str((LPWSTR) lParam, (* (SHORT *) lParam) + 1);
  5300. * (SHORT *) (LPSTR) str = * (SHORT *) lParam;
  5301. nLen = SendMessageA(hWnd, Msg, (WPARAM) wParam, (LPARAM) (LPSTR) str);
  5302. if(nLen > 0)
  5303. ((LPSTR) str)[nLen] = '\0';
  5304. return nLen;
  5305. }
  5306. case EM_SETPASSWORDCHAR:
  5307. {
  5308. WPARAM wp = 0;
  5309. ASSERT(HIWORD64(wParam) == 0);
  5310. SHUnicodeToAnsi((LPWSTR) &wParam, (LPSTR) &wp, sizeof(wp));
  5311. ASSERT(HIWORD64(wp) == 0);
  5312. return SendMessageA(hWnd, Msg, wp, lParam);
  5313. }
  5314. case EM_SETWORDBREAKPROC:
  5315. {
  5316. // There is a bug with how USER handles WH_CALLWNDPROC global hooks in Win95/98 that
  5317. // causes us to blow up if one is installed and a wordbreakproc is set. Thus,
  5318. // if an app is running that has one of these hooks installed (intellipoint 1.1 etc.) then
  5319. // if we install our wordbreakproc the app will fault when the proc is called. There
  5320. // does not appear to be any way for us to work around it since USER's thunking code
  5321. // trashes the stack so this API is disabled for Win9x.
  5322. TraceMsg(TF_WARNING, "EM_SETWORDBREAKPROC can fault on Win9x; see unicwrap.cpp for details");
  5323. return FALSE;
  5324. }
  5325. case EM_GETSEL:
  5326. {
  5327. //
  5328. // Convert multibyte indicies into unicode indicies
  5329. //
  5330. DWORD dw[2];
  5331. SendMessageA(hWnd, Msg, (WPARAM)&dw[0], (LPARAM)&dw[1]);
  5332. TranslateCharPos(hWnd, TRUE, dw, ARRAYSIZE(dw));
  5333. // Return the results
  5334. DWORD* pdwStart = (DWORD*)wParam;
  5335. DWORD* pdwEnd = (DWORD*)lParam;
  5336. if (pdwStart)
  5337. {
  5338. *pdwStart = dw[0];
  5339. }
  5340. if (pdwEnd)
  5341. {
  5342. *pdwEnd = dw[1];
  5343. }
  5344. LRESULT lr = (LRESULT)-1;
  5345. if (dw[0] <= 0xffff && dw[1] <= 0xffff)
  5346. {
  5347. lr = MAKELONG(dw[0], dw[1]);
  5348. }
  5349. return lr;
  5350. }
  5351. case EM_SETSEL:
  5352. {
  5353. //
  5354. // Convert unicode char indicies into multibyte indicies
  5355. //
  5356. DWORD dw[2];
  5357. dw[0] = (DWORD)wParam; // start
  5358. dw[1] = (DWORD)lParam; // end
  5359. TranslateCharPos(hWnd, FALSE, dw, ARRAYSIZE(dw));
  5360. return SendMessageA(hWnd, Msg, (WPARAM)dw[0], (LPARAM)dw[1]);
  5361. }
  5362. case EM_CHARFROMPOS:
  5363. {
  5364. DWORD dwPos = SendMessageA(hWnd, Msg, wParam, lParam);
  5365. if (HIWORD(dwPos) == 0)
  5366. {
  5367. TranslateCharPos(hWnd, TRUE, &dwPos, 1);
  5368. }
  5369. return dwPos;
  5370. }
  5371. case WM_SETTEXT:
  5372. case LB_ADDSTRING:
  5373. case CB_ADDSTRING:
  5374. case EM_REPLACESEL:
  5375. RIPMSG(wParam == 0, "wParam should be 0 for these messages");
  5376. // fall through
  5377. case LB_FINDSTRING:
  5378. case LB_FINDSTRINGEXACT:
  5379. case LB_INSERTSTRING:
  5380. case LB_SELECTSTRING:
  5381. case CB_FINDSTRING:
  5382. case CB_FINDSTRINGEXACT:
  5383. case CB_INSERTSTRING:
  5384. case CB_SELECTSTRING:
  5385. {
  5386. if (MLIsEnabled(hWnd))
  5387. {
  5388. UINT uiMsgTx;
  5389. switch (Msg)
  5390. {
  5391. case WM_SETTEXT:
  5392. uiMsgTx = g_ML_SETTEXT;
  5393. break;
  5394. case LB_ADDSTRING:
  5395. uiMsgTx = g_ML_LB_ADDSTRING;
  5396. break;
  5397. case CB_ADDSTRING:
  5398. uiMsgTx = g_ML_CB_ADDSTRING;
  5399. break;
  5400. case LB_FINDSTRING:
  5401. uiMsgTx = g_ML_LB_FINDSTRING;
  5402. break;
  5403. case LB_FINDSTRINGEXACT:
  5404. uiMsgTx = g_ML_LB_FINDSTRINGEXACT;
  5405. break;
  5406. case LB_INSERTSTRING:
  5407. uiMsgTx = g_ML_LB_INSERTSTRING;
  5408. break;
  5409. case LB_SELECTSTRING:
  5410. uiMsgTx = g_ML_LB_SELECTSTRING;
  5411. break;
  5412. case CB_FINDSTRING:
  5413. uiMsgTx = g_ML_CB_FINDSTRING;
  5414. break;
  5415. case CB_FINDSTRINGEXACT:
  5416. uiMsgTx = g_ML_CB_FINDSTRINGEXACT;
  5417. break;
  5418. case CB_INSERTSTRING:
  5419. uiMsgTx = g_ML_CB_INSERTSTRING;
  5420. break;
  5421. case CB_SELECTSTRING:
  5422. uiMsgTx = g_ML_CB_SELECTSTRING;
  5423. break;
  5424. default:
  5425. ASSERT(0);
  5426. }
  5427. return SendMessageA(hWnd, uiMsgTx, wParam, lParam);
  5428. }
  5429. else if (Msg == CB_FINDSTRINGEXACT && IsUnicodeComboEx(hWnd))
  5430. {
  5431. // ComboEx is in UNICODE mode so we can send it the
  5432. // unicode string
  5433. goto Ldef;
  5434. }
  5435. else
  5436. {
  5437. // WARNING: in the ADDSTRING and INSERTSTRING cases for OWNERDRAW !HASSTRING
  5438. // then this is a pointer to a structure and not a string!!! (Seems that only
  5439. // code that does this is comctl32's comboex, which currently doesn't come here.)
  5440. //
  5441. CStrIn str((LPWSTR) lParam);
  5442. return SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
  5443. }
  5444. }
  5445. case WM_GETTEXT:
  5446. case LB_GETTEXT:
  5447. case CB_GETLBTEXT:
  5448. {
  5449. if (MLIsEnabled(hWnd))
  5450. {
  5451. UINT uiMsgTx;
  5452. switch (Msg)
  5453. {
  5454. case WM_GETTEXT:
  5455. uiMsgTx = g_ML_GETTEXT;
  5456. break;
  5457. case LB_GETTEXT:
  5458. uiMsgTx = g_ML_LB_GETTEXT;
  5459. break;
  5460. case CB_GETLBTEXT:
  5461. uiMsgTx = g_ML_CB_GETLBTEXT;
  5462. break;
  5463. default:
  5464. ASSERT(0);
  5465. }
  5466. return SendMessageA(hWnd, uiMsgTx, wParam, lParam);
  5467. }
  5468. else if (Msg == CB_GETLBTEXT && IsUnicodeComboEx(hWnd))
  5469. {
  5470. // ComboEx is in UNICODE mode so we can send it the
  5471. // unicode string
  5472. goto Ldef;
  5473. }
  5474. else
  5475. {
  5476. int iStrLen;
  5477. switch (Msg)
  5478. {
  5479. case WM_GETTEXT:
  5480. iStrLen = (int)wParam;
  5481. break;
  5482. case LB_GETTEXT:
  5483. iStrLen = SendMessageA(hWnd, LB_GETTEXTLEN, wParam, lParam);
  5484. if (iStrLen == LB_ERR)
  5485. iStrLen = 255;
  5486. break;
  5487. case CB_GETLBTEXT:
  5488. iStrLen = SendMessageA(hWnd, CB_GETLBTEXTLEN, wParam, lParam);
  5489. if (iStrLen == CB_ERR)
  5490. iStrLen = 255;
  5491. break;
  5492. default:
  5493. ASSERT(0);
  5494. }
  5495. CStrOut str((LPWSTR)lParam, (iStrLen + 1));
  5496. SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
  5497. return str.ConvertExcludingNul();
  5498. }
  5499. }
  5500. case WM_GETTEXTLENGTH:
  5501. case LB_GETTEXTLEN:
  5502. case CB_GETLBTEXTLEN:
  5503. {
  5504. UINT uiMsgTx;
  5505. if (MLIsEnabled(hWnd))
  5506. {
  5507. switch (Msg)
  5508. {
  5509. case WM_GETTEXTLENGTH:
  5510. uiMsgTx = g_ML_GETTEXTLENGTH;
  5511. break;
  5512. case LB_GETTEXTLEN:
  5513. uiMsgTx = g_ML_LB_GETTEXTLEN;
  5514. break;
  5515. case CB_GETLBTEXTLEN:
  5516. uiMsgTx = g_ML_CB_GETLBTEXTLEN;
  5517. break;
  5518. default:
  5519. ASSERT(0);
  5520. }
  5521. return SendMessageA(hWnd, uiMsgTx, wParam, lParam);
  5522. }
  5523. else
  5524. {
  5525. // Bug: #70280
  5526. // we can not just return the size of ANSI character back, it breaks some localized
  5527. // version of Win98 with localized IE/OE scenario: some apps rely on the returned size
  5528. // in characters to show the string and may cause the garbage displayed beyond the end of
  5529. // the actual string.
  5530. //
  5531. LPWSTR lpwszTemp = NULL;
  5532. int iWCharLen = 0;
  5533. int iAnsiCharLen = SendMessageA(hWnd, Msg, wParam, lParam);
  5534. if ((iAnsiCharLen <= 0) || (LB_ERR == iAnsiCharLen) || (CB_ERR == iAnsiCharLen))
  5535. {
  5536. iWCharLen = iAnsiCharLen; // return error if we can not get the ANSI string length
  5537. goto L_Rtn;
  5538. }
  5539. // we always allocate the wide string buffer in the size of ANSI string length plus 1,
  5540. // it should be big enough to hold the returned wide string.
  5541. lpwszTemp = (LPWSTR)LocalAlloc(LPTR, ((iAnsiCharLen + 1) * sizeof(WCHAR)));
  5542. if (!lpwszTemp)
  5543. goto L_Rtn;
  5544. switch (Msg)
  5545. {
  5546. case WM_GETTEXTLENGTH:
  5547. uiMsgTx = WM_GETTEXT;
  5548. break;
  5549. case LB_GETTEXTLEN:
  5550. uiMsgTx = LB_GETTEXT;
  5551. break;
  5552. case CB_GETLBTEXTLEN:
  5553. uiMsgTx = CB_GETLBTEXT;
  5554. break;
  5555. default:
  5556. ASSERT(0);
  5557. }
  5558. iWCharLen = SendMessageAThunk(hWnd, uiMsgTx,
  5559. ((uiMsgTx == WM_GETTEXT) ? (WPARAM)(iAnsiCharLen + 1) : wParam),
  5560. (LPARAM)lpwszTemp);
  5561. L_Rtn:
  5562. if (lpwszTemp)
  5563. LocalFree(lpwszTemp);
  5564. // if error occured, we'll return the error (WM_, LB_, CB_),
  5565. // if fail to allocate memory, we'll return 0, the initial value of iWCharlen.
  5566. return (LRESULT)iWCharLen;
  5567. }
  5568. }
  5569. case WM_SETTINGCHANGE:
  5570. {
  5571. if (lParam)
  5572. {
  5573. CStrIn str((LPWSTR)lParam);
  5574. LRESULT lRes = 0;
  5575. SendMessageTimeoutA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str,
  5576. SMTO_NORMAL, 3000, (PULONG_PTR)&lRes);
  5577. return lRes;
  5578. }
  5579. goto Ldef;
  5580. }
  5581. // The new unicode comctl32.dll handles these correctly so we don't need to thunk:
  5582. // TTM_DELTOOL, TTM_ADDTOOL, TVM_INSERTITEM, TVM_GETITEM, TCM_INSERTITEM, TCM_SETITEM
  5583. default:
  5584. Ldef:
  5585. return SendMessageA(hWnd, Msg, wParam, lParam);
  5586. }
  5587. }
  5588. LRESULT WINAPI
  5589. SendMessageTimeoutAThunk(
  5590. HWND hWnd,
  5591. UINT uMsg,
  5592. WPARAM wParam,
  5593. LPARAM lParam,
  5594. UINT fuFlags,
  5595. UINT uTimeout,
  5596. PULONG_PTR lpdwResult)
  5597. {
  5598. switch (uMsg)
  5599. {
  5600. case WM_SETTINGCHANGE:
  5601. {
  5602. if (lParam)
  5603. {
  5604. CStrIn str((LPWSTR)lParam);
  5605. return SendMessageTimeoutA(hWnd, uMsg, wParam, (LPARAM)(LPSTR)str,
  5606. fuFlags, uTimeout, lpdwResult);
  5607. }
  5608. }
  5609. break;
  5610. }
  5611. return SendMessageTimeoutA(hWnd, uMsg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
  5612. }
  5613. LRESULT FORWARD_API WINAPI
  5614. SendMessageTimeoutWrapW(
  5615. HWND hWnd,
  5616. UINT Msg,
  5617. WPARAM wParam,
  5618. LPARAM lParam,
  5619. UINT fuFlags,
  5620. UINT uTimeout,
  5621. PULONG_PTR lpdwResult)
  5622. {
  5623. VALIDATE_PROTOTYPE(SendMessage);
  5624. // perf: we should do _asm here (see CallWindowProcWrapW), but
  5625. // to do that we need to 'outline' the below switch (o.w. we
  5626. // can't be 'naked'). that in turn slows down the non-NT case...
  5627. #ifndef UNIX
  5628. THUNK_AW(SendMessageTimeout, (hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult));
  5629. #else
  5630. return SendMessageTimeoutW(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
  5631. #endif
  5632. }
  5633. LRESULT FORWARD_API WINAPI
  5634. SendMessageWrapW(
  5635. HWND hWnd,
  5636. UINT Msg,
  5637. WPARAM wParam,
  5638. LPARAM lParam)
  5639. {
  5640. VALIDATE_PROTOTYPE(SendMessage);
  5641. // perf: we should do _asm here (see CallWindowProcWrapW), but
  5642. // to do that we need to 'outline' the below switch (o.w. we
  5643. // can't be 'naked'). that in turn slows down the non-NT case...
  5644. #ifndef UNIX
  5645. // n.b. THUNK not FORWARD
  5646. THUNK_AW(SendMessage, (hWnd, Msg, wParam, lParam));
  5647. #else
  5648. return SendMessageW(hWnd, Msg, wParam, lParam);
  5649. #endif
  5650. }
  5651. #endif // NEED_USER32_WRAPPER
  5652. #ifdef NEED_KERNEL32_WRAPPER
  5653. BOOL WINAPI
  5654. SetCurrentDirectoryWrapW(LPCWSTR lpszCurDir)
  5655. {
  5656. VALIDATE_PROTOTYPE(SetCurrentDirectory);
  5657. if (g_bRunningOnNT)
  5658. {
  5659. return SetCurrentDirectoryW(lpszCurDir);
  5660. }
  5661. CStrIn str(lpszCurDir);
  5662. return SetCurrentDirectoryA(str);
  5663. }
  5664. #endif // NEED_KERNEL32_WRAPPER
  5665. #ifdef NEED_USER32_WRAPPER
  5666. BOOL WINAPI
  5667. SetDlgItemTextWrapW(HWND hDlg, int nIDDlgItem, LPCWSTR lpString)
  5668. {
  5669. VALIDATE_PROTOTYPE(SetDlgItemText);
  5670. HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
  5671. if (hWnd)
  5672. return SetWindowTextWrapW(hWnd, lpString);
  5673. else
  5674. return FALSE;
  5675. }
  5676. #endif // NEED_USER32_WRAPPER
  5677. #ifdef NEED_USER32_WRAPPER
  5678. BOOL WINAPI
  5679. SetPropWrapW(
  5680. HWND hWnd,
  5681. LPCWSTR lpString,
  5682. HANDLE hData)
  5683. {
  5684. VALIDATE_PROTOTYPE(SetProp);
  5685. if (g_bRunningOnNT)
  5686. {
  5687. return SetPropW(hWnd, lpString, hData);
  5688. }
  5689. CStrIn str(lpString);
  5690. return SetPropA(hWnd, str, hData);
  5691. }
  5692. #endif // NEED_USER32_WRAPPER
  5693. #ifdef NEED_USER32_WRAPPER
  5694. LONG FORWARD_API WINAPI
  5695. SetWindowLongWrapW(HWND hWnd, int nIndex, LONG dwNewLong)
  5696. {
  5697. VALIDATE_PROTOTYPE(SetWindowLong);
  5698. FORWARD_AW(SetWindowLong, (hWnd, nIndex, dwNewLong));
  5699. }
  5700. #endif // NEED_USER32_WRAPPER
  5701. #ifdef NEED_USER32_WRAPPER
  5702. HHOOK
  5703. FORWARD_API WINAPI
  5704. SetWindowsHookExWrapW(
  5705. int idHook,
  5706. HOOKPROC lpfn,
  5707. HINSTANCE hmod,
  5708. DWORD dwThreadId)
  5709. {
  5710. VALIDATE_PROTOTYPE(SetWindowsHookEx);
  5711. FORWARD_AW(SetWindowsHookEx, (idHook, lpfn, hmod, dwThreadId));
  5712. }
  5713. #endif // NEED_USER32_WRAPPER
  5714. #ifdef NEED_USER32_WRAPPER
  5715. BOOL WINAPI
  5716. SetWindowTextWrapW(HWND hWnd, LPCWSTR lpString)
  5717. {
  5718. VALIDATE_PROTOTYPE(SetWindowText);
  5719. if (MLIsEnabled(hWnd))
  5720. return MLSetControlTextI(hWnd, lpString);
  5721. if (g_bRunningOnNT)
  5722. {
  5723. return SetWindowTextW(hWnd, lpString);
  5724. }
  5725. CStrIn str(lpString);
  5726. return SetWindowTextA(hWnd, str);
  5727. }
  5728. #endif // NEED_USER32_WRAPPER
  5729. #ifdef NEED_USER32_WRAPPER
  5730. BOOL WINAPI
  5731. SystemParametersInfoWrapW(
  5732. UINT uiAction,
  5733. UINT uiParam,
  5734. PVOID pvParam,
  5735. UINT fWinIni)
  5736. {
  5737. VALIDATE_PROTOTYPE(SystemParametersInfo);
  5738. if (g_bRunningOnNT)
  5739. {
  5740. return SystemParametersInfoW(
  5741. uiAction,
  5742. uiParam,
  5743. pvParam,
  5744. fWinIni);
  5745. }
  5746. BOOL ret;
  5747. char ach[LF_FACESIZE];
  5748. if (uiAction == SPI_SETDESKWALLPAPER)
  5749. {
  5750. CStrIn str((LPCWSTR) pvParam);
  5751. ret = SystemParametersInfoA(
  5752. uiAction,
  5753. uiParam,
  5754. str,
  5755. fWinIni);
  5756. }
  5757. else
  5758. ret = SystemParametersInfoA(
  5759. uiAction,
  5760. uiParam,
  5761. pvParam,
  5762. fWinIni);
  5763. if ((uiAction == SPI_GETICONTITLELOGFONT) && ret)
  5764. {
  5765. strcpy(ach, ((LPLOGFONTA)pvParam)->lfFaceName);
  5766. SHAnsiToUnicode(ach, ((LPLOGFONTW)pvParam)->lfFaceName, ARRAYSIZE(((LPLOGFONTW)pvParam)->lfFaceName));
  5767. }
  5768. return ret;
  5769. }
  5770. #endif // NEED_USER32_WRAPPER
  5771. #ifdef NEED_USER32_WRAPPER
  5772. int FORWARD_API WINAPI
  5773. TranslateAcceleratorWrapW(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
  5774. {
  5775. VALIDATE_PROTOTYPE(TranslateAccelerator);
  5776. FORWARD_AW(TranslateAccelerator, (hWnd, hAccTable, lpMsg));
  5777. }
  5778. #endif // NEED_USER32_WRAPPER
  5779. #ifdef NEED_USER32_WRAPPER
  5780. BOOL WINAPI
  5781. UnregisterClassWrapW(LPCWSTR lpClassName, HINSTANCE hInstance)
  5782. {
  5783. VALIDATE_PROTOTYPE(UnregisterClass);
  5784. if (g_bRunningOnNT)
  5785. {
  5786. return UnregisterClassW(lpClassName, hInstance);
  5787. }
  5788. CStrIn str(lpClassName);
  5789. return UnregisterClassA(str, hInstance);
  5790. }
  5791. #endif // NEED_USER32_WRAPPER
  5792. #ifdef NEED_USER32_WRAPPER
  5793. SHORT
  5794. WINAPI
  5795. VkKeyScanWrapW(WCHAR ch)
  5796. {
  5797. VALIDATE_PROTOTYPE(VkKeyScan);
  5798. if (g_bRunningOnNT)
  5799. {
  5800. return VkKeyScanW(ch);
  5801. }
  5802. CStrIn str(&ch, 1);
  5803. return VkKeyScanA(*(char *)str);
  5804. }
  5805. #endif // NEED_USER32_WRAPPER
  5806. #ifdef NEED_USER32_WRAPPER
  5807. BOOL WINAPI
  5808. WinHelpWrapW(HWND hwnd, LPCWSTR szFile, UINT uCmd, ULONG_PTR dwData)
  5809. {
  5810. VALIDATE_PROTOTYPE(WinHelp);
  5811. if (g_bRunningOnNT)
  5812. {
  5813. return WinHelpW(hwnd, szFile, uCmd, dwData);
  5814. }
  5815. CStrIn str(szFile);
  5816. return WinHelpA(hwnd, str, uCmd, dwData);
  5817. }
  5818. #endif // NEED_USER32_WRAPPER
  5819. #ifdef NEED_USER32_WRAPPER
  5820. //+---------------------------------------------------------------------------
  5821. //
  5822. // Function: wvsprintfW
  5823. //
  5824. // Synopsis: Nightmare string function
  5825. //
  5826. // Arguments: [pwszOut] --
  5827. // [pwszFormat] --
  5828. // [...] --
  5829. //
  5830. // Returns:
  5831. //
  5832. // History: 1-06-94 ErikGav Created
  5833. //
  5834. // Notes: If you're reading this, you're probably having a problem with
  5835. // this function. Make sure that your "%s" in the format string
  5836. // says "%ws" if you are passing wide strings.
  5837. //
  5838. // %s on NT means "wide string"
  5839. // %s on Chicago means "ANSI string"
  5840. //
  5841. // NOTE: This function should not be used. Use Format instead.
  5842. //
  5843. //----------------------------------------------------------------------------
  5844. int WINAPI
  5845. wvsprintfWrapW(LPWSTR pwszOut, LPCWSTR pwszFormat, va_list arglist)
  5846. {
  5847. VALIDATE_PROTOTYPE(wvsprintf);
  5848. if (g_bRunningOnNT)
  5849. {
  5850. return wvsprintfW(pwszOut, pwszFormat, arglist);
  5851. }
  5852. // Old code created a 1K ansi output buffer for wvsprintfA and then
  5853. // thunked the result. If we're going to do that, might as
  5854. // well create a 1K unicode output buffer and call our wvnsprintfW
  5855. // implementation directly. Two benefits: 1) no buffer overrun
  5856. // and 2) native W implementation so we can handle unicode strings!
  5857. WCHAR wszOut[1024];
  5858. wvnsprintfW(wszOut, ARRAYSIZE(wszOut), pwszFormat, arglist);
  5859. // Roll our own "ConvertExcludingNul" since this is W->W
  5860. int ret = SHUnicodeToUnicode(wszOut, pwszOut, ARRAYSIZE(wszOut));
  5861. if (ret > 0)
  5862. {
  5863. ret -= 1;
  5864. }
  5865. return ret;
  5866. }
  5867. #endif // NEED_USER32_WRAPPER
  5868. #ifdef NEED_MPR_WRAPPER
  5869. //+---------------------------------------------------------------------------
  5870. //
  5871. // Function: WNetRestoreConnectionWrapW
  5872. //
  5873. //----------------------------------------------------------------------------
  5874. DWORD WINAPI WNetRestoreConnectionWrapW(IN HWND hwndParent, IN LPCWSTR pwzDevice)
  5875. {
  5876. if (g_bRunningOnNT)
  5877. {
  5878. return WNetRestoreConnectionW(hwndParent, pwzDevice);
  5879. }
  5880. CStrIn strIn(pwzDevice);
  5881. return WNetRestoreConnectionA(hwndParent, strIn);
  5882. }
  5883. #endif // NEED_MPR_WRAPPER
  5884. #ifdef NEED_MPR_WRAPPER
  5885. //+---------------------------------------------------------------------------
  5886. //
  5887. // Function: WNetGetLastErrorWrapW
  5888. //
  5889. //
  5890. //----------------------------------------------------------------------------
  5891. DWORD WINAPI WNetGetLastErrorWrapW(OUT LPDWORD pdwError, OUT LPWSTR pwzErrorBuf, IN DWORD cchErrorBufSize, OUT LPWSTR pwzNameBuf, IN DWORD cchNameBufSize)
  5892. {
  5893. VALIDATE_PROTOTYPE(WNetGetLastError);
  5894. if (g_bRunningOnNT)
  5895. {
  5896. return WNetGetLastErrorW(pdwError, pwzErrorBuf, cchErrorBufSize, pwzNameBuf, cchNameBufSize);
  5897. }
  5898. // Consider: Out-string bufsize too large or small?
  5899. CStrOut strErrorOut(pwzErrorBuf, cchErrorBufSize);
  5900. CStrOut strNameOut(pwzNameBuf, cchNameBufSize);
  5901. DWORD dwResult = WNetGetLastErrorA(pdwError, strErrorOut, strErrorOut.BufSize(), strNameOut, strNameOut.BufSize());
  5902. strErrorOut.ConvertExcludingNul();
  5903. strNameOut.ConvertExcludingNul();
  5904. return dwResult;
  5905. }
  5906. #endif // NEED_MPR_WRAPPER
  5907. #ifdef NEED_USER32_WRAPPER
  5908. int WINAPI DrawTextExWrapW(
  5909. HDC hdc, // handle of device context
  5910. LPWSTR pwzText, // address of string to draw
  5911. int cchText, // length of string to draw
  5912. LPRECT lprc, // address of rectangle coordinates
  5913. UINT dwDTFormat, // formatting options
  5914. LPDRAWTEXTPARAMS lpDTParams // address of structure for more options
  5915. )
  5916. {
  5917. VALIDATE_PROTOTYPE(DrawTextEx);
  5918. if (_MayNeedFontLinking(pwzText, cchText))
  5919. {
  5920. return DrawTextExFLW(hdc, pwzText, cchText, lprc, dwDTFormat, lpDTParams);
  5921. }
  5922. else if (g_bRunningOnNT)
  5923. {
  5924. return DrawTextExW(hdc, pwzText, cchText, lprc, dwDTFormat, lpDTParams);
  5925. }
  5926. CStrIn strText(pwzText, cchText);
  5927. return DrawTextExA(hdc, strText, strText.strlen(), lprc, dwDTFormat, lpDTParams);
  5928. }
  5929. #endif // NEED_USER32_WRAPPER
  5930. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  5931. void SetThunkMenuItemInfoWToA(LPCMENUITEMINFOW pmiiW, LPMENUITEMINFOA pmiiA, LPSTR pszBuffer, DWORD cchSize)
  5932. {
  5933. *pmiiA = *(LPMENUITEMINFOA) pmiiW;
  5934. // MFT_STRING is Zero. So MFT_STRING & anything evaluates to False.
  5935. // so instead you have to check for the absence of non-string items
  5936. if ((pmiiW->dwTypeData) && (MFT_NONSTRING & pmiiW->fType) == 0)
  5937. {
  5938. pmiiA->dwTypeData = pszBuffer;
  5939. pmiiA->cch = cchSize;
  5940. SHUnicodeToAnsi(pmiiW->dwTypeData, pmiiA->dwTypeData, cchSize);
  5941. }
  5942. }
  5943. void GetThunkMenuItemInfoWToA(LPCMENUITEMINFOW pmiiW, LPMENUITEMINFOA pmiiA, LPSTR pszBuffer, DWORD cchSize)
  5944. {
  5945. *pmiiA = *(LPMENUITEMINFOA) pmiiW;
  5946. if ((pmiiW->dwTypeData) && (MFT_STRING & pmiiW->fType))
  5947. {
  5948. pszBuffer[0] = 0;
  5949. pmiiA->dwTypeData = pszBuffer;
  5950. pmiiA->cch = cchSize;
  5951. }
  5952. }
  5953. void GetThunkMenuItemInfoAToW(LPCMENUITEMINFOA pmiiA, LPMENUITEMINFOW pmiiW)
  5954. {
  5955. LPWSTR pwzText = pmiiW->dwTypeData;
  5956. UINT cch = pmiiW->cch;
  5957. *pmiiW = *(LPMENUITEMINFOW) pmiiA;
  5958. pmiiW->dwTypeData = pwzText;
  5959. pmiiW->cch = cch;
  5960. if ((pmiiA->cch > 0) && (pmiiA->dwTypeData) && (pwzText) && !((MFT_SEPARATOR | MFT_BITMAP) & pmiiA->fType))
  5961. SHAnsiToUnicode(pmiiA->dwTypeData, pmiiW->dwTypeData, pmiiW->cch);
  5962. }
  5963. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  5964. BOOL WINAPI GetMenuItemInfoWrapW(
  5965. HMENU hMenu,
  5966. UINT uItem,
  5967. BOOL fByPosition,
  5968. LPMENUITEMINFOW pmiiW)
  5969. {
  5970. BOOL fResult;
  5971. VALIDATE_PROTOTYPE(GetMenuItemInfo);
  5972. ASSERT(pmiiW->cbSize == MENUITEMINFOSIZE_WIN95); // Ensure Win95 compatibility
  5973. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  5974. BOOL fItemData;
  5975. DWORD_PTR dwItemData;
  5976. LPWSTR pwz;
  5977. UINT cch;
  5978. if (bOwnerDraw)
  5979. {
  5980. if (MIIM_DATA & pmiiW->fMask)
  5981. fItemData = TRUE;
  5982. else
  5983. {
  5984. fItemData = FALSE;
  5985. pmiiW->fMask |= MIIM_DATA;
  5986. }
  5987. pwz = pmiiW->dwTypeData; // save original buffer pointer
  5988. cch = pmiiW->cch; // save original buffer size
  5989. dwItemData = pmiiW->dwItemData; // save original dwItemData size
  5990. }
  5991. #ifndef UNIX
  5992. // Widechar API's are messed up in MAINWIN. For now assume not ruuning on
  5993. // NT for this.
  5994. if (g_bRunningOnNT)
  5995. fResult = GetMenuItemInfoW(hMenu, uItem, fByPosition, pmiiW);
  5996. else
  5997. #endif
  5998. {
  5999. if (pmiiW->fMask & MIIM_TYPE)
  6000. {
  6001. MENUITEMINFOA miiA = *(LPMENUITEMINFOA)pmiiW;
  6002. LPSTR pszText = NULL;
  6003. if (pmiiW->cch > 0)
  6004. pszText = new char[pmiiW->cch * 2]; // for DBCS, we multifly by 2
  6005. miiA.dwTypeData = pszText;
  6006. miiA.cch = (pszText)? pmiiW->cch * 2: 0; // set correct buffer size
  6007. fResult = GetMenuItemInfoA(hMenu, uItem, fByPosition, &miiA);
  6008. GetThunkMenuItemInfoAToW(&miiA, pmiiW);
  6009. if (pszText)
  6010. delete pszText;
  6011. }
  6012. else
  6013. fResult = GetMenuItemInfoA(hMenu, uItem, fByPosition, (LPMENUITEMINFOA) pmiiW); // It doesn't contain a string so W and A are the same.
  6014. }
  6015. if (bOwnerDraw)
  6016. {
  6017. if ((MIIM_TYPE & pmiiW->fMask) && (MFT_OWNERDRAW & pmiiW->fType))
  6018. {
  6019. LPPUIMENUITEM lpItem = (LPPUIMENUITEM)pmiiW->dwItemData;
  6020. if (!IsBadReadPtr(lpItem, sizeof(lpItem->dwSig)) && PUI_OWNERDRAW_SIG == lpItem->dwSig && !(MFT_OWNERDRAW & lpItem->fType))
  6021. {
  6022. if ((cch > 0) && pwz && !((MFT_SEPARATOR | MFT_BITMAP) & pmiiW->fType))
  6023. {
  6024. StrCpyNW(pwz, lpItem->lpwz, cch);
  6025. pmiiW->dwTypeData = pwz;
  6026. pmiiW->cch = lpItem->cch;
  6027. pmiiW->fType &= ~MFT_OWNERDRAW;
  6028. if (fItemData)
  6029. pmiiW->dwItemData = lpItem->dwItemData;
  6030. else
  6031. pmiiW->dwItemData = dwItemData;
  6032. }
  6033. }
  6034. }
  6035. }
  6036. return fResult;
  6037. }
  6038. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  6039. BOOL WINAPI InsertMenuItemWrapW(
  6040. HMENU hMenu,
  6041. UINT uItem,
  6042. BOOL fByPosition,
  6043. LPCMENUITEMINFOW pmiiW)
  6044. {
  6045. VALIDATE_PROTOTYPE(InsertMenuItem);
  6046. ASSERT(pmiiW->cbSize == MENUITEMINFOSIZE_WIN95); // Ensure Win95 compatibility
  6047. BOOL fResult;
  6048. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  6049. MENUITEMINFOW miiW;
  6050. if (bOwnerDraw)
  6051. {
  6052. MungeMenuItem(hMenu, pmiiW, &miiW);
  6053. pmiiW = &miiW;
  6054. }
  6055. if (g_bRunningOnNT)
  6056. return InsertMenuItemW(hMenu, uItem, fByPosition, pmiiW);
  6057. MENUITEMINFOA miiA;
  6058. CHAR szText[INTERNET_MAX_URL_LENGTH];
  6059. SetThunkMenuItemInfoWToA(pmiiW, &miiA, szText, ARRAYSIZE(szText));
  6060. fResult = InsertMenuItemA(hMenu, uItem, fByPosition, &miiA);
  6061. return fResult;
  6062. }
  6063. // This is required for ML, so do not put inside #ifdef NEED_USER32_WRAPPER
  6064. BOOL WINAPI
  6065. SetMenuItemInfoWrapW(
  6066. HMENU hMenu,
  6067. UINT uItem,
  6068. BOOL fByPosition,
  6069. LPCMENUITEMINFOW lpmiiW)
  6070. {
  6071. VALIDATE_PROTOTYPE(SetMenuItemInfo);
  6072. ASSERT(lpmiiW->cbSize == MENUITEMINFOSIZE_WIN95); // Ensure Win95 compatibility
  6073. static BOOL bOwnerDraw = NeedMenuOwnerDraw();
  6074. MENUITEMINFOW miiW;
  6075. if (bOwnerDraw)
  6076. {
  6077. if ( (MIIM_TYPE & lpmiiW->fMask) &&
  6078. 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
  6079. {
  6080. DeleteOwnerDrawMenuItem(hMenu, uItem, fByPosition);
  6081. MungeMenuItem(hMenu, lpmiiW, &miiW);
  6082. lpmiiW = &miiW;
  6083. }
  6084. }
  6085. if (g_bRunningOnNT)
  6086. {
  6087. return SetMenuItemInfoW( hMenu, uItem, fByPosition, lpmiiW);
  6088. }
  6089. BOOL fRet;
  6090. ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) &&
  6091. FIELD_OFFSET(MENUITEMINFOW, dwTypeData) ==
  6092. FIELD_OFFSET(MENUITEMINFOA, dwTypeData) );
  6093. if ( (MIIM_TYPE & lpmiiW->fMask) &&
  6094. 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
  6095. {
  6096. MENUITEMINFOA miiA;
  6097. // the cch is ignored on SetMenuItemInfo
  6098. CStrIn str((LPWSTR)lpmiiW->dwTypeData, -1);
  6099. memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) );
  6100. miiA.dwTypeData = (LPSTR)str;
  6101. miiA.cch = str.strlen();
  6102. fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA );
  6103. }
  6104. else
  6105. {
  6106. fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition,
  6107. (LPCMENUITEMINFOA)lpmiiW );
  6108. }
  6109. return fRet;
  6110. }
  6111. #ifdef NEED_GDI32_WRAPPER
  6112. HFONT WINAPI
  6113. CreateFontWrapW(int nHeight, // logical height of font
  6114. int nWidth, // logical average character width
  6115. int nEscapement, // angle of escapement
  6116. int nOrientation, // base-line orientation angle
  6117. int fnWeight, // font weight
  6118. DWORD fdwItalic, // italic attribute flag
  6119. DWORD fdwUnderline, // underline attribute flag
  6120. DWORD fdwStrikeOut, // strikeout attribute flag
  6121. DWORD fdwCharSet, // character set identifier
  6122. DWORD fdwOutputPrecision, // output precision
  6123. DWORD fdwClipPrecision, // clipping precision
  6124. DWORD fdwQuality, // output quality
  6125. DWORD fdwPitchAndFamily, // pitch and family
  6126. LPCWSTR pwzFace) // address of typeface name string )
  6127. {
  6128. VALIDATE_PROTOTYPE(CreateFont);
  6129. if (g_bRunningOnNT)
  6130. {
  6131. return CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic,
  6132. fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision,
  6133. fdwClipPrecision, fdwQuality, fdwPitchAndFamily, pwzFace);
  6134. }
  6135. CStrIn str(pwzFace);
  6136. return CreateFontA(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic,
  6137. fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision,
  6138. fdwClipPrecision, fdwQuality, fdwPitchAndFamily, str);
  6139. }
  6140. #endif // NEED_GDI32_WRAPPER
  6141. #ifdef NEED_KERNEL32_WRAPPER
  6142. HANDLE WINAPI CreateMutexWrapW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR pwzName)
  6143. {
  6144. VALIDATE_PROTOTYPE(CreateMutex);
  6145. if (g_bRunningOnNT)
  6146. return CreateMutexW(lpMutexAttributes, bInitialOwner, pwzName);
  6147. CStrIn strText(pwzName);
  6148. return CreateMutexA(lpMutexAttributes, bInitialOwner, strText);
  6149. }
  6150. #endif // NEED_KERNEL32_WRAPPER
  6151. #ifdef NEED_GDI32_WRAPPER
  6152. HDC WINAPI CreateMetaFileWrapW(LPCWSTR pwzFile)
  6153. {
  6154. VALIDATE_PROTOTYPE(CreateMetaFile);
  6155. if (g_bRunningOnNT)
  6156. return CreateMetaFileW(pwzFile);
  6157. CStrIn strText(pwzFile);
  6158. return CreateMetaFileA(strText);
  6159. }
  6160. #endif // NEED_GDI32_WRAPPER
  6161. #ifdef NEED_KERNEL32_WRAPPER
  6162. // ExpandEnvironmentStrings returns the size of the needed string
  6163. DWORD WINAPI ExpandEnvironmentStringsWrapW(LPCWSTR pwzSrc, LPWSTR pwzDst, DWORD cchSize)
  6164. {
  6165. DWORD dwRet;
  6166. if (pwzDst)
  6167. {
  6168. VALIDATE_OUTBUF(pwzDst, cchSize);
  6169. }
  6170. if (g_bRunningOnNT)
  6171. {
  6172. dwRet = ExpandEnvironmentStringsW(pwzSrc, pwzDst, cchSize);
  6173. }
  6174. else
  6175. {
  6176. CStrIn strTextIn(pwzSrc);
  6177. CStrOut strTextOut(pwzDst, cchSize);
  6178. DWORD dwResult = ExpandEnvironmentStringsA(strTextIn, strTextOut, strTextOut.BufSize());
  6179. DWORD dwResultUnicode = strTextOut.ConvertIncludingNul();
  6180. // NT4 returned the number of bytes in the UNICODE string, not the number
  6181. // of bytes in the ANSI string. NT5 returns the number of bytes in the UNICODE
  6182. // string divided by 2, so it has even less bearing on the ansi string. Hopefully
  6183. // the Win9x implementations did the right thing...
  6184. //
  6185. if (dwResult <= cchSize)
  6186. {
  6187. ASSERT(dwResultUnicode <= dwResult);
  6188. dwRet = dwResultUnicode; // we fit in the out buffer, give accurate count
  6189. }
  6190. else
  6191. {
  6192. dwRet = dwResult; // buffer was too small, let caller know (NOTE: this may be bigger than needed)
  6193. }
  6194. }
  6195. return dwRet;
  6196. }
  6197. #endif // NEED_KERNEL32_WRAPPER
  6198. // SHExpandEnvironmentStrings
  6199. //
  6200. // In all cases, this returns a valid output buffer. The buffer may
  6201. // be empty, or it may be truncated, but you can always use the string.
  6202. //
  6203. // RETURN VALUE:
  6204. // 0 implies failure, either a truncated expansion or no expansion whatsoever
  6205. // >0 implies complete expansion, value is count of characters written (excluding NULL)
  6206. //
  6207. DWORD WINAPI SHExpandEnvironmentStringsForUserW(HANDLE hToken, LPCWSTR pwzSrc, LPWSTR pwzDst, DWORD cchSize)
  6208. {
  6209. DWORD dwRet;
  6210. // 99/05/28 vtan: Handle specified users here. It's a Windows NT
  6211. // thing only. Check for both conditions then load the function
  6212. // dynamically out of userenv.dll. If the function cannot be
  6213. // located or returns a problem default to the current user as
  6214. // NULL hToken.
  6215. if (g_bRunningOnNT5OrHigher && (hToken != NULL))
  6216. {
  6217. VALIDATE_OUTBUF(pwzDst, cchSize);
  6218. if (NT5_ExpandEnvironmentStringsForUserW(hToken, pwzSrc, pwzDst, cchSize) != FALSE)
  6219. {
  6220. // userenv!ExpandEnvironmentStringsForUser returns
  6221. // a BOOL result. Convert this to a DWORD result
  6222. // that matches what kernel32!ExpandEnvironmentStrings
  6223. // returns.
  6224. dwRet = lstrlenW(pwzDst) + sizeof('\0');
  6225. }
  6226. else
  6227. {
  6228. dwRet = 0;
  6229. }
  6230. }
  6231. else
  6232. {
  6233. dwRet = ExpandEnvironmentStringsWrapW(pwzSrc, pwzDst, cchSize);
  6234. }
  6235. // The implementations of this function don't seem to gurantee gurantee certain
  6236. // things about the output buffer in failure conditions that callers rely on.
  6237. // So clean things up here.
  6238. //
  6239. // And I found code occasionally that handled semi-failure (success w/ dwRet>cchSize)
  6240. // that assumed the string wasn't properly NULL terminated in this case. Fix that here
  6241. // in the wrapper so our callers don't have to wig-out about errors.
  6242. //
  6243. // NOTE: we map all failures to 0 too.
  6244. //
  6245. if (dwRet > cchSize)
  6246. {
  6247. // Buffer too small, some code assumed there was still a string there and
  6248. // tried to NULL terminate, do it for them.
  6249. SHTruncateString(pwzDst, cchSize);
  6250. dwRet = 0;
  6251. }
  6252. else if (dwRet == 0)
  6253. {
  6254. // Failure, assume no expansions...
  6255. StrCpyNW(pwzDst, pwzSrc, cchSize);
  6256. }
  6257. return dwRet;
  6258. }
  6259. DWORD WINAPI SHExpandEnvironmentStringsW(LPCWSTR pwzSrc, LPWSTR pwzDst, DWORD cchSize)
  6260. {
  6261. return(SHExpandEnvironmentStringsForUserW(NULL, pwzSrc, pwzDst, cchSize));
  6262. }
  6263. DWORD WINAPI SHExpandEnvironmentStringsForUserA(HANDLE hToken, LPCSTR pszSrc, LPSTR pszDst, DWORD cchSize)
  6264. {
  6265. DWORD dwRet;
  6266. // 99/05/28 vtan: The ANSI version of SHExpandEnvironmentStringsForUser
  6267. // exists in case somebody calls the ANSI implementation in WindowsNT.
  6268. // This is meaningless on Win9x. This just thunks parameters and invokes
  6269. // the Unicode implementation. If a problem occurs when thunking just
  6270. // use the current user.
  6271. if (g_bRunningOnNT5OrHigher && (hToken != NULL))
  6272. {
  6273. DWORD dwResultAnsi;
  6274. CStrInW strInW(pszSrc);
  6275. CStrOutW strOutW(pszDst, cchSize);
  6276. dwRet = SHExpandEnvironmentStringsForUserW(hToken, strInW, strOutW, strOutW.BufSize());
  6277. dwResultAnsi = strOutW.ConvertIncludingNul();
  6278. if (dwResultAnsi <= cchSize)
  6279. dwRet = dwResultAnsi;
  6280. }
  6281. else
  6282. {
  6283. // NT4 returns the number of bytes in the UNICODE string.
  6284. //
  6285. // NT5 (as of June 99) returns the number of bytes in the UNICODE string / 2, so it
  6286. // really has no accurate bearing on the number of ansi characters. Plus we're not
  6287. // guranteed buffer truncation in failure case.
  6288. //
  6289. // Not much we can do about it here, eh? Hopefully our callers ignore the return result...
  6290. //
  6291. dwRet = ExpandEnvironmentStringsA(pszSrc, pszDst, cchSize);
  6292. }
  6293. // The implementations of this function don't seem to gurantee gurantee certain
  6294. // things about the output buffer in failure conditions that callers rely on.
  6295. // So clean things up here.
  6296. //
  6297. // And I found code occasionally that handled semi-failure (success w/ dwRet>cchSize)
  6298. // that assumed the string wasn't properly NULL terminated in this case. Fix that here
  6299. // in the wrapper so our callers don't have to wig-out about errors.
  6300. //
  6301. // NOTE: we map all failures to 0 too.
  6302. //
  6303. if (dwRet > cchSize)
  6304. {
  6305. // Buffer too small, make sure it's NULL terminated.
  6306. SHTruncateString(pszDst, cchSize);
  6307. dwRet = 0;
  6308. }
  6309. else if (dwRet == 0)
  6310. {
  6311. // Failure, assume no expansions...
  6312. StrCpyNA(pszDst, pszSrc, cchSize);
  6313. }
  6314. return dwRet;
  6315. }
  6316. DWORD WINAPI SHExpandEnvironmentStringsA(LPCSTR pszSrc, LPSTR pszDst, DWORD cchSize)
  6317. {
  6318. return(SHExpandEnvironmentStringsForUserA(NULL, pszSrc, pszDst, cchSize));
  6319. }
  6320. #ifdef NEED_KERNEL32_WRAPPER
  6321. HANDLE WINAPI CreateSemaphoreWrapW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR pwzName)
  6322. {
  6323. VALIDATE_PROTOTYPE(CreateSemaphore);
  6324. if (g_bRunningOnNT)
  6325. return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, pwzName);
  6326. CStrIn strText(pwzName);
  6327. return CreateSemaphoreA(lpSemaphoreAttributes, lInitialCount, lMaximumCount, strText);
  6328. }
  6329. #endif // NEED_KERNEL32_WRAPPER
  6330. // FEATURE: Todo - GetStartupInfoWrapW
  6331. #ifdef NEED_KERNEL32_WRAPPER
  6332. #define ISGOOD 0
  6333. #define ISBAD 1
  6334. BOOL WINAPI IsBadStringPtrWrapW(LPCWSTR pwzString, UINT_PTR ucchMax)
  6335. {
  6336. VALIDATE_PROTOTYPE(IsBadStringPtr);
  6337. if (g_bRunningOnNT)
  6338. return IsBadStringPtrW(pwzString, ucchMax);
  6339. if (!ucchMax)
  6340. return ISGOOD;
  6341. if (!pwzString)
  6342. return ISBAD;
  6343. LPCWSTR pwzStartAddress = pwzString;
  6344. // ucchMax maybe -1 but that's ok because the loop down below will just
  6345. // look for the terminator.
  6346. LPCWSTR pwzEndAddress = &pwzStartAddress[ucchMax - 1];
  6347. TCHAR chTest;
  6348. _try
  6349. {
  6350. chTest = *(volatile WCHAR *)pwzStartAddress;
  6351. while (chTest && (pwzStartAddress != pwzEndAddress))
  6352. {
  6353. pwzStartAddress++;
  6354. chTest = *(volatile WCHAR *)pwzStartAddress;
  6355. }
  6356. }
  6357. _except (EXCEPTION_EXECUTE_HANDLER)
  6358. {
  6359. return ISBAD;
  6360. }
  6361. __endexcept
  6362. return ISGOOD;
  6363. }
  6364. #endif // NEED_KERNEL32_WRAPPER
  6365. #ifdef NEED_KERNEL32_WRAPPER
  6366. HINSTANCE WINAPI LoadLibraryWrapW(LPCWSTR pwzLibFileName)
  6367. {
  6368. VALIDATE_PROTOTYPE(LoadLibrary);
  6369. if (g_bRunningOnNT)
  6370. return LoadLibraryW(pwzLibFileName);
  6371. CStrIn strFileName(pwzLibFileName);
  6372. return LoadLibraryA(strFileName);
  6373. }
  6374. #endif // NEED_KERNEL32_WRAPPER
  6375. #ifdef NEED_KERNEL32_WRAPPER
  6376. int WINAPI GetTimeFormatWrapW(LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpTime, LPCWSTR pwzFormat, LPWSTR pwzTimeStr, int cchTime)
  6377. {
  6378. VALIDATE_PROTOTYPE(GetTimeFormat);
  6379. if (g_bRunningOnNT)
  6380. return GetTimeFormatW(Locale, dwFlags, lpTime, pwzFormat, pwzTimeStr, cchTime);
  6381. CStrIn strTextIn(pwzFormat);
  6382. // Cross codepage text will be trashed if it is rendered in ANSI,
  6383. // Use system codepage for conversion to make sure we don't trash native ANSI text.
  6384. CStrOut strTextOut(pwzTimeStr, cchTime);
  6385. int nResult = GetTimeFormatA(Locale, dwFlags, lpTime, strTextIn, strTextOut, strTextOut.BufSize());
  6386. if (cchTime != 0)
  6387. nResult = strTextOut.ConvertIncludingNul();
  6388. return nResult;
  6389. }
  6390. #endif // NEED_KERNEL32_WRAPPER
  6391. #ifdef NEED_KERNEL32_WRAPPER
  6392. int WINAPI GetDateFormatWrapW(LCID Locale, DWORD dwFlags, CONST SYSTEMTIME * lpDate, LPCWSTR pwzFormat, LPWSTR pwzDateStr, int cchDate)
  6393. {
  6394. VALIDATE_PROTOTYPE(GetDateFormat);
  6395. if (g_bRunningOnNT)
  6396. return GetDateFormatW(Locale, dwFlags, lpDate, pwzFormat, pwzDateStr, cchDate);
  6397. CStrIn strTextIn(pwzFormat);
  6398. CStrOut strTextOut(pwzDateStr, cchDate);
  6399. int nResult = GetDateFormatA(Locale, dwFlags, lpDate, strTextIn, strTextOut, strTextOut.BufSize());
  6400. if (cchDate != 0)
  6401. nResult = strTextOut.ConvertIncludingNul();
  6402. return nResult;
  6403. }
  6404. #endif // NEED_KERNEL32_WRAPPER
  6405. #ifdef NEED_KERNEL32_WRAPPER
  6406. BOOL WINAPI WritePrivateProfileStringWrapW(LPCWSTR pwzAppName, LPCWSTR pwzKeyName, LPCWSTR pwzString, LPCWSTR pwzFileName)
  6407. {
  6408. VALIDATE_PROTOTYPE(WritePrivateProfileString);
  6409. if (g_bRunningOnNT)
  6410. return WritePrivateProfileStringW(pwzAppName, pwzKeyName, pwzString, pwzFileName);
  6411. CStrIn strTextAppName(pwzAppName);
  6412. CStrIn strTextKeyName(pwzKeyName);
  6413. CStrIn strTextString(pwzString);
  6414. CPPFIn strTextFileName(pwzFileName); // PrivateProfile filename needs special class
  6415. return WritePrivateProfileStringA(strTextAppName, strTextKeyName, strTextString, strTextFileName);
  6416. }
  6417. #endif // NEED_KERNEL32_WRAPPER
  6418. #ifdef NEED_KERNEL32_WRAPPER
  6419. DWORD WINAPI GetPrivateProfileStringWrapW(LPCWSTR pwzAppName, LPCWSTR pwzKeyName, LPCWSTR pwzDefault, LPWSTR pwzReturnedString, DWORD cchSize, LPCWSTR pwzFileName)
  6420. {
  6421. VALIDATE_PROTOTYPE(GetPrivateProfileString);
  6422. if (g_bRunningOnNT)
  6423. return GetPrivateProfileStringW(pwzAppName, pwzKeyName, pwzDefault, pwzReturnedString, cchSize, pwzFileName);
  6424. CStrIn strTextAppName(pwzAppName);
  6425. CStrIn strTextKeyName(pwzKeyName);
  6426. CStrIn strTextDefault(pwzDefault);
  6427. CPPFIn strTextFileName(pwzFileName); // PrivateProfile filename needs special class
  6428. CStrOut strTextOut(pwzReturnedString, cchSize);
  6429. DWORD dwResult = GetPrivateProfileStringA(strTextAppName, strTextKeyName, strTextDefault, strTextOut, cchSize, strTextFileName);
  6430. strTextOut.ConvertIncludingNul();
  6431. return dwResult;
  6432. }
  6433. #endif // NEED_KERNEL32_WRAPPER
  6434. #ifdef NEED_SHELL32_WRAPPER
  6435. STDAPI_(DWORD_PTR) SHGetFileInfoWrapW(LPCWSTR pwzPath, DWORD dwFileAttributes, SHFILEINFOW FAR *psfi, UINT cbFileInfo, UINT uFlags)
  6436. {
  6437. if (g_bRunningOnNT)
  6438. {
  6439. return SHGetFileInfoW(pwzPath, dwFileAttributes, psfi, cbFileInfo, uFlags);
  6440. }
  6441. SHFILEINFOA shFileInfo;
  6442. DWORD_PTR dwResult;
  6443. shFileInfo.szDisplayName[0] = 0; // Terminate so we can always thunk afterward.
  6444. shFileInfo.szTypeName[0] = 0; // Terminate so we can always thunk afterward.
  6445. // Do we need to thunk the Path?
  6446. if (SHGFI_PIDL & uFlags)
  6447. {
  6448. // No, because it's really a pidl pointer.
  6449. dwResult = SHGetFileInfoA((LPCSTR)pwzPath, dwFileAttributes, &shFileInfo, sizeof(shFileInfo), uFlags);
  6450. }
  6451. else
  6452. {
  6453. // Yes
  6454. CStrIn strPath(pwzPath);
  6455. dwResult = SHGetFileInfoA(strPath, dwFileAttributes, &shFileInfo, sizeof(shFileInfo), uFlags);
  6456. }
  6457. psfi->hIcon = shFileInfo.hIcon;
  6458. psfi->iIcon = shFileInfo.iIcon;
  6459. psfi->dwAttributes = shFileInfo.dwAttributes;
  6460. SHAnsiToUnicode(shFileInfo.szDisplayName, psfi->szDisplayName, ARRAYSIZE(shFileInfo.szDisplayName));
  6461. SHAnsiToUnicode(shFileInfo.szTypeName, psfi->szTypeName, ARRAYSIZE(shFileInfo.szTypeName));
  6462. return dwResult;
  6463. }
  6464. #endif // NEED_SHELL32_WRAPPER
  6465. #ifdef NEED_USER32_WRAPPER
  6466. STDAPI_(ATOM) RegisterClassExWrapW(CONST WNDCLASSEXW FAR * pwcx)
  6467. {
  6468. VALIDATE_PROTOTYPE(RegisterClassEx);
  6469. if (g_bRunningOnNT)
  6470. return RegisterClassExW(pwcx);
  6471. CStrIn strMenuName(pwcx->lpszMenuName);
  6472. CStrIn strClassName(pwcx->lpszClassName);
  6473. WNDCLASSEXA wcx = *(CONST WNDCLASSEXA FAR *) pwcx;
  6474. wcx.cbSize = sizeof(wcx);
  6475. wcx.lpszMenuName = strMenuName;
  6476. wcx.lpszClassName = strClassName;
  6477. return RegisterClassExA(&wcx);
  6478. }
  6479. #endif // NEED_USER32_WRAPPER
  6480. #ifdef NEED_USER32_WRAPPER
  6481. STDAPI_(BOOL) GetClassInfoExWrapW(HINSTANCE hinst, LPCWSTR pwzClass, LPWNDCLASSEXW lpwcx)
  6482. {
  6483. VALIDATE_PROTOTYPE(GetClassInfoEx);
  6484. if (g_bRunningOnNT)
  6485. return GetClassInfoExW(hinst, pwzClass, lpwcx);
  6486. BOOL fResult;
  6487. CStrIn strClassName(pwzClass);
  6488. WNDCLASSEXA wcx;
  6489. wcx.cbSize = sizeof(wcx);
  6490. fResult = GetClassInfoExA(hinst, strClassName, &wcx);
  6491. *(WNDCLASSEXA FAR *) lpwcx = wcx;
  6492. lpwcx->lpszMenuName = NULL; // GetClassInfoExA makes this point off to private data that they own.
  6493. lpwcx->lpszClassName = pwzClass;
  6494. return fResult;
  6495. }
  6496. #endif // NEED_USER32_WRAPPER
  6497. #ifdef NEED_GDI32_WRAPPER
  6498. //+---------------------------------------------------------------------------
  6499. // StartDoc
  6500. //----------------------------------------------------------------------------
  6501. int
  6502. StartDocWrapW( HDC hDC, const DOCINFO * lpdi )
  6503. {
  6504. VALIDATE_PROTOTYPE(StartDoc);
  6505. if (g_bRunningOnNT)
  6506. {
  6507. return StartDocW( hDC, lpdi );
  6508. }
  6509. CStrIn strDocName( lpdi->lpszDocName );
  6510. CStrIn strOutput( lpdi->lpszOutput );
  6511. CStrIn strDatatype( lpdi->lpszDatatype );
  6512. DOCINFOA dia;
  6513. dia.cbSize = sizeof(DOCINFO);
  6514. dia.lpszDocName = strDocName;
  6515. dia.lpszOutput = strOutput;
  6516. dia.lpszDatatype = strDatatype;
  6517. dia.fwType = lpdi->fwType;
  6518. return StartDocA( hDC, &dia );
  6519. }
  6520. #endif // NEED_GDI32_WRAPPER
  6521. #ifdef NEED_GDI32_WRAPPER
  6522. STDAPI_(HCOLORSPACE)
  6523. CreateColorSpaceWrapW(LOGCOLORSPACEW * lpLogColorSpaceW)
  6524. {
  6525. VALIDATE_PROTOTYPE(CreateColorSpace);
  6526. if (g_bRunningOnNT)
  6527. {
  6528. return CreateColorSpaceW(lpLogColorSpaceW);
  6529. }
  6530. HCOLORSPACE hColorSpace;
  6531. LOGCOLORSPACEA logColorSpaceA;
  6532. memcpy(&logColorSpaceA, lpLogColorSpaceW,
  6533. FIELD_OFFSET(LOGCOLORSPACEA, lcsFilename));
  6534. SHUnicodeToAnsi(lpLogColorSpaceW->lcsFilename,
  6535. logColorSpaceA.lcsFilename,
  6536. ARRAYSIZE(logColorSpaceA.lcsFilename));
  6537. hColorSpace = CreateColorSpaceA(&logColorSpaceA);
  6538. return hColorSpace;
  6539. }
  6540. #endif // NEED_GDI32_WRAPPER
  6541. #ifdef NEED_SHELL32_WRAPPER
  6542. STDAPI_(UINT) DragQueryFileWrapW(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch)
  6543. {
  6544. VALIDATE_OUTBUF(lpszFile, cch);
  6545. //
  6546. // We are lazy and do not support lpszFile == NULL to query the length
  6547. // of an individual string.
  6548. //
  6549. ASSERT(iFile == 0xFFFFFFFF || lpszFile);
  6550. if (g_bRunningOnNT)
  6551. {
  6552. return DragQueryFileW(hDrop, iFile, lpszFile, cch);
  6553. }
  6554. //
  6555. // If iFile is 0xFFFFFFFF, then lpszFile and cch are ignored.
  6556. //
  6557. if (iFile == 0xFFFFFFFF)
  6558. {
  6559. return DragQueryFileA(hDrop, iFile, NULL, 0);
  6560. }
  6561. CStrOut str(lpszFile, cch);
  6562. DragQueryFileA(hDrop, iFile, str, str.BufSize());
  6563. return str.ConvertExcludingNul();
  6564. }
  6565. #endif // NEED_SHELL32_WRAPPER
  6566. #ifdef NEED_VERSION_WRAPPER
  6567. //
  6568. // the version APIs are not conducive to using
  6569. // wrap versions of the APIs, but we are going to
  6570. // do something reasonable....
  6571. //
  6572. #define VERSIONINFO_BUFF (MAX_PATH * SIZEOF(WCHAR))
  6573. STDAPI_(DWORD)
  6574. GetFileVersionInfoSizeWrapW(LPWSTR pwzFilename, LPDWORD lpdwHandle)
  6575. {
  6576. if (g_bRunningOnNT)
  6577. {
  6578. return GetFileVersionInfoSizeW(pwzFilename, lpdwHandle);
  6579. }
  6580. else
  6581. {
  6582. char szFilename[MAX_PATH];
  6583. DWORD dwRet;
  6584. ASSERT(pwzFilename);
  6585. SHUnicodeToAnsi(pwzFilename, szFilename, ARRAYSIZE(szFilename));
  6586. dwRet = GetFileVersionInfoSizeA(szFilename, lpdwHandle);
  6587. if (dwRet > 0)
  6588. {
  6589. // Add a scratch buffer to front for converting to UNICODE
  6590. dwRet += VERSIONINFO_BUFF;
  6591. }
  6592. return dwRet;
  6593. }
  6594. }
  6595. #endif // NEED_VERSION_WRAPPER
  6596. #ifdef NEED_VERSION_WRAPPER
  6597. STDAPI_(BOOL)
  6598. GetFileVersionInfoWrapW(LPWSTR pwzFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData)
  6599. {
  6600. if (g_bRunningOnNT)
  6601. {
  6602. return GetFileVersionInfoW(pwzFilename, dwHandle, dwLen, lpData);
  6603. }
  6604. else
  6605. {
  6606. char szFilename[MAX_PATH];
  6607. BYTE* pb;
  6608. if (dwLen <= VERSIONINFO_BUFF)
  6609. {
  6610. return FALSE;
  6611. }
  6612. ASSERT(pwzFilename);
  6613. SHUnicodeToAnsi(pwzFilename, szFilename, ARRAYSIZE(szFilename));
  6614. //Skip over our scratch buffer at the beginning
  6615. pb = (BYTE*)lpData + VERSIONINFO_BUFF;
  6616. return GetFileVersionInfoA(szFilename, dwHandle, dwLen - VERSIONINFO_BUFF, (void*)pb);
  6617. }
  6618. }
  6619. #endif // NEED_VERSION_WRAPPER
  6620. #ifdef NEED_VERSION_WRAPPER
  6621. STDAPI_(BOOL)
  6622. VerQueryValueWrapW(const LPVOID pBlock, LPWSTR pwzSubBlock, LPVOID *ppBuffer, PUINT puLen)
  6623. {
  6624. if (g_bRunningOnNT)
  6625. {
  6626. return VerQueryValueW(pBlock, pwzSubBlock, ppBuffer, puLen);
  6627. }
  6628. else
  6629. {
  6630. const WCHAR pwzStringFileInfo[] = L"\\StringFileInfo";
  6631. //
  6632. // WARNING: This function wipes out any string previously returned
  6633. // for this pBlock because a common buffer at the beginning of the
  6634. // block is used for ansi/unicode translation!
  6635. //
  6636. char szSubBlock[MAX_PATH];
  6637. BOOL fRet;
  6638. BYTE* pb;
  6639. ASSERT(pwzSubBlock);
  6640. SHUnicodeToAnsi(pwzSubBlock, szSubBlock, ARRAYSIZE(szSubBlock));
  6641. // The first chunk is our scratch buffer for converting to UNICODE
  6642. pb = (BYTE*)pBlock + VERSIONINFO_BUFF;
  6643. fRet = VerQueryValueA((void*)pb, szSubBlock, ppBuffer, puLen);
  6644. // Convert to unicode if ansi string returned
  6645. if (fRet && StrCmpNIW(pwzSubBlock, pwzStringFileInfo, ARRAYSIZE(pwzStringFileInfo) - 1) == 0)
  6646. {
  6647. // Convert returned string to UNICODE. We use the scratch buffer
  6648. // at the beginning of pBlock
  6649. LPWSTR pwzBuff = (LPWSTR)pBlock;
  6650. if (*puLen == 0)
  6651. {
  6652. pwzBuff[0] = L'\0';
  6653. }
  6654. else
  6655. {
  6656. SHAnsiToUnicode((LPCSTR)*ppBuffer, pwzBuff, VERSIONINFO_BUFF/sizeof(WCHAR));
  6657. }
  6658. *ppBuffer = pwzBuff;
  6659. }
  6660. return fRet;
  6661. }
  6662. }
  6663. #endif // NEED_VERSION_WRAPPER
  6664. #ifdef NEED_SHELL32_WRAPPER
  6665. HRESULT WINAPI SHDefExtractIconWrapW(LPCWSTR pszFile, int nIconIndex,
  6666. UINT uFlags, HICON *phiconLarge,
  6667. HICON *phiconSmall, UINT nIconSize)
  6668. {
  6669. HRESULT hr;
  6670. if (UseUnicodeShell32())
  6671. {
  6672. hr = SHDefExtractIconW(pszFile, nIconIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
  6673. }
  6674. else
  6675. {
  6676. CStrIn striFile(pszFile);
  6677. hr = SHDefExtractIconA(striFile, nIconIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
  6678. }
  6679. return hr;
  6680. }
  6681. #endif // NEED_SHELL32_WRAPPER
  6682. BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszpdlLinkTo, LPCWSTR pszDir, LPWSTR pszName, BOOL *pfMustCopy, UINT uFlags)
  6683. {
  6684. BOOL fRet;
  6685. if (g_bRunningOnNT5OrHigher)
  6686. {
  6687. fRet = SHGetNewLinkInfoW(pszpdlLinkTo, pszDir, pszName, pfMustCopy, uFlags);
  6688. }
  6689. else
  6690. {
  6691. CStrIn striDir(pszDir);
  6692. CStrOut stroName(pszName, MAX_PATH);
  6693. if (SHGNLI_PIDL & uFlags)
  6694. {
  6695. fRet = SHGetNewLinkInfoA((LPCSTR)pszpdlLinkTo, striDir, stroName, pfMustCopy, uFlags);
  6696. }
  6697. else
  6698. {
  6699. CStrIn striLinkTo(pszpdlLinkTo);
  6700. fRet = SHGetNewLinkInfoA(striLinkTo, striDir, stroName, pfMustCopy, uFlags);
  6701. }
  6702. if (fRet)
  6703. {
  6704. stroName.ConvertIncludingNul();
  6705. }
  6706. }
  6707. return fRet;
  6708. }
  6709. #ifdef NEED_ADVAPI32_WRAPPER
  6710. LONG WINAPI RegEnumValueWrapW(HKEY hkey, DWORD dwIndex, LPWSTR lpValueName,
  6711. LPDWORD lpcbValueName, LPDWORD lpReserved,
  6712. LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
  6713. {
  6714. VALIDATE_PROTOTYPE(RegEnumValue);
  6715. LONG lRet;
  6716. if (UseUnicodeShell32())
  6717. {
  6718. lRet = RegEnumValueW(hkey, dwIndex, lpValueName, lpcbValueName,
  6719. lpReserved, lpType, lpData, lpcbData);
  6720. }
  6721. else
  6722. {
  6723. CStrOut stroValueName(lpValueName, *lpcbValueName);
  6724. DWORD dwTypeTemp;
  6725. if (lpData)
  6726. {
  6727. ASSERT(lpcbData);
  6728. CStrOut stroData((LPWSTR)lpData, (*lpcbData) / sizeof(WCHAR));
  6729. lRet = RegEnumValueA(hkey, dwIndex, stroValueName, lpcbValueName,
  6730. lpReserved, &dwTypeTemp,
  6731. (LPBYTE)(LPSTR)stroData, lpcbData);
  6732. if (ERROR_SUCCESS == lRet && REG_SZ == dwTypeTemp)
  6733. {
  6734. *lpcbData = sizeof(WCHAR) * stroData.ConvertIncludingNul();
  6735. }
  6736. }
  6737. else
  6738. {
  6739. lRet = RegEnumValueA(hkey, dwIndex, stroValueName, lpcbValueName,
  6740. lpReserved, &dwTypeTemp, lpData, lpcbData);
  6741. }
  6742. if (ERROR_SUCCESS == lRet)
  6743. *lpcbValueName = stroValueName.ConvertExcludingNul();
  6744. if (lpType)
  6745. *lpType = dwTypeTemp;
  6746. }
  6747. return lRet;
  6748. }
  6749. #endif // NEED_ADVAPI32_WRAPPER
  6750. #ifdef NEED_KERNEL32_WRAPPER
  6751. BOOL WINAPI WritePrivateProfileStructWrapW(LPCWSTR lpszSection, LPCWSTR lpszKey,
  6752. LPVOID lpStruct, UINT uSizeStruct,
  6753. LPCWSTR szFile)
  6754. {
  6755. VALIDATE_PROTOTYPE(WritePrivateProfileStruct);
  6756. BOOL fRet;
  6757. if (UseUnicodeShell32())
  6758. {
  6759. fRet = WritePrivateProfileStructW(lpszSection, lpszKey, lpStruct,
  6760. uSizeStruct, szFile);
  6761. }
  6762. else
  6763. {
  6764. CStrIn striSection(lpszSection);
  6765. CStrIn striKey(lpszKey);
  6766. CPPFIn striFile(szFile); // PrivateProfile filename needs special class
  6767. fRet = WritePrivateProfileStructA(striSection, striKey, lpStruct,
  6768. uSizeStruct, striFile);
  6769. }
  6770. return fRet;
  6771. }
  6772. #endif // NEED_KERNEL32_WRAPPER
  6773. #ifdef NEED_KERNEL32_WRAPPER
  6774. BOOL WINAPI GetPrivateProfileStructWrapW(LPCWSTR lpszSection, LPCWSTR lpszKey,
  6775. LPVOID lpStruct, UINT uSizeStruct,
  6776. LPCWSTR szFile)
  6777. {
  6778. VALIDATE_PROTOTYPE(GetPrivateProfileStruct);
  6779. BOOL fRet;
  6780. if (UseUnicodeShell32())
  6781. {
  6782. fRet = GetPrivateProfileStructW(lpszSection, lpszKey, lpStruct,
  6783. uSizeStruct, szFile);
  6784. }
  6785. else
  6786. {
  6787. CStrIn striSection(lpszSection);
  6788. CStrIn striKey(lpszKey);
  6789. CPPFIn striFile(szFile); // PrivateProfile filename needs special class
  6790. fRet = GetPrivateProfileStructA(striSection, striKey, lpStruct,
  6791. uSizeStruct, striFile);
  6792. }
  6793. return fRet;
  6794. }
  6795. #endif // NEED_KERNEL32_WRAPPER
  6796. #ifdef NEED_KERNEL32_WRAPPER
  6797. BOOL WINAPI CreateProcessWrapW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
  6798. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  6799. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  6800. BOOL bInheritHandles,
  6801. DWORD dwCreationFlags,
  6802. LPVOID lpEnvironment,
  6803. LPCWSTR lpCurrentDirectory,
  6804. LPSTARTUPINFOW lpStartupInfo,
  6805. LPPROCESS_INFORMATION lpProcessInformation)
  6806. {
  6807. BOOL fRet;
  6808. VALIDATE_PROTOTYPE(CreateProcess);
  6809. if (UseUnicodeShell32())
  6810. {
  6811. fRet = CreateProcessW(lpApplicationName, lpCommandLine,
  6812. lpProcessAttributes, lpThreadAttributes,
  6813. bInheritHandles, dwCreationFlags, lpEnvironment,
  6814. lpCurrentDirectory, lpStartupInfo,
  6815. lpProcessInformation);
  6816. }
  6817. else
  6818. {
  6819. CStrIn striApplicationName(lpApplicationName);
  6820. CStrIn striCommandLine(lpCommandLine);
  6821. CStrIn striCurrentDirectory(lpCurrentDirectory);
  6822. if (NULL == lpStartupInfo)
  6823. {
  6824. fRet = CreateProcessA(striApplicationName, striCommandLine,
  6825. lpProcessAttributes, lpThreadAttributes,
  6826. bInheritHandles, dwCreationFlags,
  6827. lpEnvironment, striCurrentDirectory,
  6828. NULL, lpProcessInformation);
  6829. }
  6830. else
  6831. {
  6832. STARTUPINFOA si = *(STARTUPINFOA*)lpStartupInfo;
  6833. CStrIn striReserved(lpStartupInfo->lpReserved);
  6834. CStrIn striDesktop(lpStartupInfo->lpDesktop);
  6835. CStrIn striTitle(lpStartupInfo->lpTitle);
  6836. si.lpReserved = striReserved;
  6837. si.lpDesktop = striDesktop;
  6838. si.lpTitle = striTitle;
  6839. fRet = CreateProcessA(striApplicationName, striCommandLine,
  6840. lpProcessAttributes, lpThreadAttributes,
  6841. bInheritHandles, dwCreationFlags,
  6842. lpEnvironment, striCurrentDirectory,
  6843. &si, lpProcessInformation);
  6844. }
  6845. }
  6846. return fRet;
  6847. }
  6848. #endif // NEED_KERNEL32_WRAPPER
  6849. #ifdef NEED_SHELL32_WRAPPER
  6850. HICON WINAPI ExtractIconWrapW(HINSTANCE hInst, LPCWSTR lpszExeFileName, UINT nIconIndex)
  6851. {
  6852. HICON hicon;
  6853. if (UseUnicodeShell32())
  6854. {
  6855. hicon = ExtractIconW(hInst, lpszExeFileName, nIconIndex);
  6856. }
  6857. else
  6858. {
  6859. CStrIn striExeFileName(lpszExeFileName);
  6860. hicon = ExtractIconA(hInst, striExeFileName, nIconIndex);
  6861. }
  6862. return hicon;
  6863. }
  6864. #endif // NEED_SHELL32_WRAPPER
  6865. #ifdef NEED_USER32_WRAPPER
  6866. UINT WINAPI DdeInitializeWrapW(LPDWORD pidInst, PFNCALLBACK pfnCallback,
  6867. DWORD afCmd, DWORD ulRes)
  6868. {
  6869. UINT uRet;
  6870. if (UseUnicodeShell32())
  6871. {
  6872. uRet = DdeInitializeW(pidInst, pfnCallback, afCmd, ulRes);
  6873. }
  6874. else
  6875. {
  6876. //
  6877. // This assumes the callback function will used the wrapped dde
  6878. // string functions (DdeCreateStringHandle and DdeQueryString)
  6879. // to access strings.
  6880. //
  6881. uRet = DdeInitializeA(pidInst, pfnCallback, afCmd, ulRes);
  6882. }
  6883. return uRet;
  6884. }
  6885. #endif // NEED_USER32_WRAPPER
  6886. #ifdef NEED_USER32_WRAPPER
  6887. HSZ WINAPI DdeCreateStringHandleWrapW(DWORD idInst, LPCWSTR psz, int iCodePage)
  6888. {
  6889. HSZ hszRet;
  6890. if (UseUnicodeShell32())
  6891. {
  6892. hszRet = DdeCreateStringHandleW(idInst, psz, iCodePage);
  6893. }
  6894. else
  6895. {
  6896. CStrIn stripsz(psz);
  6897. hszRet = DdeCreateStringHandleA(idInst, stripsz, CP_WINANSI);
  6898. }
  6899. return hszRet;
  6900. }
  6901. #endif // NEED_USER32_WRAPPER
  6902. #ifdef NEED_USER32_WRAPPER
  6903. DWORD WINAPI DdeQueryStringWrapW(DWORD idInst, HSZ hsz, LPWSTR psz,
  6904. DWORD cchMax, int iCodePage)
  6905. {
  6906. DWORD dwRet;
  6907. if (UseUnicodeShell32())
  6908. {
  6909. dwRet = DdeQueryStringW(idInst, hsz, psz, cchMax, iCodePage);
  6910. }
  6911. else
  6912. {
  6913. CStrOut stropsz(psz, cchMax);
  6914. dwRet = DdeQueryStringA(idInst, hsz, stropsz, stropsz.BufSize(),
  6915. CP_WINANSI);
  6916. if (dwRet && psz)
  6917. dwRet = stropsz.ConvertExcludingNul();
  6918. }
  6919. return dwRet;
  6920. }
  6921. #endif // NEED_USER32_WRAPPER
  6922. #ifdef NEED_KERNEL32_WRAPPER
  6923. ATOM WINAPI
  6924. GlobalAddAtomWrapW(LPCWSTR lpString)
  6925. {
  6926. VALIDATE_PROTOTYPE(GlobalAddAtom);
  6927. if (g_bRunningOnNT)
  6928. {
  6929. return GlobalAddAtomW(lpString);
  6930. }
  6931. CStrIn str(lpString);
  6932. return GlobalAddAtomA(str);
  6933. }
  6934. #endif // NEED_KERNEL32_WRAPPER
  6935. #ifdef NEED_KERNEL32_WRAPPER
  6936. ATOM WINAPI
  6937. GlobalFindAtomWrapW(LPCWSTR lpString)
  6938. {
  6939. VALIDATE_PROTOTYPE(GlobalFindAtom);
  6940. if (g_bRunningOnNT)
  6941. {
  6942. return GlobalFindAtomW(lpString);
  6943. }
  6944. CStrIn str(lpString);
  6945. return GlobalFindAtomA(str);
  6946. }
  6947. #endif // NEED_KERNEL32_WRAPPER
  6948. #ifdef NEED_COMDLG32_WRAPPER
  6949. BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW lpofn)
  6950. {
  6951. BOOL fRet;
  6952. if (UseUnicodeShell32())
  6953. {
  6954. fRet = GetSaveFileNameW(lpofn);
  6955. }
  6956. else
  6957. {
  6958. ASSERT(lpofn);
  6959. ASSERT(sizeof(OPENFILENAMEA) == sizeof(OPENFILENAMEW));
  6960. OPENFILENAMEA ofnA = *(LPOPENFILENAMEA)lpofn;
  6961. // In parameters
  6962. CStrInMulti strimFilter(lpofn->lpstrFilter);
  6963. CStrIn striInitialDir(lpofn->lpstrInitialDir);
  6964. CStrIn striTitle(lpofn->lpstrTitle);
  6965. CStrIn striDefExt(lpofn->lpstrDefExt);
  6966. CStrIn striTemplateName(lpofn->lpTemplateName);
  6967. ASSERT(NULL == lpofn->lpstrCustomFilter); // add support if you need it.
  6968. // Out parameters
  6969. CStrOut stroFile(lpofn->lpstrFile, lpofn->nMaxFile);
  6970. CStrOut stroFileTitle(lpofn->lpstrFileTitle, lpofn->nMaxFileTitle);
  6971. //In Out parameters
  6972. SHUnicodeToAnsi(lpofn->lpstrFile, stroFile, stroFile.BufSize());
  6973. // Set up the parameters
  6974. ofnA.lpstrFilter = strimFilter;
  6975. ofnA.lpstrInitialDir = striInitialDir;
  6976. ofnA.lpstrTitle = striTitle;
  6977. ofnA.lpstrDefExt = striDefExt;
  6978. ofnA.lpTemplateName = striTemplateName;
  6979. ofnA.lpstrFile = stroFile;
  6980. ofnA.lpstrFileTitle = stroFileTitle;
  6981. fRet = GetSaveFileNameA(&ofnA);
  6982. if (fRet)
  6983. {
  6984. // Copy the out parameters
  6985. lpofn->nFilterIndex = ofnA.nFilterIndex;
  6986. lpofn->Flags = ofnA.Flags;
  6987. // Get the offset to the filename
  6988. stroFile.ConvertIncludingNul();
  6989. LPWSTR psz = PathFindFileNameW(lpofn->lpstrFile);
  6990. if (psz)
  6991. {
  6992. lpofn->nFileOffset = (int) (psz-lpofn->lpstrFile);
  6993. // Get the offset of the extension
  6994. psz = PathFindExtensionW(psz);
  6995. lpofn->nFileExtension = psz ? (int)(psz-lpofn->lpstrFile) : 0;
  6996. }
  6997. else
  6998. {
  6999. lpofn->nFileOffset = 0;
  7000. lpofn->nFileExtension = 0;
  7001. }
  7002. }
  7003. }
  7004. return fRet;
  7005. }
  7006. #endif // NEED_COMDLG32_WRAPPER
  7007. #ifdef NEED_COMDLG32_WRAPPER
  7008. BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW lpofn)
  7009. {
  7010. BOOL fRet;
  7011. if (UseUnicodeShell32())
  7012. {
  7013. fRet = GetOpenFileNameW(lpofn);
  7014. }
  7015. else
  7016. {
  7017. ASSERT(lpofn);
  7018. ASSERT(sizeof(OPENFILENAMEA) == sizeof(OPENFILENAMEW));
  7019. OPENFILENAMEA ofnA = *(LPOPENFILENAMEA)lpofn;
  7020. // In parameters
  7021. CStrInMulti strimFilter(lpofn->lpstrFilter);
  7022. CStrIn striInitialDir(lpofn->lpstrInitialDir);
  7023. CStrIn striTitle(lpofn->lpstrTitle);
  7024. CStrIn striDefExt(lpofn->lpstrDefExt);
  7025. CStrIn striTemplateName(lpofn->lpTemplateName);
  7026. ASSERT(NULL == lpofn->lpstrCustomFilter); // add support if you need it.
  7027. // Out parameters
  7028. CStrOut stroFile(lpofn->lpstrFile, lpofn->nMaxFile);
  7029. CStrOut stroFileTitle(lpofn->lpstrFileTitle, lpofn->nMaxFileTitle);
  7030. //In Out parameters
  7031. SHUnicodeToAnsi(lpofn->lpstrFile, stroFile, stroFile.BufSize());
  7032. // Set up the parameters
  7033. ofnA.lpstrFilter = strimFilter;
  7034. ofnA.lpstrInitialDir = striInitialDir;
  7035. ofnA.lpstrTitle = striTitle;
  7036. ofnA.lpstrDefExt = striDefExt;
  7037. ofnA.lpTemplateName = striTemplateName;
  7038. ofnA.lpstrFile = stroFile;
  7039. ofnA.lpstrFileTitle = stroFileTitle;
  7040. fRet = GetOpenFileNameA(&ofnA);
  7041. if (fRet)
  7042. {
  7043. // Copy the out parameters
  7044. lpofn->nFilterIndex = ofnA.nFilterIndex;
  7045. lpofn->Flags = ofnA.Flags;
  7046. // Get the offset to the filename
  7047. stroFile.ConvertIncludingNul();
  7048. LPWSTR psz = PathFindFileNameW(lpofn->lpstrFile);
  7049. if (psz)
  7050. {
  7051. lpofn->nFileOffset = (int) (psz-lpofn->lpstrFile);
  7052. // Get the offset of the extension
  7053. psz = PathFindExtensionW(psz);
  7054. lpofn->nFileExtension = psz ? (int)(psz-lpofn->lpstrFile) : 0;
  7055. }
  7056. else
  7057. {
  7058. lpofn->nFileOffset = 0;
  7059. lpofn->nFileExtension = 0;
  7060. }
  7061. }
  7062. }
  7063. return fRet;
  7064. }
  7065. #endif // NEED_COMDLG32_WRAPPER
  7066. #ifdef NEED_SHELL32_WRAPPER
  7067. #define SHCNF_HAS_WSTR_PARAMS(f) ((f & SHCNF_TYPE) == SHCNF_PATHW || \
  7068. (f & SHCNF_TYPE) == SHCNF_PRINTERW || \
  7069. (f & SHCNF_TYPE) == SHCNF_PRINTJOBW )
  7070. void SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1,
  7071. LPCVOID dwItem2)
  7072. {
  7073. if (UseUnicodeShell32() || !SHCNF_HAS_WSTR_PARAMS(uFlags))
  7074. {
  7075. SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
  7076. }
  7077. else
  7078. {
  7079. CStrIn striItem1((LPWSTR)dwItem1);
  7080. CStrIn striItem2((LPWSTR)dwItem2);
  7081. if ((uFlags & SHCNF_TYPE) == SHCNF_PATHW)
  7082. {
  7083. uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PATHA;
  7084. }
  7085. else if ((uFlags & SHCNF_TYPE) == SHCNF_PRINTERW)
  7086. {
  7087. uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PRINTERA;
  7088. }
  7089. else
  7090. {
  7091. uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PRINTJOBA;
  7092. }
  7093. SHChangeNotify(wEventId, uFlags, (void*)(LPSTR)striItem1, (void*)(LPSTR)striItem2);
  7094. }
  7095. return;
  7096. }
  7097. LWSTDAPI_(void) SHFlushSFCacheWrap(void)
  7098. {
  7099. // if shell32 is not in process, then there's nothing to flush
  7100. HMODULE hShell32 = GetModuleHandleWrap(TEXT("SHELL32"));
  7101. if (hShell32)
  7102. {
  7103. // NOTE: GetProcAddress always takes ANSI strings!
  7104. DLLGETVERSIONPROC pfnGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hShell32, "DllGetVersion");
  7105. if (pfnGetVersion)
  7106. {
  7107. DLLVERSIONINFO dllinfo;
  7108. dllinfo.cbSize = sizeof(DLLVERSIONINFO);
  7109. if (pfnGetVersion(&dllinfo) == NOERROR)
  7110. {
  7111. // first, we need a version of shell32 that supports the function
  7112. if (dllinfo.dwMajorVersion >= 4)
  7113. {
  7114. if (dllinfo.dwMajorVersion == 4)
  7115. {
  7116. // to work around the "missing critical section" bug in v4 shell32.dll,
  7117. // we simply bail the call.
  7118. return;
  7119. }
  7120. SHFlushSFCache();
  7121. }
  7122. }
  7123. }
  7124. }
  7125. }
  7126. #endif // NEED_SHELL32_WRAPPER
  7127. #ifdef NEED_COMDLG32_WRAPPER
  7128. //+---------------------------------------------------------------------------
  7129. // PrintDlgWrap, PageSetupDlgWrap - wrappers
  7130. // DevNamesAFromDevNamesW, DevNamesWFromDevNamesA - helper functions
  7131. //
  7132. // Copied from mshtml\src\core\wrappers\unicwrap.cpp with some
  7133. // cosmetic changes (peterlee)
  7134. //
  7135. //+---------------------------------------------------------------------------
  7136. HGLOBAL
  7137. DevNamesAFromDevNamesW( HGLOBAL hdnw )
  7138. {
  7139. HGLOBAL hdna = NULL;
  7140. if (hdnw)
  7141. {
  7142. LPDEVNAMES lpdnw = (LPDEVNAMES) GlobalLock( hdnw );
  7143. if (lpdnw)
  7144. {
  7145. CStrIn strDriver( (LPCWSTR) lpdnw + lpdnw->wDriverOffset );
  7146. CStrIn strDevice( (LPCWSTR) lpdnw + lpdnw->wDeviceOffset );
  7147. CStrIn strOutput( (LPCWSTR) lpdnw + lpdnw->wOutputOffset );
  7148. int cchDriver = strDriver.strlen() + 1;
  7149. int cchDevice = strDevice.strlen() + 1;
  7150. int cchOutput = strOutput.strlen() + 1;
  7151. hdna = GlobalAlloc( GHND, sizeof(DEVNAMES) +
  7152. cchDriver + cchDevice + cchOutput );
  7153. if (hdna)
  7154. {
  7155. LPDEVNAMES lpdna = (LPDEVNAMES) GlobalLock( hdna );
  7156. if (!lpdna)
  7157. {
  7158. GlobalFree( hdna );
  7159. hdna = NULL;
  7160. }
  7161. else
  7162. {
  7163. lpdna->wDriverOffset = sizeof(DEVNAMES);
  7164. lpdna->wDeviceOffset = lpdna->wDriverOffset + cchDriver;
  7165. lpdna->wOutputOffset = lpdna->wDeviceOffset + cchDevice;
  7166. lpdna->wDefault = lpdnw->wDefault;
  7167. lstrcpyA( (LPSTR) lpdna + lpdna->wDriverOffset, strDriver );
  7168. lstrcpyA( (LPSTR) lpdna + lpdna->wDeviceOffset, strDevice );
  7169. lstrcpyA( (LPSTR) lpdna + lpdna->wOutputOffset, strOutput );
  7170. GlobalUnlock( hdna );
  7171. }
  7172. }
  7173. GlobalUnlock( hdnw );
  7174. GlobalFree( hdnw );
  7175. }
  7176. }
  7177. return hdna;
  7178. }
  7179. HGLOBAL
  7180. DevNamesWFromDevNamesA( HGLOBAL hdna )
  7181. {
  7182. HGLOBAL hdnw = NULL;
  7183. if (hdna)
  7184. {
  7185. LPDEVNAMES lpdna = (LPDEVNAMES) GlobalLock( hdna );
  7186. if (lpdna)
  7187. {
  7188. LPCSTR lpszDriver = (LPCSTR) lpdna + lpdna->wDriverOffset;
  7189. LPCSTR lpszDevice = (LPCSTR) lpdna + lpdna->wDeviceOffset;
  7190. LPCSTR lpszOutput = (LPCSTR) lpdna + lpdna->wOutputOffset;
  7191. int cchDriver = lstrlenA( lpszDriver ) + 1;
  7192. int cchDevice = lstrlenA( lpszDevice ) + 1;
  7193. int cchOutput = lstrlenA( lpszOutput ) + 1;
  7194. // assume the wide charcount won't exceed the multibyte charcount
  7195. hdnw = GlobalAlloc( GHND, sizeof(DEVNAMES) +
  7196. sizeof(WCHAR) * (cchDriver + cchDevice + cchOutput) );
  7197. if (hdnw)
  7198. {
  7199. LPDEVNAMES lpdnw = (LPDEVNAMES) GlobalLock( hdnw );
  7200. if (!lpdnw)
  7201. {
  7202. GlobalFree( hdnw );
  7203. hdnw = NULL;
  7204. }
  7205. else
  7206. {
  7207. lpdnw->wDriverOffset = sizeof(DEVNAMES) / sizeof(WCHAR);
  7208. lpdnw->wDeviceOffset = lpdnw->wDriverOffset + cchDriver;
  7209. lpdnw->wOutputOffset = lpdnw->wDeviceOffset + cchDevice;
  7210. lpdnw->wDefault = lpdna->wDefault;
  7211. SHAnsiToUnicode( (LPSTR) lpszDriver, (LPWSTR) lpdnw + lpdnw->wDriverOffset,
  7212. cchDriver );
  7213. SHAnsiToUnicode( lpszDevice, (LPWSTR) lpdnw + lpdnw->wDeviceOffset,
  7214. cchDevice);
  7215. SHAnsiToUnicode( lpszOutput, (LPWSTR) lpdnw + lpdnw->wOutputOffset,
  7216. cchOutput);
  7217. GlobalUnlock( hdnw );
  7218. }
  7219. }
  7220. GlobalUnlock( hdna );
  7221. GlobalFree( hdna );
  7222. }
  7223. }
  7224. return hdnw;
  7225. }
  7226. #ifdef UNIX
  7227. HGLOBAL
  7228. DevModeAFromDevModeW( HGLOBAL hdmw )
  7229. {
  7230. HGLOBAL hdma = NULL;
  7231. if (hdmw)
  7232. {
  7233. LPDEVMODEW lpdmw = (LPDEVMODEW)GlobalLock( hdmw );
  7234. if (lpdmw)
  7235. {
  7236. hdma = GlobalAlloc( GHND, sizeof(DEVMODEA) );
  7237. if (hdma)
  7238. {
  7239. LPDEVMODEA lpdma = (LPDEVMODEA) GlobalLock( hdma );
  7240. if (lpdma)
  7241. {
  7242. CStrIn strDeviceName( lpdmw->dmDeviceName );
  7243. CStrIn strFormName( lpdmw->dmFormName );
  7244. // assume memory layout is identical
  7245. memcpy( lpdma->dmDeviceName, strDeviceName, CCHDEVICENAME );
  7246. memcpy( &lpdma->dmSpecVersion,
  7247. &lpdmw->dmSpecVersion,
  7248. offsetof(DEVMODEW, dmFormName) -
  7249. offsetof(DEVMODEW, dmSpecVersion) );
  7250. memcpy( lpdma->dmFormName, strFormName, CCHFORMNAME );
  7251. memcpy( &lpdma->dmLogPixels,
  7252. &lpdmw->dmLogPixels,
  7253. sizeof(DEVMODEW) -
  7254. offsetof(DEVMODEW, dmLogPixels) );
  7255. GlobalUnlock( hdma );
  7256. }
  7257. else
  7258. {
  7259. GlobalFree( hdma );
  7260. hdma = NULL;
  7261. }
  7262. }
  7263. GlobalUnlock( hdmw );
  7264. GlobalFree( hdmw );
  7265. }
  7266. }
  7267. return hdma;
  7268. }
  7269. //--------------------------------------------------------------
  7270. // DEVMODEW from DEVMODEA
  7271. //--------------------------------------------------------------
  7272. HGLOBAL
  7273. DevModeWFromDevModeA( HGLOBAL hdma )
  7274. {
  7275. HGLOBAL hdmw = NULL;
  7276. if (hdma)
  7277. {
  7278. LPDEVMODEA lpdma = (LPDEVMODEA)GlobalLock( hdma );
  7279. if (lpdma)
  7280. {
  7281. hdmw = GlobalAlloc( GHND, sizeof(DEVMODEW) );
  7282. if (hdmw)
  7283. {
  7284. LPDEVMODEW lpdmw = (LPDEVMODEW) GlobalLock( hdmw );
  7285. if (lpdmw)
  7286. {
  7287. CStrOut strDeviceName( lpdmw->dmDeviceName, CCHDEVICENAME );
  7288. CStrOut strFormName( lpdmw->dmFormName, CCHFORMNAME );
  7289. // assume memory layout is identical
  7290. lstrcpyA( strDeviceName, (LPCSTR)lpdma->dmDeviceName );
  7291. strDeviceName.ConvertIncludingNul();
  7292. memcpy( &lpdmw->dmSpecVersion,
  7293. &lpdma->dmSpecVersion,
  7294. offsetof(DEVMODEA, dmFormName) -
  7295. offsetof(DEVMODEA, dmSpecVersion) );
  7296. lstrcpyA( strFormName, (LPCSTR)lpdmw->dmFormName );
  7297. strFormName.ConvertIncludingNul();
  7298. memcpy( &lpdmw->dmLogPixels,
  7299. &lpdma->dmLogPixels,
  7300. sizeof(DEVMODEA) -
  7301. offsetof(DEVMODEA, dmLogPixels) );
  7302. GlobalUnlock( hdmw );
  7303. }
  7304. else
  7305. {
  7306. GlobalFree( hdmw );
  7307. hdmw = NULL;
  7308. }
  7309. }
  7310. GlobalUnlock( hdma );
  7311. GlobalFree( hdma );
  7312. }
  7313. }
  7314. return hdmw;
  7315. }
  7316. #endif //UNIX
  7317. #endif // NEED_COMDLG32_WRAPPER
  7318. #ifdef NEED_COMDLG32_WRAPPER
  7319. //--------------------------------------------------------------
  7320. // PrintDlgW wrapper
  7321. //--------------------------------------------------------------
  7322. BOOL WINAPI
  7323. PrintDlgWrapW(LPPRINTDLGW lppd)
  7324. {
  7325. BOOL fRet;
  7326. if (UseUnicodeShell32())
  7327. {
  7328. fRet = PrintDlgW(lppd);
  7329. }
  7330. else
  7331. {
  7332. PRINTDLGA pda;
  7333. LPCWSTR lpPrintTemplateName = lppd->lpPrintTemplateName;
  7334. LPCWSTR lpSetupTemplateName = lppd->lpSetupTemplateName;
  7335. CStrIn strPrintTemplateName( lpPrintTemplateName );
  7336. CStrIn strSetupTemplateName( lpSetupTemplateName );
  7337. ASSERT( sizeof(pda) == sizeof( *lppd ));
  7338. memcpy( &pda, lppd, sizeof(pda) );
  7339. // IMPORTANT: We are not converting the DEVMODE structure back and forth
  7340. // from ASCII to Unicode on Win95 anymore because we are not touching the
  7341. // two strings or any other member. Converting the DEVMODE structure can
  7342. // be tricky because of potential and common discrepancies between the
  7343. // value of the dmSize member and sizeof(DEVMODE). (25155)
  7344. // So instead of: pda.hDevMode = DevModeAFromDevModeW( lppd->hDevMode );
  7345. // we just forward the DEVMODE handle:
  7346. pda.hDevMode = lppd->hDevMode;
  7347. pda.hDevNames = DevNamesAFromDevNamesW( lppd->hDevNames );
  7348. pda.lpPrintTemplateName = strPrintTemplateName;
  7349. pda.lpSetupTemplateName = strSetupTemplateName;
  7350. fRet = PrintDlgA( &pda );
  7351. // copy back wholesale, then restore strings.
  7352. memcpy( lppd, &pda, sizeof(pda) );
  7353. lppd->lpSetupTemplateName = lpSetupTemplateName;
  7354. lppd->lpPrintTemplateName = lpPrintTemplateName;
  7355. lppd->hDevNames = DevNamesWFromDevNamesA( pda.hDevNames );
  7356. // And instead of: lppd->hDevMode = DevModeWFromDevModeA( pda.hDevMode );
  7357. // we just forward the DEVMODE handle:
  7358. lppd->hDevMode = pda.hDevMode;
  7359. }
  7360. return fRet;
  7361. }
  7362. #endif // NEED_COMDLG32_WRAPPER
  7363. #ifdef NEED_COMDLG32_WRAPPER
  7364. //--------------------------------------------------------------
  7365. // PageSetupDlgW wrapper
  7366. //--------------------------------------------------------------
  7367. BOOL WINAPI
  7368. PageSetupDlgWrapW(LPPAGESETUPDLGW lppsd)
  7369. {
  7370. BOOL fRet;
  7371. if (UseUnicodeShell32())
  7372. {
  7373. fRet = PageSetupDlgW(lppsd);
  7374. }
  7375. else
  7376. {
  7377. PAGESETUPDLGA psda;
  7378. LPCWSTR lpPageSetupTemplateName = lppsd->lpPageSetupTemplateName;
  7379. CStrIn strPageSetupTemplateName( lpPageSetupTemplateName );
  7380. ASSERT( sizeof(psda) == sizeof( *lppsd ) );
  7381. memcpy( &psda, lppsd, sizeof(psda));
  7382. // IMPORTANT: We are not converting the DEVMODE structure back and forth
  7383. // from ASCII to Unicode on Win95 anymore because we are not touching the
  7384. // two strings or any other member. Converting the DEVMODE structure can
  7385. // be tricky because of potential and common discrepancies between the
  7386. // value of the dmSize member and sizeof(DEVMODE). (25155)
  7387. // So instead of: psda.hDevMode = DevModeAFromDevModeW( lppsd->hDevMode );
  7388. // we just forward the DEVMODE handle:
  7389. psda.hDevMode = lppsd->hDevMode;
  7390. psda.hDevNames = DevNamesAFromDevNamesW( lppsd->hDevNames );
  7391. psda.lpPageSetupTemplateName = strPageSetupTemplateName;
  7392. fRet = PageSetupDlgA((LPPAGESETUPDLGA)&psda);
  7393. // copy back wholesale, then restore string.
  7394. memcpy( lppsd, &psda, sizeof(psda) );
  7395. lppsd->lpPageSetupTemplateName = lpPageSetupTemplateName;
  7396. lppsd->hDevNames = DevNamesWFromDevNamesA( psda.hDevNames );
  7397. // And instead of: lppsd->hDevMode = DevModeWFromDevModeA( psda.hDevMode );
  7398. // we just forward the DEVMODE handle:
  7399. lppsd->hDevMode = psda.hDevMode;
  7400. }
  7401. return fRet;
  7402. }
  7403. #endif // NEED_COMDLG32_WRAPPER
  7404. #ifdef NEED_OLE32_WRAPPER
  7405. // CLSIDFromXXX puke when input is >= 248
  7406. #define SAFE_OLE_BUF_LEN 247
  7407. HRESULT WINAPI CLSIDFromStringWrap(LPOLESTR lpsz, LPCLSID pclsid)
  7408. {
  7409. return GUIDFromStringW(lpsz, pclsid) ? S_OK : E_INVALIDARG;
  7410. }
  7411. HRESULT WINAPI CLSIDFromProgIDWrap(LPCOLESTR lpszProgID, LPCLSID lpclsid)
  7412. {
  7413. HRESULT hr;
  7414. if (lstrlenW(lpszProgID) < SAFE_OLE_BUF_LEN)
  7415. {
  7416. hr = CLSIDFromProgID(lpszProgID, lpclsid);
  7417. }
  7418. else
  7419. {
  7420. hr = E_INVALIDARG;
  7421. }
  7422. return hr;
  7423. }
  7424. #endif // NEED_OLE32_WRAPPER
  7425. //************************************************************************
  7426. // function GETLONGPATHNAME :
  7427. //
  7428. // These wrappers are needed on all platforms (x86 and Alpha) because they
  7429. // implement the functionality for the Kernel32 function GetLongPathName that
  7430. // exists only on Win2K (Unicode/Ansi) and Win98 (Ansi only). Hence these
  7431. // wrappers provide this functionality for lower level platforms (NT4 & Win95)
  7432. //
  7433. #define achGETLONGPATHNAMEA "GetLongPathNameA"
  7434. typedef DWORD (*PROC_GETLONGPATHNAMEA) (LPCSTR, LPSTR, DWORD);
  7435. LWSTDAPI_(DWORD)
  7436. GetLongPathNameWrapA(
  7437. LPCSTR lpszShortPath,
  7438. LPSTR lpszLongPath,
  7439. DWORD cchBuffer)
  7440. {
  7441. VALIDATE_PROTOTYPE(GetLongPathName);
  7442. // If NT5 or Win98, use the system API for ANSI
  7443. if (g_bRunningOnNT5OrHigher || g_bRunningOnMemphis)
  7444. {
  7445. static PROC_GETLONGPATHNAMEA s_fpGLPNA = NULL;
  7446. if (!s_fpGLPNA)
  7447. {
  7448. // This codepath is used for Memphis also, hence need to use the
  7449. // wrapper for GetModuleHandle.
  7450. s_fpGLPNA = (PROC_GETLONGPATHNAMEA)GetProcAddress(GetModuleHandleWrap(L"kernel32"),achGETLONGPATHNAMEA);
  7451. }
  7452. ASSERT(s_fpGLPNA);
  7453. if (s_fpGLPNA)
  7454. {
  7455. return s_fpGLPNA(lpszShortPath, lpszLongPath, cchBuffer);
  7456. }
  7457. }
  7458. // Otherwise use our own logic to do the conversion....
  7459. BOOL bCountMode = FALSE;
  7460. CHAR cTmp;
  7461. HANDLE hFind;
  7462. LPSTR pTmp = NULL;
  7463. DWORD dwReturnLen = 0;
  7464. WIN32_FIND_DATAA Find_Data;
  7465. UINT PrevErrorMode;
  7466. // Since we are going to be touchin the media, turn off file error
  7467. // pop-ups. Remember the current mode and set it back in the end.
  7468. PrevErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  7469. if (lpszLongPath == NULL)
  7470. { // No OUT buffer provided ==> counting mode.
  7471. bCountMode = TRUE;
  7472. }
  7473. else
  7474. { // Initialize OUT buffer.
  7475. *lpszLongPath = '\0';
  7476. }
  7477. // Validate the input parameters...
  7478. if ((lpszShortPath == NULL)
  7479. || (0xFFFFFFFF == GetFileAttributesA(lpszShortPath)) )
  7480. {
  7481. SetLastError(ERROR_INVALID_PARAMETER);
  7482. dwReturnLen = 0;
  7483. goto Done;
  7484. }
  7485. if (PathIsUNCA(lpszShortPath))
  7486. {
  7487. // This is a UNC Path, don't know how to handle
  7488. SetLastError(ERROR_INVALID_PARAMETER);
  7489. dwReturnLen = 0;
  7490. goto Done;
  7491. }
  7492. // Input must be a full path.
  7493. // Since Drive letter cannot be multi-byte, just check 2nd and 3rd chars.
  7494. if ( lpszShortPath[1] != ':' ||
  7495. lpszShortPath[2] != '\\')
  7496. {
  7497. SetLastError(ERROR_INVALID_PARAMETER);
  7498. dwReturnLen = 0;
  7499. goto Done;
  7500. }
  7501. // Create the drive root for the LFN.
  7502. if ( !bCountMode && cchBuffer >= 3)
  7503. { // Copy the drive letter.
  7504. StrCpyNA(lpszLongPath, lpszShortPath, 3);
  7505. }
  7506. else
  7507. { // Supplied buffer is so small, can't even copy the drive letter!!
  7508. bCountMode = TRUE;
  7509. }
  7510. dwReturnLen += 2;
  7511. // Create a local copy of the input Short name to party on.
  7512. // Also, as per the documentation, OUT buffer can be the same as the IN.
  7513. // Hence need to save the IN buffer before we start filling the OUT.
  7514. CHAR lpLocalCopy[MAX_PATH];
  7515. StrCpyNA(lpLocalCopy, lpszShortPath, MAX_PATH);
  7516. // Now starts the main processing....
  7517. // Skip past the root backslash in lpszShortPath.
  7518. pTmp = lpLocalCopy+3;
  7519. while (*pTmp)
  7520. {
  7521. // Get the next Backslash
  7522. pTmp = StrChrA(pTmp, L'\\');
  7523. if ( pTmp == NULL)
  7524. {
  7525. // Fell off the end of the str. So point pTmp to the terminating \0
  7526. pTmp = lpLocalCopy + lstrlenA(lpLocalCopy);
  7527. }
  7528. cTmp = *pTmp;
  7529. *pTmp = '\0';
  7530. hFind = FindFirstFileA(lpLocalCopy, &Find_Data);
  7531. if (hFind != INVALID_HANDLE_VALUE)
  7532. {
  7533. FindClose(hFind);
  7534. dwReturnLen += lstrlenA(Find_Data.cFileName);
  7535. dwReturnLen += 1; // Plus for the '\' introduced by PathCombine.
  7536. if (!bCountMode && dwReturnLen < cchBuffer)
  7537. { // Add the LFN to the path
  7538. PathCombineA(lpszLongPath, lpszLongPath, Find_Data.cFileName);
  7539. }
  7540. else
  7541. { // We are out of buffer space. Continue loop to find space reqd.
  7542. bCountMode = TRUE;
  7543. *lpszLongPath = '\0';
  7544. }
  7545. }
  7546. else
  7547. {
  7548. //Error: Input path does not exist. The earlier check should catch
  7549. //this
  7550. SetLastError(ERROR_INVALID_PARAMETER);
  7551. if (!bCountMode)
  7552. *lpszLongPath = '\0';
  7553. *pTmp = cTmp;
  7554. dwReturnLen = 0;
  7555. goto Done;
  7556. }
  7557. *pTmp = cTmp;
  7558. if (*pTmp)
  7559. pTmp = CharNextA(pTmp);
  7560. }
  7561. Done:
  7562. // restore error mode.
  7563. SetErrorMode(PrevErrorMode);
  7564. if ( dwReturnLen && bCountMode)
  7565. { // If everything OK (dwReturnLen!=0) and Counting Mode, add one.
  7566. return (dwReturnLen+1);
  7567. }
  7568. else
  7569. { // Return error (dwReturnLen==0) Or
  7570. // No. of chars (dwReturnLen != 0 && bCountMode == FALSE)
  7571. return (dwReturnLen);
  7572. }
  7573. }
  7574. #define achGETLONGPATHNAMEW "GetLongPathNameW"
  7575. typedef DWORD (*PROC_GETLONGPATHNAMEW) (LPCWSTR, LPWSTR, DWORD);
  7576. LWSTDAPI_(DWORD)
  7577. GetLongPathNameWrapW(
  7578. LPCWSTR lpszShortPath,
  7579. LPWSTR lpszLongPath,
  7580. DWORD cchBuffer)
  7581. {
  7582. VALIDATE_PROTOTYPE(GetLongPathName);
  7583. // If we are running on NT5, use the system API for Unicode
  7584. if (g_bRunningOnNT5OrHigher)
  7585. {
  7586. static PROC_GETLONGPATHNAMEW s_fpGLPNW = NULL;
  7587. if (!s_fpGLPNW)
  7588. {
  7589. s_fpGLPNW = (PROC_GETLONGPATHNAMEW)GetProcAddress(GetModuleHandle(TEXT("kernel32")),achGETLONGPATHNAMEW);
  7590. }
  7591. ASSERT(s_fpGLPNW);
  7592. if (s_fpGLPNW)
  7593. {
  7594. return s_fpGLPNW(lpszShortPath, lpszLongPath, cchBuffer);
  7595. }
  7596. }
  7597. // All other platforms, convert UNICODE inputs to ANSI and use the
  7598. // ANSI wrapper.
  7599. CStrIn strShortPath(lpszShortPath);
  7600. CStrOut strLongPath(lpszLongPath, cchBuffer);
  7601. // DWORD dwRet = GetLongPathNameWrapA(strShortPath, strLongPath, strLongPath.BufSize());
  7602. DWORD dwRet = GetLongPathNameWrapA(strShortPath, strLongPath, cchBuffer);
  7603. if (dwRet != 0)
  7604. { // If the call succeeded, thunk back the size.
  7605. if (dwRet < (DWORD)cchBuffer)
  7606. { // Succeeded in getting LFN value in the OUT buffer. Thunk it back
  7607. // to Unicode.
  7608. dwRet = strLongPath.ConvertIncludingNul() - 1;
  7609. }
  7610. // else ==> buffer small, need dwRet character space.
  7611. }
  7612. return dwRet;
  7613. }
  7614. // End of GETLONGPATHNAME wrapper implementation.
  7615. // NOTE: This wrapper is to be built on all platforms.
  7616. //************************************************************************