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.

937 lines
22 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WCALL16.C
  8. * WOW32 16-bit message/callback support
  9. *
  10. * History:
  11. * Created 11-Mar-1991 by Jeff Parsons (jeffpar)
  12. * Changed 18-Aug-1992 by Mike Tricker (MikeTri) Added DOS PDB and SFT functions
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. MODNAME(wcall16.c);
  17. #define WOWFASTEDIT
  18. #ifdef WOWFASTEDIT
  19. typedef struct _LOCALHANDLEENTRY {
  20. WORD lhe_address; // actual address of object
  21. BYTE lhe_flags; // flags and priority level
  22. BYTE lhe_count; // lock count
  23. } LOCALHANDLEENTRY, *PLOCALHANDLEENTRY;
  24. #define LA_MOVEABLE 0x0002 // moveable or fixed?
  25. #define LHE_DISCARDED 0x0040 // Marks objects that have been discarded.
  26. #endif
  27. /* Common callback functions
  28. */
  29. HANDLE LocalAlloc16(WORD wFlags, INT cb, HANDLE hInstance)
  30. {
  31. PARM16 Parm16;
  32. VPVOID vp = 0;
  33. if (LOWORD(hInstance) == 0 ) { /* if lo word == 0, then this is a 32-bit
  34. hInstance, which makes no sense */
  35. WOW32ASSERT(LOWORD(hInstance));
  36. return (HANDLE)0;
  37. }
  38. if (cb < 0 || cb > 0xFFFF) {
  39. WOW32ASSERT(cb > 0 && cb <= 0xFFFF);
  40. return (HANDLE)0;
  41. }
  42. Parm16.WndProc.wMsg = LOWORD(hInstance) | 1;
  43. Parm16.WndProc.wParam = wFlags;
  44. Parm16.WndProc.lParam = cb;
  45. CallBack16(RET_LOCALALLOC, &Parm16, 0, &vp);
  46. if (LOWORD(vp) == 0)
  47. vp = 0;
  48. return (HANDLE)vp;
  49. }
  50. HANDLE LocalReAlloc16(HANDLE hMem, INT cb, WORD wFlags)
  51. {
  52. PARM16 Parm16;
  53. VPVOID vp = 0;
  54. if (HIWORD(hMem) == 0 || cb < 0 || cb > 0xFFFF) {
  55. WOW32ASSERT(HIWORD(hMem) && cb >= 0 && cb <= 0xFFFF);
  56. return (HANDLE)0;
  57. }
  58. LOGDEBUG(4,("LocalRealloc DS = %x, hMem = %x, bytes = %x, flags = %x\n",HIWORD(hMem),LOWORD(hMem),cb,wFlags));
  59. Parm16.WndProc.lParam = (LONG)hMem;
  60. Parm16.WndProc.wParam = wFlags;
  61. Parm16.WndProc.wMsg = (WORD)cb;
  62. CallBack16(RET_LOCALREALLOC, &Parm16, 0, &vp);
  63. if (LOWORD(vp) == 0)
  64. vp = 0;
  65. return (HANDLE)vp;
  66. }
  67. #ifndef WOWFASTEDIT
  68. VPVOID LocalLock16(HANDLE hMem)
  69. {
  70. PARM16 Parm16;
  71. VPVOID vp = 0;
  72. if (HIWORD(hMem) == 0) {
  73. WOW32ASSERT(HIWORD(hMem) != 0);
  74. return (VPVOID)0;
  75. }
  76. Parm16.WndProc.lParam = (LONG)hMem;
  77. CallBack16(RET_LOCALLOCK, &Parm16, 0, &vp);
  78. return vp;
  79. }
  80. BOOL LocalUnlock16(HANDLE hMem)
  81. {
  82. PARM16 Parm16;
  83. VPVOID vp = FALSE;
  84. if (HIWORD(hMem) == 0) {
  85. WOW32ASSERT(HIWORD(hMem));
  86. return FALSE;
  87. }
  88. Parm16.WndProc.lParam = (LONG)hMem;
  89. CallBack16(RET_LOCALUNLOCK, &Parm16, 0, &vp);
  90. return (BOOL)vp;
  91. }
  92. #else
  93. VPVOID LocalLock16(HANDLE hMem)
  94. {
  95. WORD h16;
  96. LONG retval;
  97. if (HIWORD(hMem) == 0) {
  98. WOW32ASSERT(HIWORD(hMem) != 0);
  99. return (VPVOID)0;
  100. }
  101. h16 = LOWORD(hMem);
  102. retval = (VPVOID)hMem;
  103. if (h16 & LA_MOVEABLE) {
  104. PLOCALHANDLEENTRY plhe;
  105. GETVDMPTR(hMem, sizeof(*plhe), plhe);
  106. if (plhe->lhe_flags & LHE_DISCARDED) {
  107. goto LOCK1;
  108. }
  109. plhe->lhe_count++;
  110. if (!plhe->lhe_count)
  111. plhe->lhe_count--;
  112. LOCK1:
  113. LOW(retval) = plhe->lhe_address;
  114. FLUSHVDMPTR((ULONG)hMem, sizeof(*plhe), plhe);
  115. FREEVDMPTR(plhe);
  116. }
  117. if (LOWORD(retval) == 0)
  118. retval = 0;
  119. return retval;
  120. }
  121. BOOL LocalUnlock16(HANDLE hMem)
  122. {
  123. WORD h16;
  124. BOOL rc;
  125. PLOCALHANDLEENTRY plhe;
  126. BYTE count;
  127. if (HIWORD(hMem) == 0) {
  128. WOW32ASSERT(HIWORD(hMem));
  129. return FALSE;
  130. }
  131. rc = FALSE;
  132. h16 = LOWORD(hMem);
  133. if (!(h16 & LA_MOVEABLE)) {
  134. goto UNLOCK2;
  135. }
  136. GETVDMPTR(hMem, sizeof(*plhe), plhe);
  137. if (plhe->lhe_flags & LHE_DISCARDED)
  138. goto UNLOCK1;
  139. count = plhe->lhe_count;
  140. count--;
  141. if (count >= (BYTE)(0xff-1))
  142. goto UNLOCK1;
  143. plhe->lhe_count = count;
  144. rc = (BOOL)((SHORT)count);
  145. FLUSHVDMPTR((ULONG)hMem, sizeof(*plhe), plhe);
  146. UNLOCK1:
  147. FREEVDMPTR(plhe);
  148. UNLOCK2:
  149. return rc;
  150. }
  151. #endif // WOWFASTEDIT
  152. WORD LocalSize16(HANDLE hMem)
  153. {
  154. PARM16 Parm16;
  155. VPVOID vp = 0;
  156. if (HIWORD(hMem) == 0) {
  157. WOW32ASSERT(HIWORD(hMem));
  158. return FALSE;
  159. }
  160. Parm16.WndProc.lParam = (LONG)hMem;
  161. CallBack16(RET_LOCALSIZE, &Parm16, 0, &vp);
  162. return (WORD)vp;
  163. }
  164. HANDLE LocalFree16(HANDLE hMem)
  165. {
  166. PARM16 Parm16;
  167. VPVOID vp = FALSE;
  168. if (HIWORD(hMem) == 0) {
  169. WOW32ASSERT(HIWORD(hMem));
  170. return (HANDLE)0;
  171. }
  172. Parm16.WndProc.lParam = (LONG)hMem;
  173. CallBack16(RET_LOCALFREE, &Parm16, 0, &vp);
  174. if (LOWORD(vp) == 0) {
  175. vp = 0;
  176. } else {
  177. WOW32ASSERT(LOWORD(vp) == LOWORD(hMem));
  178. vp = (VPVOID)hMem;
  179. }
  180. return (HANDLE)vp;
  181. }
  182. BOOL LockSegment16(WORD wSeg)
  183. {
  184. PARM16 Parm16;
  185. VPVOID vp = FALSE;
  186. Parm16.WndProc.wParam = wSeg;
  187. CallBack16(RET_LOCKSEGMENT, &Parm16, 0, &vp);
  188. return (BOOL)vp;
  189. }
  190. BOOL UnlockSegment16(WORD wSeg)
  191. {
  192. PARM16 Parm16;
  193. VPVOID vp = FALSE;
  194. Parm16.WndProc.wParam = wSeg;
  195. CallBack16(RET_UNLOCKSEGMENT, &Parm16, 0, &vp);
  196. return (BOOL)vp;
  197. }
  198. VPVOID WOWGlobalAllocLock16(WORD wFlags, DWORD cb, HMEM16 *phMem)
  199. {
  200. PARM16 Parm16;
  201. VPVOID vp = 0;
  202. Parm16.WndProc.wParam = wFlags;
  203. Parm16.WndProc.lParam = cb;
  204. CallBack16(RET_GLOBALALLOCLOCK, &Parm16, 0, &vp);
  205. if (vp) {
  206. // Get handle of 16-bit object
  207. if (phMem) {
  208. *phMem = Parm16.WndProc.wParam;
  209. }
  210. }
  211. return vp;
  212. }
  213. HMEM16 WOWGlobalAlloc16(WORD wFlags, DWORD cb)
  214. {
  215. HMEM16 hMem;
  216. VPVOID vp;
  217. if (vp = WOWGlobalAllocLock16(wFlags, cb, &hMem)) {
  218. WOWGlobalUnlock16(hMem);
  219. } else {
  220. hMem = 0;
  221. }
  222. return hMem;
  223. }
  224. VPVOID WOWGlobalLockSize16(HMEM16 hMem, PDWORD pcb)
  225. {
  226. PARM16 Parm16;
  227. VPVOID vp = 0;
  228. Parm16.WndProc.wParam = hMem;
  229. CallBack16(RET_GLOBALLOCK, &Parm16, 0, &vp);
  230. // Get size of 16-bit object (will be 0 if lock failed)
  231. if (pcb) {
  232. *pcb = Parm16.WndProc.lParam;
  233. }
  234. return vp;
  235. }
  236. VPVOID WOWGlobalLock16(HMEM16 hMem)
  237. {
  238. return WOWGlobalLockSize16(hMem, NULL);
  239. }
  240. BOOL WOWGlobalUnlock16(HMEM16 hMem)
  241. {
  242. PARM16 Parm16;
  243. VPVOID vp = FALSE;
  244. Parm16.WndProc.wParam = hMem;
  245. CallBack16(RET_GLOBALUNLOCK, &Parm16, 0, &vp);
  246. return (BOOL)vp;
  247. }
  248. HMEM16 WOWGlobalUnlockFree16(VPVOID vpMem)
  249. {
  250. PARM16 Parm16;
  251. VPVOID vp = FALSE;
  252. Parm16.WndProc.lParam = vpMem;
  253. CallBack16(RET_GLOBALUNLOCKFREE, &Parm16, 0, &vp);
  254. return (HMEM16)vp;
  255. }
  256. HMEM16 WOWGlobalFree16(HMEM16 hMem)
  257. {
  258. VPVOID vp;
  259. if (vp = WOWGlobalLock16(hMem)) {
  260. hMem = WOWGlobalUnlockFree16(vp);
  261. } else {
  262. // On failure we return the passed-in handle,
  263. // so there's nothing to do.
  264. }
  265. return hMem;
  266. }
  267. HAND16 GetExePtr16( HAND16 hInst )
  268. {
  269. PARM16 Parm16;
  270. ULONG ul;
  271. PTD ptd;
  272. INT i;
  273. if (hInst == 0) return (HAND16)0;
  274. //
  275. // see if this is the hInst for the current task
  276. //
  277. ptd = CURRENTPTD();
  278. if (hInst == ptd->hInst16) {
  279. return ptd->hMod16;
  280. }
  281. //
  282. // check the cache
  283. //
  284. for (i = 0; i < CHMODCACHE; i++) {
  285. if (ghModCache[i].hInst16 == hInst)
  286. return ghModCache[i].hMod16;
  287. }
  288. /*
  289. ** Function returns a hModule, given an hInstance
  290. */
  291. Parm16.WndProc.wParam = hInst;
  292. CallBack16(RET_GETEXEPTR, &Parm16, 0, &ul);
  293. //
  294. // GetExePtr(hmod) returns hmod, don't cache these.
  295. //
  296. if (hInst != (HAND16)LOWORD(ul)) {
  297. //
  298. // update the cache
  299. // slide everybody down 1 entry, put this new guy at the top
  300. //
  301. RtlMoveMemory(ghModCache+1, ghModCache, sizeof(HMODCACHE)*(CHMODCACHE-1));
  302. ghModCache[0].hInst16 = hInst;
  303. ghModCache[0].hMod16 = (HAND16)LOWORD(ul);
  304. }
  305. return (HAND16)LOWORD(ul);
  306. }
  307. WORD GetModuleFileName16( HAND16 hInst, VPVOID lpszModuleName, WORD cchModuleName )
  308. {
  309. PARM16 Parm16;
  310. ULONG ul;
  311. if (hInst == 0) return 0;
  312. Parm16.WndProc.wParam = hInst;
  313. Parm16.WndProc.lParam = lpszModuleName;
  314. Parm16.WndProc.wMsg = cchModuleName;
  315. CallBack16(RET_GETMODULEFILENAME, &Parm16, 0, &ul );
  316. return( LOWORD(ul) );
  317. }
  318. ULONG GetDosPDB16(VOID)
  319. {
  320. PARM16 Parm16;
  321. DWORD dwReturn = 0;
  322. CallBack16(RET_GETDOSPDB, &Parm16, 0, &dwReturn);
  323. return (ULONG)dwReturn;
  324. }
  325. ULONG GetDosSFT16(VOID)
  326. {
  327. PARM16 Parm16;
  328. DWORD dwReturn = 0;
  329. CallBack16(RET_GETDOSSFT, &Parm16, 0, &dwReturn);
  330. return (ULONG)dwReturn;
  331. }
  332. // Given a data selector change it into a code selector
  333. WORD ChangeSelector16(WORD wSeg)
  334. {
  335. PARM16 Parm16;
  336. VPVOID vp = FALSE;
  337. Parm16.WndProc.wParam = wSeg;
  338. CallBack16(RET_CHANGESELECTOR, &Parm16, 0, &vp);
  339. return LOWORD(vp);
  340. }
  341. VPVOID RealLockResource16(HMEM16 hMem, PINT pcb)
  342. {
  343. PARM16 Parm16;
  344. VPVOID vp = 0;
  345. Parm16.WndProc.wParam = hMem;
  346. CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp);
  347. // Get size of 16-bit object (will be 0 if lock failed)
  348. if (pcb) {
  349. *pcb = Parm16.WndProc.lParam;
  350. }
  351. return vp;
  352. }
  353. int WINAPI WOWlstrcmp16(LPCWSTR lpString1, LPCWSTR lpString2)
  354. {
  355. PARM16 Parm16;
  356. DWORD dwReturn = 0;
  357. DWORD cb1, cb2;
  358. VPSTR vp1, vp2;
  359. LPSTR p1, p2;
  360. //
  361. // to handle DBCS correctly allocate enough room
  362. // for two DBCS bytes for every unicode char.
  363. //
  364. cb1 = sizeof(WCHAR) * (wcslen(lpString1) + 1);
  365. cb2 = sizeof(WCHAR) * (wcslen(lpString2) + 1);
  366. // be sure allocation size matches stackfree16() size below
  367. vp1 = stackalloc16(cb1 + cb2);
  368. vp2 = vp1 + cb1;
  369. p1 = VDMPTR(vp1, cb1);
  370. p2 = p1 + cb1;
  371. RtlUnicodeToMultiByteN(
  372. p1,
  373. cb1,
  374. NULL,
  375. (LPWSTR) lpString1, // cast because arg isn't declared const
  376. cb1
  377. );
  378. RtlUnicodeToMultiByteN(
  379. p2,
  380. cb2,
  381. NULL,
  382. (LPWSTR) lpString2, // cast because arg isn't declared const
  383. cb2
  384. );
  385. FREEVDMPTR(p1);
  386. Parm16.lstrcmpParms.lpstr1 = vp1;
  387. Parm16.lstrcmpParms.lpstr2 = vp2;
  388. CallBack16(RET_LSTRCMP, &Parm16, 0, &dwReturn);
  389. stackfree16(vp1, (cb1 + cb2));
  390. return (int)(short int)LOWORD(dwReturn);
  391. }
  392. DWORD WOWCallback16(DWORD vpFn, DWORD dwParam)
  393. {
  394. PARM16 Parm16;
  395. VPVOID vp;
  396. //
  397. // Copy DWORD parameter to PARM16 structure.
  398. //
  399. RtlCopyMemory(&Parm16.WOWCallback16.wArgs, &dwParam, sizeof(dwParam));
  400. //
  401. // Use semi-slimy method to pass argument size to CallBack16.
  402. //
  403. vp = (VPVOID) sizeof(dwParam);
  404. CallBack16(RET_WOWCALLBACK16, &Parm16, (VPPROC)vpFn, &vp);
  405. return (DWORD)vp;
  406. }
  407. BOOL WOWCallback16Ex(
  408. DWORD vpFn,
  409. DWORD dwFlags,
  410. DWORD cbArgs,
  411. PVOID pArgs,
  412. PDWORD pdwRetCode
  413. )
  414. {
  415. #ifdef DEBUG
  416. static BOOL fFirstTime = TRUE;
  417. if (fFirstTime) {
  418. //
  419. // Ensure that wownt32.h's definition of WCB16_MAX_CBARGS
  420. // matches wow.h's definition of PARMWCB16.
  421. //
  422. WOW32ASSERT( WCB16_MAX_CBARGS == sizeof(PARMWCB16) );
  423. //
  424. // If the PARMWCB16 structure is smaller than the PARM16
  425. // union, we should increase the size of PARMWCB16 and
  426. // WCB16_MAX_CBARG to allow the use of the extra bytes.
  427. //
  428. WOW32ASSERT( sizeof(PARMWCB16) == sizeof(PARM16) );
  429. fFirstTime = FALSE;
  430. }
  431. #endif // DEBUG
  432. if (cbArgs > sizeof(PARM16)) {
  433. LOGDEBUG(LOG_ALWAYS, ("WOWCallback16V: cbArgs = %u, must be <= %u",
  434. cbArgs, (unsigned) sizeof(PARM16)));
  435. SetLastError(ERROR_INVALID_PARAMETER);
  436. return FALSE;
  437. }
  438. //
  439. // For cdecl functions we don't want to "sub SP, cbArgs" after calling
  440. // the function, so we pass 0 as cbArgs to the 16-bit side.
  441. //
  442. if (dwFlags & WCB16_CDECL) {
  443. cbArgs = 0;
  444. }
  445. //
  446. // Use semi-slimy method to pass argument size to CallBack16.
  447. //
  448. *pdwRetCode = cbArgs;
  449. CallBack16(RET_WOWCALLBACK16, (PPARM16)pArgs, (VPPROC)vpFn, (PVPVOID)pdwRetCode);
  450. return TRUE;
  451. }
  452. BOOL CallBack16(INT iRetID, PPARM16 pParm16, VPPROC vpfnProc, PVPVOID pvpReturn)
  453. {
  454. #ifdef DEBUG
  455. static PSZ apszCallBacks[] = {
  456. "ERROR:RETURN", // RET_RETURN (not a callback!)
  457. "ERROR:DEBUGRETURN", // RET_DEBUGRETURN (not a callback!)
  458. "DEBUG", // RET_DEBUG
  459. "WNDPROC", // RET_WNDPROC
  460. "ENUMFONTPROC", // RET_ENUMFONTPROC
  461. "ENUMWINDOWPROC", // RET_ENUMWINDOWPROC
  462. "LOCALALLOC", // RET_LOCALALLOC
  463. "LOCALREALLOC", // RET_LOCALREALLOC
  464. "LOCALLOCK", // RET_LOCALLOCK
  465. "LOCALUNLOCK", // RET_LOCALUNLOCK
  466. "LOCALSIZE", // RET_LOCALSIZE
  467. "LOCALFREE", // RET_LOCALFREE
  468. "GLOBALALLOCLOCK", // RET_GLOBALALLOCLOCK
  469. "GLOBALLOCK", // RET_GLOBALLOCK
  470. "GLOBALUNLOCK", // RET_GLOBALUNLOCK
  471. "GLOBALUNLOCKFREE", // RET_GLOBALUNLOCKFREE
  472. "FINDRESOURCE", // RET_FINDRESOURCE
  473. "LOADRESOURCE", // RET_LOADRESOURCE
  474. "FREERESOURCE", // RET_FREERESOURCE
  475. "LOCKRESOURCE", // RET_LOCKRESOURCE
  476. "UNLOCKRESOURCE", // RET_UNLOCKRESOURCE
  477. "SIZEOFRESOURCE", // RET_SIZEOFRESOURCE
  478. "LOCKSEGMENT", // RET_LOCKSEGMENT
  479. "UNLOCKSEGMENT", // RET_UNLOCKSEGMENT
  480. "ENUMMETAFILEPROC", // RET_ENUMMETAFILEPROC
  481. "TASKSTARTED ", // RET_TASKSTARTED
  482. "HOOKPROC", // RET_HOOKPROC
  483. "SUBCLASSPROC", // RET_SUBCLASSPROC
  484. "LINEDDAPROC", // RET_LINEDDAPROC
  485. "GRAYSTRINGPROC", // RET_GRAYSTRINGPROC
  486. "FORCETASKEXIT", // RET_FORCETASKEXIT
  487. "SETCURDIR", // RET_SETCURDIR
  488. "ENUMOBJPROC", // RET_ENUMOBJPROC
  489. "SETCURSORICONFLAG", // RET_SETCURSORICONFLAG
  490. "SETABORTPROC", // RET_SETABORTPROC
  491. "ENUMPROPSPROC", // RET_ENUMPROPSPROC
  492. "FORCESEGMENTFAULT", // RET_FORCESEGMENTFAULT
  493. "LSTRCMP", // RET_LSTRCMP
  494. "UNUSEDFUNC", //
  495. "UNUSEDFUNC", //
  496. "UNUSEDFUNC", //
  497. "UNUSEDFUNC", //
  498. "GETEXEPTR", // RET_GETEXEPTR
  499. "UNUSEDFUNC", //
  500. "FORCETASKFAULT", // RET_FORCETASKFAULT
  501. "GETEXPWINVER", // RET_GETEXPWINVER
  502. "GETCURDIR", // RET_GETCURDIR
  503. "GETDOSPDB", // RET_GETDOSPDB
  504. "GETDOSSFT", // RET_GETDOSSFT
  505. "FOREGROUNDIDLE", // RET_FOREGROUNDIDLE
  506. "WINSOCKBLOCKHOOK", // RET_WINSOCKBLOCKHOOK
  507. "WOWDDEFREEHANDLE", // RET_WOWDDEFREEHANDLE
  508. "CHANGESELECTOR", // RET_CHANGESELECTOR
  509. "GETMODULEFILENAME", // RET_GETMODULEFILENAME
  510. "WORDBREAKPROC", // RET_WORDBREAKPROC
  511. "WINEXEC", // RET_WINEXEC
  512. "WOWCALLBACK16", // RET_WOWCALLBACK16
  513. "GETDIBSIZE", // RET_GETDIBSIZE
  514. "GETDIBFLAGS", // RET_GETDIBFLAGS
  515. "SETDIBSEL", // RET_SETDIBSEL
  516. "FREEDIBSEL", // RET_FREEDIBSEL
  517. };
  518. #endif
  519. register PTD ptd;
  520. register PVDMFRAME pFrame;
  521. register PCBVDMFRAME pCBFrame;
  522. WORD wAX;
  523. BOOL fComDlgSync = FALSE;
  524. INT cStackAlloc16;
  525. VPVOID vpCBStack; // See NOTES in walloc16.c\stackalloc16()
  526. #if FASTBOPPING
  527. #else
  528. USHORT SaveIp;
  529. #endif
  530. #ifdef DEBUG
  531. VPVOID vpStackT;
  532. #endif
  533. WOW32ASSERT(iRetID != RET_RETURN && iRetID != RET_DEBUGRETURN);
  534. ptd = CURRENTPTD();
  535. // ssync 16-bit & 32-bit common dialog structs (see wcommdlg.c)
  536. if(ptd->CommDlgTd) {
  537. // only ssync for stuff that might actually callback into the app
  538. // ie. we don't need to ssync every time wow32 calls GlobalLock16
  539. switch(iRetID) {
  540. case RET_WNDPROC: // try to get these in a most frequently
  541. case RET_HOOKPROC: // used order
  542. case RET_WINSOCKBLOCKHOOK:
  543. case RET_ENUMFONTPROC:
  544. case RET_ENUMWINDOWPROC:
  545. case RET_ENUMOBJPROC:
  546. case RET_ENUMPROPSPROC:
  547. case RET_LINEDDAPROC:
  548. case RET_GRAYSTRINGPROC:
  549. case RET_SETWORDBREAKPROC:
  550. case RET_SETABORTPROC:
  551. // Note: This call can invalidate flat ptrs to 16-bit mem
  552. Ssync_WOW_CommDlg_Structs(ptd->CommDlgTd, w32to16, 0);
  553. fComDlgSync = TRUE; // set this for return ssync
  554. break;
  555. default:
  556. break;
  557. }
  558. }
  559. GETFRAMEPTR(ptd->vpStack, pFrame);
  560. // Just making sure that this thread matches the current 16-bit task
  561. WOW32ASSERT((pFrame->wTDB == ptd->htask16) ||
  562. (ptd->dwFlags & TDF_IGNOREINPUT) ||
  563. (ptd->htask16 == 0));
  564. // set up the callback stack frame from the correct location
  565. // & make it word aligned.
  566. // if stackalloc16() hasn't been called since the app called into wow32
  567. if (ptd->cStackAlloc16 == 0) {
  568. vpCBStack = ptd->vpStack;
  569. ptd->vpCBStack = (ptd->vpStack - sizeof(CBVDMFRAME)) & (~0x1);
  570. }
  571. else {
  572. vpCBStack = ptd->vpCBStack;
  573. ptd->vpCBStack = (ptd->vpCBStack - sizeof(CBVDMFRAME)) & (~0x1);
  574. }
  575. GETFRAMEPTR(ptd->vpCBStack, (PVDMFRAME)pCBFrame);
  576. pCBFrame->vpStack = ptd->vpStack;
  577. pCBFrame->wRetID = (WORD)iRetID;
  578. pCBFrame->wTDB = pFrame->wTDB;
  579. pCBFrame->wLocalBP = pFrame->wLocalBP;
  580. // save the current context stackalloc16() count and set the count to
  581. // 0 for the next context. This will force ptd->vpCBStack to be calc'd
  582. // correctly in any future calls to stackalloc16() if the app callsback
  583. // into WOW
  584. cStackAlloc16 = ptd->cStackAlloc16;
  585. ptd->cStackAlloc16 = 0;
  586. #ifdef DEBUG
  587. // Save
  588. vpStackT = ptd->vpStack;
  589. #endif
  590. if (pParm16)
  591. RtlCopyMemory(&pCBFrame->Parm16, pParm16, sizeof(PARM16));
  592. //if (vpfnProc) // cheaper to just do it
  593. STOREDWORD(pCBFrame->vpfnProc, vpfnProc);
  594. wAX = HIWORD(ptd->vpStack); // Put SS in AX register for callback
  595. if ( iRetID == RET_WNDPROC ) {
  596. if ( pParm16->WndProc.hInst )
  597. wAX = pParm16->WndProc.hInst | 1;
  598. }
  599. pCBFrame->wAX = wAX; // Use this AX for the callback
  600. //
  601. // Semi-slimy way we pass byte count of arguments into this function
  602. // for generic callbacks (WOWCallback16).
  603. //
  604. if (RET_WOWCALLBACK16 == iRetID) {
  605. pCBFrame->wGenUse1 = (WORD)(DWORD)*pvpReturn;
  606. }
  607. #ifdef DEBUG
  608. if (iRetID == RET_WNDPROC) {
  609. LOGDEBUG(9,("%04X Calling WIN16 WNDPROC(%08lx:%04x,%04x,%04x,%04x,%04x)\n",
  610. pFrame->wTDB,
  611. vpfnProc,
  612. pParm16->WndProc.hwnd,
  613. pParm16->WndProc.wMsg,
  614. pParm16->WndProc.wParam,
  615. HIWORD(pParm16->WndProc.lParam),
  616. LOWORD(pParm16->WndProc.lParam)
  617. )
  618. );
  619. } else if (iRetID == RET_HOOKPROC) {
  620. LOGDEBUG(9,("%04X Calling WIN16 HOOKPROC(%08lx: %04x,%04x,%04x,%04x)\n",
  621. pFrame->wTDB,
  622. vpfnProc,
  623. pParm16->HookProc.nCode,
  624. pParm16->HookProc.wParam,
  625. HIWORD(pParm16->HookProc.lParam),
  626. LOWORD(pParm16->HookProc.lParam)
  627. )
  628. );
  629. } else {
  630. LOGDEBUG(9,("%04X Calling WIN16 %s(%04x,%04x,%04x)\n",
  631. pFrame->wTDB,
  632. apszCallBacks[iRetID],
  633. pParm16->WndProc.wParam,
  634. HIWORD(pParm16->WndProc.lParam),
  635. LOWORD(pParm16->WndProc.lParam)
  636. )
  637. );
  638. }
  639. #endif
  640. FREEVDMPTR(pFrame);
  641. FLUSHVDMPTR(ptd->vpCBStack, sizeof(CBVDMFRAME), pCBFrame);
  642. FREEVDMPTR(pCBFrame);
  643. // Set up to use the right 16-bit stack for this thread
  644. #if FASTBOPPING
  645. SETFASTVDMSTACK(ptd->vpCBStack);
  646. #else
  647. SETVDMSTACK(ptd->vpCBStack);
  648. #endif
  649. //
  650. // do the callback!
  651. //
  652. #if FASTBOPPING
  653. CurrentMonitorTeb = NtCurrentTeb();
  654. FastWOWCallbackCall();
  655. // fastbop code refreshes ptd->vpStack
  656. #else
  657. // Time to get the IEU running task-time code again
  658. SaveIp = getIP();
  659. host_simulate();
  660. setIP(SaveIp);
  661. ptd->vpStack = VDMSTACK();
  662. #endif
  663. // after return from callback ptd->vpStack will point to PCBVDMFRAME
  664. ptd->vpCBStack = ptd->vpStack;
  665. // reset the stackalloc16() count back to this context
  666. ptd->cStackAlloc16 = cStackAlloc16;
  667. GETFRAMEPTR(ptd->vpCBStack, (PVDMFRAME)pCBFrame);
  668. // Just making sure that this thread matches the current 16-bit task
  669. WOW32ASSERT((pCBFrame->wTDB == ptd->htask16) ||
  670. (ptd->htask16 == 0));
  671. if (pvpReturn) {
  672. LOW(*pvpReturn) = pCBFrame->wAX;
  673. HIW(*pvpReturn) = pCBFrame->wDX;
  674. }
  675. switch(iRetID) {
  676. case RET_GLOBALLOCK:
  677. case RET_LOCKRESOURCE:
  678. if(pParm16) {
  679. pParm16->WndProc.lParam =
  680. pCBFrame->wGenUse2 | (LONG)pCBFrame->wGenUse1 << 16;
  681. }
  682. break;
  683. case RET_GLOBALALLOCLOCK:
  684. if(pParm16) {
  685. pParm16->WndProc.wParam = pCBFrame->wGenUse1;
  686. }
  687. break;
  688. case RET_FINDRESOURCE:
  689. if(pParm16) {
  690. pParm16->WndProc.lParam = (ULONG)pCBFrame->wGenUse1;
  691. }
  692. break;
  693. } // end switch
  694. LOGDEBUG(9,("%04X WIN16 %s returning: %lx\n",
  695. pCBFrame->wTDB, apszCallBacks[iRetID], (pvpReturn) ? *pvpReturn : 0));
  696. // restore the stack to its original value.
  697. // ie. fake the 'pop' of callback stack by resetting the vpStack
  698. // to its original value. The ss:sp will actually be updated when
  699. // the 'api thunk' returns.
  700. // consistency check
  701. WOW32ASSERT(pCBFrame->vpStack == vpStackT);
  702. // restore the stack & callback frame ptrs to original values
  703. ptd->vpStack = pCBFrame->vpStack;
  704. ptd->vpCBStack = vpCBStack;
  705. // ssync 16-bit & 32-bit common dialog structs (see wcommdlg.c)
  706. if(fComDlgSync) {
  707. // Note: This call can invalidate flat ptrs to 16-bit mem
  708. Ssync_WOW_CommDlg_Structs(ptd->CommDlgTd, w16to32, 0);
  709. }
  710. FREEVDMPTR(pCBFrame);
  711. return TRUE;
  712. }