Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

738 lines
20 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WALIAS.C
  8. * WOW32 16-bit handle alias support
  9. *
  10. * History:
  11. * Created 27-Jan-1991 by Jeff Parsons (jeffpar)
  12. * Modified 12-May-1992 by Mike Tricker (miketri) to add MultiMedia support
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. MODNAME(walias.c);
  17. extern CRITICAL_SECTION gcsWOW;
  18. extern PTD gptdTaskHead;
  19. //BUGBUG - this must be removed once MM_MCISYSTEM_STRING is defined in MMSYSTEM.H.
  20. #ifndef MM_MCISYSTEM_STRING
  21. #define MM_MCISYSTEM_STRING 0x3CA
  22. #endif
  23. #ifdef DEBUG
  24. extern BOOL fSkipLog; // TRUE to temporarily skip certain logging
  25. #endif
  26. typedef struct _stdclass {
  27. LPSTR lpszClassName;
  28. ATOM aClassAtom;
  29. WNDPROC lpfnWndProc;
  30. INT iOrdinal;
  31. DWORD vpfnWndProc;
  32. } STDCLASS;
  33. // Some cool defines stolen from USERSRV.H
  34. #define MENUCLASS MAKEINTATOM(0x8000)
  35. #define DESKTOPCLASS MAKEINTATOM(0x8001)
  36. #define DIALOGCLASS MAKEINTATOM(0x8002)
  37. #define SWITCHWNDCLASS MAKEINTATOM(0x8003)
  38. #define ICONTITLECLASS MAKEINTATOM(0x8004)
  39. // See WARNING below!
  40. STDCLASS stdClasses[] = {
  41. NULL, 0, NULL, 0, 0, // WOWCLASS_UNKNOWN
  42. NULL, 0, NULL, 0, 0, // WOWCLASS_WIN16
  43. "BUTTON", 0, NULL, FUN_BUTTONWNDPROC, 0, // WOWCLASS_BUTTON,
  44. "COMBOBOX", 0, NULL, FUN_COMBOBOXCTLWNDPROC, 0, // WOWCLASS_COMBOBOX,
  45. "EDIT", 0, NULL, FUN_EDITWNDPROC, 0, // WOWCLASS_EDIT,
  46. "LISTBOX", 0, NULL, FUN_LBOXCTLWNDPROC, 0, // WOWCLASS_LISTBOX,
  47. "MDICLIENT", 0, NULL, FUN_MDICLIENTWNDPROC, 0, // WOWCLASS_MDICLIENT,
  48. "SCROLLBAR", 0, NULL, FUN_SBWNDPROC, 0, // WOWCLASS_SCROLLBAR,
  49. "STATIC", 0, NULL, FUN_STATICWNDPROC, 0, // WOWCLASS_STATIC,
  50. "#32769", (WORD)DESKTOPCLASS, NULL, FUN_DESKTOPWNDPROC, 0, // WOWCLASS_DESKTOP,
  51. "#32770", (WORD)DIALOGCLASS, NULL, FUN_DEFDLGPROCTHUNK, 0, // WOWCLASS_DIALOG,
  52. "#32772", (WORD)ICONTITLECLASS, NULL, FUN_TITLEWNDPROC, 0, // WOWCLASS_ICONTITLE,
  53. "#32768", (WORD)MENUCLASS, NULL, FUN_MENUWNDPROC, 0, // WOWCLASS_MENU,
  54. "#32771", (WORD)SWITCHWNDCLASS, NULL, 0, 0, // WOWCLASS_SWITCHWND,
  55. "COMBOLBOX", 0, NULL, FUN_LBOXCTLWNDPROC, 0, // WOWCLASS_COMBOLBOX
  56. };
  57. //
  58. // WARNING! The above sequence and values must be maintained otherwise the
  59. // table in WMSG16.C for message thunking must be changed. Same goes for
  60. // the #define's in WALIAS.H
  61. //
  62. // The above COMBOLBOX case is special because it is class that is
  63. // almost identical to a listbox. Therefore we lie about it.
  64. INT GetStdClassNumber(
  65. PSZ pszClass
  66. ) {
  67. INT i;
  68. if ( HIWORD(pszClass) ) {
  69. // They passed us a string
  70. for ( i = WOWCLASS_BUTTON; i < NUMEL(stdClasses); i++ ) {
  71. if ( WOW32_stricmp(pszClass, stdClasses[i].lpszClassName) == 0 ) {
  72. return( i );
  73. }
  74. }
  75. } else {
  76. // They passed us an atom
  77. for ( i = WOWCLASS_BUTTON; i < NUMEL(stdClasses); i++ ) {
  78. if ( stdClasses[i].aClassAtom == 0 ) {
  79. // RegisterWindowMessage is an undocumented way of determining
  80. // an atom value in the context of the server-side heap.
  81. stdClasses[i].aClassAtom = (ATOM)RegisterWindowMessage(stdClasses[i].lpszClassName);
  82. }
  83. if ( (ATOM)LOWORD(pszClass) == stdClasses[i].aClassAtom ) {
  84. return( i );
  85. }
  86. }
  87. }
  88. return( WOWCLASS_WIN16 ); // private 16-bit class created by the app
  89. }
  90. // Returns a 32 window proc given a class index
  91. WNDPROC GetStdClassWndProc(
  92. DWORD iClass
  93. ) {
  94. WNDPROC lpfn32;
  95. if ( iClass < WOWCLASS_WIN16 || iClass > WOWCLASS_MAX ) {
  96. WOW32ASSERT(FALSE);
  97. return( NULL );
  98. }
  99. lpfn32 = stdClasses[iClass].lpfnWndProc;
  100. if ( lpfn32 == NULL ) {
  101. WNDCLASS wc;
  102. BOOL f;
  103. f = GetClassInfo( NULL, stdClasses[iClass].lpszClassName, &wc );
  104. if ( f ) {
  105. VPVOID vp;
  106. DWORD UNALIGNED * lpdw;
  107. lpfn32 = wc.lpfnWndProc;
  108. stdClasses[iClass].lpfnWndProc = lpfn32;
  109. vp = GetStdClassThunkProc(iClass);
  110. vp = (VPVOID)((DWORD)vp - sizeof(DWORD)*3);
  111. GETVDMPTR( vp, sizeof(DWORD)*3, lpdw );
  112. WOW32ASSERT(*lpdw == SUBCLASS_MAGIC); // Are we editing the right stuff?
  113. if (!lpdw)
  114. *(lpdw+2) = (DWORD)lpfn32;
  115. FLUSHVDMCODEPTR( vp, sizeof(DWORD)*3, lpdw );
  116. FREEVDMPTR( lpdw );
  117. }
  118. }
  119. return( lpfn32 );
  120. }
  121. // Returns a 16 window proc thunk given a class index
  122. DWORD GetStdClassThunkProc(
  123. INT iClass
  124. ) {
  125. DWORD dwResult;
  126. SHORT iOrdinal;
  127. PARM16 Parm16;
  128. if ( iClass < WOWCLASS_WIN16 || iClass > WOWCLASS_MAX ) {
  129. WOW32ASSERT(FALSE);
  130. return( 0 );
  131. }
  132. iOrdinal = (SHORT)stdClasses[iClass].iOrdinal;
  133. if ( iOrdinal == 0 ) {
  134. return( (DWORD)NULL );
  135. }
  136. // If we've already gotten this proc, then don't bother calling into 16-bit
  137. dwResult = stdClasses[iClass].vpfnWndProc;
  138. if ( dwResult == (DWORD)NULL ) {
  139. // Callback into the 16-bit world asking for the 16:16 address
  140. Parm16.SubClassProc.iOrdinal = iOrdinal;
  141. if (!CallBack16(RET_SUBCLASSPROC, &Parm16, (VPPROC)NULL,
  142. (PVPVOID)&dwResult)) {
  143. WOW32ASSERT(FALSE);
  144. return( 0 );
  145. }
  146. // Save it since it is a constant.
  147. stdClasses[iClass].vpfnWndProc = dwResult;
  148. }
  149. return( dwResult );
  150. }
  151. /*
  152. * PWC GetClassWOWWords(hInst, pszClass)
  153. * is a ***private*** API for WOW only. It returns a pointer to the
  154. * WOW Class structure in the server's window class structure.
  155. * This is similar to GetClassLong(hwnd32, GCL_WOWWORDS) (see FindPWC),
  156. * but in this case we don't have a hwnd32, we have the class name
  157. * and instance handle.
  158. */
  159. PWC FindClass16(LPCSTR pszClass, HAND16 hInst)
  160. {
  161. register PWC pwc;
  162. pwc = (PWC)(pfnOut.pfnGetClassWOWWords)(HMODINST32(hInst), pszClass);
  163. WOW32WARNMSGF(
  164. pwc,
  165. ("WOW32 warning: GetClassWOWWords('%s', %04x) returned NULL\n", pszClass, hInst)
  166. );
  167. return (pwc);
  168. }
  169. #ifdef DEBUG
  170. INT nAliases;
  171. INT iLargestListSlot;
  172. PSZ apszHandleClasses[] = {
  173. "Unknown", // WOWCLASS_UNKNOWN
  174. "Window", // WOWCLASS_WIN16
  175. "Button", // WOWCLASS_BUTTON
  176. "ComboBox", // WOWCLASS_COMBOBOX
  177. "Edit", // WOWCLASS_EDIT
  178. "ListBox", // WOWCLASS_LISTBOX
  179. "MDIClient", // WOWCLASS_MDICLIENT
  180. "Scrollbar", // WOWCLASS_SCROLLBAR
  181. "Static", // WOWCLASS_STATIC
  182. "Desktop", // WOWCLASS_DESKTOP
  183. "Dialog", // WOWCLASS_DIALOG
  184. "Menu", // WOWCLASS_MENU
  185. "IconTitle", // WOWCLASS_ICONTITLE
  186. "Accel", // WOWCLASS_ACCEL
  187. "Cursor", // WOWCLASS_CURSOR
  188. "Icon", // WOWCLASS_ICON
  189. "DC", // WOWCLASS_DC
  190. "Font", // WOWCLASS_FONT
  191. "MetaFile", // WOWCLASS_METAFILE
  192. "Region", // WOWCLASS_RGN
  193. "Bitmap", // WOWCLASS_BITMAP
  194. "Brush", // WOWCLASS_BRUSH
  195. "Palette", // WOWCLASS_PALETTE
  196. "Pen", // WOWCLASS_PEN
  197. "Object" // WOWCLASS_OBJECT
  198. };
  199. BOOL MessageNeedsThunking(UINT uMsg)
  200. {
  201. switch (uMsg) {
  202. case WM_CREATE:
  203. case WM_ACTIVATE:
  204. case WM_SETFOCUS:
  205. case WM_KILLFOCUS:
  206. case WM_SETTEXT:
  207. case WM_GETTEXT:
  208. case WM_ERASEBKGND:
  209. case WM_WININICHANGE:
  210. case WM_DEVMODECHANGE:
  211. case WM_ACTIVATEAPP:
  212. case WM_SETCURSOR:
  213. case WM_MOUSEACTIVATE:
  214. case WM_GETMINMAXINFO:
  215. case WM_ICONERASEBKGND:
  216. case WM_NEXTDLGCTL:
  217. case WM_DRAWITEM:
  218. case WM_MEASUREITEM:
  219. case WM_DELETEITEM:
  220. case WM_VKEYTOITEM:
  221. case WM_CHARTOITEM:
  222. case WM_SETFONT:
  223. case WM_GETFONT:
  224. case WM_QUERYDRAGICON:
  225. case WM_COMPAREITEM:
  226. case WM_OTHERWINDOWCREATED:
  227. case WM_OTHERWINDOWDESTROYED:
  228. case WM_COMMNOTIFY:
  229. case WM_WINDOWPOSCHANGING:
  230. case WM_WINDOWPOSCHANGED:
  231. case WM_NCCREATE:
  232. case WM_NCCALCSIZE:
  233. case WM_COMMAND:
  234. case WM_HSCROLL:
  235. case WM_VSCROLL:
  236. case WM_INITMENU:
  237. case WM_INITMENUPOPUP:
  238. case WM_MENUSELECT:
  239. case WM_MENUCHAR:
  240. case WM_ENTERIDLE:
  241. case WM_CTLCOLORMSGBOX:
  242. case WM_CTLCOLOREDIT:
  243. case WM_CTLCOLORLISTBOX:
  244. case WM_CTLCOLORBTN:
  245. case WM_CTLCOLORDLG:
  246. case WM_CTLCOLORSCROLLBAR:
  247. case WM_CTLCOLORSTATIC:
  248. case WM_PARENTNOTIFY:
  249. case WM_MDICREATE:
  250. case WM_MDIDESTROY:
  251. case WM_MDIACTIVATE:
  252. case WM_MDIGETACTIVE:
  253. case WM_MDISETMENU:
  254. case WM_RENDERFORMAT:
  255. case WM_PAINTCLIPBOARD:
  256. case WM_VSCROLLCLIPBOARD:
  257. case WM_SIZECLIPBOARD:
  258. case WM_ASKCBFORMATNAME:
  259. case WM_CHANGECBCHAIN:
  260. case WM_HSCROLLCLIPBOARD:
  261. case WM_PALETTEISCHANGING:
  262. case WM_PALETTECHANGED:
  263. case MM_JOY1MOVE:
  264. case MM_JOY2MOVE:
  265. case MM_JOY1ZMOVE:
  266. case MM_JOY2ZMOVE:
  267. case MM_JOY1BUTTONDOWN:
  268. case MM_JOY2BUTTONDOWN:
  269. case MM_JOY1BUTTONUP:
  270. case MM_JOY2BUTTONUP:
  271. case MM_MCINOTIFY:
  272. case MM_MCISYSTEM_STRING:
  273. case MM_WOM_OPEN:
  274. case MM_WOM_CLOSE:
  275. case MM_WOM_DONE:
  276. case MM_WIM_OPEN:
  277. case MM_WIM_CLOSE:
  278. case MM_WIM_DATA:
  279. case MM_MIM_OPEN:
  280. case MM_MIM_CLOSE:
  281. case MM_MIM_DATA:
  282. case MM_MIM_LONGDATA:
  283. case MM_MIM_ERROR:
  284. case MM_MIM_LONGERROR:
  285. case MM_MOM_OPEN:
  286. case MM_MOM_CLOSE:
  287. case MM_MOM_DONE:
  288. LOGDEBUG(LOG_IMPORTANT,
  289. ("MessageNeedsThunking: WM_msg %04x is not thunked\n", uMsg));
  290. return TRUE;
  291. default:
  292. return FALSE;
  293. }
  294. }
  295. #endif
  296. PTD ThreadProcID32toPTD(DWORD dwThreadID, DWORD dwProcessID)
  297. {
  298. PTD ptd, ptdThis;
  299. PWOAINST pWOA;
  300. //
  301. // If we have active child instances of WinOldAp,
  302. // try to map the process ID of a child Win32 app
  303. // to the corresponding WinOldAp PTD.
  304. //
  305. ptdThis = CURRENTPTD();
  306. EnterCriticalSection(&ptdThis->csTD);
  307. pWOA = ptdThis->pWOAList;
  308. while (pWOA && pWOA->dwChildProcessID != dwProcessID) {
  309. pWOA = pWOA->pNext;
  310. }
  311. if (pWOA) {
  312. ptd = pWOA->ptdWOA;
  313. LeaveCriticalSection(&ptdThis->csTD);
  314. } else {
  315. LeaveCriticalSection(&ptdThis->csTD);
  316. //
  317. // We didn't find a WinOldAp PTD to return, see
  318. // if the thread ID matches one of our app threads.
  319. //
  320. EnterCriticalSection(&gcsWOW);
  321. ptd = gptdTaskHead;
  322. while (ptd && ptd->dwThreadID != dwThreadID) {
  323. ptd = ptd->ptdNext;
  324. }
  325. LeaveCriticalSection(&gcsWOW);
  326. }
  327. return ptd;
  328. }
  329. PTD Htask16toPTD(
  330. HTASK16 htask16
  331. ) {
  332. PTD ptd;
  333. EnterCriticalSection(&gcsWOW);
  334. ptd = gptdTaskHead;
  335. while(ptd) {
  336. if ( ptd->htask16 == htask16 ) {
  337. break;
  338. }
  339. ptd = ptd->ptdNext;
  340. }
  341. LeaveCriticalSection(&gcsWOW);
  342. return ptd;
  343. }
  344. HTASK16 ThreadID32toHtask16(
  345. DWORD ThreadID32
  346. ) {
  347. PTD ptd;
  348. HTASK16 htask16;
  349. if ( ThreadID32 == 0 ) {
  350. WOW32ASSERTMSG(ThreadID32, "WOW::ThreadID32tohTask16: Thread ID is 0\n");
  351. htask16 = 0;
  352. } else {
  353. ptd = ThreadProcID32toPTD( ThreadID32, (DWORD)-1 );
  354. if ( ptd ) {
  355. // Good, its one of our wow threads.
  356. htask16 = ptd->htask16;
  357. } else {
  358. // Nope, its is some other 32-bit thread
  359. htask16 = FindHtaskAlias( ThreadID32 );
  360. if ( htask16 == 0 ) {
  361. //
  362. // See the comment in WOLE2.C for a nice description
  363. //
  364. htask16 = AddHtaskAlias( ThreadID32 );
  365. }
  366. }
  367. }
  368. return htask16;
  369. }
  370. DWORD Htask16toThreadID32(
  371. HTASK16 htask16
  372. ) {
  373. if ( htask16 == 0 ) {
  374. return( 0 );
  375. }
  376. if ( ISTASKALIAS(htask16) ) {
  377. return( GetHtaskAlias(htask16,NULL) );
  378. } else {
  379. return( THREADID32(htask16) );
  380. }
  381. }
  382. //***************************************************************************
  383. // GetGCL_HMODULE - returns the valid hmodule if the window corresponds to
  384. // a 16bit class else returns the hmodule of 16bit user.exe
  385. // if the window is of a standard class.
  386. //
  387. // These cases are required for compatibility sake.
  388. // apps like VirtualMonitor, hDC etc depend on such behaviour.
  389. // - Nanduri
  390. //***************************************************************************
  391. WORD gUser16hInstance = 0;
  392. ULONG GetGCL_HMODULE(HWND hwnd)
  393. {
  394. ULONG ul;
  395. PTD ptd;
  396. PWOAINST pWOA;
  397. DWORD dwProcessID;
  398. ul = (ULONG)GetClassLong(hwnd, GCL_HMODULE);
  399. //
  400. // hMod32 = 0xZZZZ0000
  401. //
  402. if (ul != 0 && LOWORD(ul) == 0) {
  403. //
  404. // If we have active WinOldAp children, see if this window
  405. // belongs to a Win32 process spawned by one of the
  406. // active winoldap's. If it is, return the hmodule
  407. // of the corresponding winoldap. Otherwise we
  408. // return user.exe's hinstance (why not hmodule?)
  409. //
  410. dwProcessID = (DWORD)-1;
  411. GetWindowThreadProcessId(hwnd, &dwProcessID);
  412. ptd = CURRENTPTD();
  413. EnterCriticalSection(&ptd->csTD);
  414. pWOA = ptd->pWOAList;
  415. while (pWOA && pWOA->dwChildProcessID != dwProcessID) {
  416. pWOA = pWOA->pNext;
  417. }
  418. if (pWOA) {
  419. ul = pWOA->ptdWOA->hMod16;
  420. LOGDEBUG(LOG_ALWAYS, ("WOW32 GetClassLong(0x%x, GWW_HMODULE) returning 0x%04x\n",
  421. hwnd, ul));
  422. } else {
  423. ul = (ULONG) gUser16hInstance;
  424. WOW32ASSERT(ul);
  425. }
  426. LeaveCriticalSection(&ptd->csTD);
  427. }
  428. else {
  429. ul = (ULONG)GETHMOD16(ul); // 32-bit hmod is HMODINST32
  430. }
  431. return ul;
  432. }
  433. //
  434. // EXPORTED handle mapping functions. WOW32 code should use the
  435. // macros defined in walias.h -- these functions are for use by
  436. // third-party 32-bit code running in WOW, for example called
  437. // using generic thunks from WOW-specific 16-bit code.
  438. //
  439. HANDLE WOWHandle32 (WORD h16, WOW_HANDLE_TYPE htype)
  440. {
  441. switch (htype) {
  442. case WOW_TYPE_HWND:
  443. return HWND32(h16);
  444. case WOW_TYPE_HMENU:
  445. return HMENU32(h16);
  446. case WOW_TYPE_HDWP:
  447. return HDWP32(h16);
  448. case WOW_TYPE_HDROP:
  449. return HDROP32(h16);
  450. case WOW_TYPE_HDC:
  451. return HDC32(h16);
  452. case WOW_TYPE_HFONT:
  453. return HFONT32(h16);
  454. case WOW_TYPE_HMETAFILE:
  455. return HMETA32(h16);
  456. case WOW_TYPE_HRGN:
  457. return HRGN32(h16);
  458. case WOW_TYPE_HBITMAP:
  459. return HBITMAP32(h16);
  460. case WOW_TYPE_HBRUSH:
  461. return HBRUSH32(h16);
  462. case WOW_TYPE_HPALETTE:
  463. return HPALETTE32(h16);
  464. case WOW_TYPE_HPEN:
  465. return HPEN32(h16);
  466. case WOW_TYPE_HACCEL:
  467. return HACCEL32(h16);
  468. case WOW_TYPE_HTASK:
  469. return (HANDLE)HTASK32(h16);
  470. case WOW_TYPE_FULLHWND:
  471. return (HANDLE)FULLHWND32(h16);
  472. default:
  473. return(INVALID_HANDLE_VALUE);
  474. }
  475. }
  476. WORD WOWHandle16 (HANDLE h32, WOW_HANDLE_TYPE htype)
  477. {
  478. switch (htype) {
  479. case WOW_TYPE_HWND:
  480. return GETHWND16(h32);
  481. case WOW_TYPE_HMENU:
  482. return GETHMENU16(h32);
  483. case WOW_TYPE_HDWP:
  484. return GETHDWP16(h32);
  485. case WOW_TYPE_HDROP:
  486. return GETHDROP16(h32);
  487. case WOW_TYPE_HDC:
  488. return GETHDC16(h32);
  489. case WOW_TYPE_HFONT:
  490. return GETHFONT16(h32);
  491. case WOW_TYPE_HMETAFILE:
  492. return GETHMETA16(h32);
  493. case WOW_TYPE_HRGN:
  494. return GETHRGN16(h32);
  495. case WOW_TYPE_HBITMAP:
  496. return GETHBITMAP16(h32);
  497. case WOW_TYPE_HBRUSH:
  498. return GETHBRUSH16(h32);
  499. case WOW_TYPE_HPALETTE:
  500. return GETHPALETTE16(h32);
  501. case WOW_TYPE_HPEN:
  502. return GETHPEN16(h32);
  503. case WOW_TYPE_HACCEL:
  504. return GETHACCEL16(h32);
  505. case WOW_TYPE_HTASK:
  506. return GETHTASK16(h32);
  507. default:
  508. return(0xffff);
  509. }
  510. }
  511. PVOID gpGdiHandleInfo = (PVOID)-1;
  512. //WARNING: This structure must match ENTRY in ntgdi\inc\hmgshare.h
  513. typedef struct _ENTRYWOW
  514. {
  515. LONG l1;
  516. LONG l2;
  517. USHORT FullUnique;
  518. USHORT us1;
  519. LONG l3;
  520. } ENTRYWOW, *PENTRYWOW;
  521. //
  522. // this routine converts a 16bit GDI handle to a 32bit handle. There
  523. // is no need to do any validation on the handle since the 14bit space
  524. // for handles ignoring the low two bits is completely contained in the
  525. // valid 32bit handle space.
  526. //
  527. HANDLE hConvert16to32(int h16)
  528. {
  529. ULONG h32;
  530. int i = h16 >> 2;
  531. h32 = i | (ULONG)(((PENTRYWOW)gpGdiHandleInfo)[i].FullUnique) << 16;
  532. return((HANDLE)h32);
  533. }
  534. // Implemented as temporary fix for Whistler Bug #435401
  535. // Should be fixed for Blackcomb or sooner
  536. extern HANDLE hmodWOW32;
  537. HAND16 hConvert32to16(DWORD h32)
  538. {
  539. PARM16 Parm16;
  540. VPVOID vp = 0;
  541. // see if handle is over 14-bits
  542. if(LOWORD(h32) > 0x00003FFF) {
  543. char szErrorMessage[512];
  544. char szTitle[512];
  545. char szModName[9];
  546. PTDB pTDB;
  547. pTDB = (PVOID)SEGPTR(CURRENTPTD()->htask16,0);
  548. RtlCopyMemory(szModName, pTDB->TDB_ModName, sizeof(szModName)-1);
  549. szModName[sizeof(szModName)-1] = 0;
  550. if (!LoadString(hmodWOW32, iszApplication,
  551. szTitle, sizeof(szTitle)/sizeof(CHAR)))
  552. {
  553. szTitle[0] = 0;
  554. }
  555. strcat(szTitle, szModName);
  556. LoadString(hmodWOW32,
  557. iszExceedGDIHandleLimit,
  558. szErrorMessage,
  559. sizeof szErrorMessage);
  560. // The GDI32 handle allocation has gone over the 16K threshhold
  561. // This thread is toast.
  562. WOWSysErrorBox(szTitle, szErrorMessage, SEB_OK | SEB_DEFBUTTON, 0, 0);
  563. LOGDEBUG(LOG_ALWAYS,
  564. ("GDI32 handle limit exceeded for Task %04X \n",
  565. CURRENTPTD()->htask16));
  566. CallBack16(RET_FORCETASKEXIT, &Parm16, 0, &vp);
  567. // this should never return
  568. return(0);
  569. }
  570. // everything is hunky dory
  571. return((HAND16)(((DWORD) (h32)) << 2));
  572. }
  573. // We probably don't need to worry about this buffer being too small since we're
  574. // really only interested in the predefined standard classes which tend to
  575. // be rather short-named.
  576. #define MAX_CLASSNAME_LEN 64
  577. // There is a time frame (from when an app calls CreateWindow until USER32 gets
  578. // a message at one of its WndProc's for the window - see FritzS) during which
  579. // the fnid (class type) can't be set officially for the window. If the
  580. // GETICLASS macro is invoked during this period, it will be unable to find the
  581. // iClass for windows created on any of the standard control classes using the
  582. // fast fnid index method (see walias.h). Once the time frame is passed, the
  583. // fast fnid method will work fine for these windows.
  584. //
  585. // This is manifested in apps that set CBT hooks and try to subclass the
  586. // standard classes while in their hook proc. See bug #143811.
  587. INT GetIClass(PWW pww, HWND hwnd)
  588. {
  589. INT iClass;
  590. DWORD dwClassAtom;
  591. // if it is a standard class
  592. if(((pww->fnid & 0xfff) >= FNID_START) &&
  593. ((pww->fnid & 0xfff) <= FNID_END)) {
  594. // return the class id for this initialized window
  595. iClass = pfnOut.aiWowClass[( pww->fnid & 0xfff) - FNID_START];
  596. }
  597. else {
  598. iClass = WOWCLASS_WIN16; // default return: app private class
  599. dwClassAtom = GetClassLong(hwnd, GCW_ATOM);
  600. if(dwClassAtom) {
  601. iClass = GetStdClassNumber((PSZ)dwClassAtom);
  602. }
  603. }
  604. return(iClass);
  605. }