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

5280 lines
163 KiB

  1. /**************************************************************************\
  2. * Module Name: client.c
  3. *
  4. * Client/Server call related routines.
  5. *
  6. * Copyright (c) 1985 - 1999, Microsoft Corporation
  7. *
  8. * History:
  9. * 04-Dec-1990 SMeans Created.
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "kbd.h"
  14. #include "ntsend.h"
  15. #include "vdm.h"
  16. /*
  17. * NOTE -- this table must match the FNID list in user.h. It provides a WOWCLASS for each FNID.
  18. */
  19. int aiClassWow[] = {
  20. WOWCLASS_SCROLLBAR,
  21. WOWCLASS_ICONTITLE,
  22. WOWCLASS_MENU,
  23. WOWCLASS_DESKTOP,
  24. WOWCLASS_WIN16,
  25. WOWCLASS_WIN16,
  26. WOWCLASS_SWITCHWND,
  27. WOWCLASS_BUTTON,
  28. WOWCLASS_COMBOBOX,
  29. WOWCLASS_COMBOLBOX,
  30. WOWCLASS_DIALOG,
  31. WOWCLASS_EDIT,
  32. WOWCLASS_LISTBOX,
  33. WOWCLASS_MDICLIENT,
  34. WOWCLASS_STATIC,
  35. WOWCLASS_WIN16, // 2A9
  36. WOWCLASS_WIN16,
  37. WOWCLASS_WIN16,
  38. WOWCLASS_WIN16,
  39. WOWCLASS_WIN16,
  40. WOWCLASS_WIN16,
  41. WOWCLASS_WIN16,
  42. WOWCLASS_WIN16,
  43. WOWCLASS_WIN16, // 2B1
  44. WOWCLASS_WIN16,
  45. WOWCLASS_WIN16,
  46. WOWCLASS_WIN16,
  47. WOWCLASS_WIN16,
  48. WOWCLASS_WIN16,
  49. WOWCLASS_WIN16,
  50. WOWCLASS_WIN16
  51. };
  52. HBITMAP WOWLoadBitmapA(HINSTANCE hmod, LPCSTR lpName, LPBYTE pResData, DWORD cbResData);
  53. HMENU WowServerLoadCreateMenu(HANDLE hMod, LPTSTR lpName, CONST LPMENUTEMPLATE pmt,
  54. DWORD cb, BOOL fCallClient);
  55. DWORD GetFullUserHandle(WORD wHandle);
  56. UINT GetClipboardCodePage(LCID, LCTYPE);
  57. extern HANDLE WOWFindResourceExWCover(HANDLE hmod, LPCWSTR rt, LPCWSTR lpUniName, WORD LangId);
  58. extern BOOL APIENTRY EnableEUDC();
  59. CONST WCHAR szKLKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Keyboard Layouts\\";
  60. CONST WCHAR szKLFile[] = L"Layout File";
  61. CONST WCHAR szKLAttributes[] = L"Attributes";
  62. CONST WCHAR szKLId[] = L"Layout ID";
  63. #define NSZKLKEY (sizeof szKLKey + 16)
  64. CONST LPWSTR pwszKLLibSafety = L"kbdus.dll";
  65. CONST UINT wKbdLocaleSafety = 0x04090409;
  66. CONST LPWSTR pwszKLLibSafetyJPN = L"kbdjpn.dll";
  67. CONST UINT wKbdLocaleSafetyJPN = 0x04110411;
  68. CONST LPWSTR pwszKLLibSafetyKOR = L"kbdkor.dll";
  69. CONST UINT wKbdLocaleSafetyKOR = 0x04120412;
  70. #define CCH_KL_LIBNAME 256
  71. #define CCH_KL_ID 16
  72. UNICODE_STRING strRootDirectory;
  73. VOID CheckValidLayoutName(LPWSTR lpszName);
  74. BOOL WOWModuleUnload(HANDLE hModule) {
  75. return (BOOL)NtUserCallOneParam((ULONG_PTR)hModule,
  76. SFI__WOWMODULEUNLOAD);
  77. }
  78. BOOL WOWCleanup(HANDLE hInstance, DWORD hTaskWow) {
  79. return (BOOL)NtUserCallTwoParam((ULONG_PTR)hInstance,
  80. (ULONG_PTR)hTaskWow,
  81. SFI__WOWCLEANUP);
  82. }
  83. /***************************************************************************\
  84. * BringWindowToTop (API)
  85. *
  86. *
  87. * History:
  88. * 11-Jul-1991 DarrinM Ported from Win 3.1 sources.
  89. \***************************************************************************/
  90. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, BringWindowToTop, HWND, hwnd)
  91. BOOL BringWindowToTop(
  92. HWND hwnd)
  93. {
  94. return NtUserSetWindowPos(hwnd,
  95. HWND_TOP,
  96. 0,
  97. 0,
  98. 0,
  99. 0,
  100. SWP_NOSIZE | SWP_NOMOVE);
  101. }
  102. FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, ChildWindowFromPoint, HWND, hwndParent, POINT, point)
  103. HWND ChildWindowFromPoint(
  104. HWND hwndParent,
  105. POINT point)
  106. {
  107. /*
  108. * Cool Hack Alert... Corel Ventura 5.0
  109. * Dies after it calls ChildWindowFromPoint, and
  110. * the combobox doesn't have its edit window at 1,1...
  111. */
  112. if ((point.x == 1) && (point.y == 1)) {
  113. PCBOX pcCombo;
  114. PWND pwnd;
  115. pwnd = ValidateHwnd(hwndParent);
  116. if (pwnd == NULL)
  117. return NULL;
  118. if (!TestWF(pwnd, WFWIN40COMPAT) &&
  119. GETFNID(pwnd) == FNID_COMBOBOX &&
  120. TestWindowProcess(pwnd) &&
  121. ((pcCombo = ((PCOMBOWND)pwnd)->pcbox) != NULL) &&
  122. !(pcCombo->fNoEdit)) {
  123. RIPMSG0(RIP_WARNING, "ChildWindowFromPoint: Combobox @1,1. Returning spwndEdit");
  124. return HWq(pcCombo->spwndEdit);
  125. }
  126. }
  127. return NtUserChildWindowFromPointEx(hwndParent, point, 0);
  128. }
  129. FUNCLOG1(LOG_GENERAL, HICON, DUMMYCALLINGTYPE, CopyIcon, HICON, hicon)
  130. HICON CopyIcon(
  131. HICON hicon)
  132. {
  133. HICON hIconT = NULL;
  134. ICONINFO ii;
  135. if (GetIconInfo(hicon, &ii)) {
  136. hIconT = CreateIconIndirect(&ii);
  137. DeleteObject(ii.hbmMask);
  138. if (ii.hbmColor != NULL)
  139. DeleteObject(ii.hbmColor);
  140. }
  141. return hIconT;
  142. }
  143. /***************************************************************************\
  144. * AdjustWindowRect (API)
  145. *
  146. * History:
  147. * 01-Jul-1991 MikeKe Created.
  148. \***************************************************************************/
  149. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, AdjustWindowRect, LPRECT, lprc, DWORD, style, BOOL, fMenu)
  150. BOOL WINAPI AdjustWindowRect(
  151. LPRECT lprc,
  152. DWORD style,
  153. BOOL fMenu)
  154. {
  155. ConnectIfNecessary(0);
  156. return _AdjustWindowRectEx(lprc, style, fMenu, 0L);
  157. }
  158. /***************************************************************************\
  159. * TranslateAcceleratorA/W
  160. *
  161. * Put here so we can check for NULL on client side, and before validation
  162. * for both DOS and NT cases.
  163. *
  164. * 05-29-91 ScottLu Created.
  165. * 01-05-93 IanJa Unicode/ANSI.
  166. \***************************************************************************/
  167. FUNCLOG3(LOG_GENERAL, int, WINAPI, TranslateAcceleratorW, HWND, hwnd, HACCEL, hAccel, LPMSG, lpMsg)
  168. int WINAPI TranslateAcceleratorW(
  169. HWND hwnd,
  170. HACCEL hAccel,
  171. LPMSG lpMsg)
  172. {
  173. /*
  174. * NULL pwnd is a valid case - since this is called from the center
  175. * of main loops, pwnd == NULL happens all the time, and we shouldn't
  176. * generate a warning because of it.
  177. */
  178. if (hwnd == NULL)
  179. return FALSE;
  180. /*
  181. * We only need to pass key-down messages to the server,
  182. * everything else ends up returning 0/FALSE from this function.
  183. */
  184. switch (lpMsg->message) {
  185. case WM_KEYDOWN:
  186. case WM_SYSKEYDOWN:
  187. case WM_CHAR:
  188. case WM_SYSCHAR:
  189. return NtUserTranslateAccelerator(hwnd, hAccel, lpMsg);
  190. default:
  191. return 0;
  192. }
  193. }
  194. FUNCLOG3(LOG_GENERAL, int, WINAPI, TranslateAcceleratorA, HWND, hwnd, HACCEL, hAccel, LPMSG, lpMsg)
  195. int WINAPI TranslateAcceleratorA(
  196. HWND hwnd,
  197. HACCEL hAccel,
  198. LPMSG lpMsg)
  199. {
  200. WPARAM wParamT;
  201. int iT;
  202. /*
  203. * NULL pwnd is a valid case - since this is called from the center
  204. * of main loops, pwnd == NULL happens all the time, and we shouldn't
  205. * generate a warning because of it.
  206. */
  207. if (hwnd == NULL)
  208. return FALSE;
  209. /*
  210. * We only need to pass key-down messages to the server,
  211. * everything else ends up returning 0/FALSE from this function.
  212. */
  213. switch (lpMsg->message) {
  214. case WM_KEYDOWN:
  215. case WM_SYSKEYDOWN:
  216. case WM_CHAR:
  217. case WM_SYSCHAR:
  218. wParamT = lpMsg->wParam;
  219. RtlMBMessageWParamCharToWCS(lpMsg->message, &(lpMsg->wParam));
  220. iT = NtUserTranslateAccelerator(hwnd, hAccel, lpMsg);
  221. lpMsg->wParam = wParamT;
  222. return iT;
  223. default:
  224. return 0;
  225. }
  226. }
  227. /***************************************************************************\
  228. * Clipboard functions
  229. *
  230. * 11-Oct-1991 mikeke Created.
  231. \***************************************************************************/
  232. typedef struct _HANDLENODE {
  233. struct _HANDLENODE *pnext;
  234. UINT fmt;
  235. HANDLE handleServer;
  236. HANDLE handleClient;
  237. BOOL fGlobalHandle;
  238. } HANDLENODE;
  239. typedef HANDLENODE *PHANDLENODE;
  240. PHANDLENODE gphn = NULL;
  241. /***************************************************************************\
  242. * DeleteClientClipboardHandle
  243. *
  244. * 11-Oct-1991 MikeKe Created.
  245. \***************************************************************************/
  246. BOOL DeleteClientClipboardHandle(
  247. PHANDLENODE phn)
  248. {
  249. LPMETAFILEPICT lpMFP;
  250. UserAssert(phn->handleClient != (HANDLE)0);
  251. switch (phn->fmt) {
  252. case CF_BITMAP:
  253. case CF_DSPBITMAP:
  254. case CF_PALETTE:
  255. // Does nothing (should remove).
  256. //
  257. //GdiDeleteLocalObject((ULONG)hobjDelete);
  258. break;
  259. case CF_METAFILEPICT:
  260. case CF_DSPMETAFILEPICT:
  261. USERGLOBALLOCK(phn->handleClient, lpMFP);
  262. if (lpMFP) {
  263. DeleteMetaFile(lpMFP->hMF);
  264. USERGLOBALUNLOCK(phn->handleClient);
  265. UserGlobalFree(phn->handleClient);
  266. } else {
  267. RIPMSGF1(RIP_ERROR,
  268. "Can't lock client handle 0x%p",
  269. phn->handleClient);
  270. return FALSE;
  271. }
  272. break;
  273. case CF_ENHMETAFILE:
  274. case CF_DSPENHMETAFILE:
  275. DeleteEnhMetaFile((HENHMETAFILE)phn->handleClient);
  276. break;
  277. default:
  278. //case CF_TEXT:
  279. //case CF_OEMTEXT:
  280. //case CF_UNICODETEXT:
  281. //case CF_LOCALE:
  282. //case CF_DSPTEXT:
  283. //case CF_DIB:
  284. //case CF_DIBV5:
  285. if (phn->fGlobalHandle) {
  286. if (UserGlobalFree(phn->handleClient)) {
  287. RIPMSGF1(RIP_WARNING,
  288. "UserGlobalFree(0x%p) failed",
  289. phn->handleClient);
  290. return FALSE;
  291. }
  292. } else {
  293. UserAssert(GlobalFlags(phn->handleClient) == GMEM_INVALID_HANDLE);
  294. }
  295. break;
  296. }
  297. /*
  298. * Deleted successfully
  299. */
  300. return TRUE;
  301. }
  302. /***************************************************************************\
  303. * ClientEmptyClipboard
  304. *
  305. * Empties the client side clipboard list.
  306. *
  307. * 01-15-93 ScottLu Created.
  308. \***************************************************************************/
  309. void ClientEmptyClipboard(void)
  310. {
  311. PHANDLENODE phnNext;
  312. PHANDLENODE phnT;
  313. RtlEnterCriticalSection(&gcsClipboard);
  314. phnT = gphn;
  315. while (phnT != NULL) {
  316. phnNext = phnT->pnext;
  317. if (phnT->handleClient != (HANDLE)0) {
  318. DeleteClientClipboardHandle(phnT);
  319. }
  320. UserLocalFree(phnT);
  321. phnT = phnNext;
  322. }
  323. gphn = NULL;
  324. /*
  325. * Tell wow to cleanup it's clipboard stuff
  326. */
  327. if (pfnWowEmptyClipBoard) {
  328. pfnWowEmptyClipBoard();
  329. }
  330. RtlLeaveCriticalSection(&gcsClipboard);
  331. }
  332. /***************************************************************************\
  333. * GetClipboardData
  334. *
  335. * 11-Oct-1991 mikeke Created.
  336. \***************************************************************************/
  337. FUNCLOG1(LOG_GENERAL, HANDLE, WINAPI, GetClipboardData, UINT, uFmt)
  338. HANDLE WINAPI GetClipboardData(
  339. UINT uFmt)
  340. {
  341. HANDLE handleClient;
  342. HANDLE handleServer;
  343. PHANDLENODE phn;
  344. PHANDLENODE phnNew;
  345. GETCLIPBDATA gcd;
  346. /*
  347. * Get the Server's Data; return if there is no data.
  348. */
  349. if (!(handleServer = NtUserGetClipboardData(uFmt, &gcd)))
  350. return (HANDLE)NULL;
  351. /*
  352. * Handle any translation that must be done for text items. The
  353. * format returned will only differ for text items. Metafile and
  354. * Enhanced-Metafiles are handled through GDI for their converstions.
  355. * And Bitmap color space convertion also nessesary for CF_BITMAP,
  356. * CF_DIB and CF_DIBV5 with color space.
  357. */
  358. if (uFmt != gcd.uFmtRet) {
  359. LPBYTE lpSrceData = NULL;
  360. LPBYTE lpDestData = NULL;
  361. LPBYTE lptData = NULL;
  362. LPDWORD lpLocale;
  363. DWORD uLocale;
  364. int iSrce;
  365. int iDest;
  366. UINT uCPage;
  367. SETCLIPBDATA scd;
  368. UINT cbNULL = 0;
  369. /*
  370. * Make sure handleServer is server-side memory handle
  371. */
  372. if ((gcd.uFmtRet == CF_TEXT) || (gcd.uFmtRet == CF_OEMTEXT) ||
  373. (gcd.uFmtRet == CF_UNICODETEXT) ||
  374. (gcd.uFmtRet == CF_DIB) || (gcd.uFmtRet == CF_DIBV5)) {
  375. if ((lpSrceData = CreateLocalMemHandle(handleServer)) == NULL) {
  376. goto AbortDummyHandle;
  377. }
  378. /*
  379. * Allocate space for the converted TEXT data.
  380. */
  381. if (!(iSrce = (UINT)GlobalSize(lpSrceData))) {
  382. goto AbortDummyHandle;
  383. }
  384. /*
  385. * Only CF_xxxTEXT may have locale information.
  386. */
  387. if ((gcd.uFmtRet == CF_TEXT) || (gcd.uFmtRet == CF_OEMTEXT) ||
  388. (gcd.uFmtRet == CF_UNICODETEXT)) {
  389. /*
  390. * Get the locale out of the parameter-struct. We will
  391. * use this to get the codepage for text-translation.
  392. */
  393. if (lpLocale = (LPDWORD)CreateLocalMemHandle(gcd.hLocale)) {
  394. uLocale = *lpLocale;
  395. GlobalFree(lpLocale);
  396. } else {
  397. uLocale = 0;
  398. }
  399. /*
  400. * And also, pre-allocate translated buffer in same size as source.
  401. */
  402. if ((lpDestData = GlobalAlloc(LPTR, iSrce)) == NULL) {
  403. goto AbortDummyHandle;
  404. }
  405. }
  406. switch (uFmt) {
  407. case CF_TEXT:
  408. cbNULL = 1;
  409. if (gcd.uFmtRet == CF_OEMTEXT) {
  410. /*
  411. * CF_OEMTEXT --> CF_TEXT conversion
  412. */
  413. OemToAnsi((LPSTR)lpSrceData, (LPSTR)lpDestData);
  414. } else {
  415. uCPage = GetClipboardCodePage(uLocale,
  416. LOCALE_IDEFAULTANSICODEPAGE);
  417. /*
  418. * CF_UNICODETEXT --> CF_TEXT conversion
  419. */
  420. iDest = 0;
  421. if ((iDest = WideCharToMultiByte(uCPage,
  422. (DWORD)0,
  423. (LPWSTR)lpSrceData,
  424. (int)(iSrce / sizeof(WCHAR)),
  425. (LPSTR)NULL,
  426. (int)iDest,
  427. (LPSTR)NULL,
  428. (LPBOOL)NULL)) == 0) {
  429. AbortGetClipData:
  430. UserGlobalFree(lpDestData);
  431. AbortDummyHandle:
  432. if (lpSrceData) {
  433. UserGlobalFree(lpSrceData);
  434. }
  435. return NULL;
  436. }
  437. if (!(lptData = GlobalReAlloc(lpDestData, iDest, LPTR | LMEM_MOVEABLE)))
  438. goto AbortGetClipData;
  439. lpDestData = lptData;
  440. if (WideCharToMultiByte(uCPage,
  441. (DWORD)0,
  442. (LPWSTR)lpSrceData,
  443. (int)(iSrce / sizeof(WCHAR)),
  444. (LPSTR)lpDestData,
  445. (int)iDest,
  446. (LPSTR)NULL,
  447. (LPBOOL)NULL) == 0)
  448. goto AbortGetClipData;
  449. }
  450. break;
  451. case CF_OEMTEXT:
  452. cbNULL = 1;
  453. if (gcd.uFmtRet == CF_TEXT) {
  454. /*
  455. * CF_TEXT --> CF_OEMTEXT conversion
  456. */
  457. AnsiToOem((LPSTR)lpSrceData, (LPSTR)lpDestData);
  458. } else {
  459. uCPage = GetClipboardCodePage(uLocale,
  460. LOCALE_IDEFAULTCODEPAGE);
  461. /*
  462. * CF_UNICODETEXT --> CF_OEMTEXT conversion
  463. */
  464. iDest = 0;
  465. if ((iDest = WideCharToMultiByte(uCPage,
  466. (DWORD)0,
  467. (LPWSTR)lpSrceData,
  468. (int)(iSrce / sizeof(WCHAR)),
  469. (LPSTR)NULL,
  470. (int)iDest,
  471. (LPSTR)NULL,
  472. (LPBOOL)NULL)) == 0)
  473. goto AbortGetClipData;
  474. if (!(lptData = GlobalReAlloc(lpDestData, iDest, LPTR | LMEM_MOVEABLE)))
  475. goto AbortGetClipData;
  476. lpDestData = lptData;
  477. if (WideCharToMultiByte(uCPage,
  478. (DWORD)0,
  479. (LPWSTR)lpSrceData,
  480. (int)(iSrce / sizeof(WCHAR)),
  481. (LPSTR)lpDestData,
  482. (int)iDest,
  483. (LPSTR)NULL,
  484. (LPBOOL)NULL) == 0)
  485. goto AbortGetClipData;
  486. }
  487. break;
  488. case CF_UNICODETEXT:
  489. cbNULL = 2;
  490. if (gcd.uFmtRet == CF_TEXT) {
  491. uCPage = GetClipboardCodePage(uLocale,
  492. LOCALE_IDEFAULTANSICODEPAGE);
  493. /*
  494. * CF_TEXT --> CF_UNICODETEXT conversion
  495. */
  496. iDest = 0;
  497. if ((iDest = MultiByteToWideChar(uCPage,
  498. (DWORD)MB_PRECOMPOSED,
  499. (LPSTR)lpSrceData,
  500. (int)iSrce,
  501. (LPWSTR)NULL,
  502. (int)iDest)) == 0)
  503. goto AbortGetClipData;
  504. if (!(lptData = GlobalReAlloc(lpDestData,
  505. iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE)))
  506. goto AbortGetClipData;
  507. lpDestData = lptData;
  508. if (MultiByteToWideChar(uCPage,
  509. (DWORD)MB_PRECOMPOSED,
  510. (LPSTR)lpSrceData,
  511. (int)iSrce,
  512. (LPWSTR)lpDestData,
  513. (int)iDest) == 0)
  514. goto AbortGetClipData;
  515. } else {
  516. uCPage = GetClipboardCodePage(uLocale,
  517. LOCALE_IDEFAULTCODEPAGE);
  518. /*
  519. * CF_OEMTEXT --> CF_UNICDOETEXT conversion
  520. */
  521. iDest = 0;
  522. if ((iDest = MultiByteToWideChar(uCPage,
  523. (DWORD)MB_PRECOMPOSED,
  524. (LPSTR)lpSrceData,
  525. (int)iSrce,
  526. (LPWSTR)NULL,
  527. (int)iDest)) == 0)
  528. goto AbortGetClipData;
  529. if (!(lptData = GlobalReAlloc(lpDestData,
  530. iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE)))
  531. goto AbortGetClipData;
  532. lpDestData = lptData;
  533. if (MultiByteToWideChar(uCPage,
  534. (DWORD)MB_PRECOMPOSED,
  535. (LPSTR)lpSrceData,
  536. (int)iSrce,
  537. (LPWSTR)lpDestData,
  538. (int)iDest) == 0)
  539. goto AbortGetClipData;
  540. }
  541. break;
  542. case CF_BITMAP:
  543. if (gcd.uFmtRet == CF_DIBV5) {
  544. /*
  545. * CF_DIBV5 --> CF_BITMAP (sRGB)
  546. *
  547. * The GDI bitmap handle will be returned in handleServer.
  548. */
  549. if ((handleServer = GdiConvertBitmapV5(lpSrceData,iSrce,
  550. gcd.hPalette,CF_BITMAP)) == NULL) {
  551. /*
  552. * GDI failed to convert.
  553. */
  554. RIPMSG0(RIP_ERROR,
  555. "GetClipboardData: Failed CF_DIBV5 -> CF_BITMAP");
  556. goto AbortDummyHandle;
  557. }
  558. } else {
  559. RIPMSG0(RIP_ERROR, "GetClipboardData: bad conversion request");
  560. goto AbortDummyHandle;
  561. }
  562. break;
  563. case CF_DIB:
  564. if (gcd.uFmtRet == CF_DIBV5) {
  565. /*
  566. * CF_DIBV5 --> CF_DIB (sRGB)
  567. *
  568. * The local memory handle will be returned in lpDestData.
  569. */
  570. if ((lpDestData = (LPBYTE) GdiConvertBitmapV5(lpSrceData,iSrce,
  571. gcd.hPalette,CF_DIB)) == NULL) {
  572. /*
  573. * GDI failed to convert.
  574. */
  575. RIPMSG0(RIP_ERROR,
  576. "GetClipboardData: Failed CF_DIBV5 -> CF_DIB");
  577. goto AbortDummyHandle;
  578. }
  579. } else {
  580. RIPMSG0(RIP_ERROR, "GetClipboardData: bad conversion request");
  581. goto AbortDummyHandle;
  582. }
  583. break;
  584. }
  585. }
  586. if (lpDestData) {
  587. /*
  588. * Replace the dummy user-mode memory handle with the actual handle.
  589. */
  590. handleServer = ConvertMemHandle(lpDestData, cbNULL);
  591. if (handleServer == NULL)
  592. goto AbortGetClipData;
  593. }
  594. /*
  595. * Update the server. If that is successfull update the client
  596. */
  597. RtlEnterCriticalSection(&gcsClipboard);
  598. scd.fGlobalHandle = gcd.fGlobalHandle;
  599. scd.fIncSerialNumber = FALSE;
  600. if (!NtUserSetClipboardData(uFmt, handleServer, &scd)) {
  601. handleServer = NULL;
  602. }
  603. RtlLeaveCriticalSection(&gcsClipboard);
  604. if (lpDestData)
  605. UserGlobalFree(lpDestData);
  606. if (lpSrceData)
  607. UserGlobalFree(lpSrceData);
  608. if (handleServer == NULL)
  609. return NULL;
  610. }
  611. /*
  612. * See if we already have a client side handle; validate the format
  613. * as well because some server objects, metafile for example, are dual mode
  614. * and yield two kinds of client objects enhanced and regular metafiles
  615. */
  616. handleClient = NULL;
  617. RtlEnterCriticalSection(&gcsClipboard);
  618. phn = gphn;
  619. while (phn) {
  620. if ((phn->handleServer == handleServer) && (phn->fmt == uFmt)) {
  621. handleClient = phn->handleClient;
  622. goto Exit;
  623. }
  624. phn = phn->pnext;
  625. }
  626. /*
  627. * We don't have a handle cached so we'll create one.
  628. */
  629. phnNew = (PHANDLENODE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(HANDLENODE));
  630. if (phnNew == NULL) {
  631. goto Exit;
  632. }
  633. phnNew->handleServer = handleServer;
  634. phnNew->fmt = gcd.uFmtRet;
  635. phnNew->fGlobalHandle = gcd.fGlobalHandle;
  636. switch (uFmt) {
  637. /*
  638. * Misc GDI Handles
  639. */
  640. case CF_BITMAP:
  641. case CF_DSPBITMAP:
  642. case CF_PALETTE:
  643. phnNew->handleClient = handleServer;
  644. break;
  645. case CF_METAFILEPICT:
  646. case CF_DSPMETAFILEPICT:
  647. phnNew->handleClient = GdiCreateLocalMetaFilePict(handleServer);
  648. break;
  649. case CF_ENHMETAFILE:
  650. case CF_DSPENHMETAFILE:
  651. phnNew->handleClient = GdiCreateLocalEnhMetaFile(handleServer);
  652. break;
  653. /*
  654. * GlobalHandle Cases
  655. */
  656. case CF_TEXT:
  657. case CF_OEMTEXT:
  658. case CF_UNICODETEXT:
  659. case CF_LOCALE:
  660. case CF_DSPTEXT:
  661. case CF_DIB:
  662. case CF_DIBV5:
  663. phnNew->handleClient = CreateLocalMemHandle(handleServer);
  664. phnNew->fGlobalHandle = TRUE;
  665. break;
  666. default:
  667. /*
  668. * Private Data Format; If this is global data, create a copy of that
  669. * data here on the client. If it isn't global data, it is just a dword
  670. * in which case we just return a dword. If it is global data and
  671. * the server fails to give us that memory, return NULL. If it isn't
  672. * global data, handleClient is just a dword.
  673. */
  674. if (phnNew->fGlobalHandle) {
  675. phnNew->handleClient = CreateLocalMemHandle(handleServer);
  676. } else {
  677. phnNew->handleClient = handleServer;
  678. }
  679. break;
  680. }
  681. if (phnNew->handleClient == NULL) {
  682. /*
  683. * Something bad happened; GDI didn't give us back a handle. Since
  684. * GDI has logged the error, we'll just clean up and return an error.
  685. */
  686. RIPMSGF1(RIP_WARNING,
  687. "Unable to convert server handle 0x%p to client handle",
  688. handleServer);
  689. UserLocalFree(phnNew);
  690. goto Exit;
  691. }
  692. #if DBG
  693. /*
  694. * If handleClient came from a GlobalAlloc, then fGlobalHandle must be TRUE.
  695. * Some formats are acutally global handles but require special cleanup.
  696. */
  697. switch (phnNew->fmt) {
  698. case CF_METAFILEPICT:
  699. case CF_DSPMETAFILEPICT:
  700. break;
  701. default:
  702. UserAssert(phnNew->fGlobalHandle
  703. ^ (GlobalFlags(phnNew->handleClient) == GMEM_INVALID_HANDLE));
  704. break;
  705. }
  706. #endif
  707. /*
  708. * Cache the new handle by linking it into our list
  709. */
  710. phnNew->pnext = gphn;
  711. gphn = phnNew;
  712. handleClient = phnNew->handleClient;
  713. Exit:
  714. RtlLeaveCriticalSection(&gcsClipboard);
  715. return handleClient;
  716. }
  717. /***************************************************************************\
  718. * GetClipboardCodePage (internal)
  719. *
  720. * This routine returns the code-page associated with the given locale.
  721. *
  722. * 24-Aug-1995 ChrisWil Created.
  723. \***************************************************************************/
  724. #define GETCCP_SIZE 8
  725. UINT GetClipboardCodePage(
  726. LCID uLocale,
  727. LCTYPE uLocaleType)
  728. {
  729. WCHAR wszCodePage[GETCCP_SIZE];
  730. DWORD uCPage;
  731. if (GetLocaleInfoW(uLocale, uLocaleType, wszCodePage, GETCCP_SIZE)) {
  732. uCPage = (UINT)wcstol(wszCodePage, NULL, 10);
  733. } else {
  734. switch(uLocaleType) {
  735. case LOCALE_IDEFAULTCODEPAGE:
  736. uCPage = CP_OEMCP;
  737. break;
  738. case LOCALE_IDEFAULTANSICODEPAGE:
  739. uCPage = CP_ACP;
  740. break;
  741. default:
  742. uCPage = CP_MACCP;
  743. break;
  744. }
  745. }
  746. return uCPage;
  747. }
  748. /***************************************************************************\
  749. * SetClipboardData
  750. *
  751. * Stub routine needs to exist on the client side so any global data gets
  752. * allocated DDESHARE.
  753. *
  754. * 05-20-91 ScottLu Created.
  755. \***************************************************************************/
  756. FUNCLOG2(LOG_GENERAL, HANDLE, WINAPI, SetClipboardData, UINT, wFmt, HANDLE, hMem)
  757. HANDLE WINAPI SetClipboardData(
  758. UINT wFmt,
  759. HANDLE hMem)
  760. {
  761. PHANDLENODE phnNew;
  762. HANDLE hServer = NULL;
  763. SETCLIPBDATA scd;
  764. BOOL fGlobalHandle = FALSE;
  765. if (hMem != NULL) {
  766. switch(wFmt) {
  767. case CF_BITMAP:
  768. case CF_DSPBITMAP:
  769. case CF_PALETTE:
  770. hServer = hMem;
  771. break;
  772. case CF_METAFILEPICT:
  773. case CF_DSPMETAFILEPICT:
  774. hServer = GdiConvertMetaFilePict(hMem);
  775. break;
  776. case CF_ENHMETAFILE:
  777. case CF_DSPENHMETAFILE:
  778. hServer = GdiConvertEnhMetaFile(hMem);
  779. break;
  780. /*
  781. * Must have a valid hMem (GlobalHandle)
  782. */
  783. case CF_TEXT:
  784. case CF_OEMTEXT:
  785. case CF_LOCALE:
  786. case CF_DSPTEXT:
  787. hServer = ConvertMemHandle(hMem, 1);
  788. fGlobalHandle = TRUE;
  789. break;
  790. case CF_UNICODETEXT:
  791. hServer = ConvertMemHandle(hMem, 2);
  792. fGlobalHandle = TRUE;
  793. break;
  794. case CF_DIB:
  795. case CF_DIBV5:
  796. hServer = ConvertMemHandle(hMem, 0);
  797. fGlobalHandle = TRUE;
  798. break;
  799. /*
  800. * hMem should have been NULL but Write sends non-null when told
  801. * to render
  802. */
  803. case CF_OWNERDISPLAY:
  804. // Fall Through;
  805. /*
  806. * May have an hMem (GlobalHandle) or may be private handle\info
  807. */
  808. default:
  809. if (GlobalFlags(hMem) == GMEM_INVALID_HANDLE) {
  810. hServer = hMem; // No server equivalent; private data
  811. goto SCD_AFTERNULLCHECK;
  812. } else {
  813. fGlobalHandle = TRUE;
  814. hServer = ConvertMemHandle(hMem, 0);
  815. }
  816. break;
  817. }
  818. if (hServer == NULL) {
  819. /*
  820. * Something bad happened, gdi didn't give us back a handle.
  821. * Since gdi has logged the error, we'll just clean up and
  822. * return an error.
  823. */
  824. RIPMSG0(RIP_WARNING, "SetClipboardData: bad handle");
  825. return NULL;
  826. }
  827. }
  828. SCD_AFTERNULLCHECK:
  829. RtlEnterCriticalSection(&gcsClipboard);
  830. /*
  831. * Update the server if that is successfull update the client
  832. */
  833. scd.fGlobalHandle = fGlobalHandle;
  834. scd.fIncSerialNumber = TRUE;
  835. if (!NtUserSetClipboardData(wFmt, hServer, &scd)) {
  836. RtlLeaveCriticalSection(&gcsClipboard);
  837. return NULL;
  838. }
  839. /*
  840. * See if we already have a client handle of this type. If so
  841. * delete it.
  842. */
  843. phnNew = gphn;
  844. while (phnNew) {
  845. if (phnNew->fmt == wFmt) {
  846. if (phnNew->handleClient != NULL) {
  847. DeleteClientClipboardHandle(phnNew);
  848. /*
  849. * Notify WOW to clear its associated cached h16 for this format
  850. * so that OLE32 thunked calls, which bypass the WOW cache will work.
  851. */
  852. if (pfnWowCBStoreHandle) {
  853. pfnWowCBStoreHandle((WORD)wFmt, 0);
  854. }
  855. }
  856. break;
  857. }
  858. phnNew = phnNew->pnext;
  859. }
  860. /*
  861. * If we aren't re-using an old client cache entry alloc a new one
  862. */
  863. if (!phnNew) {
  864. phnNew = (PHANDLENODE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(HANDLENODE));
  865. if (phnNew == NULL) {
  866. RIPMSG0(RIP_WARNING, "SetClipboardData: not enough memory");
  867. RtlLeaveCriticalSection(&gcsClipboard);
  868. return NULL;
  869. }
  870. /*
  871. * Link in the newly allocated cache entry
  872. */
  873. phnNew->pnext = gphn;
  874. gphn = phnNew;
  875. }
  876. phnNew->handleServer = hServer;
  877. phnNew->handleClient = hMem;
  878. phnNew->fmt = wFmt;
  879. phnNew->fGlobalHandle = fGlobalHandle;
  880. RtlLeaveCriticalSection(&gcsClipboard);
  881. return hMem;
  882. }
  883. /**************************************************************************\
  884. * SetDeskWallpaper
  885. *
  886. * 22-Jul-1991 mikeke Created
  887. * 01-Mar-1992 GregoryW Modified to call SystemParametersInfo.
  888. \**************************************************************************/
  889. BOOL SetDeskWallpaper(
  890. IN LPCSTR pString OPTIONAL)
  891. {
  892. return SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, (PVOID)pString, TRUE);
  893. }
  894. /***************************************************************************\
  895. * ReleaseDC (API)
  896. *
  897. * A complete Thank cannot be generated for ReleaseDC because its first
  898. * parameter (hwnd) unnecessary and should be discarded before calling the
  899. * server-side routine _ReleaseDC.
  900. *
  901. * History:
  902. * 03-28-91 SMeans Created.
  903. * 06-17-91 ChuckWh Added support for local DCs.
  904. \***************************************************************************/
  905. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, ReleaseDC, HWND, hwnd, HDC, hdc)
  906. BOOL WINAPI ReleaseDC(
  907. HWND hwnd,
  908. HDC hdc)
  909. {
  910. /*
  911. * NOTE: This is a smart stub that calls _ReleaseDC so there is
  912. * no need for a separate ReleaseDC layer or client-server stub.
  913. * _ReleaseDC has simpler layer and client-server stubs since the
  914. * hwnd can be ignored.
  915. */
  916. UNREFERENCED_PARAMETER(hwnd);
  917. /*
  918. * Translate the handle.
  919. */
  920. if (hdc == NULL)
  921. return FALSE;
  922. /*
  923. * call GDI to release user mode DC resources
  924. */
  925. GdiReleaseDC(hdc);
  926. return (BOOL)NtUserCallOneParam((ULONG_PTR)hdc, SFI__RELEASEDC);
  927. }
  928. int WINAPI
  929. ToAscii(
  930. UINT wVirtKey,
  931. UINT wScanCode,
  932. CONST BYTE *lpKeyState,
  933. LPWORD lpChar,
  934. UINT wFlags
  935. )
  936. {
  937. WCHAR UnicodeChar[2];
  938. int cch, retval;
  939. retval = ToUnicode(wVirtKey, wScanCode, lpKeyState, UnicodeChar,2, wFlags);
  940. cch = (retval < 0) ? -retval : retval;
  941. if (cch != 0) {
  942. if (!NT_SUCCESS(RtlUnicodeToMultiByteN(
  943. (LPSTR)lpChar,
  944. (ULONG) sizeof(*lpChar),
  945. (PULONG)&cch,
  946. UnicodeChar,
  947. cch * sizeof(WCHAR)))) {
  948. return 0;
  949. }
  950. }
  951. return (retval < 0) ? -cch : cch;
  952. }
  953. static UINT uCachedCP = 0;
  954. static HKL hCachedHKL = 0;
  955. int WINAPI
  956. ToAsciiEx(
  957. UINT wVirtKey,
  958. UINT wScanCode,
  959. CONST BYTE *lpKeyState,
  960. LPWORD lpChar,
  961. UINT wFlags,
  962. HKL hkl
  963. )
  964. {
  965. WCHAR UnicodeChar[2];
  966. int cch, retval;
  967. BOOL fUsedDefaultChar;
  968. retval = ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, UnicodeChar,2, wFlags, hkl);
  969. cch = (retval < 0) ? -retval : retval;
  970. if (cch != 0) {
  971. if (hkl != hCachedHKL) {
  972. DWORD dwCodePage;
  973. if (!GetLocaleInfoW(
  974. HandleToUlong(hkl) & 0xffff,
  975. LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
  976. (LPWSTR)&dwCodePage,
  977. sizeof(dwCodePage) / sizeof(WCHAR)
  978. )) {
  979. return 0;
  980. }
  981. uCachedCP = dwCodePage;
  982. hCachedHKL = hkl;
  983. }
  984. if (!WideCharToMultiByte(
  985. uCachedCP,
  986. 0,
  987. UnicodeChar,
  988. cch,
  989. (LPSTR)lpChar,
  990. sizeof(*lpChar),
  991. NULL,
  992. &fUsedDefaultChar)) {
  993. return 0;
  994. }
  995. }
  996. return (retval < 0) ? -cch : cch;
  997. }
  998. /**************************************************************************\
  999. * ScrollDC *
  1000. * DrawIcon *
  1001. * ExcludeUpdateRgn *
  1002. * ValidateRgn *
  1003. * DrawFocusRect *
  1004. * FrameRect *
  1005. * ReleaseDC *
  1006. * GetUpdateRgn *
  1007. * *
  1008. * These USER entry points all need handles translated before the call is *
  1009. * passed to the server side handler. *
  1010. * *
  1011. * History: *
  1012. * Mon 17-Jun-1991 22:51:45 -by- Charles Whitmer [chuckwh] *
  1013. * Wrote the stubs. The final form of these routines depends strongly on *
  1014. * what direction the user stubs take in general. *
  1015. \**************************************************************************/
  1016. BOOL WINAPI ScrollDC(
  1017. HDC hDC,
  1018. int dx,
  1019. int dy,
  1020. CONST RECT *lprcScroll,
  1021. CONST RECT *lprcClip,
  1022. HRGN hrgnUpdate,
  1023. LPRECT lprcUpdate)
  1024. {
  1025. if (hDC == NULL)
  1026. return FALSE;
  1027. /*
  1028. * If we're not scrolling, just empty the update region and return.
  1029. */
  1030. if (dx == 0 && dy == 0) {
  1031. if (hrgnUpdate)
  1032. SetRectRgn(hrgnUpdate, 0, 0, 0, 0);
  1033. if (lprcUpdate)
  1034. SetRectEmpty(lprcUpdate);
  1035. return TRUE;
  1036. }
  1037. return NtUserScrollDC(hDC, dx, dy, lprcScroll, lprcClip,
  1038. hrgnUpdate, lprcUpdate);
  1039. }
  1040. FUNCLOG4(LOG_GENERAL, BOOL, WINAPI, DrawIcon, HDC, hdc, int, x, int, y, HICON, hicon)
  1041. BOOL WINAPI DrawIcon(HDC hdc,int x,int y,HICON hicon)
  1042. {
  1043. return DrawIconEx(hdc, x, y, hicon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );
  1044. }
  1045. FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawIconEx, HDC, hdc, int, x, int, y, HICON, hIcon, int, cx, int, cy, UINT, istepIfAniCur, HBRUSH, hbrFlickerFreeDraw, UINT, diFlags)
  1046. BOOL DrawIconEx( HDC hdc, int x, int y, HICON hIcon,
  1047. int cx, int cy, UINT istepIfAniCur,
  1048. HBRUSH hbrFlickerFreeDraw, UINT diFlags)
  1049. {
  1050. DRAWICONEXDATA did;
  1051. HBITMAP hbmT;
  1052. BOOL retval = FALSE;
  1053. HDC hdcr;
  1054. BOOL fAlpha = FALSE;
  1055. LONG rop = (diFlags & DI_NOMIRROR) ? NOMIRRORBITMAP : 0;
  1056. if (diFlags & ~DI_VALID) {
  1057. RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
  1058. return(FALSE);
  1059. }
  1060. if (diFlags & DI_DEFAULTSIZE) {
  1061. cx = 0;
  1062. cy = 0;
  1063. }
  1064. if (!IsMetaFile(hdc)) {
  1065. hdcr = GdiConvertAndCheckDC(hdc);
  1066. if (hdcr == (HDC)0)
  1067. return FALSE;
  1068. return NtUserDrawIconEx(hdcr, x, y, hIcon, cx, cy, istepIfAniCur,
  1069. hbrFlickerFreeDraw, diFlags, FALSE, &did);
  1070. }
  1071. if (!NtUserDrawIconEx(NULL, 0, 0, hIcon, cx, cy, 0, NULL, 0, TRUE, &did)) {
  1072. return FALSE;
  1073. }
  1074. if ((diFlags & ~DI_NOMIRROR) == 0)
  1075. return TRUE;
  1076. RtlEnterCriticalSection(&gcsHdc);
  1077. /*
  1078. * We really want to draw an alpha icon if we can. But we need to
  1079. * respect the user's request to draw only the image or only the
  1080. * mask. We decide if we are, or are not, going to draw the icon
  1081. * with alpha information here.
  1082. */
  1083. if (did.hbmUserAlpha != NULL && ((diFlags & DI_NORMAL) == DI_NORMAL)) {
  1084. fAlpha = TRUE;
  1085. }
  1086. RIPMSG5(RIP_WARNING, "Drawing to metafile! fAlpha=%d, did.cx=%d, did.cy=%d, cx=%d, cy=%d", fAlpha, did.cx, did.cy, cx, cy);
  1087. /*
  1088. * Setup the attributes
  1089. */
  1090. if (!cx)
  1091. cx = did.cx;
  1092. if (!cy)
  1093. cy = did.cy / 2;
  1094. SetTextColor(hdc, 0x00000000L);
  1095. SetBkColor(hdc, 0x00FFFFFFL);
  1096. if (fAlpha) {
  1097. BLENDFUNCTION bf;
  1098. hbmT = SelectObject(ghdcBits2, did.hbmUserAlpha);
  1099. bf.BlendOp = AC_SRC_OVER;
  1100. bf.BlendFlags = AC_MIRRORBITMAP;
  1101. bf.SourceConstantAlpha = 0xFF;
  1102. bf.AlphaFormat = AC_SRC_ALPHA;
  1103. AlphaBlend(hdc,
  1104. x,
  1105. y,
  1106. cx,
  1107. cy,
  1108. ghdcBits2,
  1109. 0,
  1110. 0,
  1111. did.cx,
  1112. did.cy / 2,
  1113. bf);
  1114. SelectObject(ghdcBits2,hbmT);
  1115. retval = TRUE;
  1116. } else {
  1117. if (diFlags & DI_MASK) {
  1118. if (did.hbmMask) {
  1119. hbmT = SelectObject(ghdcBits2, did.hbmMask);
  1120. StretchBlt(hdc,
  1121. x,
  1122. y,
  1123. cx,
  1124. cy,
  1125. ghdcBits2,
  1126. 0,
  1127. 0,
  1128. did.cx,
  1129. did.cy / 2,
  1130. rop | SRCAND);
  1131. SelectObject(ghdcBits2,hbmT);
  1132. retval = TRUE;
  1133. }
  1134. }
  1135. if (diFlags & DI_IMAGE) {
  1136. if (did.hbmColor != NULL) {
  1137. hbmT = SelectObject(ghdcBits2, did.hbmColor);
  1138. StretchBlt(hdc,
  1139. x,
  1140. y,
  1141. cx,
  1142. cy,
  1143. ghdcBits2,
  1144. 0,
  1145. 0,
  1146. did.cx,
  1147. did.cy / 2,
  1148. rop | SRCINVERT);
  1149. SelectObject(ghdcBits2, hbmT);
  1150. retval = TRUE;
  1151. } else {
  1152. if (did.hbmMask) {
  1153. hbmT = SelectObject(ghdcBits2, did.hbmMask);
  1154. StretchBlt(hdc,
  1155. x,
  1156. y,
  1157. cx,
  1158. cy,
  1159. ghdcBits2,
  1160. 0,
  1161. did.cy / 2,
  1162. did.cx,
  1163. did.cy / 2,
  1164. rop | SRCINVERT);
  1165. SelectObject(ghdcBits2, hbmT);
  1166. retval = TRUE;
  1167. }
  1168. }
  1169. }
  1170. }
  1171. RtlLeaveCriticalSection(&gcsHdc);
  1172. return retval;
  1173. }
  1174. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, ValidateRgn, HWND, hWnd, HRGN, hRgn)
  1175. BOOL WINAPI ValidateRgn(HWND hWnd,HRGN hRgn)
  1176. {
  1177. return (BOOL)NtUserCallHwndParamLock(hWnd, (ULONG_PTR)hRgn,
  1178. SFI_XXXVALIDATERGN);
  1179. }
  1180. FUNCLOG3(LOG_GENERAL, int, WINAPI, GetUpdateRgn, HWND, hWnd, HRGN, hRgn, BOOL, bErase)
  1181. int WINAPI GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
  1182. {
  1183. PWND pwnd;
  1184. if (hRgn == NULL) {
  1185. RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid region %#p", hRgn);
  1186. return ERROR;
  1187. }
  1188. if ((pwnd = ValidateHwnd(hWnd)) == NULL) {
  1189. return ERROR;
  1190. }
  1191. /*
  1192. * Check for the simple case where nothing needs to be done.
  1193. */
  1194. if (pwnd->hrgnUpdate == NULL &&
  1195. !TestWF(pwnd, WFSENDERASEBKGND) &&
  1196. !TestWF(pwnd, WFSENDNCPAINT) &&
  1197. !TestWF(pwnd, WFUPDATEDIRTY) &&
  1198. !TestWF(pwnd, WFPAINTNOTPROCESSED)) {
  1199. SetRectRgn(hRgn, 0, 0, 0, 0);
  1200. return NULLREGION;
  1201. }
  1202. return NtUserGetUpdateRgn(hWnd, hRgn, bErase);
  1203. }
  1204. FUNCLOG3(LOG_GENERAL, int, WINAPI, GetUpdateRect, HWND, hWnd, LPRECT, lprc, BOOL, bErase)
  1205. int WINAPI GetUpdateRect(HWND hWnd, LPRECT lprc, BOOL bErase)
  1206. {
  1207. PWND pwnd;
  1208. if ((pwnd = ValidateHwnd(hWnd)) == NULL) {
  1209. return FALSE;
  1210. }
  1211. /*
  1212. * Check for the simple case where nothing needs to be done.
  1213. */
  1214. if (pwnd->hrgnUpdate == NULL &&
  1215. !TestWF(pwnd, WFSENDERASEBKGND) &&
  1216. !TestWF(pwnd, WFSENDNCPAINT) &&
  1217. !TestWF(pwnd, WFUPDATEDIRTY) &&
  1218. !TestWF(pwnd, WFPAINTNOTPROCESSED)) {
  1219. if (lprc)
  1220. SetRectEmpty(lprc);
  1221. return FALSE;
  1222. }
  1223. return NtUserGetUpdateRect(hWnd, lprc, bErase);
  1224. }
  1225. /***************************************************************************\
  1226. * ScrollWindow (API)
  1227. *
  1228. *
  1229. * History:
  1230. * 18-Jul-1991 DarrinM Ported from Win 3.1 sources.
  1231. \***************************************************************************/
  1232. #define SW_FLAG_RC (SW_SCROLLWINDOW | SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN)
  1233. #define SW_FLAG_NRC (SW_SCROLLWINDOW | SW_INVALIDATE | SW_ERASE)
  1234. BOOL WINAPI
  1235. ScrollWindow(
  1236. HWND hwnd,
  1237. int dx,
  1238. int dy,
  1239. CONST RECT *prcScroll,
  1240. CONST RECT *prcClip)
  1241. {
  1242. return NtUserScrollWindowEx(
  1243. hwnd,
  1244. dx,
  1245. dy,
  1246. prcScroll,
  1247. prcClip,
  1248. NULL,
  1249. NULL,
  1250. !IS_PTR(prcScroll) ? SW_FLAG_RC : SW_FLAG_NRC) != ERROR;
  1251. }
  1252. /***************************************************************************\
  1253. * SwitchToThisWindow
  1254. \***************************************************************************/
  1255. FUNCLOGVOID2(LOG_GENERAL, WINAPI, SwitchToThisWindow, HWND, hwnd, BOOL, fAltTab)
  1256. VOID WINAPI SwitchToThisWindow(
  1257. HWND hwnd,
  1258. BOOL fAltTab)
  1259. {
  1260. (VOID)NtUserCallHwndParamLock(hwnd, fAltTab, SFI_XXXSWITCHTOTHISWINDOW);
  1261. }
  1262. /***************************************************************************\
  1263. * WaitForInputIdle
  1264. *
  1265. * Waits for a given process to go idle.
  1266. *
  1267. * 09-18-91 ScottLu Created.
  1268. \***************************************************************************/
  1269. FUNCLOG2(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, WaitForInputIdle, HANDLE, hProcess, DWORD, dwMilliseconds)
  1270. DWORD WaitForInputIdle(
  1271. HANDLE hProcess,
  1272. DWORD dwMilliseconds)
  1273. {
  1274. PROCESS_BASIC_INFORMATION processinfo;
  1275. ULONG_PTR idProcess;
  1276. NTSTATUS Status;
  1277. /*
  1278. * First get the process id from the hProcess.
  1279. */
  1280. Status = NtQueryInformationProcess(hProcess,
  1281. ProcessBasicInformation,
  1282. &processinfo, sizeof(processinfo),
  1283. NULL);
  1284. if (!NT_SUCCESS(Status)) {
  1285. if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
  1286. if ((ULONG_PTR)hProcess & 0x2) {
  1287. /*
  1288. * WOW Process handles are really semaphore handles.
  1289. * CreateProcess ORs in a 0x2 (the low 2 bits of handles
  1290. * are not used) so we can identify it more clearly.
  1291. */
  1292. idProcess = ((ULONG_PTR)hProcess & ~0x03);
  1293. return NtUserWaitForInputIdle(idProcess, dwMilliseconds, TRUE);
  1294. }
  1295. /*
  1296. * VDM (DOS) Process handles are really semaphore handles.
  1297. * CreateProcess ORs in a 0x1 (the low 2 bits of handles
  1298. * are not used) so we can identify and return immidiately.
  1299. */
  1300. if ((ULONG_PTR)hProcess & 0x1) {
  1301. return 0;
  1302. }
  1303. }
  1304. RIPERR1(ERROR_INVALID_HANDLE,
  1305. RIP_WARNING,
  1306. "WaitForInputIdle invalid process 0x%p",
  1307. hProcess);
  1308. return WAIT_FAILED;
  1309. }
  1310. idProcess = processinfo.UniqueProcessId;
  1311. return NtUserWaitForInputIdle(idProcess, dwMilliseconds, FALSE);
  1312. }
  1313. DWORD WINAPI MsgWaitForMultipleObjects(
  1314. DWORD nCount,
  1315. CONST HANDLE *pHandles,
  1316. BOOL fWaitAll,
  1317. DWORD dwMilliseconds,
  1318. DWORD dwWakeMask)
  1319. {
  1320. return MsgWaitForMultipleObjectsEx(nCount, pHandles,
  1321. dwMilliseconds, dwWakeMask, fWaitAll?MWMO_WAITALL:0);
  1322. }
  1323. DWORD WINAPI MsgWaitForMultipleObjectsEx(
  1324. DWORD nCount,
  1325. CONST HANDLE *pHandles,
  1326. DWORD dwMilliseconds,
  1327. DWORD dwWakeMask,
  1328. DWORD dwFlags)
  1329. #ifdef MESSAGE_PUMP_HOOK
  1330. {
  1331. DWORD dwResult;
  1332. BEGIN_MESSAGEPUMPHOOK()
  1333. if (fInsideHook) {
  1334. dwResult = gmph.pfnMsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags);
  1335. } else {
  1336. dwResult = RealMsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags);
  1337. }
  1338. END_MESSAGEPUMPHOOK()
  1339. return dwResult;
  1340. }
  1341. DWORD WINAPI RealMsgWaitForMultipleObjectsEx(
  1342. DWORD nCount,
  1343. CONST HANDLE *pHandles,
  1344. DWORD dwMilliseconds,
  1345. DWORD dwWakeMask,
  1346. DWORD dwFlags)
  1347. #endif
  1348. {
  1349. HANDLE hEventInput;
  1350. PHANDLE ph;
  1351. DWORD dwIndex;
  1352. BOOL ReenterWowScheduler;
  1353. PCLIENTINFO pci;
  1354. HANDLE rgHandles[ 8 + 1 ];
  1355. BOOL fWaitAll = ((dwFlags & MWMO_WAITALL) != 0);
  1356. BOOL fAlertable = ((dwFlags & MWMO_ALERTABLE) != 0);
  1357. CLIENTTHREADINFO *pcti;
  1358. if (dwFlags & ~MWMO_VALID) {
  1359. RIPERR1(ERROR_INVALID_PARAMETER,
  1360. RIP_WARNING,
  1361. "MsgWaitForMultipleObjectsEx, invalid flags 0x%x", dwFlags);
  1362. return WAIT_FAILED;
  1363. }
  1364. pci = GetClientInfo();
  1365. pcti = GETCLIENTTHREADINFO();
  1366. if (pcti && (!fWaitAll || !nCount)) {
  1367. if (GetInputBits(pcti, LOWORD(dwWakeMask), (dwFlags & MWMO_INPUTAVAILABLE))) {
  1368. return nCount;
  1369. }
  1370. }
  1371. /*
  1372. * Note -- the wake mask is a WORD, and only 3 flags are defined, so
  1373. * they can be combined for the call.
  1374. */
  1375. hEventInput = (HANDLE)NtUserCallOneParam(MAKELONG(dwWakeMask, dwFlags), SFI_XXXGETINPUTEVENT);
  1376. if (hEventInput == NULL) {
  1377. RIPMSG0(RIP_WARNING, "MsgWaitForMultipleObjectsEx, GetInputEvent failed");
  1378. return WAIT_FAILED;
  1379. }
  1380. /*
  1381. * If needed, allocate a new array of handles that will include the
  1382. * input event handle.
  1383. */
  1384. ph = rgHandles;
  1385. if (pHandles) {
  1386. if (nCount > 8) {
  1387. ph = (PHANDLE)UserLocalAlloc(HEAP_ZERO_MEMORY,
  1388. sizeof(HANDLE) * (nCount + 1));
  1389. if (ph == NULL) {
  1390. NtUserCallNoParam(SFI_CLEARWAKEMASK);
  1391. return WAIT_FAILED;
  1392. }
  1393. }
  1394. RtlCopyMemory((PVOID)ph, pHandles, sizeof(HANDLE) * nCount);
  1395. } else {
  1396. /*
  1397. * If this isn't zero, the function parameters are invalid.
  1398. */
  1399. nCount = 0;
  1400. }
  1401. ph[nCount] = hEventInput;
  1402. /*
  1403. * WowApps must exit the Wow scheduler otherwise other tasks in this
  1404. * Wow scheduler can't run. The only exception is if the timeout is
  1405. * Zero. We pass HEVENT_REMOVEME as the handle so we will go into the
  1406. * sleeptask AND return without going to sleep but letting other apps
  1407. * run.
  1408. */
  1409. if ((pci->dwTIFlags & TIF_16BIT) && dwMilliseconds) {
  1410. ReenterWowScheduler = TRUE;
  1411. NtUserWaitForMsgAndEvent(HEVENT_REMOVEME);
  1412. /*
  1413. * If our wait condition is satisfied, make sure we won't wait.
  1414. * We must have a pcti now since we just went to the kernel.
  1415. */
  1416. pcti = GETCLIENTTHREADINFO();
  1417. if (GetInputBits(pcti, LOWORD(dwWakeMask), (dwFlags & MWMO_INPUTAVAILABLE))) {
  1418. SetEvent(hEventInput);
  1419. }
  1420. } else {
  1421. ReenterWowScheduler = FALSE;
  1422. }
  1423. dwIndex = WaitForMultipleObjectsEx(nCount + 1, ph, fWaitAll, dwMilliseconds, fAlertable);
  1424. /*
  1425. * Clear the wake mask since we're done waiting on these events.
  1426. */
  1427. NtUserCallNoParam(SFI_CLEARWAKEMASK);
  1428. /*
  1429. * If needed reenter the wow scheduler.
  1430. */
  1431. if (ReenterWowScheduler) {
  1432. NtUserCallOneParam(DY_OLDYIELD, SFI_XXXDIRECTEDYIELD);
  1433. }
  1434. if (ph != rgHandles) {
  1435. UserLocalFree(ph);
  1436. }
  1437. return dwIndex;
  1438. }
  1439. /***************************************************************************\
  1440. * GrayString
  1441. *
  1442. * GrayStingA used to convert the string and call GrayStringW but that
  1443. * did not work in a number of special cases such as the app passing in
  1444. * a pointer to a zero length string. Eventually GrayStringA had almost as
  1445. * much code as GrayStringW so now they are one.
  1446. *
  1447. * History:
  1448. * 06-11-91 JimA Created.
  1449. * 06-17-91 ChuckWh Added GDI handle conversion.
  1450. * 02-12-92 mikeke Made it completely client side
  1451. \***************************************************************************/
  1452. BOOL InnerGrayStringAorW(
  1453. HDC hdc,
  1454. HBRUSH hbr,
  1455. GRAYSTRINGPROC lpfnPrint,
  1456. LPARAM lParam,
  1457. int cch,
  1458. int x,
  1459. int y,
  1460. int cx,
  1461. int cy,
  1462. BOOL bAnsi)
  1463. {
  1464. HBITMAP hbm;
  1465. HBITMAP hbmOld;
  1466. BOOL fResult;
  1467. HFONT hFontSave = NULL;
  1468. BOOL fReturn = FALSE;
  1469. DWORD dwOldLayout = GDI_ERROR;
  1470. /*
  1471. * Win 3.1 tries to calc the size even if we don't know if it is a string.
  1472. */
  1473. if (cch == 0) {
  1474. try {
  1475. cch = bAnsi ? strlen((LPSTR)lParam) : wcslen((LPWSTR)lParam);
  1476. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  1477. fReturn = TRUE;
  1478. }
  1479. if (fReturn)
  1480. return FALSE;
  1481. }
  1482. if (cx == 0 || cy == 0) {
  1483. SIZE size;
  1484. /*
  1485. * We use the caller supplied hdc (instead of hdcBits) since we may be
  1486. * graying a font which is different than the system font and we want to
  1487. * get the proper text extents.
  1488. */
  1489. try {
  1490. if (bAnsi) {
  1491. GetTextExtentPointA(hdc, (LPSTR)lParam, cch, &size);
  1492. } else {
  1493. GetTextExtentPointW(hdc, (LPWSTR)lParam, cch, &size);
  1494. }
  1495. cx = size.cx;
  1496. cy = size.cy;
  1497. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  1498. fReturn = TRUE;
  1499. }
  1500. if (fReturn)
  1501. return FALSE;
  1502. }
  1503. UserAssert (ghdcGray != NULL);
  1504. RtlEnterCriticalSection(&gcsHdc);
  1505. if (gcxGray < cx || gcyGray < cy) {
  1506. if ((hbm = CreateBitmap(cx, cy, 1, 1, 0L)) != NULL) {
  1507. hbmOld = SelectObject(ghdcGray, hbm);
  1508. DeleteObject(hbmOld);
  1509. gcxGray = cx;
  1510. gcyGray = cy;
  1511. } else {
  1512. cx = gcxGray;
  1513. cy = gcyGray;
  1514. }
  1515. }
  1516. /*
  1517. * If the caller hdc is mirrored then mirror ghdcGray.
  1518. */
  1519. if (MIRRORED_HDC(hdc)) {
  1520. dwOldLayout = SetLayoutWidth(ghdcGray, cx, LAYOUT_RTL);
  1521. }
  1522. /*
  1523. * Force the ghdcGray font to be the same as hDC; ghdcGray is always
  1524. * the system font
  1525. */
  1526. hFontSave = SelectObject(hdc, ghFontSys);
  1527. if (hFontSave != ghFontSys) {
  1528. SelectObject(hdc, hFontSave);
  1529. hFontSave = SelectObject(ghdcGray, hFontSave);
  1530. }
  1531. if (lpfnPrint != NULL) {
  1532. PatBlt(ghdcGray, 0, 0, cx, cy, WHITENESS);
  1533. fResult = (*lpfnPrint)(ghdcGray, lParam, cch);
  1534. } else {
  1535. if (bAnsi) {
  1536. fResult = TextOutA(ghdcGray, 0, 0, (LPSTR)lParam, cch);
  1537. } else {
  1538. fResult = TextOutW(ghdcGray, 0, 0, (LPWSTR)lParam, cch);
  1539. }
  1540. }
  1541. if (fResult)
  1542. PatBlt(ghdcGray, 0, 0, cx, cy, DESTINATION | PATTERN);
  1543. if (fResult || cch == -1) {
  1544. HBRUSH hbrSave;
  1545. DWORD textColorSave;
  1546. DWORD bkColorSave;
  1547. textColorSave = SetTextColor(hdc, 0x00000000L);
  1548. bkColorSave = SetBkColor(hdc, 0x00FFFFFFL);
  1549. hbrSave = SelectObject(hdc, hbr ? hbr : ghbrWindowText);
  1550. BitBlt(hdc,
  1551. x,
  1552. y,
  1553. cx,
  1554. cy,
  1555. ghdcGray,
  1556. 0,
  1557. 0,
  1558. (((PATTERN ^ DESTINATION) & SOURCE) ^ PATTERN));
  1559. SelectObject(hdc, hbrSave);
  1560. /*
  1561. * Restore saved colors
  1562. */
  1563. SetTextColor(hdc, textColorSave);
  1564. SetBkColor(hdc, bkColorSave);
  1565. }
  1566. SelectObject(ghdcGray, hFontSave);
  1567. /*
  1568. * Restore ghdcGray layout state.
  1569. */
  1570. if (dwOldLayout != GDI_ERROR) {
  1571. SetLayoutWidth(ghdcGray, cx, dwOldLayout);
  1572. }
  1573. RtlLeaveCriticalSection(&gcsHdc);
  1574. return fResult;
  1575. }
  1576. FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GrayStringA, HDC, hdc, HBRUSH, hbr, GRAYSTRINGPROC, lpfnPrint, LPARAM, lParam, int, cch, int, x, int, y, int, cx, int, cy)
  1577. BOOL GrayStringA(
  1578. HDC hdc,
  1579. HBRUSH hbr,
  1580. GRAYSTRINGPROC lpfnPrint,
  1581. LPARAM lParam,
  1582. int cch,
  1583. int x,
  1584. int y,
  1585. int cx,
  1586. int cy)
  1587. {
  1588. return (InnerGrayStringAorW(hdc,
  1589. hbr,
  1590. lpfnPrint,
  1591. lParam,
  1592. cch,
  1593. x,
  1594. y,
  1595. cx,
  1596. cy,
  1597. TRUE));
  1598. }
  1599. FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GrayStringW, HDC, hdc, HBRUSH, hbr, GRAYSTRINGPROC, lpfnPrint, LPARAM, lParam, int, cch, int, x, int, y, int, cx, int, cy)
  1600. BOOL GrayStringW(
  1601. HDC hdc,
  1602. HBRUSH hbr,
  1603. GRAYSTRINGPROC lpfnPrint,
  1604. LPARAM lParam,
  1605. int cch,
  1606. int x,
  1607. int y,
  1608. int cx,
  1609. int cy)
  1610. {
  1611. return (InnerGrayStringAorW(hdc,
  1612. hbr,
  1613. lpfnPrint,
  1614. lParam,
  1615. cch,
  1616. x,
  1617. y,
  1618. cx,
  1619. cy,
  1620. FALSE));
  1621. }
  1622. /***************************************************************************\
  1623. * GetUserObjectSecurity (API)
  1624. *
  1625. * Gets the security descriptor of an object
  1626. *
  1627. * History:
  1628. * 07-01-91 JimA Created.
  1629. \***************************************************************************/
  1630. FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetUserObjectSecurity, HANDLE, hObject, PSECURITY_INFORMATION, pRequestedInformation, PSECURITY_DESCRIPTOR, pSecurityDescriptor, DWORD, nLength, LPDWORD, lpnLengthRequired)
  1631. BOOL GetUserObjectSecurity(
  1632. HANDLE hObject,
  1633. PSECURITY_INFORMATION pRequestedInformation,
  1634. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1635. DWORD nLength,
  1636. LPDWORD lpnLengthRequired)
  1637. {
  1638. NTSTATUS Status;
  1639. Status = NtQuerySecurityObject(hObject,
  1640. *pRequestedInformation,
  1641. pSecurityDescriptor,
  1642. nLength,
  1643. lpnLengthRequired);
  1644. if (!NT_SUCCESS(Status)) {
  1645. RIPNTERR0(Status, RIP_VERBOSE, "");
  1646. return FALSE;
  1647. }
  1648. return TRUE;
  1649. }
  1650. /***************************************************************************\
  1651. * SetUserObjectSecurity (API)
  1652. *
  1653. * Sets the security descriptor of an object
  1654. *
  1655. * History:
  1656. * 07-01-91 JimA Created.
  1657. \***************************************************************************/
  1658. FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetUserObjectSecurity, HANDLE, hObject, PSECURITY_INFORMATION, pRequestedInformation, PSECURITY_DESCRIPTOR, pSecurityDescriptor)
  1659. BOOL SetUserObjectSecurity(
  1660. HANDLE hObject,
  1661. PSECURITY_INFORMATION pRequestedInformation,
  1662. PSECURITY_DESCRIPTOR pSecurityDescriptor)
  1663. {
  1664. NTSTATUS Status;
  1665. Status = NtSetSecurityObject(hObject,
  1666. *pRequestedInformation,
  1667. pSecurityDescriptor);
  1668. if (!NT_SUCCESS(Status)) {
  1669. RIPNTERR0(Status, RIP_VERBOSE, "");
  1670. return FALSE;
  1671. }
  1672. return TRUE;
  1673. }
  1674. /***************************************************************************\
  1675. * GetUserObjectInformation (API)
  1676. *
  1677. * Gets information about an object
  1678. *
  1679. * History:
  1680. \***************************************************************************/
  1681. FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetUserObjectInformationA, HANDLE, hObject, int, nIndex, PVOID, pvInfo, DWORD, nLength, LPDWORD, pnLengthNeeded)
  1682. BOOL GetUserObjectInformationA(
  1683. HANDLE hObject,
  1684. int nIndex,
  1685. PVOID pvInfo,
  1686. DWORD nLength,
  1687. LPDWORD pnLengthNeeded)
  1688. {
  1689. PVOID pvInfoW;
  1690. DWORD nLengthW;
  1691. BOOL fSuccess;
  1692. if (nIndex == UOI_NAME || nIndex == UOI_TYPE) {
  1693. nLengthW = nLength * sizeof(WCHAR);
  1694. pvInfoW = UserLocalAlloc(HEAP_ZERO_MEMORY, nLengthW);
  1695. fSuccess = NtUserGetObjectInformation(hObject,
  1696. nIndex,
  1697. pvInfoW,
  1698. nLengthW,
  1699. pnLengthNeeded);
  1700. if (fSuccess) {
  1701. if (pnLengthNeeded != NULL) {
  1702. *pnLengthNeeded /= sizeof(WCHAR);
  1703. }
  1704. WCSToMB(pvInfoW, -1, &(PCHAR)pvInfo, nLength, FALSE);
  1705. }
  1706. UserLocalFree(pvInfoW);
  1707. return fSuccess;
  1708. } else {
  1709. return NtUserGetObjectInformation(hObject,
  1710. nIndex,
  1711. pvInfo,
  1712. nLength,
  1713. pnLengthNeeded);
  1714. }
  1715. }
  1716. BOOL GetWinStationInfo(
  1717. WSINFO* pWsInfo)
  1718. {
  1719. return (BOOL)NtUserCallOneParam((ULONG_PTR)pWsInfo, SFI__GETWINSTATIONINFO);
  1720. }
  1721. /***************************************************************************\
  1722. * GetServerIMEKeyboardLayout
  1723. *
  1724. * This routine finds HKL matches the IME module name sent from the Hydra
  1725. * client at its session startup.
  1726. * Hydra server tries to load the same IME module in the client, rather
  1727. * than to use the same HKL: that's because, on FE machines,
  1728. * the same IME might have different HKL dependent to each system.
  1729. *
  1730. * If the same IME name is found in registry, then it returns the HKL.
  1731. * If it cannot find, return value is 0.
  1732. *
  1733. * History:
  1734. \***************************************************************************/
  1735. ULONG GetServerIMEKeyboardLayout(
  1736. LPTSTR pszImeFileName)
  1737. {
  1738. BOOL fFound = FALSE;
  1739. ULONG wLayoutId;
  1740. UNICODE_STRING UnicodeStringKLKey;
  1741. UNICODE_STRING UnicodeStringSubKLKey;
  1742. UNICODE_STRING UnicodeStringIME;
  1743. OBJECT_ATTRIBUTES OA;
  1744. HANDLE hKey;
  1745. ULONG Index;
  1746. WCHAR awchKLRegKey[NSZKLKEY];
  1747. LPWSTR lpszKLRegKey = awchKLRegKey;
  1748. NTSTATUS Status;
  1749. RtlInitUnicodeString(&UnicodeStringKLKey, szKLKey);
  1750. InitializeObjectAttributes(&OA, &UnicodeStringKLKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
  1751. if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) {
  1752. for (Index = 0; TRUE; Index++) {
  1753. BYTE KeyBuffer[sizeof(KEY_BASIC_INFORMATION) + KL_NAMELENGTH * sizeof(WCHAR)];
  1754. PKEY_BASIC_INFORMATION pKeyInfo;
  1755. ULONG ResultLength;
  1756. pKeyInfo = (PKEY_BASIC_INFORMATION)KeyBuffer;
  1757. Status = NtEnumerateKey(hKey,
  1758. Index,
  1759. KeyBasicInformation,
  1760. pKeyInfo,
  1761. sizeof(KeyBuffer),
  1762. &ResultLength);
  1763. if (NT_SUCCESS(Status)) {
  1764. UnicodeStringSubKLKey.Buffer = (PWSTR)&(pKeyInfo->Name[0]);
  1765. UnicodeStringSubKLKey.Length = (USHORT)pKeyInfo->NameLength;
  1766. UnicodeStringSubKLKey.MaximumLength = (USHORT)pKeyInfo->NameLength;
  1767. RtlUnicodeStringToInteger(&UnicodeStringSubKLKey, 16, &wLayoutId);
  1768. if (IS_IME_KBDLAYOUT(wLayoutId)) {
  1769. HANDLE hSubKey;
  1770. wcscpy(lpszKLRegKey, szKLKey);
  1771. wcsncat(lpszKLRegKey, UnicodeStringSubKLKey.Buffer,
  1772. UnicodeStringSubKLKey.Length / sizeof(WCHAR));
  1773. RtlInitUnicodeString(&UnicodeStringKLKey, lpszKLRegKey);
  1774. InitializeObjectAttributes(&OA, &UnicodeStringKLKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
  1775. if (NT_SUCCESS(NtOpenKey(&hSubKey, KEY_READ, &OA))) {
  1776. /*
  1777. * GetIME file name from "HKLM\...\<Index>\IME File"
  1778. */
  1779. static CONST WCHAR szIMEfile[] = L"IME file";
  1780. struct {
  1781. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  1782. WCHAR awchImeName[CCH_KL_LIBNAME];
  1783. } IMEfile;
  1784. LPWSTR pwszIME;
  1785. DWORD cbSize;
  1786. RtlInitUnicodeString(&UnicodeStringIME, szIMEfile);
  1787. Status = NtQueryValueKey(hSubKey,
  1788. &UnicodeStringIME,
  1789. KeyValuePartialInformation,
  1790. &IMEfile,
  1791. sizeof IMEfile,
  1792. &cbSize);
  1793. NtClose(hSubKey);
  1794. if (NT_SUCCESS(Status)) {
  1795. pwszIME = (LPWSTR)IMEfile.KeyInfo.Data;
  1796. pwszIME[CCH_KL_LIBNAME - 1] = L'\0';
  1797. if (!lstrcmpi(pwszIME, pszImeFileName)) {
  1798. /*
  1799. * IME file name match !!
  1800. */
  1801. fFound = TRUE;
  1802. break;
  1803. }
  1804. }
  1805. }
  1806. }
  1807. }
  1808. else {
  1809. break;
  1810. }
  1811. }
  1812. NtClose(hKey);
  1813. }
  1814. if (fFound)
  1815. return wLayoutId;
  1816. return 0;
  1817. }
  1818. /***************************************************************************\
  1819. * GetRemoteKeyboardLayout
  1820. *
  1821. * Returns TRUE if the client winstation specified a keyboard layout.
  1822. * If TRUE, the LayoutBuf contains the name of the keyboard layout.
  1823. * History:
  1824. \***************************************************************************/
  1825. extern ULONG GetRemoteKeyboardLayoutFromConfigData(VOID);
  1826. extern BOOL GetRemoteInputLanguage(LANGID*, PWCHAR);
  1827. BOOL
  1828. GetRemoteKeyboardLayout(
  1829. PWCHAR pwszKLName,
  1830. LANGID* pLangId)
  1831. {
  1832. ULONG KeyboardLayout;
  1833. BOOL fLangDataOK;
  1834. WCHAR wszImeFileName[FIELD_SIZE(WINSTATIONCLIENTW, imeFileName) / sizeof(WCHAR)];
  1835. /*
  1836. * Skip if this is the main session
  1837. */
  1838. if (!ISREMOTESESSION()) {
  1839. return FALSE;
  1840. }
  1841. KeyboardLayout = GetRemoteKeyboardLayoutFromConfigData();
  1842. fLangDataOK = GetRemoteInputLanguage(pLangId, wszImeFileName);
  1843. if (IS_IME_ENABLED()) {
  1844. if (!fLangDataOK) {
  1845. /*
  1846. * To preserve the W2k/XP behavior,
  1847. * if ClientData was not retrieved
  1848. * and if the machine is IME enabled,
  1849. * bail out here.
  1850. */
  1851. return FALSE;
  1852. }
  1853. if (IS_IME_KBDLAYOUT(KeyboardLayout)) {
  1854. KeyboardLayout = GetServerIMEKeyboardLayout(wszImeFileName);
  1855. }
  1856. }
  1857. if (KeyboardLayout != 0) {
  1858. wsprintfW(pwszKLName, L"%8.8lx", KeyboardLayout);
  1859. return TRUE;
  1860. }
  1861. return FALSE;
  1862. }
  1863. ULONG GetRemoteKeyboardLayoutFromConfigData(VOID)
  1864. {
  1865. WINSTATIONCONFIG ConfigData;
  1866. ULONG Length;
  1867. if (!ISREMOTESESSION()) {
  1868. RIPMSGF0(RIP_WARNING, "This is not a remote session!");
  1869. }
  1870. /*
  1871. * Fetch the WinStation's basic information
  1872. */
  1873. if (!WinStationQueryInformationW(SERVERNAME_CURRENT,
  1874. LOGONID_CURRENT,
  1875. WinStationConfiguration,
  1876. &ConfigData,
  1877. sizeof(ConfigData),
  1878. &Length)) {
  1879. RIPMSGF0(RIP_WARNING, "Failed to get remote client ConfigData.");
  1880. return 0;
  1881. }
  1882. RIPMSGF1(RIP_WARNING, "The keyboard layout is %08x", ConfigData.User.KeyboardLayout);
  1883. return ConfigData.User.KeyboardLayout;
  1884. }
  1885. BOOL GetRemoteInputLanguage(LANGID* pLangId,
  1886. PWCHAR pwszImeFileName)
  1887. {
  1888. WINSTATIONCLIENTW ClientData;
  1889. ULONG Length;
  1890. if (!ISREMOTESESSION()) {
  1891. RIPMSGF0(RIP_WARNING, "This is not a remote session!");
  1892. }
  1893. /*
  1894. * Fetch the more remote client information.
  1895. * N.b. this and above functions are departed from GetRemoteKeyboardLayout()
  1896. * to reduce the stack consumption.
  1897. */
  1898. if (!WinStationQueryInformationW(SERVERNAME_CURRENT,
  1899. LOGONID_CURRENT,
  1900. WinStationClient,
  1901. &ClientData,
  1902. sizeof(ClientData),
  1903. &Length)) {
  1904. RIPMSGF0(RIP_WARNING, "Failed to get the remote ClientData -> no info about the langid");
  1905. *pLangId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  1906. return FALSE;
  1907. }
  1908. *pLangId = LOWORD(ClientData.ActiveInputLocale);
  1909. TAGMSGF1(DBGTAG_KBD, "remote InputLocale is %08x", (DWORD)*pLangId);
  1910. RtlCopyMemory(pwszImeFileName, ClientData.imeFileName, sizeof ClientData.imeFileName);
  1911. return TRUE;
  1912. }
  1913. /***************************************************************************\
  1914. * CommonCreateWindowStation (API)
  1915. *
  1916. * Creates a windowstation object
  1917. *
  1918. * History:
  1919. \***************************************************************************/
  1920. HWINSTA CommonCreateWindowStation(
  1921. PUNICODE_STRING pstrName,
  1922. ACCESS_MASK amRequest,
  1923. DWORD dwFlags,
  1924. PSECURITY_ATTRIBUTES lpsa)
  1925. {
  1926. OBJECT_ATTRIBUTES Obja;
  1927. HANDLE hRootDirectory;
  1928. HWINSTA hwinstaNew = NULL;
  1929. WCHAR wszKLName[KL_NAMELENGTH];
  1930. HANDLE hKeyboardFile = NULL;
  1931. DWORD offTable;
  1932. UNICODE_STRING strKLID;
  1933. UINT uKbdInputLocale, uFlags;
  1934. NTSTATUS Status;
  1935. /*
  1936. * Load initial keyboard layout. Continue even if
  1937. * this fails (esp. important with KLF_INITTIME set)
  1938. */
  1939. ULONG KeyboardLayout = 0;
  1940. KBDTABLE_MULTI_INTERNAL kbdTableMulti;
  1941. extern BOOL CtxInitUser32(VOID);
  1942. TAGMSGF0(DBGTAG_KBD, "entering");
  1943. hKeyboardFile = NULL;
  1944. /*
  1945. * Get winstation info
  1946. */
  1947. if (ISREMOTESESSION()) {
  1948. LANGID langidKbd;
  1949. if (GetRemoteKeyboardLayout(wszKLName, &langidKbd)) { // will we make the short-cut version?
  1950. uFlags = KLF_ACTIVATE | KLF_INITTIME;
  1951. hKeyboardFile = OpenKeyboardLayoutFile(wszKLName, langidKbd,
  1952. &uFlags, &offTable, &uKbdInputLocale, &kbdTableMulti);
  1953. if (hKeyboardFile == NULL) {
  1954. RIPMSGF0(RIP_WARNING, "OpenKeyboardLayoutFile() failed for the remote layout, will use the fallback.");
  1955. }
  1956. }
  1957. }
  1958. if (hKeyboardFile == NULL) {
  1959. GetActiveKeyboardName(wszKLName);
  1960. retry:
  1961. uFlags = KLF_ACTIVATE | KLF_INITTIME;
  1962. hKeyboardFile = OpenKeyboardLayoutFile(wszKLName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  1963. &uFlags, &offTable, &uKbdInputLocale, &kbdTableMulti);
  1964. if (hKeyboardFile == NULL) {
  1965. if (wcscmp(wszKLName, L"00000409")) {
  1966. wcscpy(wszKLName, L"00000409");
  1967. RIPMSG0(RIP_WARNING, "OpendKeyboardLayoutFile() failed: will use the fallback keyboard layout.");
  1968. goto retry;
  1969. }
  1970. uKbdInputLocale = 0x04090409;
  1971. }
  1972. }
  1973. /*
  1974. * Finish the rest of the DLL initialization for WinStations.
  1975. * Until this point we had no video driver.
  1976. *
  1977. * clupu: We have to prevent this for NOIO windowstations !!!
  1978. */
  1979. if (ISTS()) {
  1980. if (!CtxInitUser32()) {
  1981. RIPMSG0(RIP_WARNING, "CtxInitUser32 failed");
  1982. goto Exit;
  1983. }
  1984. }
  1985. RtlInitUnicodeString(&strKLID, wszKLName);
  1986. /*
  1987. * If a name was specified, open the parent directory. Be sure
  1988. * to test the length rather than the buffer because for NULL
  1989. * string RtlCreateUnicodeStringFromAsciiz will allocate a
  1990. * buffer pointing to an empty string.
  1991. */
  1992. if (pstrName->Length != 0) {
  1993. InitializeObjectAttributes(&Obja,
  1994. (PUNICODE_STRING)&strRootDirectory,
  1995. OBJ_CASE_INSENSITIVE,
  1996. NULL, NULL);
  1997. Status = NtOpenDirectoryObject(&hRootDirectory,
  1998. DIRECTORY_CREATE_OBJECT, &Obja);
  1999. if (!NT_SUCCESS(Status)) {
  2000. RIPNTERR0(Status, RIP_VERBOSE, "");
  2001. goto Exit;
  2002. }
  2003. } else {
  2004. pstrName = NULL;
  2005. hRootDirectory = NULL;
  2006. }
  2007. InitializeObjectAttributes(&Obja,
  2008. pstrName,
  2009. OBJ_CASE_INSENSITIVE |
  2010. ((dwFlags & CWF_CREATE_ONLY) ? 0 : OBJ_OPENIF) |
  2011. ((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0),
  2012. hRootDirectory,
  2013. lpsa ? lpsa->lpSecurityDescriptor : NULL);
  2014. /*
  2015. * NULL hKeyboardFile will let the kernel to utilize
  2016. * the kbdnull layout which is a built in as a fallback layout
  2017. * in Win32k.sys.
  2018. */
  2019. hwinstaNew = NtUserCreateWindowStation(
  2020. &Obja,
  2021. amRequest,
  2022. hKeyboardFile,
  2023. offTable,
  2024. &kbdTableMulti,
  2025. &strKLID,
  2026. uKbdInputLocale);
  2027. if (hRootDirectory != NULL)
  2028. NtClose(hRootDirectory);
  2029. Exit:
  2030. if (hKeyboardFile) {
  2031. NtClose(hKeyboardFile);
  2032. }
  2033. return hwinstaNew;
  2034. }
  2035. FUNCLOG4(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, CreateWindowStationA, LPCSTR, pwinsta, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa)
  2036. HWINSTA CreateWindowStationA(
  2037. LPCSTR pwinsta,
  2038. DWORD dwFlags,
  2039. ACCESS_MASK amRequest,
  2040. PSECURITY_ATTRIBUTES lpsa)
  2041. {
  2042. UNICODE_STRING UnicodeString;
  2043. HWINSTA hwinsta;
  2044. if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pwinsta))
  2045. return NULL;
  2046. hwinsta = CommonCreateWindowStation(&UnicodeString, amRequest, dwFlags, lpsa);
  2047. RtlFreeUnicodeString(&UnicodeString);
  2048. return hwinsta;
  2049. }
  2050. FUNCLOG4(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, CreateWindowStationW, LPCWSTR, pwinsta, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa)
  2051. HWINSTA CreateWindowStationW(
  2052. LPCWSTR pwinsta,
  2053. DWORD dwFlags,
  2054. ACCESS_MASK amRequest,
  2055. PSECURITY_ATTRIBUTES lpsa)
  2056. {
  2057. UNICODE_STRING strWinSta;
  2058. RtlInitUnicodeString(&strWinSta, pwinsta);
  2059. return CommonCreateWindowStation(&strWinSta, amRequest, dwFlags, lpsa);
  2060. }
  2061. /***************************************************************************\
  2062. * OpenWindowStation (API)
  2063. *
  2064. * Opens a windowstation object
  2065. *
  2066. * History:
  2067. \***************************************************************************/
  2068. HWINSTA CommonOpenWindowStation(
  2069. CONST UNICODE_STRING *pstrName,
  2070. BOOL fInherit,
  2071. ACCESS_MASK amRequest)
  2072. {
  2073. WCHAR awchName[sizeof(WINSTA_NAME) / sizeof(WCHAR)];
  2074. UNICODE_STRING strDefaultName;
  2075. OBJECT_ATTRIBUTES ObjA;
  2076. HANDLE hRootDirectory;
  2077. HWINSTA hwinsta;
  2078. NTSTATUS Status;
  2079. InitializeObjectAttributes(&ObjA,
  2080. (PUNICODE_STRING)&strRootDirectory,
  2081. OBJ_CASE_INSENSITIVE,
  2082. NULL, NULL);
  2083. Status = NtOpenDirectoryObject(&hRootDirectory,
  2084. DIRECTORY_TRAVERSE,
  2085. &ObjA);
  2086. if (!NT_SUCCESS(Status)) {
  2087. RIPNTERR0(Status, RIP_VERBOSE, "");
  2088. return NULL;
  2089. }
  2090. if (pstrName->Length == 0) {
  2091. RtlCopyMemory(awchName, WINSTA_NAME, sizeof(WINSTA_NAME));
  2092. RtlInitUnicodeString(&strDefaultName, awchName);
  2093. pstrName = &strDefaultName;
  2094. }
  2095. InitializeObjectAttributes(&ObjA,
  2096. (PUNICODE_STRING)pstrName,
  2097. OBJ_CASE_INSENSITIVE,
  2098. hRootDirectory,
  2099. NULL);
  2100. if (fInherit)
  2101. ObjA.Attributes |= OBJ_INHERIT;
  2102. hwinsta = NtUserOpenWindowStation(&ObjA, amRequest);
  2103. NtClose(hRootDirectory);
  2104. return hwinsta;
  2105. }
  2106. FUNCLOG3(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, OpenWindowStationA, LPCSTR, pwinsta, BOOL, fInherit, ACCESS_MASK, amRequest)
  2107. HWINSTA OpenWindowStationA(
  2108. LPCSTR pwinsta,
  2109. BOOL fInherit,
  2110. ACCESS_MASK amRequest)
  2111. {
  2112. UNICODE_STRING UnicodeString;
  2113. HWINSTA hwinsta;
  2114. if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pwinsta))
  2115. return NULL;
  2116. hwinsta = CommonOpenWindowStation(&UnicodeString, fInherit, amRequest);
  2117. RtlFreeUnicodeString(&UnicodeString);
  2118. return hwinsta;
  2119. }
  2120. FUNCLOG3(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, OpenWindowStationW, LPCWSTR, pwinsta, BOOL, fInherit, ACCESS_MASK, amRequest)
  2121. HWINSTA OpenWindowStationW(
  2122. LPCWSTR pwinsta,
  2123. BOOL fInherit,
  2124. ACCESS_MASK amRequest)
  2125. {
  2126. UNICODE_STRING strWinSta;
  2127. RtlInitUnicodeString(&strWinSta, pwinsta);
  2128. return CommonOpenWindowStation(&strWinSta, fInherit, amRequest);
  2129. }
  2130. /***************************************************************************\
  2131. * CommonCreateDesktop (API)
  2132. *
  2133. * Creates a desktop object
  2134. *
  2135. * History:
  2136. \***************************************************************************/
  2137. HDESK CommonCreateDesktop(
  2138. PUNICODE_STRING pstrDesktop,
  2139. PUNICODE_STRING pstrDevice,
  2140. LPDEVMODEW pDevmode,
  2141. DWORD dwFlags,
  2142. ACCESS_MASK amRequest,
  2143. PSECURITY_ATTRIBUTES lpsa)
  2144. {
  2145. OBJECT_ATTRIBUTES Obja;
  2146. HDESK hdesk = NULL;
  2147. InitializeObjectAttributes(&Obja,
  2148. pstrDesktop,
  2149. OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
  2150. ((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0),
  2151. NtUserGetProcessWindowStation(),
  2152. lpsa ? lpsa->lpSecurityDescriptor : NULL);
  2153. hdesk = NtUserCreateDesktop(&Obja,
  2154. pstrDevice,
  2155. pDevmode,
  2156. dwFlags,
  2157. amRequest);
  2158. return hdesk;
  2159. }
  2160. /***************************************************************************\
  2161. * CreateDesktopA (API)
  2162. *
  2163. * Creates a desktop object
  2164. *
  2165. * History:
  2166. \***************************************************************************/
  2167. FUNCLOG6(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, CreateDesktopA, LPCSTR, pDesktop, LPCSTR, pDevice, LPDEVMODEA, pDevmode, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa)
  2168. HDESK CreateDesktopA(
  2169. LPCSTR pDesktop,
  2170. LPCSTR pDevice,
  2171. LPDEVMODEA pDevmode,
  2172. DWORD dwFlags,
  2173. ACCESS_MASK amRequest,
  2174. PSECURITY_ATTRIBUTES lpsa)
  2175. {
  2176. NTSTATUS Status;
  2177. ANSI_STRING AnsiString;
  2178. UNICODE_STRING UnicodeDesktop;
  2179. UNICODE_STRING UnicodeDevice;
  2180. PUNICODE_STRING pUnicodeDevice = NULL;
  2181. LPDEVMODEW lpDevModeW = NULL;
  2182. HDESK hdesk;
  2183. RtlInitAnsiString(&AnsiString, pDesktop);
  2184. Status = RtlAnsiStringToUnicodeString(&UnicodeDesktop, &AnsiString, TRUE);
  2185. if (!NT_SUCCESS(Status)) {
  2186. RIPNTERR1(Status,
  2187. RIP_WARNING,
  2188. "CreateDesktop fails with Status = 0x%x",
  2189. Status);
  2190. return NULL;
  2191. }
  2192. if (pDevice) {
  2193. pUnicodeDevice = &UnicodeDevice;
  2194. RtlInitAnsiString(&AnsiString, pDevice);
  2195. Status = RtlAnsiStringToUnicodeString(&UnicodeDevice, &AnsiString, TRUE);
  2196. if (!NT_SUCCESS(Status)) {
  2197. RIPNTERR0(Status, RIP_VERBOSE, "");
  2198. RtlFreeUnicodeString(&UnicodeDesktop);
  2199. return NULL;
  2200. }
  2201. }
  2202. if (pDevmode) {
  2203. lpDevModeW = GdiConvertToDevmodeW(pDevmode);
  2204. }
  2205. hdesk = CommonCreateDesktop(&UnicodeDesktop,
  2206. pUnicodeDevice,
  2207. lpDevModeW,
  2208. dwFlags,
  2209. amRequest,
  2210. lpsa);
  2211. RtlFreeUnicodeString(&UnicodeDesktop);
  2212. if (pDevice) {
  2213. RtlFreeUnicodeString(&UnicodeDevice);
  2214. }
  2215. if (lpDevModeW) {
  2216. RtlFreeHeap(RtlProcessHeap(), 0, lpDevModeW);
  2217. }
  2218. return hdesk;
  2219. }
  2220. /***************************************************************************\
  2221. * CreateDesktopW (API)
  2222. *
  2223. * Creates a desktop object
  2224. *
  2225. * History:
  2226. \***************************************************************************/
  2227. FUNCLOG6(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, CreateDesktopW, LPCWSTR, pDesktop, LPCWSTR, pDevice, LPDEVMODEW, pDevmode, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa)
  2228. HDESK CreateDesktopW(
  2229. LPCWSTR pDesktop,
  2230. LPCWSTR pDevice,
  2231. LPDEVMODEW pDevmode,
  2232. DWORD dwFlags,
  2233. ACCESS_MASK amRequest,
  2234. PSECURITY_ATTRIBUTES lpsa)
  2235. {
  2236. UNICODE_STRING strDesktop;
  2237. UNICODE_STRING strDevice;
  2238. RtlInitUnicodeString(&strDesktop, pDesktop);
  2239. RtlInitUnicodeString(&strDevice, pDevice);
  2240. return CommonCreateDesktop(&strDesktop,
  2241. pDevice ? &strDevice : NULL,
  2242. pDevmode,
  2243. dwFlags,
  2244. amRequest,
  2245. lpsa);
  2246. }
  2247. /***************************************************************************\
  2248. * OpenDesktop (API)
  2249. *
  2250. * Opens a desktop object
  2251. *
  2252. * History:
  2253. \***************************************************************************/
  2254. HDESK CommonOpenDesktop(
  2255. PUNICODE_STRING pstrDesktop,
  2256. DWORD dwFlags,
  2257. BOOL fInherit,
  2258. ACCESS_MASK amRequest)
  2259. {
  2260. OBJECT_ATTRIBUTES ObjA;
  2261. InitializeObjectAttributes(&ObjA,
  2262. pstrDesktop,
  2263. OBJ_CASE_INSENSITIVE,
  2264. NtUserGetProcessWindowStation(),
  2265. NULL);
  2266. if (fInherit) {
  2267. ObjA.Attributes |= OBJ_INHERIT;
  2268. }
  2269. return NtUserOpenDesktop(&ObjA, dwFlags, amRequest);
  2270. }
  2271. FUNCLOG4(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, OpenDesktopA, LPCSTR, pdesktop, DWORD, dwFlags, BOOL, fInherit, ACCESS_MASK, amRequest)
  2272. HDESK OpenDesktopA(
  2273. LPCSTR pdesktop,
  2274. DWORD dwFlags,
  2275. BOOL fInherit,
  2276. ACCESS_MASK amRequest)
  2277. {
  2278. UNICODE_STRING UnicodeString;
  2279. HDESK hdesk;
  2280. if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pdesktop))
  2281. return NULL;
  2282. hdesk = CommonOpenDesktop(&UnicodeString, dwFlags, fInherit, amRequest);
  2283. RtlFreeUnicodeString(&UnicodeString);
  2284. return hdesk;
  2285. }
  2286. FUNCLOG4(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, OpenDesktopW, LPCWSTR, pdesktop, DWORD, dwFlags, BOOL, fInherit, ACCESS_MASK, amRequest)
  2287. HDESK OpenDesktopW(
  2288. LPCWSTR pdesktop,
  2289. DWORD dwFlags,
  2290. BOOL fInherit,
  2291. ACCESS_MASK amRequest)
  2292. {
  2293. UNICODE_STRING strDesktop;
  2294. RtlInitUnicodeString(&strDesktop, pdesktop);
  2295. return CommonOpenDesktop(&strDesktop, dwFlags, fInherit, amRequest);
  2296. }
  2297. /***************************************************************************\
  2298. * RegisterClassWOW(API)
  2299. *
  2300. * History:
  2301. * 28-Jul-1992 ChandanC Created.
  2302. \***************************************************************************/
  2303. ATOM
  2304. WINAPI
  2305. RegisterClassWOWA(
  2306. WNDCLASSA *lpWndClass,
  2307. LPDWORD pdwWOWstuff)
  2308. {
  2309. WNDCLASSEXA wc;
  2310. /*
  2311. * On 64-bit plaforms we'll have 32 bits of padding between style and
  2312. * lpfnWndProc in WNDCLASS, so start the copy from the first 64-bit
  2313. * aligned field and hand copy the rest.
  2314. */
  2315. RtlCopyMemory(&(wc.lpfnWndProc), &(lpWndClass->lpfnWndProc), sizeof(WNDCLASSA) - FIELD_OFFSET(WNDCLASSA, lpfnWndProc));
  2316. wc.style = lpWndClass->style;
  2317. wc.hIconSm = NULL;
  2318. wc.cbSize = sizeof(WNDCLASSEXA);
  2319. return RegisterClassExWOWA(&wc, pdwWOWstuff, 0, 0);
  2320. }
  2321. /**************************************************************************\
  2322. * WowGetDefWindowProcBits - Fills in bit array for WOW
  2323. *
  2324. * 22-Jul-1991 mikeke Created
  2325. \**************************************************************************/
  2326. WORD WowGetDefWindowProcBits(
  2327. PBYTE pDefWindowProcBits,
  2328. WORD cbDefWindowProcBits)
  2329. {
  2330. WORD wMaxMsg;
  2331. KPBYTE pbSrc;
  2332. PBYTE pbDst, pbDstEnd;
  2333. UNREFERENCED_PARAMETER(cbDefWindowProcBits);
  2334. /*
  2335. * Merge the bits from gpsi->gabDefWindowMsgs and
  2336. * gpsi->gabDefWindowSpecMsgs into WOW's DefWindowProcBits. These two
  2337. * indicate which messages must go directly to the server and which
  2338. * can be handled with some special code in DefWindowProcWorker.
  2339. * Bitwise OR'ing the two gives a bit array with 1 in the bit field
  2340. * for each message that must go to user32's DefWindowProc, and 0
  2341. * for those that can be returned back to the client immediately.
  2342. *
  2343. * For speed we assume WOW has zeroed the buffer, in fact it's in
  2344. * USER.EXE's code segment and is zeroed in the image.
  2345. */
  2346. wMaxMsg = max(gSharedInfo.DefWindowMsgs.maxMsgs,
  2347. gSharedInfo.DefWindowSpecMsgs.maxMsgs);
  2348. UserAssert((wMaxMsg / 8 + 1) <= cbDefWindowProcBits);
  2349. //
  2350. // If the above assertion fires, the size of the DWPBits array in
  2351. // \nt\private\mvdm\wow16\user\user.asm needs to be increased.
  2352. //
  2353. /* First copy the bits from DefWindowMsgs */
  2354. RtlCopyMemory(
  2355. pDefWindowProcBits,
  2356. gSharedInfo.DefWindowMsgs.abMsgs,
  2357. gSharedInfo.DefWindowMsgs.maxMsgs / 8 + 1
  2358. );
  2359. /* Next OR in the bits from DefWindowSpecMsgs */
  2360. pbSrc = gSharedInfo.DefWindowSpecMsgs.abMsgs;
  2361. pbDst = pDefWindowProcBits;
  2362. pbDstEnd = pbDst + (gSharedInfo.DefWindowSpecMsgs.maxMsgs / 8 + 1);
  2363. while (pbDst < pbDstEnd)
  2364. {
  2365. *pbDst++ |= *pbSrc++;
  2366. }
  2367. return wMaxMsg;
  2368. }
  2369. FUNCLOG2(LOG_GENERAL, ULONG_PTR, DUMMYCALLINGTYPE, UserRegisterWowHandlers, APFNWOWHANDLERSIN, apfnWowIn, APFNWOWHANDLERSOUT, apfnWowOut)
  2370. ULONG_PTR UserRegisterWowHandlers(
  2371. APFNWOWHANDLERSIN apfnWowIn,
  2372. APFNWOWHANDLERSOUT apfnWowOut)
  2373. {
  2374. VDM_QUERY_VDM_PROCESS_DATA QueryVdmProcessData;
  2375. NTSTATUS Status;
  2376. //
  2377. // Check the Target Process to see if this is a Wx86 process
  2378. //
  2379. QueryVdmProcessData.IsVdmProcess = FALSE;
  2380. QueryVdmProcessData.ProcessHandle = NtCurrentProcess();
  2381. Status = NtVdmControl(VdmQueryVdmProcess, &QueryVdmProcessData);
  2382. if (!NT_SUCCESS(Status) || QueryVdmProcessData.IsVdmProcess == FALSE) {
  2383. return STATUS_ACCESS_DENIED;
  2384. }
  2385. // In'ees
  2386. pfnLocalAlloc = apfnWowIn->pfnLocalAlloc;
  2387. pfnLocalReAlloc = apfnWowIn->pfnLocalReAlloc;
  2388. pfnLocalLock = apfnWowIn->pfnLocalLock;
  2389. pfnLocalUnlock = apfnWowIn->pfnLocalUnlock;
  2390. pfnLocalSize = apfnWowIn->pfnLocalSize;
  2391. pfnLocalFree = apfnWowIn->pfnLocalFree;
  2392. pfnGetExpWinVer = apfnWowIn->pfnGetExpWinVer;
  2393. pfn16GlobalAlloc = apfnWowIn->pfn16GlobalAlloc;
  2394. pfn16GlobalFree = apfnWowIn->pfn16GlobalFree;
  2395. pfnWowEmptyClipBoard = apfnWowIn->pfnEmptyCB;
  2396. pfnWowEditNextWord = apfnWowIn->pfnWowEditNextWord;
  2397. pfnWowCBStoreHandle = apfnWowIn->pfnWowCBStoreHandle;
  2398. pfnFindResourceExA = apfnWowIn->pfnFindResourceEx;
  2399. pfnLoadResource = apfnWowIn->pfnLoadResource;
  2400. pfnLockResource = apfnWowIn->pfnLockResource;
  2401. pfnUnlockResource = apfnWowIn->pfnUnlockResource;
  2402. pfnFreeResource = apfnWowIn->pfnFreeResource;
  2403. pfnSizeofResource = apfnWowIn->pfnSizeofResource;
  2404. pfnFindResourceExW = WOWFindResourceExWCover;
  2405. pfnWowDlgProcEx = apfnWowIn->pfnWowDlgProcEx;
  2406. pfnWowWndProcEx = apfnWowIn->pfnWowWndProcEx;
  2407. pfnWowGetProcModule = apfnWowIn->pfnGetProcModule16;
  2408. pfnWowTask16SchedNotify = apfnWowIn->pfnWowTask16SchedNotify;
  2409. pfnWOWTellWOWThehDlg = apfnWowIn->pfnWOWTellWOWThehDlg;
  2410. pfnWowMsgBoxIndirectCallback = apfnWowIn->pfnWowMsgBoxIndirectCallback;
  2411. pfnWowIlstrcmp = apfnWowIn->pfnWowIlstrsmp;
  2412. // Out'ees
  2413. #if DBG
  2414. apfnWowOut->dwBldInfo = (WINVER << 16) | 0x80000000;
  2415. #else
  2416. apfnWowOut->dwBldInfo = (WINVER << 16);
  2417. #endif
  2418. apfnWowOut->pfnCsCreateWindowEx = _CreateWindowEx;
  2419. apfnWowOut->pfnDirectedYield = DirectedYield;
  2420. apfnWowOut->pfnFreeDDEData = FreeDDEData;
  2421. apfnWowOut->pfnGetClassWOWWords = GetClassWOWWords;
  2422. apfnWowOut->pfnInitTask = InitTask;
  2423. apfnWowOut->pfnRegisterClassWOWA = RegisterClassWOWA;
  2424. apfnWowOut->pfnRegisterUserHungAppHandlers = RegisterUserHungAppHandlers;
  2425. apfnWowOut->pfnServerCreateDialog = InternalCreateDialog;
  2426. apfnWowOut->pfnServerLoadCreateCursorIcon = WowServerLoadCreateCursorIcon;
  2427. apfnWowOut->pfnServerLoadCreateMenu = WowServerLoadCreateMenu;
  2428. apfnWowOut->pfnWOWCleanup = WOWCleanup;
  2429. apfnWowOut->pfnWOWModuleUnload = WOWModuleUnload;
  2430. apfnWowOut->pfnWOWFindWindow = WOWFindWindow;
  2431. apfnWowOut->pfnWOWLoadBitmapA = WOWLoadBitmapA;
  2432. apfnWowOut->pfnWowWaitForMsgAndEvent = NtUserWaitForMsgAndEvent;
  2433. apfnWowOut->pfnYieldTask = NtUserYieldTask;
  2434. apfnWowOut->pfnGetFullUserHandle = GetFullUserHandle;
  2435. apfnWowOut->pfnGetMenuIndex = NtUserGetMenuIndex;
  2436. apfnWowOut->pfnWowGetDefWindowProcBits = WowGetDefWindowProcBits;
  2437. apfnWowOut->pfnFillWindow = FillWindow;
  2438. apfnWowOut->aiWowClass = aiClassWow;
  2439. return (ULONG_PTR)&gSharedInfo;
  2440. }
  2441. /***************************************************************************\
  2442. * GetEditDS
  2443. *
  2444. * This is a callback to WOW used to allocate a segment for DS_LOCALEDIT
  2445. * edit controls. The segment is disguised to look like a WOW hInstance.
  2446. *
  2447. * 06-19-92 sanfords Created
  2448. \***************************************************************************/
  2449. HANDLE GetEditDS()
  2450. {
  2451. UserAssert(pfn16GlobalAlloc != NULL);
  2452. return((HANDLE)((*pfn16GlobalAlloc)(GHND | GMEM_SHARE, 256)));
  2453. }
  2454. /***************************************************************************\
  2455. * ReleaseEditDS
  2456. *
  2457. * This is a callback to WOW used to free a segment for DS_LOCALEDIT
  2458. * edit controls.
  2459. *
  2460. * 06-19-92 sanfords Created
  2461. \***************************************************************************/
  2462. VOID ReleaseEditDS(
  2463. HANDLE h)
  2464. {
  2465. UserAssert(pfn16GlobalFree != NULL);
  2466. (*pfn16GlobalFree)(LOWORD(HandleToUlong(h)));
  2467. }
  2468. /***************************************************************************\
  2469. * TellWOWThehDlg
  2470. *
  2471. * This is a callback to WOW used to inform WOW of the hDlg of a newly
  2472. * created dialog window.
  2473. *
  2474. * 08-31-97 cmjones Created
  2475. \***************************************************************************/
  2476. VOID TellWOWThehDlg(
  2477. HWND hDlg)
  2478. {
  2479. UserAssert(pfnWOWTellWOWThehDlg != NULL);
  2480. (*pfnWOWTellWOWThehDlg)(hDlg);
  2481. }
  2482. /***************************************************************************\
  2483. * DispatchClientMessage
  2484. *
  2485. * pwnd is threadlocked in the kernel and thus always valid.
  2486. *
  2487. * 19-Aug-1992 mikeke created
  2488. \***************************************************************************/
  2489. LRESULT DispatchClientMessage(
  2490. PWND pwnd,
  2491. UINT message,
  2492. WPARAM wParam,
  2493. LPARAM lParam,
  2494. ULONG_PTR pfn)
  2495. {
  2496. PCLIENTINFO pci = GetClientInfo();
  2497. HWND hwnd = KHWND_TO_HWND(pci->CallbackWnd.hwnd);
  2498. PACTIVATION_CONTEXT pActCtx = pci->CallbackWnd.pActCtx;
  2499. LRESULT lRet = 0;
  2500. /*
  2501. * Assert that the header comment is legit (it must be). For WM_TIMER
  2502. * messages not associated with a window, pwnd can be NULL. So don't
  2503. * rip validating the handle.
  2504. */
  2505. UserAssert(pwnd == ValidateHwndNoRip(hwnd));
  2506. /*
  2507. * Add assert to catch dispatching messages to a thread not associated
  2508. * with a desktop.
  2509. */
  2510. UserAssert(GetClientInfo()->ulClientDelta != 0);
  2511. if (message == WM_TIMER && lParam != 0) {
  2512. /*
  2513. * Console windows use WM_TIMER for the caret. However, they don't
  2514. * use a timer callback, so if this is CSRSS and there's a WM_TIMER
  2515. * for us, the only way lParam would be non-zero is if someone's trying
  2516. * to make us fault. No, this isn't a nice thing to do, but there
  2517. * are bad, bad people out there. Windows Bug #361246.
  2518. */
  2519. if (!gfServerProcess) {
  2520. /*
  2521. * We can't really trust what's in lParam, so make sure we
  2522. * handle any exceptions that occur during this call.
  2523. */
  2524. try {
  2525. lRet = UserCallWinProcCheckWow(pActCtx,
  2526. (WNDPROC)pfn,
  2527. hwnd,
  2528. message,
  2529. wParam,
  2530. NtGetTickCount(),
  2531. &(pwnd->state),
  2532. TRUE);
  2533. } except ((GetAppCompatFlags2(VER40) & GACF2_NO_TRYEXCEPT_CALLWNDPROC) ?
  2534. EXCEPTION_CONTINUE_SEARCH : W32ExceptionHandler(FALSE, RIP_WARNING)) {
  2535. /*
  2536. * Windows NT Bug #359866.
  2537. * Some applications like Hagaki Studio 2000 need to handle
  2538. * the exception in WndProc in their handler, even though it
  2539. * skips the API calls. For those apps, we have to honor the
  2540. * behavior of NT4, with no protection.
  2541. */
  2542. }
  2543. }
  2544. } else {
  2545. lRet = UserCallWinProcCheckWow(pActCtx, (WNDPROC)pfn, hwnd, message, wParam, lParam, &(pwnd->state), TRUE);
  2546. }
  2547. return lRet;
  2548. }
  2549. /**************************************************************************\
  2550. * ArrangeIconicWindows
  2551. *
  2552. * 22-Jul-1991 mikeke Created
  2553. \**************************************************************************/
  2554. FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, ArrangeIconicWindows, HWND, hwnd)
  2555. UINT ArrangeIconicWindows(
  2556. HWND hwnd)
  2557. {
  2558. return (UINT)NtUserCallHwndLock(hwnd, SFI_XXXARRANGEICONICWINDOWS);
  2559. }
  2560. /**************************************************************************\
  2561. * BeginDeferWindowPos
  2562. *
  2563. * 22-Jul-1991 mikeke Created
  2564. \**************************************************************************/
  2565. FUNCLOG1(LOG_GENERAL, HANDLE, DUMMYCALLINGTYPE, BeginDeferWindowPos, int, nNumWindows)
  2566. HANDLE BeginDeferWindowPos(
  2567. int nNumWindows)
  2568. {
  2569. if (nNumWindows < 0) {
  2570. RIPERR1(ERROR_INVALID_PARAMETER,
  2571. RIP_WARNING,
  2572. "Invalid parameter \"nNumWindows\" (%ld) to BeginDeferWindowPos",
  2573. nNumWindows);
  2574. return 0;
  2575. }
  2576. return (HANDLE)NtUserCallOneParam(nNumWindows, SFI__BEGINDEFERWINDOWPOS);
  2577. }
  2578. /**************************************************************************\
  2579. * EndDeferWindowPos
  2580. *
  2581. * 22-Jul-1991 mikeke Created
  2582. \**************************************************************************/
  2583. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EndDeferWindowPos, HDWP, hWinPosInfo)
  2584. BOOL EndDeferWindowPos(
  2585. HDWP hWinPosInfo)
  2586. {
  2587. return NtUserEndDeferWindowPosEx(hWinPosInfo, FALSE);
  2588. }
  2589. /**************************************************************************\
  2590. * CascadeChildWindows
  2591. *
  2592. * 22-Jul-1991 mikeke Created
  2593. \**************************************************************************/
  2594. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CascadeChildWindows, HWND, hwndParent, UINT, nCode)
  2595. BOOL CascadeChildWindows(
  2596. HWND hwndParent,
  2597. UINT nCode)
  2598. {
  2599. return (BOOL) CascadeWindows(hwndParent, nCode, NULL, 0, NULL);
  2600. }
  2601. /**************************************************************************\
  2602. * CloseWindow
  2603. *
  2604. * 22-Jul-1991 mikeke Created
  2605. * 17-Feb-1998 MCostea Use xxxShowWindow instead of xxxCloseWindow
  2606. \**************************************************************************/
  2607. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CloseWindow, HWND, hwnd)
  2608. BOOL CloseWindow(
  2609. HWND hwnd)
  2610. {
  2611. PWND pwnd;
  2612. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  2613. return FALSE;
  2614. }
  2615. if (!TestWF(pwnd, WFMINIMIZED)) {
  2616. NtUserShowWindow(hwnd, SW_SHOWMINIMIZED);
  2617. }
  2618. return TRUE;
  2619. }
  2620. /**************************************************************************\
  2621. * CreateMenu
  2622. *
  2623. * 22-Jul-1991 mikeke Created
  2624. \**************************************************************************/
  2625. HMENU CreateMenu()
  2626. {
  2627. return (HMENU)NtUserCallNoParam(SFI__CREATEMENU);
  2628. }
  2629. /**************************************************************************\
  2630. * CreatePopupMenu
  2631. *
  2632. * 22-Jul-1991 mikeke Created
  2633. \**************************************************************************/
  2634. HMENU CreatePopupMenu()
  2635. {
  2636. return (HMENU)NtUserCallNoParam(SFI__CREATEPOPUPMENU);
  2637. }
  2638. /**************************************************************************\
  2639. * CurrentTaskLock
  2640. *
  2641. * 21-Apr-1992 jonpa Created
  2642. \**************************************************************************/
  2643. #if 0 /* WOW is not using this but they might some day */
  2644. DWORD CurrentTaskLock(
  2645. DWORD hlck)
  2646. {
  2647. return (DWORD)NtUserCallOneParam(hlck, SFI_CURRENTTASKLOCK);
  2648. }
  2649. #endif
  2650. /**************************************************************************\
  2651. * DestroyCaret
  2652. *
  2653. * 22-Jul-1991 mikeke Created
  2654. \**************************************************************************/
  2655. BOOL DestroyCaret()
  2656. {
  2657. return (BOOL)NtUserCallNoParam(SFI_ZZZDESTROYCARET);
  2658. }
  2659. /**************************************************************************\
  2660. * DirectedYield
  2661. *
  2662. * 22-Jul-1991 mikeke Created
  2663. \**************************************************************************/
  2664. void DirectedYield(
  2665. DWORD dwThreadId)
  2666. {
  2667. NtUserCallOneParam(dwThreadId, SFI_XXXDIRECTEDYIELD);
  2668. }
  2669. /**************************************************************************\
  2670. * DrawMenuBar
  2671. *
  2672. * 22-Jul-1991 mikeke Created
  2673. \**************************************************************************/
  2674. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawMenuBar, HWND, hwnd)
  2675. BOOL DrawMenuBar(
  2676. HWND hwnd)
  2677. {
  2678. return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXDRAWMENUBAR);
  2679. }
  2680. /**************************************************************************\
  2681. * EnableWindow
  2682. *
  2683. * 22-Jul-1991 mikeke Created
  2684. \**************************************************************************/
  2685. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnableWindow, HWND, hwnd, BOOL, bEnable)
  2686. BOOL EnableWindow(
  2687. HWND hwnd,
  2688. BOOL bEnable)
  2689. {
  2690. return (BOOL)NtUserCallHwndParamLock(hwnd, bEnable,
  2691. SFI_XXXENABLEWINDOW);
  2692. }
  2693. /**************************************************************************\
  2694. * EnumClipboardFormats
  2695. *
  2696. * 22-Jul-1991 mikeke Created
  2697. \**************************************************************************/
  2698. FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, EnumClipboardFormats, UINT, fmt)
  2699. UINT EnumClipboardFormats(
  2700. UINT fmt)
  2701. {
  2702. /*
  2703. * So apps can tell if the API failed or just ran out of formats
  2704. * we "clear" the last error.
  2705. */
  2706. UserSetLastError(ERROR_SUCCESS);
  2707. return (UINT)NtUserCallOneParam(fmt, SFI__ENUMCLIPBOARDFORMATS);
  2708. }
  2709. /**************************************************************************\
  2710. * FlashWindow
  2711. *
  2712. * 22-Jul-1991 mikeke Created
  2713. * 08-Aug-1997 Gerardob Added FlashWindowEx.
  2714. * 16-Nov-1997 MCostea Make it use NtUserFlashWindowEx
  2715. \**************************************************************************/
  2716. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, FlashWindow, HWND, hwnd, BOOL, bInvert)
  2717. BOOL FlashWindow(
  2718. HWND hwnd,
  2719. BOOL bInvert)
  2720. {
  2721. FLASHWINFO fwi = {
  2722. sizeof(FLASHWINFO), // cbSize
  2723. hwnd, // hwnd
  2724. bInvert ? (FLASHW_CAPTION | FLASHW_TRAY) : 0, // flags
  2725. 1, // uCount
  2726. 0 // dwTimeout
  2727. };
  2728. return (BOOL)NtUserFlashWindowEx(&fwi);
  2729. }
  2730. /**************************************************************************\
  2731. * GetDialogBaseUnits
  2732. *
  2733. * 22-Jul-1991 mikeke Created
  2734. \**************************************************************************/
  2735. LONG GetDialogBaseUnits(
  2736. VOID)
  2737. {
  2738. return MAKELONG(gpsi->cxSysFontChar, gpsi->cySysFontChar);
  2739. }
  2740. /**************************************************************************\
  2741. * GetInputDesktop
  2742. *
  2743. * 22-Jul-1991 mikeke Created
  2744. \**************************************************************************/
  2745. HDESK GetInputDesktop(
  2746. VOID)
  2747. {
  2748. return (HDESK)NtUserCallNoParam(SFI__GETINPUTDESKTOP);
  2749. }
  2750. /***************************************************************************\
  2751. * GetClientKeyboardType
  2752. *
  2753. * This routine returns the keyboard type sent from the Hydra client.
  2754. * Hydra client sends keyboard types at session startup.
  2755. *
  2756. * Returns the client winstation specified a keyboard type.
  2757. * History:
  2758. \***************************************************************************/
  2759. BOOL GetClientKeyboardType(
  2760. PCLIENTKEYBOARDTYPE KeyboardType)
  2761. {
  2762. ULONG Length;
  2763. WINSTATIONCLIENTW ClientData;
  2764. static CLIENTKEYBOARDTYPE ClientKeyboard = { (ULONG)-1, (ULONG)-1, (ULONG)-1 };
  2765. //
  2766. // Should be called only if this is a HYDRA remote session.
  2767. //
  2768. if (!ISREMOTESESSION()) {
  2769. RIPMSGF0(RIP_WARNING, "This is not a remote session!");
  2770. }
  2771. // Skip if this is the console
  2772. if (!ISREMOTESESSION()) {
  2773. return FALSE;
  2774. }
  2775. if (ClientKeyboard.Type == (ULONG)-1) {
  2776. // Fetch the WinStation's basic information
  2777. if (!WinStationQueryInformationW(SERVERNAME_CURRENT,
  2778. LOGONID_CURRENT,
  2779. WinStationClient,
  2780. &ClientData,
  2781. sizeof(ClientData),
  2782. &Length)) {
  2783. return FALSE;
  2784. }
  2785. ClientKeyboard.Type = ClientData.KeyboardType;
  2786. ClientKeyboard.SubType = ClientData.KeyboardSubType;
  2787. ClientKeyboard.FunctionKey = ClientData.KeyboardFunctionKey;
  2788. }
  2789. *KeyboardType = ClientKeyboard;
  2790. return TRUE;
  2791. }
  2792. /**************************************************************************\
  2793. * GetKeyboardType
  2794. *
  2795. * 22-Jul-1991 mikeke Created
  2796. \**************************************************************************/
  2797. FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetKeyboardType, int, nTypeFlags)
  2798. int GetKeyboardType(
  2799. int nTypeFlags)
  2800. {
  2801. if (ISREMOTESESSION()) {
  2802. //
  2803. // Get keyboard type from Hydra client if this is not the console
  2804. //
  2805. CLIENTKEYBOARDTYPE KeyboardType;
  2806. if (GetClientKeyboardType(&KeyboardType)) {
  2807. switch (nTypeFlags) {
  2808. case 0:
  2809. return KeyboardType.Type;
  2810. case 1:
  2811. if (KeyboardType.Type == 7) { /* 7 is a Japanese */
  2812. // Because HIWORD has been using private value
  2813. // for Japanese keyboard layout.
  2814. return LOWORD(KeyboardType.SubType);
  2815. }
  2816. else
  2817. return KeyboardType.SubType;
  2818. case 2:
  2819. return KeyboardType.FunctionKey;
  2820. default:
  2821. break;
  2822. }
  2823. }
  2824. return 0;
  2825. }
  2826. return (int)NtUserCallOneParam(nTypeFlags, SFI__GETKEYBOARDTYPE);
  2827. }
  2828. /**************************************************************************\
  2829. * GetMessagePos
  2830. *
  2831. * 22-Jul-1991 mikeke Created
  2832. \**************************************************************************/
  2833. DWORD GetMessagePos()
  2834. {
  2835. return (DWORD)NtUserCallNoParam(SFI__GETMESSAGEPOS);
  2836. }
  2837. /**************************************************************************\
  2838. * GetQueueStatus
  2839. *
  2840. * 22-Jul-1991 mikeke Created
  2841. * 14-Dec-2000 JStall Converted to WMH
  2842. \**************************************************************************/
  2843. FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetQueueStatus, UINT, flags)
  2844. DWORD GetQueueStatus(
  2845. UINT flags)
  2846. #ifdef MESSAGE_PUMP_HOOK
  2847. {
  2848. DWORD dwResult;
  2849. BEGIN_MESSAGEPUMPHOOK()
  2850. if (fInsideHook) {
  2851. dwResult = gmph.pfnGetQueueStatus(flags);
  2852. } else {
  2853. dwResult = RealGetQueueStatus(flags);
  2854. }
  2855. END_MESSAGEPUMPHOOK()
  2856. return dwResult;
  2857. }
  2858. DWORD RealGetQueueStatus(
  2859. UINT flags)
  2860. #endif
  2861. {
  2862. if (flags & ~QS_VALID) {
  2863. RIPERR2(ERROR_INVALID_FLAGS, RIP_WARNING, "Invalid flags %x & ~%x != 0",
  2864. flags, QS_VALID);
  2865. return 0;
  2866. }
  2867. return (DWORD)NtUserCallOneParam(flags, SFI__GETQUEUESTATUS);
  2868. }
  2869. /**************************************************************************\
  2870. * KillSystemTimer
  2871. *
  2872. * 7-Jul-1992 mikehar Created
  2873. \**************************************************************************/
  2874. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, KillSystemTimer, HWND, hwnd, UINT, nIDEvent)
  2875. BOOL KillSystemTimer(
  2876. HWND hwnd,
  2877. UINT nIDEvent)
  2878. {
  2879. return (BOOL)NtUserCallHwndParam(hwnd, nIDEvent, SFI__KILLSYSTEMTIMER);
  2880. }
  2881. /**************************************************************************\
  2882. * LoadRemoteFonts
  2883. * 02-Dec-1993 -by- Bodin Dresevic [BodinD]
  2884. * Wrote it.
  2885. \**************************************************************************/
  2886. void LoadRemoteFonts(void)
  2887. {
  2888. NtUserCallOneParam(TRUE,SFI_XXXLW_LOADFONTS);
  2889. /*
  2890. * After load remote fonts, let eudc enabled.
  2891. */
  2892. EnableEUDC(TRUE);
  2893. }
  2894. /**************************************************************************\
  2895. * LoadLocalFonts
  2896. * 31-Mar-1994 -by- Bodin Dresevic [gerritv]
  2897. * Wrote it.
  2898. \**************************************************************************/
  2899. void LoadLocalFonts(void)
  2900. {
  2901. NtUserCallOneParam(FALSE,SFI_XXXLW_LOADFONTS);
  2902. }
  2903. /**************************************************************************\
  2904. * MessageBeep
  2905. *
  2906. * 22-Jul-1991 mikeke Created
  2907. \**************************************************************************/
  2908. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, MessageBeep, UINT, wType)
  2909. BOOL MessageBeep(
  2910. UINT wType)
  2911. {
  2912. return (BOOL)NtUserCallOneParam(wType, SFI_XXXMESSAGEBEEP);
  2913. }
  2914. /**************************************************************************\
  2915. * OpenIcon
  2916. *
  2917. * 22-Jul-1991 mikeke Created
  2918. * 17-Feb-1998 MCostea Use xxxShowWindow instead of xxxCloseWindow
  2919. \**************************************************************************/
  2920. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, OpenIcon, HWND, hwnd)
  2921. BOOL OpenIcon(
  2922. HWND hwnd)
  2923. {
  2924. PWND pwnd;
  2925. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  2926. return FALSE;
  2927. }
  2928. if (TestWF(pwnd, WFMINIMIZED)) {
  2929. NtUserShowWindow(hwnd, SW_NORMAL);
  2930. }
  2931. return TRUE;
  2932. }
  2933. HWND GetShellWindow(void) {
  2934. PCLIENTINFO pci;
  2935. PWND pwnd;
  2936. ConnectIfNecessary(0);
  2937. pci = GetClientInfo();
  2938. pwnd = pci->pDeskInfo->spwndShell;
  2939. if (pwnd != NULL) {
  2940. pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta);
  2941. return HWq(pwnd);
  2942. }
  2943. return NULL;
  2944. }
  2945. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetShellWindow, HWND, hwnd)
  2946. BOOL SetShellWindow(HWND hwnd)
  2947. {
  2948. return (BOOL)NtUserSetShellWindowEx(hwnd, hwnd);
  2949. }
  2950. HWND GetProgmanWindow(void) {
  2951. PCLIENTINFO pci;
  2952. PWND pwnd;
  2953. ConnectIfNecessary(0);
  2954. pci = GetClientInfo();
  2955. pwnd = pci->pDeskInfo->spwndProgman;
  2956. if (pwnd != NULL) {
  2957. pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta);
  2958. return HWq(pwnd);
  2959. }
  2960. return NULL;
  2961. }
  2962. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetProgmanWindow, HWND, hwnd)
  2963. BOOL SetProgmanWindow(
  2964. HWND hwnd)
  2965. {
  2966. return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETPROGMANWINDOW);
  2967. }
  2968. HWND GetTaskmanWindow(void) {
  2969. PCLIENTINFO pci;
  2970. PWND pwnd;
  2971. ConnectIfNecessary(0);
  2972. pci = GetClientInfo();
  2973. pwnd = pci->pDeskInfo->spwndTaskman;
  2974. if (pwnd != NULL) {
  2975. pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta);
  2976. return HWq(pwnd);
  2977. }
  2978. return NULL;
  2979. }
  2980. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetTaskmanWindow, HWND, hwnd)
  2981. BOOL SetTaskmanWindow(
  2982. HWND hwnd)
  2983. {
  2984. return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETTASKMANWINDOW);
  2985. }
  2986. /**************************************************************************\
  2987. * SetWindowContextHelpId
  2988. *
  2989. * 22-Jul-1991 mikeke Created
  2990. \**************************************************************************/
  2991. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetWindowContextHelpId, HWND, hwnd, DWORD, id)
  2992. BOOL SetWindowContextHelpId(
  2993. HWND hwnd,
  2994. DWORD id)
  2995. {
  2996. return (BOOL)NtUserCallHwndParam(hwnd, id, SFI__SETWINDOWCONTEXTHELPID);
  2997. }
  2998. /**************************************************************************\
  2999. * GetWindowContextHelpId
  3000. *
  3001. * 22-Jul-1991 mikeke Created
  3002. \**************************************************************************/
  3003. FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetWindowContextHelpId, HWND, hwnd)
  3004. DWORD GetWindowContextHelpId(
  3005. HWND hwnd)
  3006. {
  3007. return (BOOL)NtUserCallHwnd(hwnd, SFI__GETWINDOWCONTEXTHELPID);
  3008. }
  3009. VOID SetWindowState(
  3010. PWND pwnd,
  3011. UINT flags)
  3012. {
  3013. if (TestWF(pwnd, flags) != LOBYTE(flags)) {
  3014. NtUserCallHwndParam(HWq(pwnd), flags, SFI_SETWINDOWSTATE);
  3015. }
  3016. }
  3017. VOID ClearWindowState(
  3018. PWND pwnd,
  3019. UINT flags)
  3020. {
  3021. if (TestWF(pwnd, flags)) {
  3022. NtUserCallHwndParam(HWq(pwnd), flags, SFI_CLEARWINDOWSTATE);
  3023. }
  3024. }
  3025. /**************************************************************************\
  3026. * PostQuitMessage
  3027. *
  3028. * 22-Jul-1991 mikeke Created
  3029. \**************************************************************************/
  3030. FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, PostQuitMessage, int, nExitCode)
  3031. VOID PostQuitMessage(
  3032. int nExitCode)
  3033. {
  3034. NtUserCallOneParam(nExitCode, SFI__POSTQUITMESSAGE);
  3035. }
  3036. /**************************************************************************\
  3037. * REGISTERUSERHUNAPPHANDLERS
  3038. *
  3039. * 01-Apr-1992 jonpa Created
  3040. \**************************************************************************/
  3041. BOOL RegisterUserHungAppHandlers(
  3042. PFNW32ET pfnW32EndTask,
  3043. HANDLE hEventWowExec)
  3044. {
  3045. return (BOOL)NtUserCallTwoParam((ULONG_PTR)pfnW32EndTask,
  3046. (ULONG_PTR)hEventWowExec,
  3047. SFI_XXXREGISTERUSERHUNGAPPHANDLERS);
  3048. }
  3049. /**************************************************************************\
  3050. * ReleaseCapture
  3051. *
  3052. * 22-Jul-1991 mikeke Created
  3053. \**************************************************************************/
  3054. BOOL ReleaseCapture(
  3055. VOID)
  3056. {
  3057. return (BOOL)NtUserCallNoParam(SFI_XXXRELEASECAPTURE);
  3058. }
  3059. /**************************************************************************\
  3060. * ReplyMessage
  3061. *
  3062. * 22-Jul-1991 mikeke Created
  3063. \**************************************************************************/
  3064. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ReplyMessage, LRESULT, pp1)
  3065. BOOL ReplyMessage(
  3066. LRESULT pp1)
  3067. {
  3068. return (BOOL)NtUserCallOneParam(pp1, SFI__REPLYMESSAGE);
  3069. }
  3070. /**************************************************************************\
  3071. * RegisterSystemThread
  3072. *
  3073. * 21-Jun-1994 johnc Created
  3074. \**************************************************************************/
  3075. FUNCLOGVOID2(LOG_GENERAL, DUMMYCALLINGTYPE, RegisterSystemThread, DWORD, dwFlags, DWORD, dwReserved)
  3076. VOID RegisterSystemThread(
  3077. DWORD dwFlags, DWORD dwReserved)
  3078. {
  3079. NtUserCallTwoParam(dwFlags, dwReserved, SFI_ZZZREGISTERSYSTEMTHREAD);
  3080. }
  3081. /**************************************************************************\
  3082. * SetCaretBlinkTime
  3083. *
  3084. * 22-Jul-1991 mikeke Created
  3085. \**************************************************************************/
  3086. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCaretBlinkTime, UINT, wMSeconds)
  3087. BOOL SetCaretBlinkTime(
  3088. UINT wMSeconds)
  3089. {
  3090. return (BOOL)NtUserCallOneParam(wMSeconds, SFI__SETCARETBLINKTIME);
  3091. }
  3092. /**************************************************************************\
  3093. * SetCaretPos
  3094. *
  3095. * 22-Jul-1991 mikeke Created
  3096. \**************************************************************************/
  3097. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCaretPos, int, X, int, Y)
  3098. BOOL SetCaretPos(
  3099. int X,
  3100. int Y)
  3101. {
  3102. return (BOOL)NtUserCallTwoParam(X, Y, SFI_ZZZSETCARETPOS);
  3103. }
  3104. /**************************************************************************\
  3105. * SetCursorPos
  3106. *
  3107. * 22-Jul-1991 mikeke Created
  3108. \**************************************************************************/
  3109. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCursorPos, int, X, int, Y)
  3110. BOOL SetCursorPos(
  3111. int X,
  3112. int Y)
  3113. {
  3114. return (BOOL)NtUserCallTwoParam(X, Y, SFI_ZZZSETCURSORPOS);
  3115. }
  3116. /**************************************************************************\
  3117. * SetDoubleClickTime
  3118. *
  3119. * 22-Jul-1991 mikeke Created
  3120. \**************************************************************************/
  3121. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetDoubleClickTime, UINT, cms)
  3122. BOOL SetDoubleClickTime(
  3123. UINT cms)
  3124. {
  3125. return (BOOL)NtUserCallOneParam(cms, SFI__SETDOUBLECLICKTIME);
  3126. }
  3127. /**************************************************************************\
  3128. * SetForegroundWindow
  3129. *
  3130. * 22-Jul-1991 mikeke Created
  3131. \**************************************************************************/
  3132. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetForegroundWindow, HWND, hwnd)
  3133. BOOL SetForegroundWindow(
  3134. HWND hwnd)
  3135. {
  3136. return NtUserSetForegroundWindow(hwnd);
  3137. }
  3138. /**************************************************************************\
  3139. * AllowSetForegroundWindow
  3140. *
  3141. * 28-Jan-1998 GerardoB Created
  3142. \**************************************************************************/
  3143. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, AllowSetForegroundWindow, DWORD, dwProcessId)
  3144. BOOL AllowSetForegroundWindow(
  3145. DWORD dwProcessId)
  3146. {
  3147. return (BOOL)NtUserCallOneParam(dwProcessId, SFI_XXXALLOWSETFOREGROUNDWINDOW);
  3148. }
  3149. /**************************************************************************\
  3150. * LockSetForegroundWindow
  3151. *
  3152. * 07-Apr-1998 GerardoB Created
  3153. \**************************************************************************/
  3154. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, LockSetForegroundWindow, UINT, uLockCode)
  3155. BOOL LockSetForegroundWindow(
  3156. UINT uLockCode)
  3157. {
  3158. return (BOOL)NtUserCallOneParam(uLockCode, SFI__LOCKSETFOREGROUNDWINDOW);
  3159. }
  3160. /**************************************************************************\
  3161. * ShowCursor
  3162. *
  3163. * 22-Jul-1991 mikeke Created
  3164. \**************************************************************************/
  3165. FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, ShowCursor, BOOL, bShow)
  3166. int ShowCursor(
  3167. BOOL bShow)
  3168. {
  3169. return (int)NtUserCallOneParam(bShow, SFI_ZZZSHOWCURSOR);
  3170. }
  3171. /**************************************************************************\
  3172. * ShowOwnedPopups
  3173. *
  3174. * 22-Jul-1991 mikeke Created
  3175. \**************************************************************************/
  3176. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ShowOwnedPopups, HWND, hwnd, BOOL, fShow)
  3177. BOOL ShowOwnedPopups(
  3178. HWND hwnd,
  3179. BOOL fShow)
  3180. {
  3181. return (BOOL)NtUserCallHwndParamLock(hwnd, fShow,
  3182. SFI_XXXSHOWOWNEDPOPUPS);
  3183. }
  3184. /**************************************************************************\
  3185. * ShowStartGlass
  3186. *
  3187. * 10-Sep-1992 scottlu Created
  3188. \**************************************************************************/
  3189. FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, ShowStartGlass, DWORD, dwTimeout)
  3190. VOID ShowStartGlass(
  3191. DWORD dwTimeout)
  3192. {
  3193. NtUserCallOneParam(dwTimeout, SFI_ZZZSHOWSTARTGLASS);
  3194. }
  3195. /**************************************************************************\
  3196. * SwapMouseButton
  3197. *
  3198. * 22-Jul-1991 mikeke Created
  3199. \**************************************************************************/
  3200. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SwapMouseButton, BOOL, fSwap)
  3201. BOOL SwapMouseButton(
  3202. BOOL fSwap)
  3203. {
  3204. return (BOOL)NtUserCallOneParam(fSwap, SFI__SWAPMOUSEBUTTON);
  3205. }
  3206. /**************************************************************************\
  3207. * TileChildWindows
  3208. *
  3209. * 22-Jul-1991 mikeke Created
  3210. \**************************************************************************/
  3211. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, TileChildWindows, HWND, hwndParent, UINT, flags)
  3212. BOOL TileChildWindows(
  3213. HWND hwndParent,
  3214. UINT flags)
  3215. {
  3216. return (BOOL)TileWindows(hwndParent, flags, NULL, 0, NULL);
  3217. }
  3218. /**************************************************************************\
  3219. * UnhookWindowsHook
  3220. *
  3221. * 22-Jul-1991 mikeke Created
  3222. \**************************************************************************/
  3223. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, UnhookWindowsHook, int, nCode, HOOKPROC, pfnFilterProc)
  3224. BOOL UnhookWindowsHook(
  3225. int nCode,
  3226. HOOKPROC pfnFilterProc)
  3227. {
  3228. return (BOOL)NtUserCallTwoParam(nCode, (ULONG_PTR)pfnFilterProc,
  3229. SFI_ZZZUNHOOKWINDOWSHOOK);
  3230. }
  3231. /**************************************************************************\
  3232. * UpdateWindow
  3233. *
  3234. * 22-Jul-1991 mikeke Created
  3235. \**************************************************************************/
  3236. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, UpdateWindow, HWND, hwnd)
  3237. BOOL UpdateWindow(
  3238. HWND hwnd)
  3239. {
  3240. PWND pwnd;
  3241. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  3242. return FALSE;
  3243. }
  3244. /*
  3245. * Don't need to do anything if this window does not need any painting
  3246. * and it has no child windows
  3247. */
  3248. if (!NEEDSPAINT(pwnd) && (pwnd->spwndChild == NULL)) {
  3249. return TRUE;
  3250. }
  3251. return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXUPDATEWINDOW);
  3252. }
  3253. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, RegisterShellHookWindow, HWND, hwnd)
  3254. BOOL RegisterShellHookWindow(
  3255. HWND hwnd)
  3256. {
  3257. return (BOOL)NtUserCallHwnd(hwnd, SFI__REGISTERSHELLHOOKWINDOW);
  3258. }
  3259. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DeregisterShellHookWindow, HWND, hwnd)
  3260. BOOL DeregisterShellHookWindow(
  3261. HWND hwnd)
  3262. {
  3263. return (BOOL)NtUserCallHwnd(hwnd, SFI__DEREGISTERSHELLHOOKWINDOW);
  3264. }
  3265. /**************************************************************************\
  3266. * UserRealizePalette
  3267. *
  3268. * 13-Nov-1992 mikeke Created
  3269. \**************************************************************************/
  3270. FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, UserRealizePalette, HDC, hdc)
  3271. UINT UserRealizePalette(
  3272. HDC hdc)
  3273. {
  3274. return (UINT)NtUserCallOneParam((ULONG_PTR)hdc, SFI_XXXREALIZEPALETTE);
  3275. }
  3276. /**************************************************************************\
  3277. * WindowFromDC
  3278. *
  3279. * 22-Jul-1991 mikeke Created
  3280. \**************************************************************************/
  3281. FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, WindowFromDC, HDC, hdc)
  3282. HWND WindowFromDC(
  3283. HDC hdc)
  3284. {
  3285. return (HWND)NtUserCallOneParam((ULONG_PTR)hdc, SFI__WINDOWFROMDC);
  3286. }
  3287. /***************************************************************************\
  3288. * GetWindowRgn
  3289. *
  3290. * Parameters:
  3291. * hwnd -- Window handle
  3292. * hrgn -- Region to copy window region into
  3293. *
  3294. * Returns:
  3295. * Region complexity code
  3296. *
  3297. * Comments:
  3298. * hrgn gets returned in window rect coordinates (not client rect)
  3299. *
  3300. * 30-JUl-1994 ScottLu Created.
  3301. \***************************************************************************/
  3302. FUNCLOG2(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetWindowRgn, HWND, hwnd, HRGN, hrgn)
  3303. int GetWindowRgn(
  3304. HWND hwnd,
  3305. HRGN hrgn)
  3306. {
  3307. int code;
  3308. PWND pwnd;
  3309. if (hrgn == NULL) {
  3310. return ERROR;
  3311. }
  3312. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  3313. return ERROR;
  3314. }
  3315. /*
  3316. * If there is no region selected into this window, then return error
  3317. */
  3318. if (pwnd->hrgnClip == NULL || TestWF(pwnd, WFMAXFAKEREGIONAL)) {
  3319. return ERROR;
  3320. }
  3321. code = CombineRgn(hrgn, KHRGN_TO_HRGN(pwnd->hrgnClip), NULL, RGN_COPY);
  3322. if (code == ERROR) {
  3323. return ERROR;
  3324. }
  3325. /*
  3326. * Offset it to window rect coordinates (not client rect coordinates)
  3327. */
  3328. if (GETFNID(pwnd) != FNID_DESKTOP) {
  3329. code = OffsetRgn(hrgn, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
  3330. }
  3331. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  3332. MirrorRgn(HW(pwnd), hrgn);
  3333. }
  3334. return code;
  3335. }
  3336. /***************************************************************************\
  3337. * GetWindowRgnBox
  3338. *
  3339. * Parameters:
  3340. * hwnd -- Window handle
  3341. * lprc -- Rectangle for bounding box
  3342. *
  3343. * Returns:
  3344. * Region complexity code
  3345. *
  3346. * Comments:
  3347. * This function is designed after GetWindowRgn(), but does not require
  3348. * an HRGN to be passed in since it only returns the complexity code.
  3349. *
  3350. * 06-JUN-2000 JStall Created.
  3351. \***************************************************************************/
  3352. FUNCLOG2(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetWindowRgnBox, HWND, hwnd, LPRECT, lprc)
  3353. int GetWindowRgnBox(
  3354. HWND hwnd,
  3355. LPRECT lprc)
  3356. {
  3357. int code;
  3358. PWND pwnd;
  3359. if (lprc == NULL) {
  3360. return ERROR;
  3361. }
  3362. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  3363. return ERROR;
  3364. }
  3365. /*
  3366. * If there is no region selected into this window, then return error
  3367. */
  3368. if (pwnd->hrgnClip == NULL || TestWF(pwnd, WFMAXFAKEREGIONAL)) {
  3369. return ERROR;
  3370. }
  3371. code = GetRgnBox(KHRGN_TO_HRGN(pwnd->hrgnClip), lprc);
  3372. if (code == ERROR) {
  3373. return ERROR;
  3374. }
  3375. /*
  3376. * Offset it to window rect coordinates (not client rect coordinates)
  3377. */
  3378. if (GETFNID(pwnd) != FNID_DESKTOP) {
  3379. OffsetRect(lprc, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
  3380. }
  3381. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  3382. MirrorWindowRect(pwnd, lprc);
  3383. }
  3384. return code;
  3385. }
  3386. /***************************************************************************\
  3387. * GetActiveKeyboardName
  3388. *
  3389. * Retrieves the active keyboard layout ID from the registry.
  3390. *
  3391. * 01-11-95 JimA Created.
  3392. * 03-06-95 GregoryW Modified to use new registry layout
  3393. \***************************************************************************/
  3394. VOID GetActiveKeyboardName(
  3395. LPWSTR lpszName)
  3396. {
  3397. LPTSTR szKbdActive = TEXT("Active");
  3398. LPTSTR szKbdLayout = TEXT("Keyboard Layout");
  3399. LPTSTR szKbdLayoutPreload = TEXT("Keyboard Layout\\Preload");
  3400. NTSTATUS rc;
  3401. DWORD cbSize;
  3402. HANDLE UserKeyHandle, hKey, hKeyPreload;
  3403. OBJECT_ATTRIBUTES ObjA;
  3404. UNICODE_STRING UnicodeString;
  3405. ULONG CreateDisposition;
  3406. struct {
  3407. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  3408. WCHAR KeyLayoutId[KL_NAMELENGTH];
  3409. } KeyValueId;
  3410. /*
  3411. * Load initial keyboard name ( HKEY_CURRENT_USER\Keyboard Layout\Preload\1 )
  3412. */
  3413. rc = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserKeyHandle);
  3414. if (!NT_SUCCESS(rc)) {
  3415. RIPMSGF1(RIP_WARNING, "Could NOT open HKEY_CURRENT_USER (%lx).", rc);
  3416. wcscpy(lpszName, L"00000409");
  3417. return;
  3418. }
  3419. RtlInitUnicodeString(&UnicodeString, szKbdLayoutPreload);
  3420. InitializeObjectAttributes(&ObjA,
  3421. &UnicodeString,
  3422. OBJ_CASE_INSENSITIVE,
  3423. UserKeyHandle,
  3424. NULL );
  3425. rc = NtOpenKey(&hKey,
  3426. KEY_ALL_ACCESS,
  3427. &ObjA );
  3428. if (NT_SUCCESS(rc)) {
  3429. /*
  3430. * Query the value from the registry.
  3431. */
  3432. RtlInitUnicodeString(&UnicodeString, L"1");
  3433. rc = NtQueryValueKey(hKey,
  3434. &UnicodeString,
  3435. KeyValuePartialInformation,
  3436. &KeyValueId,
  3437. sizeof(KeyValueId),
  3438. &cbSize );
  3439. if (rc == STATUS_BUFFER_OVERFLOW) {
  3440. RIPMSGF0(RIP_WARNING, "Buffer overflow.");
  3441. rc = STATUS_SUCCESS;
  3442. }
  3443. if (NT_SUCCESS(rc)) {
  3444. wcsncpycch(lpszName, (LPWSTR)KeyValueId.KeyInfo.Data, KL_NAMELENGTH - 1);
  3445. lpszName[KL_NAMELENGTH - 1] = L'\0';
  3446. } else {
  3447. /*
  3448. * Error reading value...use default
  3449. */
  3450. wcscpy(lpszName, L"00000409");
  3451. }
  3452. NtClose(hKey);
  3453. NtClose(UserKeyHandle);
  3454. if (IS_IME_ENABLED()) {
  3455. CheckValidLayoutName(lpszName);
  3456. }
  3457. return;
  3458. }
  3459. /*
  3460. * NOTE: The code below is only executed the first time a user logs
  3461. * on after an upgrade from NT3.x to NT4.0.
  3462. *
  3463. * The Preload key does not exist in the registry. Try reading the
  3464. * old registry entry "Keyboard Layout\Active". If it exists, we
  3465. * convert it to the new style Preload key.
  3466. */
  3467. RtlInitUnicodeString(&UnicodeString, szKbdLayout);
  3468. InitializeObjectAttributes(&ObjA,
  3469. &UnicodeString,
  3470. OBJ_CASE_INSENSITIVE,
  3471. UserKeyHandle,
  3472. NULL );
  3473. rc = NtOpenKey(&hKey, KEY_ALL_ACCESS, &ObjA);
  3474. NtClose(UserKeyHandle);
  3475. if (!NT_SUCCESS(rc)) {
  3476. RIPMSGF1(RIP_WARNING,
  3477. "Could not determine active keyboard layout 0x%x.",
  3478. rc);
  3479. wcscpy(lpszName, L"00000409");
  3480. return;
  3481. }
  3482. /*
  3483. * Query the value from the registry.
  3484. */
  3485. RtlInitUnicodeString(&UnicodeString, szKbdActive);
  3486. rc = NtQueryValueKey(hKey,
  3487. &UnicodeString,
  3488. KeyValuePartialInformation,
  3489. &KeyValueId,
  3490. sizeof(KeyValueId),
  3491. &cbSize );
  3492. if (rc == STATUS_BUFFER_OVERFLOW) {
  3493. RIPMSGF0(RIP_WARNING, "Buffer overflow.");
  3494. rc = STATUS_SUCCESS;
  3495. }
  3496. if (NT_SUCCESS(rc)) {
  3497. wcsncpycch(lpszName, (LPWSTR)KeyValueId.KeyInfo.Data, KL_NAMELENGTH - 1);
  3498. lpszName[KL_NAMELENGTH - 1] = L'\0';
  3499. } else {
  3500. /*
  3501. * Error reading value...use default
  3502. */
  3503. RIPMSGF1(RIP_WARNING,
  3504. "Could not query active keyboard layout 0x%x.",
  3505. rc);
  3506. wcscpy(lpszName, L"00000409");
  3507. NtClose(hKey);
  3508. return;
  3509. }
  3510. /*
  3511. * if 'Active' keyboard layout is for Japanese/Korean layout. just put
  3512. * IME prefix, because user prefer to have keyboard layout with IME as
  3513. * default.
  3514. */
  3515. if (IS_IME_ENABLED()) {
  3516. UINT wLanguageId = (UINT)wcstoul(lpszName, NULL, 16);
  3517. /*
  3518. * Default keyboard layout values.
  3519. *
  3520. * [LATER, if needed]
  3521. *
  3522. * The hard-codeed default value might be wanted
  3523. * come from registry or somewhere...
  3524. */
  3525. CONST LPWSTR lpszJapaneseDefaultLayout = L"E0010411";
  3526. CONST LPWSTR lpszKoreanDefaultLayout = L"E0010412";
  3527. /*
  3528. * Need to mask off hi-word to look up locale ID, because
  3529. * NEC PC-9800 Series version of Windows NT 3.5 contains
  3530. * bogus value in hi-word.
  3531. */
  3532. wLanguageId &= 0x0000FFFF;
  3533. if (PRIMARYLANGID(wLanguageId) == LANG_JAPANESE) {
  3534. /*
  3535. * Set Japanese default layout Id.
  3536. */
  3537. wcscpy(lpszName,lpszJapaneseDefaultLayout);
  3538. } else if (PRIMARYLANGID(wLanguageId) == LANG_KOREAN) {
  3539. /*
  3540. * Set Korean default layout Id.
  3541. */
  3542. wcscpy(lpszName,lpszKoreanDefaultLayout);
  3543. }
  3544. }
  3545. /*
  3546. * We have the Active value. Now create the Preload key.
  3547. */
  3548. RtlInitUnicodeString(&UnicodeString, L"Preload");
  3549. InitializeObjectAttributes(&ObjA,
  3550. &UnicodeString,
  3551. OBJ_CASE_INSENSITIVE,
  3552. hKey,
  3553. NULL );
  3554. rc = NtCreateKey(&hKeyPreload,
  3555. STANDARD_RIGHTS_WRITE |
  3556. KEY_QUERY_VALUE |
  3557. KEY_ENUMERATE_SUB_KEYS |
  3558. KEY_SET_VALUE |
  3559. KEY_CREATE_SUB_KEY,
  3560. &ObjA,
  3561. 0,
  3562. NULL,
  3563. 0,
  3564. &CreateDisposition );
  3565. if (!NT_SUCCESS(rc)) {
  3566. RIPMSGF1(RIP_WARNING, "Could NOT create Preload key (0x%x).", rc);
  3567. NtClose(hKey);
  3568. return;
  3569. }
  3570. /*
  3571. * Set the new value entry.
  3572. */
  3573. RtlInitUnicodeString(&UnicodeString, L"1");
  3574. rc = NtSetValueKey(hKeyPreload,
  3575. &UnicodeString,
  3576. 0,
  3577. REG_SZ,
  3578. lpszName,
  3579. (wcslen(lpszName) + 1) * sizeof(WCHAR));
  3580. if (!NT_SUCCESS(rc)) {
  3581. RIPMSGF1(RIP_WARNING,
  3582. "Could NOT create value entry 1 for Preload key (0x%x).",
  3583. rc);
  3584. NtClose(hKey);
  3585. NtClose(hKeyPreload);
  3586. return;
  3587. }
  3588. /*
  3589. * Success: attempt to delete the Active value key.
  3590. */
  3591. RtlInitUnicodeString(&UnicodeString, szKbdActive);
  3592. rc = NtDeleteValueKey(hKey, &UnicodeString);
  3593. if (!NT_SUCCESS(rc)) {
  3594. RIPMSGF1(RIP_WARNING, "Could NOT delete value key 'Active'.", rc);
  3595. }
  3596. NtClose(hKey);
  3597. NtClose(hKeyPreload);
  3598. }
  3599. /***************************************************************************\
  3600. * LoadPreloadKeyboardLayouts
  3601. *
  3602. * Loads the keyboard layouts stored under the Preload key in the user's
  3603. * registry. The first layout, the default, was already loaded.
  3604. *
  3605. * 03-06-95 GregoryW Created.
  3606. \***************************************************************************/
  3607. // size allows up to 999 preloaded!!!!!
  3608. #define NSIZEPRELOAD (4)
  3609. VOID LoadPreloadKeyboardLayouts(
  3610. VOID)
  3611. {
  3612. UINT i;
  3613. WCHAR szPreLoadee[NSIZEPRELOAD];
  3614. WCHAR lpszName[KL_NAMELENGTH];
  3615. if (!ISREMOTESESSION()) {
  3616. /*
  3617. * Console doesn't have a client layout, so start from 2.
  3618. */
  3619. i = 2;
  3620. } else {
  3621. /*
  3622. * Client might have specified a keyboard layout, if this
  3623. * is so, then Preload\1 was not loaded, so start from 1.
  3624. */
  3625. i = 1;
  3626. }
  3627. for (; i < 1000; i++) {
  3628. wsprintf(szPreLoadee, L"%d", i );
  3629. if ((GetPrivateProfileStringW(
  3630. L"Preload",
  3631. szPreLoadee,
  3632. L"",
  3633. lpszName,
  3634. KL_NAMELENGTH,
  3635. L"keyboardlayout.ini") == -1 ) || (*lpszName == L'\0')) {
  3636. break;
  3637. }
  3638. LoadKeyboardLayoutW(lpszName, KLF_REPLACELANG |KLF_SUBSTITUTE_OK |KLF_NOTELLSHELL);
  3639. }
  3640. }
  3641. LPWSTR GetKeyboardDllName(
  3642. LPWSTR pwszLibIn,
  3643. LPWSTR pszKLName,
  3644. LANGID langid,
  3645. PUINT puFlags,
  3646. PUINT pKbdInputLocale)
  3647. {
  3648. NTSTATUS Status;
  3649. WCHAR awchKL[KL_NAMELENGTH];
  3650. WCHAR awchKLRegKey[NSZKLKEY];
  3651. LPWSTR lpszKLRegKey = &awchKLRegKey[0];
  3652. LPWSTR pwszLib;
  3653. LPWSTR pwszId;
  3654. UINT wLayoutId;
  3655. UNICODE_STRING UnicodeString;
  3656. OBJECT_ATTRIBUTES OA;
  3657. HANDLE hKey;
  3658. DWORD cbSize;
  3659. struct {
  3660. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  3661. WCHAR awchLibName[CCH_KL_LIBNAME];
  3662. } KeyFile;
  3663. struct {
  3664. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  3665. WCHAR awchId[CCH_KL_ID];
  3666. } KeyId;
  3667. struct {
  3668. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  3669. DWORD Attributes;
  3670. } KeyAttributes;
  3671. if (pszKLName == NULL) {
  3672. return NULL;
  3673. }
  3674. if (langid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)) {
  3675. langid = (UINT)wcstoul(pszKLName, NULL, 16);
  3676. TAGMSGF1(DBGTAG_KBD, "langid is acquired from pszKLName: %04x", langid);
  3677. } else {
  3678. TAGMSGF1(DBGTAG_KBD, "langid is passed in: %04x", langid);
  3679. }
  3680. /*
  3681. * Substitute Layout if required.
  3682. */
  3683. if (*puFlags & KLF_SUBSTITUTE_OK) {
  3684. GetPrivateProfileStringW(L"Substitutes",
  3685. pszKLName,
  3686. pszKLName,
  3687. awchKL,
  3688. ARRAY_SIZE(awchKL),
  3689. L"keyboardlayout.ini");
  3690. /*
  3691. * #273562 : Flush the registry cache, because the cpanel applet
  3692. * destroys and recreates the Substitutes section a lot, which
  3693. * would otherwise leave us with STATUS_KEY_DELETED.
  3694. */
  3695. WritePrivateProfileStringW(NULL, NULL, NULL, NULL);
  3696. awchKL[KL_NAMELENGTH - 1] = L'\0';
  3697. wcscpy(pszKLName, awchKL);
  3698. }
  3699. wLayoutId = (UINT)wcstoul(pszKLName, NULL, 16);
  3700. /*
  3701. * Get DLL name from the registry, load it, and get the entry point.
  3702. */
  3703. pwszLib = NULL;
  3704. wcscpy(lpszKLRegKey, szKLKey);
  3705. wcscat(lpszKLRegKey, pszKLName);
  3706. RtlInitUnicodeString(&UnicodeString, lpszKLRegKey);
  3707. InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
  3708. if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) {
  3709. /*
  3710. * Read the "Layout File" value.
  3711. */
  3712. RtlInitUnicodeString(&UnicodeString, szKLFile);
  3713. Status = NtQueryValueKey(hKey,
  3714. &UnicodeString,
  3715. KeyValuePartialInformation,
  3716. &KeyFile,
  3717. sizeof(KeyFile),
  3718. &cbSize);
  3719. if (Status == STATUS_BUFFER_OVERFLOW) {
  3720. RIPMSGF0(RIP_WARNING, "(Layout File) - Buffer overflow.");
  3721. Status = STATUS_SUCCESS;
  3722. }
  3723. if (NT_SUCCESS(Status)) {
  3724. pwszLib = (LPWSTR)KeyFile.KeyInfo.Data;
  3725. pwszLib[CCH_KL_LIBNAME - 1] = L'\0';
  3726. } else {
  3727. RIPMSGF1(RIP_WARNING,
  3728. "Failed to get the DLL name for %ws",
  3729. pszKLName);
  3730. }
  3731. RtlInitUnicodeString(&UnicodeString, szKLAttributes);
  3732. Status = NtQueryValueKey(hKey,
  3733. &UnicodeString,
  3734. KeyValuePartialInformation,
  3735. &KeyAttributes,
  3736. sizeof(KeyAttributes),
  3737. &cbSize);
  3738. if (NT_SUCCESS(Status)) {
  3739. if ((*((PDWORD)KeyAttributes.KeyInfo.Data) & ~KLF_ATTRMASK) != 0) {
  3740. RIPMSGF1(RIP_WARNING,
  3741. "Unexpected attributes %lx",
  3742. *((PDWORD)KeyAttributes.KeyInfo.Data));
  3743. }
  3744. *puFlags |= (*(PDWORD)KeyAttributes.KeyInfo.Data & KLF_ATTRMASK);
  3745. }
  3746. /*
  3747. * If the high word of wLayoutId is 0xE??? then this is an IME based
  3748. * keyboard layout.
  3749. */
  3750. if (IS_IME_KBDLAYOUT(wLayoutId)) {
  3751. wLayoutId = (UINT)HIWORD(wLayoutId);
  3752. } else if (HIWORD(wLayoutId)) {
  3753. /*
  3754. * If the high word of wLayoutId is non-null then read the
  3755. * "Layout ID" value. Layout IDs start at 1, increase
  3756. * sequentially and are unique.
  3757. */
  3758. RtlInitUnicodeString(&UnicodeString, szKLId);
  3759. Status = NtQueryValueKey(hKey,
  3760. &UnicodeString,
  3761. KeyValuePartialInformation,
  3762. &KeyId,
  3763. sizeof(KeyId),
  3764. &cbSize);
  3765. if (Status == STATUS_BUFFER_OVERFLOW) {
  3766. RIPMSGF0(RIP_WARNING, "Buffer overflow.");
  3767. Status = STATUS_SUCCESS;
  3768. }
  3769. if (NT_SUCCESS(Status)) {
  3770. pwszId = (LPWSTR)KeyId.KeyInfo.Data;
  3771. pwszId[CCH_KL_ID - 1] = L'\0';
  3772. wLayoutId = (wcstol(pwszId, NULL, 16) & 0x0fff) | 0xf000;
  3773. } else {
  3774. wLayoutId = (UINT)0xfffe ; // error in layout ID, load separately
  3775. }
  3776. }
  3777. NtClose(hKey);
  3778. } else {
  3779. /*
  3780. * Get DLL name from the registry, load it, and get the entry point.
  3781. */
  3782. pwszLib = NULL;
  3783. RtlInitUnicodeString(&UnicodeString,
  3784. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Keyboard Layout");
  3785. InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
  3786. if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) {
  3787. RtlInitUnicodeString(&UnicodeString, pszKLName);
  3788. Status = NtQueryValueKey(hKey,
  3789. &UnicodeString,
  3790. KeyValuePartialInformation,
  3791. &KeyFile,
  3792. sizeof(KeyFile),
  3793. &cbSize);
  3794. if (Status == STATUS_BUFFER_OVERFLOW) {
  3795. RIPMSGF0(RIP_WARNING, "Buffer overflow.");
  3796. Status = STATUS_SUCCESS;
  3797. }
  3798. if (NT_SUCCESS(Status)) {
  3799. pwszLib = (LPWSTR)KeyFile.KeyInfo.Data;
  3800. pwszLib[CCH_KL_LIBNAME - 1] = L'\0';
  3801. }
  3802. NtClose(hKey);
  3803. }
  3804. if (pwszLib == NULL) {
  3805. RIPMSGF1(RIP_WARNING,
  3806. "Failed to get the library name for %ws",
  3807. pszKLName);
  3808. }
  3809. }
  3810. *pKbdInputLocale = (UINT)MAKELONG(LOWORD(langid),LOWORD(wLayoutId));
  3811. if (pwszLib == NULL) {
  3812. if (ISREMOTESESSION() && IS_IME_KBDLAYOUT(wLayoutId)) {
  3813. /*
  3814. * -- port from HYDRA --
  3815. * Could not find the keyboard KL for FE, so give them some reasonable one.
  3816. * If the high word of wLayoutId is 0xE??? then this is an IME based
  3817. * keyboard layout.
  3818. * And, the safe KL name is KBDJPN.DLL for Japanese.
  3819. * or KBDKOR.DLL for Korean
  3820. * or KBDUS.DLL for other Far East
  3821. */
  3822. if (PRIMARYLANGID(langid) == LANG_JAPANESE) {
  3823. pwszLib = pwszKLLibSafetyJPN;
  3824. *pKbdInputLocale = wKbdLocaleSafetyJPN;
  3825. } else if (PRIMARYLANGID(langid) == LANG_KOREAN) {
  3826. pwszLib = pwszKLLibSafetyKOR;
  3827. *pKbdInputLocale = wKbdLocaleSafetyKOR;
  3828. } else {
  3829. pwszLib = pwszKLLibSafety;
  3830. *pKbdInputLocale = MAKELONG(LOWORD(langid), LOWORD(langid));
  3831. }
  3832. } else if (*puFlags & KLF_INITTIME) {
  3833. pwszLib = pwszKLLibSafety;
  3834. *pKbdInputLocale = wKbdLocaleSafety;
  3835. } else {
  3836. RIPMSG1(RIP_WARNING, "no DLL name for %ws", pszKLName);
  3837. /*
  3838. * We're going to use the fallback layout...
  3839. * This could happen when IMM32 is trying to unload the IME,
  3840. * by making any non IME keyboard layout tentatively active.
  3841. */
  3842. pwszLib = pwszKLLibSafety;
  3843. *pKbdInputLocale = wKbdLocaleSafety;
  3844. }
  3845. }
  3846. if (pwszLib) {
  3847. wcscpy(pwszLibIn, pwszLib);
  3848. pwszLib = pwszLibIn;
  3849. }
  3850. return pwszLib;
  3851. }
  3852. /***************************************************************************\
  3853. * OpenKeyboardLayoutFile
  3854. *
  3855. * Opens a layout file and computes the table offset.
  3856. *
  3857. * 01-11-95 JimA Moved LoadLibrary code from server.
  3858. \***************************************************************************/
  3859. HANDLE OpenKeyboardLayoutFileWorker(
  3860. LPWSTR pwszLib,
  3861. LPWSTR lpszKLName,
  3862. CONST UINT* puFlags,
  3863. PUINT poffTable,
  3864. OUT OPTIONAL PKBDTABLE_MULTI_INTERNAL pKbdTableMultiIn)
  3865. {
  3866. WCHAR awchRealLayoutFile[MAX_PATH];
  3867. HANDLE hLibModule, hLibMulti = NULL;
  3868. WCHAR awchModName[MAX_PATH];
  3869. PKBDTABLES (*pfn)(void); // @1
  3870. PKBDNLSTABLES (* pfnNls)(void); // @2
  3871. BOOL (*pfnLayerNT4)(LPWSTR); // @3
  3872. BOOL (*pfnLayer)(HKL, LPWSTR, PCLIENTKEYBOARDTYPE, LPVOID); // @5
  3873. BOOL (*pfnMulti)(PKBDTABLE_MULTI); // @6
  3874. TAGMSGF1(DBGTAG_KBD, "opening '%S'", pwszLib);
  3875. RetryLoad:
  3876. hLibModule = LoadLibraryW(pwszLib);
  3877. if (hLibModule == NULL) {
  3878. RIPMSG1(RIP_WARNING, "Keyboard Layout: cannot load %ws", pwszLib);
  3879. /*
  3880. * It is OK to fail to load DLL here. If this ever happens, the
  3881. * fallback keyboard layout built in win32k.sys shall be used.
  3882. */
  3883. return NULL;
  3884. }
  3885. if (pwszLib != pwszKLLibSafety) {
  3886. /*
  3887. * if the layout driver is not "REAL" layout driver, the driver has
  3888. * "3" or "5" entry point, then we call this to get real layout driver..
  3889. * This is neccesary for Japanese and Korean systems. because their
  3890. * keyboard layout driver is "KBDJPN.DLL" or "KBDKOR.DLL", but its
  3891. * "REAL" driver becomes different depending their keyboard hardware.
  3892. */
  3893. /*
  3894. * Get the entrypoints.
  3895. */
  3896. pfnLayerNT4 = (BOOL(*)(LPWSTR))GetProcAddress(hLibModule, (LPCSTR)3);
  3897. pfnLayer = (BOOL(*)(HKL, LPWSTR, PCLIENTKEYBOARDTYPE, LPVOID))GetProcAddress(hLibModule, (LPCSTR)5);
  3898. if (pKbdTableMultiIn && !ISREMOTESESSION()) {
  3899. pfnMulti = (BOOL(*)(PKBDTABLE_MULTI))GetProcAddress(hLibModule, (LPCSTR)6);
  3900. } else {
  3901. pfnMulti = NULL;
  3902. }
  3903. /*
  3904. * Firstly check if multiple layout is included.
  3905. * This needs to be done before the dll name is redirected to
  3906. * the real one (if layered).
  3907. */
  3908. if (pfnMulti) {
  3909. UserAssert(pKbdTableMultiIn);
  3910. UserAssert(!ISREMOTESESSION());
  3911. if (pfnMulti(&pKbdTableMultiIn->multi)) {
  3912. UINT i;
  3913. /*
  3914. * Do multi layout stuff only if the layout dll returns
  3915. * a legitimate result.
  3916. */
  3917. if (pKbdTableMultiIn->multi.nTables < KBDTABLE_MULTI_MAX) {
  3918. for (i = 0; i < pKbdTableMultiIn->multi.nTables; ++i) {
  3919. UINT uiOffset;
  3920. TAGMSGF2(DBGTAG_KBD | RIP_THERESMORE, "opening %d, %S", i, pKbdTableMultiIn->multi.aKbdTables[i].wszDllName);
  3921. UserAssert(i < KBDTABLE_MULTI_MAX);
  3922. pKbdTableMultiIn->files[i].hFile = OpenKeyboardLayoutFileWorker(pKbdTableMultiIn->multi.aKbdTables[i].wszDllName,
  3923. NULL,
  3924. puFlags,
  3925. &uiOffset,
  3926. NULL);
  3927. TAGMSG1(DBGTAG_KBD, "hFile = %p", pKbdTableMultiIn->files[i].hFile);
  3928. if (pKbdTableMultiIn->files[i].hFile) {
  3929. pKbdTableMultiIn->files[i].wTable = LOWORD(uiOffset);
  3930. pKbdTableMultiIn->files[i].wNls = HIWORD(uiOffset);
  3931. }
  3932. }
  3933. } else {
  3934. pKbdTableMultiIn->multi.nTables = 0;
  3935. RIPMSGF2(RIP_ERROR, "KL=%S returned bogus nTables=%x",
  3936. lpszKLName, pKbdTableMultiIn->multi.nTables);
  3937. }
  3938. }
  3939. }
  3940. /*
  3941. * If there are private entries, call them.
  3942. */
  3943. if (pfnLayer || pfnLayerNT4) {
  3944. HKL hkl;
  3945. UNICODE_STRING UnicodeString;
  3946. CLIENTKEYBOARDTYPE clientKbdType;
  3947. PCLIENTKEYBOARDTYPE pClientKbdType = NULL;
  3948. UserAssert(lpszKLName);
  3949. RtlInitUnicodeString(&UnicodeString, lpszKLName);
  3950. RtlUnicodeStringToInteger(&UnicodeString, 0x10, (PULONG)&hkl);
  3951. /*
  3952. * When we reach here, the layout DLL may have KBDNLSTABLE
  3953. * even if we fail from now on. Our temporary layout
  3954. * dll should have the fallback tables for just in case.
  3955. */
  3956. if (ISREMOTESESSION() && GetClientKeyboardType(&clientKbdType)) {
  3957. pClientKbdType = &clientKbdType;
  3958. }
  3959. /*
  3960. * Call the entry.
  3961. * a. NT5 / Hydra (oridinal=5)
  3962. * b. NT4 compatible (3)
  3963. */
  3964. if ((pfnLayer && pfnLayer(hkl, awchRealLayoutFile, pClientKbdType, NULL)) ||
  3965. (pfnLayerNT4 && pfnLayerNT4(awchRealLayoutFile))) {
  3966. HANDLE hLibModuleNew;
  3967. /*
  3968. * Try to load "REAL" keyboard layout file.
  3969. */
  3970. TAGMSG1(DBGTAG_KBD, "awchRealLayoutFile='%S'", awchRealLayoutFile);
  3971. if (hLibModuleNew = LoadLibraryW(awchRealLayoutFile)) {
  3972. /*
  3973. * Set "REAL" layout file name.
  3974. */
  3975. pwszLib = awchRealLayoutFile;
  3976. /*
  3977. * Unload temporary layout driver.
  3978. */
  3979. FreeLibrary(hLibModule);
  3980. /*
  3981. * Updates it.
  3982. */
  3983. hLibModule = hLibModuleNew;
  3984. }
  3985. }
  3986. }
  3987. }
  3988. /*
  3989. * HACK Part 1! Get the pointer to the layout table and
  3990. * change it to a virtual offset. The server will then
  3991. * use this offset when poking through the file header to
  3992. * locate the table within the file.
  3993. */
  3994. pfn = (PKBDTABLES(*)(void))GetProcAddress(hLibModule, (LPCSTR)1);
  3995. if (pfn == NULL) {
  3996. RIPMSGF0(RIP_ERROR, "cannot get proc addr of '1'");
  3997. if (pKbdTableMultiIn) {
  3998. /*
  3999. * Main load somehow failed. Need to clean up
  4000. * the dynamic layout switching stuff.
  4001. */
  4002. UINT i;
  4003. RIPMSGF0(RIP_WARNING, "multi table exists, cleaning up");
  4004. for (i = 0; i < pKbdTableMultiIn->multi.nTables && i < KBDTABLE_MULTI_MAX; ++i) {
  4005. if (pKbdTableMultiIn->files[i].hFile) {
  4006. NtClose(pKbdTableMultiIn->files[i].hFile);
  4007. pKbdTableMultiIn->files[i].hFile = NULL;
  4008. }
  4009. }
  4010. pKbdTableMultiIn->multi.nTables = 0;
  4011. }
  4012. if ((*puFlags & KLF_INITTIME) && (pwszLib != pwszKLLibSafety)) {
  4013. pwszLib = pwszKLLibSafety;
  4014. goto RetryLoad;
  4015. }
  4016. return NULL;
  4017. }
  4018. *poffTable = (UINT)((PBYTE)pfn() - (PBYTE)hLibModule);
  4019. if (pKbdTableMultiIn) {
  4020. /*
  4021. * Save the toplevel Dll name
  4022. */
  4023. lstrcpyn(pKbdTableMultiIn->wszDllName, pwszLib, ARRAY_SIZE(pKbdTableMultiIn->wszDllName));
  4024. pKbdTableMultiIn->wszDllName[ARRAY_SIZE(pKbdTableMultiIn->wszDllName) - 1] = 0;
  4025. TAGMSGF1(DBGTAG_KBD, " real DllName is '%ls'", pKbdTableMultiIn->wszDllName);
  4026. }
  4027. pfnNls = (PKBDNLSTABLES(*)(void))GetProcAddress(hLibModule, (LPCSTR)2);
  4028. if (pfnNls != NULL) {
  4029. UINT offNlsTable;
  4030. offNlsTable = (UINT)((PBYTE)pfnNls() - (PBYTE)hLibModule);
  4031. TAGMSGF2(DBGTAG_KBD | RIP_THERESMORE, "Offset to KBDTABLES = %d (%x)", *poffTable, *poffTable);
  4032. TAGMSGF2(DBGTAG_KBD, "Offset to KBDNLSTABLES = %d (%x)", offNlsTable, offNlsTable);
  4033. /*
  4034. * Combine these offsets...
  4035. *
  4036. * LOWORD(*poffTable) = Offset to KBDTABLES.
  4037. * HIWORD(*poffTable) = Offset to KBDNLSTABLES.
  4038. */
  4039. *poffTable |= (offNlsTable << 16);
  4040. }
  4041. /*
  4042. * Open the dll for read access.
  4043. */
  4044. GetModuleFileName(hLibModule, awchModName, ARRAY_SIZE(awchModName));
  4045. FreeLibrary(hLibModule);
  4046. return CreateFileW(awchModName,
  4047. GENERIC_READ,
  4048. FILE_SHARE_READ,
  4049. NULL,
  4050. OPEN_EXISTING,
  4051. 0,
  4052. NULL);
  4053. }
  4054. HANDLE OpenKeyboardLayoutFile(
  4055. LPWSTR lpszKLName,
  4056. LANGID langid,
  4057. PUINT puFlags,
  4058. PUINT poffTable,
  4059. PUINT pKbdInputLocale,
  4060. OUT OPTIONAL PKBDTABLE_MULTI_INTERNAL pKbdTableMultiIn)
  4061. {
  4062. LPWSTR pwszLib;
  4063. WCHAR awchModName[MAX_PATH];
  4064. if (pKbdTableMultiIn) {
  4065. RtlZeroMemory(pKbdTableMultiIn, sizeof(*pKbdTableMultiIn));
  4066. }
  4067. pwszLib = GetKeyboardDllName(awchModName, lpszKLName, langid, puFlags, pKbdInputLocale);
  4068. if (pwszLib == NULL) {
  4069. return NULL;
  4070. }
  4071. TAGMSG0(DBGTAG_KBD, "=================");
  4072. TAGMSGF1(DBGTAG_KBD, "loading '%S'", lpszKLName);
  4073. TAGMSGF1(DBGTAG_KBD, "input locale is %08x", *pKbdInputLocale);
  4074. return OpenKeyboardLayoutFileWorker(pwszLib, lpszKLName, puFlags, poffTable, pKbdTableMultiIn);
  4075. }
  4076. /***************************************************************************\
  4077. * LoadKeyboardLayoutEx
  4078. *
  4079. * Loads a keyboard translation table from a dll, replacing the layout associated
  4080. * with hkl. This routine is needed to provide Win95 compatibility.
  4081. *
  4082. * 10-27-95 GregoryW Created.
  4083. \***************************************************************************/
  4084. HKL LoadKeyboardLayoutWorker(
  4085. HKL hkl,
  4086. LPCWSTR lpszKLName,
  4087. LANGID langid,
  4088. UINT uFlags,
  4089. BOOL fFailSafe)
  4090. {
  4091. UINT offTable;
  4092. KBDTABLE_MULTI_INTERNAL kbdTableMulti;
  4093. UINT i;
  4094. UINT KbdInputLocale;
  4095. HANDLE hFile;
  4096. HKL hKbdLayout;
  4097. WCHAR awchKL[KL_NAMELENGTH];
  4098. TAGMSGF1(DBGTAG_KBD, "called with KLNAME=%S", lpszKLName);
  4099. /*
  4100. * If there is a substitute keyboard layout OpenKeyboardLayoutFile returns
  4101. * the substitute keyboard layout name to load.
  4102. */
  4103. wcsncpy(awchKL, lpszKLName, KL_NAMELENGTH - 1);
  4104. awchKL[KL_NAMELENGTH - 1] = L'\0';
  4105. /*
  4106. * "langid" is non-zero to propagate the client side
  4107. * input locale. This should be zero for the console
  4108. * session.
  4109. */
  4110. UserAssert(langid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) || ISREMOTESESSION());
  4111. /*
  4112. * Open the layout file
  4113. */
  4114. hFile = OpenKeyboardLayoutFile(awchKL, langid, &uFlags, &offTable, &KbdInputLocale, &kbdTableMulti);
  4115. if (hFile == NULL) {
  4116. RIPMSGF1(RIP_WARNING, "Couldn't open layout file for '%ws'", awchKL);
  4117. if (!fFailSafe && (uFlags & KLF_FAILSAFE) == 0) {
  4118. // If not fail safe mode, just bail to fail.
  4119. return NULL;
  4120. }
  4121. uFlags &= ~KLF_SUBSTITUTE_OK;
  4122. /*
  4123. * If the first attempt fails, we should not try to setup the
  4124. * dynamic switching.
  4125. */
  4126. kbdTableMulti.multi.nTables = 0;
  4127. if (wcscmp(awchKL, L"00000409")) {
  4128. wcscpy(awchKL, L"00000409");
  4129. hFile = OpenKeyboardLayoutFile(awchKL, langid, &uFlags, &offTable, &KbdInputLocale, NULL);
  4130. }
  4131. }
  4132. /*
  4133. * Call the server to read the keyboard tables. Note that the server
  4134. * will close the file handle when it is done.
  4135. */
  4136. hKbdLayout = _LoadKeyboardLayoutEx(hFile, offTable,
  4137. &kbdTableMulti,
  4138. hkl, awchKL, KbdInputLocale, uFlags);
  4139. NtClose(hFile);
  4140. /*
  4141. * Free opened files for dynamic layout switching.
  4142. */
  4143. for (i = 0; i < kbdTableMulti.multi.nTables && i < KBDTABLE_MULTI_MAX; ++i) {
  4144. if (kbdTableMulti.files[i].hFile) {
  4145. NtClose(kbdTableMulti.files[i].hFile);
  4146. }
  4147. }
  4148. CliImmInitializeHotKeys(ISHK_ADD, UlongToHandle(KbdInputLocale));
  4149. return hKbdLayout;
  4150. }
  4151. FUNCLOG3(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutEx, HKL, hkl, LPCWSTR, lpszKLName, UINT, uFlags)
  4152. HKL LoadKeyboardLayoutEx(
  4153. HKL hkl,
  4154. LPCWSTR lpszKLName,
  4155. UINT uFlags)
  4156. {
  4157. /*
  4158. * NULL hkl is not allowed.
  4159. */
  4160. if (hkl == (HKL)NULL) {
  4161. return NULL;
  4162. }
  4163. return LoadKeyboardLayoutWorker(hkl, lpszKLName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), uFlags, FALSE);
  4164. }
  4165. /***************************************************************************\
  4166. * LoadKeyboardLayout
  4167. *
  4168. * Loads a keyboard translation table from a dll.
  4169. *
  4170. * 01-09-95 JimA Moved LoadLibrary code from server.
  4171. \***************************************************************************/
  4172. FUNCLOG2(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutW, LPCWSTR, lpszKLName, UINT, uFlags)
  4173. HKL LoadKeyboardLayoutW(
  4174. LPCWSTR lpszKLName,
  4175. UINT uFlags)
  4176. {
  4177. return LoadKeyboardLayoutWorker(NULL,
  4178. lpszKLName,
  4179. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  4180. uFlags,
  4181. FALSE);
  4182. }
  4183. FUNCLOG2(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutA, LPCSTR, lpszKLName, UINT, uFlags)
  4184. HKL LoadKeyboardLayoutA(
  4185. LPCSTR lpszKLName,
  4186. UINT uFlags)
  4187. {
  4188. WCHAR awchKLName[MAX_PATH];
  4189. LPWSTR lpBuffer = awchKLName;
  4190. if (!MBToWCS(lpszKLName, -1, &lpBuffer, sizeof(awchKLName), FALSE)) {
  4191. return (HKL)NULL;
  4192. }
  4193. return LoadKeyboardLayoutW(awchKLName, uFlags);
  4194. }
  4195. BOOL UnloadKeyboardLayout(
  4196. IN HKL hkl)
  4197. {
  4198. BOOL fRet = NtUserUnloadKeyboardLayout(hkl);
  4199. if (fRet) {
  4200. CliImmInitializeHotKeys(ISHK_REMOVE, hkl);
  4201. return TRUE;
  4202. }
  4203. return FALSE;
  4204. }
  4205. /**************************************************************************\
  4206. * GetKeyboardLayout
  4207. *
  4208. * 01-17-95 GregoryW Created
  4209. \**************************************************************************/
  4210. FUNCLOG1(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, GetKeyboardLayout, DWORD, idThread)
  4211. HKL GetKeyboardLayout(
  4212. DWORD idThread)
  4213. {
  4214. return (HKL)NtUserCallOneParam(idThread, SFI__GETKEYBOARDLAYOUT);
  4215. }
  4216. FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, SetDebugErrorLevel, DWORD, dwLevel)
  4217. VOID SetDebugErrorLevel(
  4218. DWORD dwLevel)
  4219. {
  4220. UNREFERENCED_PARAMETER(dwLevel);
  4221. }
  4222. VOID CheckValidLayoutName(
  4223. LPWSTR lpszKLName)
  4224. {
  4225. UINT wLayoutId;
  4226. WCHAR awchKLRegKey[NSZKLKEY];
  4227. LPWSTR lpszKLRegKey = &awchKLRegKey[0];
  4228. OBJECT_ATTRIBUTES OA;
  4229. HANDLE hKey;
  4230. UNICODE_STRING UnicodeString;
  4231. UserAssert(IS_IME_ENABLED());
  4232. wLayoutId = (UINT)wcstoul(lpszKLName, NULL, 16);
  4233. if (IS_IME_KBDLAYOUT(wLayoutId)) {
  4234. /*
  4235. * If it's an IME layout, we need to check if the layout name exists
  4236. * in the HKEY_LOCAL_MACHINE. If we've upgraded from NT 3.51 the
  4237. * corresponding entry might be lost because those process-type IMEs
  4238. * that are supported on NT 3.51 are not supported in NT 4.0.
  4239. */
  4240. wcscpy(lpszKLRegKey, szKLKey);
  4241. wcscat(lpszKLRegKey, lpszKLName);
  4242. RtlInitUnicodeString(&UnicodeString, lpszKLRegKey);
  4243. InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
  4244. if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) {
  4245. NtClose(hKey);
  4246. } else {
  4247. /*
  4248. * Quick and dirty way to make the fallback name...
  4249. */
  4250. lpszKLName[0] = lpszKLName[1] = lpszKLName[2] = lpszKLName[3] = L'0';
  4251. }
  4252. }
  4253. }
  4254. /**************************************************************************\
  4255. * GetProcessDefaultLayout
  4256. *
  4257. * 22-Jan-1998 SamerA Created
  4258. \**************************************************************************/
  4259. BOOL WINAPI GetProcessDefaultLayout(
  4260. DWORD *pdwDefaultLayout)
  4261. {
  4262. return (BOOL)NtUserCallOneParam((ULONG_PTR)pdwDefaultLayout,
  4263. SFI__GETPROCESSDEFAULTLAYOUT);
  4264. }
  4265. /**************************************************************************\
  4266. * SetProcessDefaultLayout
  4267. *
  4268. * 22-Jan-1998 SamerA Created
  4269. \**************************************************************************/
  4270. FUNCLOG1(LOG_GENERAL, BOOL, WINAPI, SetProcessDefaultLayout, DWORD, dwDefaultLayout)
  4271. BOOL WINAPI SetProcessDefaultLayout(
  4272. DWORD dwDefaultLayout)
  4273. {
  4274. return (BOOL)NtUserCallOneParam(dwDefaultLayout, SFI__SETPROCESSDEFAULTLAYOUT);
  4275. }
  4276. /***************************************************************************\
  4277. * IsWinEventHookInstalled
  4278. *
  4279. * History:
  4280. * Jul-18-2000 DwayneN Created
  4281. \***************************************************************************/
  4282. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWinEventHookInstalled, DWORD, event)
  4283. BOOL
  4284. IsWinEventHookInstalled(
  4285. DWORD event)
  4286. {
  4287. /*
  4288. * We need to ensure that we are a GUI thread. If we fail to convert
  4289. * to a GUI thread, we have to return TRUE to indicate that there might
  4290. * be a hook installed for the event - since we can't check it for sure.
  4291. * In reality, any future calls to User APIs like NotifyWinEvent will
  4292. * probably fail as well, so this is probably a dead-end anyway.
  4293. */
  4294. ConnectIfNecessary(TRUE);
  4295. return(FEVENTHOOKED(event));
  4296. };
  4297. HWND
  4298. VerNtUserCreateWindowEx(
  4299. IN DWORD dwExStyle,
  4300. IN PLARGE_STRING pstrClassName,
  4301. IN PLARGE_STRING pstrWindowName OPTIONAL,
  4302. IN DWORD dwStyle,
  4303. IN int x,
  4304. IN int y,
  4305. IN int nWidth,
  4306. IN int nHeight,
  4307. IN HWND hwndParent,
  4308. IN HMENU hmenu,
  4309. IN HANDLE hModule,
  4310. IN LPVOID pParam,
  4311. IN DWORD dwFlags)
  4312. {
  4313. HWND hwnd = NULL;
  4314. PACTIVATION_CONTEXT pActCtx = NULL;
  4315. LARGE_IN_STRING strClassNameVer;
  4316. PLARGE_STRING pstrClassNameVer = pstrClassName;
  4317. NTSTATUS Status;
  4318. WCHAR ClassNameVer[MAX_ATOM_LEN];
  4319. LPWSTR lpClassNameVer;
  4320. #ifdef LAME_BUTTON
  4321. PWND pwnd;
  4322. #endif
  4323. LPWSTR lpDllName = NULL;
  4324. HMODULE hDllMod = NULL;
  4325. PREGISTERCLASSNAMEW pRegisterClassNameW = NULL;
  4326. BOOL bRegistered = FALSE;
  4327. PACTIVATION_CONTEXT lpActivationContext = NULL;
  4328. strClassNameVer.fAllocated = FALSE;
  4329. if (GetClientInfo()->dwTIFlags & TIF_16BIT) {
  4330. /*
  4331. * No Fusion redirection for 16BIT apps
  4332. */
  4333. if (!(GetAppCompatFlags2(VERMAX) & GACF2_FORCEFUSION)) {
  4334. dwFlags &= ~CW_FLAGS_VERSIONCLASS;
  4335. }
  4336. }
  4337. #ifdef LAZY_CLASS_INIT
  4338. LazyInitClasses();
  4339. #endif
  4340. if (dwFlags & CW_FLAGS_VERSIONCLASS) {
  4341. /*
  4342. * Get the current active App context to be activated whenever we call
  4343. * the user WndProc.
  4344. * Be aware that RtlGetActiveActivationContext will increment the pActCtx
  4345. * ref count for that reason we have to release it in fnNCDESTROY.
  4346. */
  4347. ACTIVATION_CONTEXT_BASIC_INFORMATION ActivationContextInfo = {0};
  4348. const ACTIVATIONCONTEXTINFOCLASS ActivationContextInfoClass = ActivationContextBasicInformation;
  4349. Status =
  4350. RtlQueryInformationActiveActivationContext(
  4351. ActivationContextInfoClass,
  4352. &ActivationContextInfo,
  4353. sizeof(ActivationContextInfo),
  4354. NULL
  4355. );
  4356. UserAssert (NT_SUCCESS(Status));
  4357. if ((ActivationContextInfo.Flags & ACTIVATION_CONTEXT_FLAG_NO_INHERIT) == 0) {
  4358. pActCtx = ActivationContextInfo.ActivationContext;
  4359. } else {
  4360. RtlReleaseActivationContext(ActivationContextInfo.ActivationContext);
  4361. }
  4362. /*
  4363. * Now convert the class name to class name+version.
  4364. */
  4365. if (IS_PTR(pstrClassName)) {
  4366. lpClassNameVer = ClassNameToVersion((LPWSTR)pstrClassName->Buffer, ClassNameVer, &lpDllName, &lpActivationContext, FALSE);
  4367. } else {
  4368. lpClassNameVer = ClassNameToVersion((LPWSTR)pstrClassName, ClassNameVer, &lpDllName, &lpActivationContext, FALSE);
  4369. }
  4370. if (lpClassNameVer == NULL) {
  4371. RIPMSG0(RIP_WARNING, "CreateWindowEx: Couldn't resolve the class name");
  4372. return NULL;
  4373. }
  4374. if (IS_PTR(lpClassNameVer)) {
  4375. RtlInitLargeUnicodeString(
  4376. (PLARGE_UNICODE_STRING)&strClassNameVer.strCapture,
  4377. lpClassNameVer, (UINT)-1);
  4378. pstrClassNameVer = (PLARGE_STRING)&strClassNameVer.strCapture;
  4379. } else {
  4380. pstrClassNameVer = (PLARGE_STRING)lpClassNameVer;
  4381. }
  4382. }
  4383. TryAgain:
  4384. hwnd = NtUserCreateWindowEx(dwExStyle,
  4385. pstrClassName,
  4386. pstrClassNameVer,
  4387. pstrWindowName,
  4388. dwStyle,
  4389. x,
  4390. y,
  4391. nWidth,
  4392. nHeight,
  4393. hwndParent,
  4394. hmenu,
  4395. hModule,
  4396. pParam,
  4397. dwFlags,
  4398. pActCtx);
  4399. /*
  4400. * Did we fail to create the window due to the class not being
  4401. * registered?
  4402. */
  4403. if (hwnd == NULL &&
  4404. (dwFlags & CW_FLAGS_VERSIONCLASS) &&
  4405. lpDllName != NULL &&
  4406. !bRegistered &&
  4407. GetLastError() == ERROR_CANNOT_FIND_WND_CLASS) {
  4408. /*
  4409. * Then try to register it by loading its DLL. Notice that this DLL
  4410. * will never get unloaded unless we failed to create the window.
  4411. * But once we created a window by loading this DLL we'll never free it.
  4412. */
  4413. bRegistered = VersionRegisterClass(IS_PTR(pstrClassName) ? pstrClassName->Buffer : pstrClassName, lpDllName, lpActivationContext, &hDllMod);
  4414. if (bRegistered) {
  4415. goto TryAgain;
  4416. }
  4417. }
  4418. if (hwnd == NULL && hDllMod != NULL) {
  4419. FREE_LIBRARY_SAVE_ERROR(hDllMod);
  4420. hDllMod = NULL;
  4421. }
  4422. if (lpActivationContext != NULL) {
  4423. RtlReleaseActivationContext(lpActivationContext);
  4424. lpActivationContext = NULL;
  4425. }
  4426. #ifdef LAME_BUTTON
  4427. pwnd = ValidateHwnd(hwnd);
  4428. if (pwnd != NULL && TestWF(pwnd, WEFLAMEBUTTON)) {
  4429. ULONG nCallers;
  4430. PVOID stack[16];
  4431. PVOID pStackTrace = NULL;
  4432. /*
  4433. * Get a stack trace and store it for use when the button is
  4434. * pressed.
  4435. */
  4436. nCallers = RtlWalkFrameChain(stack, ARRAY_SIZE(stack), 0);
  4437. if (nCallers > 0) {
  4438. pStackTrace = UserLocalAlloc(HEAP_ZERO_MEMORY,
  4439. (nCallers + 1) * sizeof(PVOID));
  4440. if (pStackTrace != NULL) {
  4441. RtlCopyMemory(pStackTrace, stack, nCallers * sizeof(PVOID));
  4442. /*
  4443. * NULL terminate the array so we know where it ends.
  4444. */
  4445. ((PVOID*)pStackTrace)[nCallers] = NULL;
  4446. }
  4447. }
  4448. SetProp(hwnd, MAKEINTATOM(gatomLameButton), pStackTrace);
  4449. }
  4450. #endif
  4451. CLEANUPLPSTRW(strClassNameVer);
  4452. return hwnd;
  4453. }
  4454. /**************************************************************************\
  4455. * AllowForegroundActivation
  4456. *
  4457. * 26-Apr-2001 clupu Created
  4458. \**************************************************************************/
  4459. VOID AllowForegroundActivation(
  4460. VOID)
  4461. {
  4462. NtUserCallNoParam(SFI__ALLOWFOREGROUNDACTIVATION);
  4463. }
  4464. /**************************************************************************\
  4465. * DisableProcessWindowGhosting
  4466. *
  4467. * 31-May-2001 msadek Created
  4468. \**************************************************************************/
  4469. VOID DisableProcessWindowsGhosting(
  4470. VOID)
  4471. {
  4472. NtUserCallNoParam(SFI__DISABLEPROCESSWINDOWSGHOSTING);
  4473. }
  4474. /**************************************************************************\
  4475. * IsProcess16Bit
  4476. *
  4477. * This is a private function for the GDI guys. Exporting this function is
  4478. * more expendient than fixing the headers such that they can include what
  4479. * they need to do this themselves. Longterm, this function should be removed
  4480. * and the headers properly munged.
  4481. *
  4482. * 15-Oct-2001 JasonSch Created
  4483. \**************************************************************************/
  4484. BOOL IsProcess16Bit(
  4485. VOID)
  4486. {
  4487. return (GetClientInfo()->CI_flags & CI_16BIT) != 0;
  4488. }