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.

973 lines
27 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1992, Microsoft Corporation
  6. *
  7. * wkgthunk.C
  8. * WOW32 Generic Thunk Mechanism (for OLE 2.0 and others)
  9. *
  10. * History:
  11. * Created 11-MARCH-1993 by Matt Felton (mattfe)
  12. *
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. MODNAME(wkgthunk.c);
  17. #ifdef i386 // on RISC this is implemented in this file.
  18. extern DWORD WK32ICallProc32MakeCall(DWORD pfn, DWORD cbArgs, DWORD *pArgs);
  19. #endif
  20. #ifdef WX86
  21. typedef
  22. HMODULE
  23. (*PFNWX86LOADX86DLL)(
  24. LPCWSTR lpLibFileName,
  25. DWORD dwFlags
  26. );
  27. typedef
  28. BOOL
  29. (*PFNWX86FREEX86DLL)(
  30. HMODULE hMod
  31. );
  32. typedef
  33. PVOID
  34. (*PFNWX86THUNKPROC)(
  35. PVOID pvAddress,
  36. PVOID pvCBDispatch,
  37. BOOL fNativeToX86
  38. );
  39. typedef
  40. ULONG
  41. (*PFNWX86EMULATEX86)(
  42. PVOID StartAddress,
  43. ULONG nParameters,
  44. PULONG Parameters
  45. );
  46. typedef
  47. (*PFNWX86THUNKEMULATEX86)(
  48. ULONG nParameters,
  49. PULONG Parameters
  50. );
  51. typedef
  52. BOOL
  53. (*PFNWX86THUNKINFO)(
  54. PVOID ThunkProc,
  55. PVOID *pAddress,
  56. BOOL *pfNativeToX86
  57. );
  58. HMODULE hWx86Dll = FALSE;
  59. PFNWX86LOADX86DLL Wx86LoadX86Dll= NULL;
  60. PFNWX86FREEX86DLL Wx86FreeX86Dll= NULL;
  61. PFNWX86THUNKPROC Wx86ThunkProc= NULL;
  62. PFNWX86THUNKEMULATEX86 Wx86ThunkEmulateX86= NULL;
  63. PFNWX86EMULATEX86 Wx86EmulateX86= NULL;
  64. PFNWX86THUNKINFO Wx86ThunkInfo= NULL;
  65. VOID
  66. TermWx86System(
  67. VOID
  68. )
  69. {
  70. if (hWx86Dll) {
  71. FreeLibrary(hWx86Dll);
  72. hWx86Dll = NULL;
  73. Wx86LoadX86Dll = NULL;
  74. Wx86FreeX86Dll = NULL;
  75. Wx86ThunkProc = NULL;
  76. Wx86ThunkEmulateX86 = NULL;
  77. Wx86EmulateX86 = NULL;
  78. }
  79. }
  80. BOOL
  81. InitWx86System(
  82. VOID
  83. )
  84. {
  85. if (hWx86Dll) {
  86. return TRUE;
  87. }
  88. hWx86Dll = LoadLibraryExW(L"Wx86.Dll", NULL, 0);
  89. if (!hWx86Dll) {
  90. return FALSE;
  91. }
  92. Wx86LoadX86Dll = (PFNWX86LOADX86DLL) GetProcAddress(hWx86Dll, "Wx86LoadX86Dll");
  93. Wx86FreeX86Dll = (PFNWX86FREEX86DLL) GetProcAddress(hWx86Dll, "Wx86FreeX86Dll");
  94. Wx86ThunkProc = (PFNWX86THUNKPROC) GetProcAddress(hWx86Dll, "Wx86ThunkProc");
  95. Wx86ThunkEmulateX86 = (PFNWX86THUNKEMULATEX86) GetProcAddress(hWx86Dll, "Wx86ThunkEmulateX86");
  96. Wx86EmulateX86 = (PFNWX86EMULATEX86) GetProcAddress(hWx86Dll, "Wx86EmulateX86");
  97. if (!Wx86LoadX86Dll || !Wx86FreeX86Dll || !Wx86ThunkProc ||
  98. !Wx86ThunkEmulateX86 || !Wx86EmulateX86)
  99. {
  100. TermWx86System();
  101. return FALSE;
  102. }
  103. return TRUE;
  104. }
  105. BOOL
  106. IsX86Dll(
  107. HMODULE hModule
  108. )
  109. {
  110. if (((ULONG)hModule & 0x01) || !hWx86Dll) {
  111. return FALSE;
  112. }
  113. return (RtlImageNtHeader((PVOID)hModule)->FileHeader.Machine == IMAGE_FILE_MACHINE_I386);
  114. }
  115. ULONG
  116. ThunkProcDispatchP32(
  117. ULONG p1, ULONG p2, ULONG p3, ULONG p4,
  118. ULONG p5, ULONG p6, ULONG p7, ULONG p8,
  119. ULONG p9, ULONG p10, ULONG p11, ULONG p12,
  120. ULONG p13, ULONG p14, ULONG p15, ULONG p16,
  121. ULONG p17, ULONG p18, ULONG p19, ULONG p20,
  122. ULONG p21, ULONG p22, ULONG p23, ULONG p24,
  123. ULONG p25, ULONG p26, ULONG p27, ULONG p28,
  124. ULONG p29, ULONG p30, ULONG p31, ULONG p32
  125. )
  126. {
  127. ULONG Parameters[32];
  128. Parameters[0] = p1;
  129. Parameters[1] = p2;
  130. Parameters[2] = p3;
  131. Parameters[3] = p4;
  132. Parameters[4] = p5;
  133. Parameters[5] = p6;
  134. Parameters[6] = p7;
  135. Parameters[7] = p8;
  136. Parameters[8] = p9;
  137. Parameters[9] = p10;
  138. Parameters[10] = p11;
  139. Parameters[11] = p12;
  140. Parameters[12] = p13;
  141. Parameters[13] = p14;
  142. Parameters[14] = p15;
  143. Parameters[15] = p16;
  144. Parameters[16] = p17;
  145. Parameters[17] = p18;
  146. Parameters[18] = p19;
  147. Parameters[19] = p20;
  148. Parameters[20] = p21;
  149. Parameters[21] = p22;
  150. Parameters[22] = p23;
  151. Parameters[23] = p24;
  152. Parameters[24] = p25;
  153. Parameters[25] = p26;
  154. Parameters[26] = p27;
  155. Parameters[27] = p28;
  156. Parameters[28] = p29;
  157. Parameters[29] = p30;
  158. Parameters[30] = p31;
  159. Parameters[31] = p32;
  160. return (*Wx86ThunkEmulateX86)(32, Parameters);
  161. }
  162. #endif
  163. char szServicePack[] = "Service Pack 2";
  164. BOOL GtCompGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
  165. {
  166. BOOL bReturn;
  167. if(lpVersionInfo == NULL) {
  168. return(FALSE);
  169. }
  170. bReturn = GetVersionExA(lpVersionInfo);
  171. // WHISTLER RAID BUG 366613
  172. // Business Plan Pro was failing to install because of a version problem.
  173. // Added compatibility flag for version lie to fix the problem. Solution is
  174. // to add/change the string pointed to by the szCSVersion param to "Service Pack 2"
  175. if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_PLATFORMVERSIONLIE)
  176. { PFLAGINFOBITS pFlagInfoBits;
  177. LPSTR *pFlagArgv;
  178. pFlagInfoBits = CheckFlagInfo(WOWCOMPATFLAGSEX, WOWCFEX_PLATFORMVERSIONLIE);
  179. if(pFlagInfoBits && pFlagInfoBits->dwFlagArgc == 6 && pFlagInfoBits->pFlagArgv) {
  180. LOGDEBUG(LOG_WARNING,("GtCompGetVersionExA: Platform version lie applied\n"));
  181. pFlagArgv = pFlagInfoBits->pFlagArgv;
  182. if(*pFlagArgv) {
  183. lpVersionInfo->dwOSVersionInfoSize = atoi(*pFlagArgv);
  184. }
  185. pFlagArgv++;
  186. if(*pFlagArgv) {
  187. lpVersionInfo->dwMajorVersion = atoi(*pFlagArgv);
  188. }
  189. pFlagArgv++;
  190. if(*pFlagArgv) {
  191. lpVersionInfo->dwMinorVersion = atoi(*pFlagArgv);
  192. }
  193. pFlagArgv++;
  194. if(*pFlagArgv) {
  195. lpVersionInfo->dwBuildNumber = atoi(*pFlagArgv);
  196. }
  197. pFlagArgv++;
  198. if(*pFlagArgv) {
  199. lpVersionInfo->dwPlatformId = atoi(*pFlagArgv);
  200. }
  201. pFlagArgv++;
  202. if(*pFlagArgv) {
  203. WOW32_strncpy(lpVersionInfo->szCSDVersion,*pFlagArgv,128);
  204. lpVersionInfo->szCSDVersion[127] = '\0';
  205. }
  206. }
  207. }
  208. return bReturn;
  209. }
  210. HANDLE GtCompCreateFileA(LPSTR lpFileName,
  211. DWORD dwDesiredAccess,
  212. DWORD dwShareMode,
  213. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  214. DWORD dwCreationDisposition,
  215. DWORD dwFlagsAndAttributes,
  216. HANDLE hTemplateFile
  217. ) {
  218. CHAR szNewFilePath[MAX_PATH];
  219. if(W32Map9xSpecialPath(lpFileName, szNewFilePath, sizeof(szNewFilePath))) {
  220. lpFileName = szNewFilePath;
  221. }
  222. return DPM_CreateFile(lpFileName,
  223. dwDesiredAccess,
  224. dwShareMode,
  225. lpSecurityAttributes,
  226. dwCreationDisposition,
  227. dwFlagsAndAttributes,
  228. hTemplateFile);
  229. }
  230. BOOL GtCompMoveFileA( LPSTR lpExistingFileName, // file name
  231. LPSTR lpNewFileName // new file name
  232. ) {
  233. CHAR szNewSourcePath[MAX_PATH];
  234. CHAR szNewDestPath[MAX_PATH];
  235. if(W32Map9xSpecialPath(lpExistingFileName, szNewSourcePath, sizeof(szNewSourcePath))) {
  236. lpExistingFileName = szNewSourcePath;
  237. }
  238. if(W32Map9xSpecialPath(lpNewFileName, szNewDestPath, sizeof(szNewDestPath))) {
  239. lpNewFileName = szNewDestPath;
  240. }
  241. return DPM_MoveFile(lpExistingFileName, lpNewFileName);
  242. }
  243. ULONG FASTCALL WK32LoadLibraryEx32W(PVDMFRAME pFrame)
  244. {
  245. PSZ psz1;
  246. HINSTANCE hinstance;
  247. PLOADLIBRARYEX32W16 parg16;
  248. #ifdef i386
  249. BYTE FpuState[108];
  250. // Save the 487 state
  251. _asm {
  252. lea ecx, [FpuState]
  253. fsave [ecx]
  254. }
  255. #endif
  256. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  257. GETVDMPTR(parg16->lpszLibFile,0,psz1);
  258. //
  259. // Make sure the Win32 current directory matches this task's.
  260. //
  261. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  262. hinstance = LoadLibraryEx(psz1, (HANDLE)parg16->hFile, parg16->dwFlags);
  263. #ifdef WX86
  264. //
  265. // If load failed it might be an x86 binary on risc.
  266. // try it thru Wx86
  267. //
  268. if (!hinstance) {
  269. LONG LastError;
  270. NTSTATUS Status;
  271. ANSI_STRING AnsiString;
  272. UNICODE_STRING UniString;
  273. //
  274. // Prserve the LastError, if wx86 can't handle it, we will restore it
  275. // so caller won't see any difference.
  276. //
  277. LastError = GetLastError();
  278. if (InitWx86System()) {
  279. RtlInitString(&AnsiString, psz1);
  280. if (AreFileApisANSI()) {
  281. Status = RtlAnsiStringToUnicodeString(&UniString, &AnsiString, TRUE);
  282. }
  283. else {
  284. Status = RtlOemStringToUnicodeString(&UniString, &AnsiString, TRUE);
  285. }
  286. if (NT_SUCCESS(Status)) {
  287. hinstance = (*Wx86LoadX86Dll)(UniString.Buffer, parg16->dwFlags);
  288. RtlFreeUnicodeString(&UniString);
  289. }
  290. }
  291. if (!hinstance) {
  292. SetLastError(LastError);
  293. }
  294. }
  295. #endif
  296. if (hinstance) {
  297. PSZ pszModuleFilePart = WOW32_strrchr(psz1, '\\');
  298. if (pszModuleFilePart) {
  299. pszModuleFilePart++;
  300. }
  301. else {
  302. pszModuleFilePart = psz1;
  303. }
  304. if(!WOW32_strnicmp("~glf",pszModuleFilePart,4)) {
  305. PSZ pszTemp = GtCompGetExportDirectory((PBYTE)hinstance);
  306. if (pszTemp && !WOW32_stricmp("w32inst.dll",pszTemp)) {
  307. pfnShellLink = (PFNSHELLLINK)GetProcAddress(hinstance,"ShellLink");
  308. }
  309. }
  310. else if(!WOW32_strnicmp("smackw32.dll",pszModuleFilePart,5) &&
  311. GetProcAddress(hinstance,"_SmackSoundUseMSS@4")) {
  312. GtCompHookImport((PBYTE)hinstance,"kernel32.dll",(DWORD)pfnLoadLibraryA,(DWORD)GtCompLoadLibraryA);
  313. }
  314. }
  315. FREEARGPTR(parg16);
  316. #ifdef i386
  317. // Restore the 487 state
  318. _asm {
  319. lea ecx, [FpuState]
  320. frstor [ecx]
  321. }
  322. #endif
  323. return (ULONG)hinstance;
  324. }
  325. ULONG FASTCALL WK32FreeLibrary32W(PVDMFRAME pFrame)
  326. {
  327. ULONG fResult;
  328. PFREELIBRARY32W16 parg16;
  329. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  330. #ifdef WX86
  331. if (IsX86Dll((HMODULE)parg16->hLibModule)) {
  332. fResult = (*Wx86FreeX86Dll)((HMODULE)parg16->hLibModule);
  333. FREEARGPTR(parg16);
  334. return (fResult);
  335. }
  336. #endif
  337. fResult = FreeLibrary((HMODULE)parg16->hLibModule);
  338. FREEARGPTR(parg16);
  339. return (fResult);
  340. }
  341. ULONG FASTCALL WK32GetProcAddress32W(PVDMFRAME pFrame)
  342. {
  343. PVOID lpAddress;
  344. PSZ psz1;
  345. PGETPROCADDRESS32W16 parg16;
  346. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  347. GETPSZIDPTR(parg16->lpszProc, psz1);
  348. lpAddress = GetProcAddress((HMODULE)parg16->hModule, psz1);
  349. #ifdef WX86
  350. if (lpAddress && IsX86Dll((HMODULE)parg16->hModule)) {
  351. PVOID pv;
  352. pv = (*Wx86ThunkProc)(lpAddress, ThunkProcDispatchP32, TRUE);
  353. if (pv && pv != (PVOID)-1) {
  354. lpAddress = (ULONG)pv;
  355. }
  356. else {
  357. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  358. lpAddress = 0;
  359. }
  360. }
  361. #endif
  362. // WHISTLER RAID BUG 366613
  363. // Business Plan Pro was failing to install because of a version problem.
  364. // Added compatibility flag to account for version lie. Here we redirect to
  365. // function GtCompGetVersionExA.
  366. if(lpAddress == pfnGetVersionExA) {
  367. lpAddress = GtCompGetVersionExA;
  368. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: GetVersionExA call redirected to function GtCompGetVersionExA"));
  369. }
  370. else if(lpAddress == pfnCreateDirectoryA) {
  371. lpAddress = GtCompCreateDirectoryA;
  372. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: CreateDirectoryA call redirected to function GtCompCreateDirectory"));
  373. }
  374. else if(lpAddress == pfnCreateFileA) {
  375. lpAddress = GtCompCreateFileA;
  376. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: CreateFileA call redirected to function GtCompCreateFileA"));
  377. }
  378. else if(lpAddress == pfnMoveFileA) {
  379. lpAddress = GtCompMoveFileA;
  380. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: MoveFileA call redirected to function GtCompMoveFileA"));
  381. }
  382. else if(pfnShellLink && lpAddress == pfnShellLink) {
  383. lpAddress = GtCompShellLink;
  384. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: ShellLink call redirected to function GtCompShellLink"));
  385. }
  386. // else if Dynamic Module Patching is turned on for this task....
  387. else if(CURRENTPTD()->dwWOWCompatFlags2 & WOWCF2_DPM_PATCHES) {
  388. // ...see if we need to patch the address
  389. lpAddress = GetDpmAddress(lpAddress);
  390. }
  391. FREEARGPTR(parg16);
  392. return ((ULONG)lpAddress);
  393. }
  394. ULONG FASTCALL WK32GetVDMPointer32W(PVDMFRAME pFrame)
  395. {
  396. ULONG lpAddress;
  397. PGETVDMPOINTER32W16 parg16;
  398. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  399. lpAddress = (ULONG) WOWGetVDMPointer(parg16->lpAddress, 0, parg16->fMode);
  400. FREEARGPTR(parg16);
  401. return(lpAddress);
  402. }
  403. #ifndef i386
  404. //
  405. // x86 code in i386\callpr32.asm.
  406. //
  407. DWORD WK32ICallProc32MakeCall(DWORD pfn, DWORD cbArgs, DWORD *pArgs)
  408. {
  409. typedef int (FAR WINAPIV *FARFUNC)();
  410. DWORD dw;
  411. #ifdef WX86
  412. if (Wx86ThunkInfo) {
  413. PVOID Address;
  414. if (Wx86ThunkInfo((PVOID)pfn, &Address, NULL)) {
  415. return Wx86EmulateX86(Address, cbArgs/sizeof(DWORD), pArgs);
  416. }
  417. }
  418. #endif
  419. if (cbArgs <= (4 * sizeof(DWORD))) {
  420. dw = ((FARFUNC) pfn) (
  421. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3] );
  422. } else if (cbArgs <= (8 * sizeof(DWORD))) {
  423. dw = ((FARFUNC) pfn) (
  424. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3],
  425. pArgs[ 4], pArgs[ 5], pArgs[ 6], pArgs[ 7] );
  426. } else {
  427. dw = ((FARFUNC) pfn) (
  428. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3],
  429. pArgs[ 4], pArgs[ 5], pArgs[ 6], pArgs[ 7],
  430. pArgs[ 8], pArgs[ 9], pArgs[10], pArgs[11],
  431. pArgs[12], pArgs[13], pArgs[14], pArgs[15],
  432. pArgs[16], pArgs[17], pArgs[18], pArgs[19],
  433. pArgs[20], pArgs[21], pArgs[22], pArgs[23],
  434. pArgs[24], pArgs[25], pArgs[26], pArgs[27],
  435. pArgs[28], pArgs[29], pArgs[30], pArgs[31] );
  436. }
  437. return dw;
  438. }
  439. #endif
  440. ULONG FASTCALL WK32ICallProc32W(PVDMFRAME pFrame)
  441. {
  442. register DWORD dwReturn;
  443. PICALLPROC32W16 parg16;
  444. UNALIGNED DWORD *pArg;
  445. DWORD fAddress;
  446. BOOL fSourceCDECL;
  447. UINT cParams;
  448. UINT nParam;
  449. UNALIGNED DWORD *lpArgs;
  450. DWORD dwTemp[32];
  451. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  452. fSourceCDECL = HIWORD(parg16->cParams) & CPEX32_SOURCE_CDECL;
  453. // fDestCDECL = HIWORD(parg16->cParams) & CPEX32_DEST_CDECL; // not needed
  454. // We only support up to 32 parameters
  455. cParams = LOWORD(parg16->cParams);
  456. if (cParams > 32)
  457. return(0);
  458. // Don't call to Zero
  459. if (parg16->lpProcAddress == 0) {
  460. LOGDEBUG(LOG_ALWAYS,("WK32ICallProc32 - Error calling to 0 not allowed"));
  461. return(0);
  462. }
  463. lpArgs = &parg16->p1;
  464. // Convert Any 16:16 Addresses to 32 bit
  465. // flat as required by fAddressConvert
  466. pArg = lpArgs;
  467. fAddress = parg16->fAddressConvert;
  468. while (fAddress != 0) {
  469. if (fAddress & 0x1) {
  470. *pArg = (DWORD) GetPModeVDMPointer(*pArg, 0);
  471. }
  472. pArg++;
  473. fAddress = fAddress >> 1;
  474. }
  475. //
  476. // The above code is funny. It means that parameter translation will
  477. // occur before accounting for the calling convention. This means that
  478. // they will be specifying the bit position for CallProc32W by counting the
  479. // parameters from the end, whereas with CallProc32ExW, they count from the
  480. // beginning. Weird for pascal, but that is compatible with what we've
  481. // already shipped. cdecl should be more understandable.
  482. //
  483. //
  484. // Make sure the Win32 current directory matches this task's.
  485. //
  486. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  487. if (!fSourceCDECL) {
  488. //
  489. // Invert the parameters
  490. //
  491. pArg = lpArgs;
  492. nParam = cParams;
  493. while ( nParam != 0 ) {
  494. --nParam;
  495. dwTemp[nParam] = *pArg;
  496. pArg++;
  497. }
  498. } else {
  499. //
  500. // To make usage of WK32ICallProc32MakeCall consistent on all
  501. // platforms we copy the parameters to dwTemp, to ensure the parameter
  502. // array is dword aligned. Impact is insignificnt since primary calling
  503. // convention for win16 is PASCAL.
  504. //
  505. memcpy(dwTemp, lpArgs, cParams * sizeof(DWORD));
  506. }
  507. //
  508. // dwTemp now points to the very first parameter in any calling convention
  509. // And all of the parameters have been appropriately converted to flat ptrs.
  510. //
  511. // Note that on the 32-bit side, the parameter ordering is always push
  512. // right-to-left, so the first parameter is at the lowest address. This
  513. // is true for x86 _cdecl and _stdcall as well as RISC, which has only
  514. // _cdecl.
  515. //
  516. //
  517. // On x86 we call an assembly routine to actually make the call to
  518. // the client's Win32 routine. The code is much more compact
  519. // this way, and it's the only way we can be compatible with
  520. // Win95's implementation, which cleans up the stack if the
  521. // routine doesn't.
  522. //
  523. // This assembly routine "pushes" the arguments by copying
  524. // them as a block, so they must be in the proper order for
  525. // the destination calling convention.
  526. //
  527. // The RISC C code for this routine is just below. On RISC the caller
  528. // is always responsible for cleaning up the stack, so that shouldn't
  529. // be a problem.
  530. //
  531. dwReturn = WK32ICallProc32MakeCall(
  532. parg16->lpProcAddress,
  533. cParams * sizeof(DWORD),
  534. dwTemp
  535. );
  536. FREEARGPTR(parg16);
  537. return(dwReturn);
  538. }
  539. //
  540. // Chicago has WOWGetVDMPointerFix, which is just like WOWGetVDMPointer
  541. // but also calls GlobalFix to keep the 16-bit memory from moving. It
  542. // has a companion WOWGetVDMPointerUnfix, which is basically a Win32-callable
  543. // GlobalUnfix.
  544. //
  545. // Chicago found the need for these functions because their global heaps
  546. // can be rearranged while Win32 code called from a generic thunk is
  547. // executing. In Windows NT, global memory cannot move while in a thunk
  548. // unless the thunk calls back to the 16-bit side.
  549. //
  550. // Our exported WOWGetVDMPointerFix is simply an alias to WOWGetVDMPointer --
  551. // it does *not* call GlobalFix because it is not needed in 99% of the
  552. // cases. WOWGetVDMPointerUnfix is implemented below as NOP.
  553. //
  554. VOID WOWGetVDMPointerUnfix(VPVOID vp)
  555. {
  556. UNREFERENCED_PARAMETER(vp);
  557. return;
  558. }
  559. //
  560. // Yielding functions allow 32-bit thunks to avoid 4 16<-->32 transitions
  561. // involved in calling back to 16-bit side to call Yield or DirectedYield,
  562. // which are thunked back to user32.
  563. //
  564. VOID WOWYield16(VOID)
  565. {
  566. //
  567. // Since WK32Yield (the thunk for Yield) doesn't use pStack16,
  568. // just call it rather than duplicate the code.
  569. //
  570. WK32Yield(NULL);
  571. }
  572. VOID WOWDirectedYield16(WORD hTask16)
  573. {
  574. //
  575. // This is duplicating the code of WK32DirectedYield, the
  576. // two must be kept synchronized.
  577. //
  578. BlockWOWIdle(TRUE);
  579. (pfnOut.pfnDirectedYield)(THREADID32(hTask16));
  580. BlockWOWIdle(FALSE);
  581. }
  582. #ifdef DEBUG // called by test code in checked wowexec
  583. DWORD WINAPI WOWStdCall32ArgsTestTarget(
  584. DWORD p1,
  585. DWORD p2,
  586. DWORD p3,
  587. DWORD p4,
  588. DWORD p5,
  589. DWORD p6,
  590. DWORD p7,
  591. DWORD p8,
  592. DWORD p9,
  593. DWORD p10,
  594. DWORD p11,
  595. DWORD p12,
  596. DWORD p13,
  597. DWORD p14,
  598. DWORD p15,
  599. DWORD p16,
  600. DWORD p17,
  601. DWORD p18,
  602. DWORD p19,
  603. DWORD p20,
  604. DWORD p21,
  605. DWORD p22,
  606. LPDWORD p23,
  607. DWORD p24,
  608. DWORD p25,
  609. DWORD p26,
  610. DWORD p27,
  611. DWORD p28,
  612. DWORD p29,
  613. DWORD p30,
  614. DWORD p31,
  615. LPDWORD p32
  616. )
  617. {
  618. return ((((p1+p2+p3+p4+p5+p6+p7+p8+p9+p10) -
  619. (p11+p12+p13+p14+p15+p16+p17+p18+p19+p20)) << p21) +
  620. ((p22+*p23+p24+p25+p26) - (p27+p28+p29+p30+p31+*p32)));
  621. }
  622. #endif // DEBUG
  623. PFNSHELLLINK pfnShellLink;
  624. /* ShellLink exported by W32Inst.dll (installshield dll)
  625. * takes a pointer to struct.
  626. * At offset 40, it has a pointer (pShellLinkArg->pszShortCut) to a string.
  627. * The string actually consists of several strings delimited by 0x7f chars and
  628. * ultimately terminated by a NULL char. Path where the shortcut needs to go
  629. * is located after second 0x7f. Unfortunately some apps use hardcoded paths
  630. * valid for 9x only, so we attempt to correct them here.
  631. * see bug Whistler 177738
  632. *
  633. */
  634. ULONG GtCompShellLink( PSHELLLINKARG pShellLinkArg
  635. )
  636. {
  637. PSZ pszNewShortCut = NULL;
  638. PSZ pszOldShortCut;
  639. PSZ pszTemp;
  640. DWORD dwCount, dwLen;
  641. ULONG uReturn;
  642. if(!pShellLinkArg || !pShellLinkArg->pszShortCut) {
  643. return(0);
  644. }
  645. pszOldShortCut = pShellLinkArg->pszShortCut;
  646. pszTemp = pszOldShortCut;
  647. // get to the beginning of the shortcut path which starts after second 0x7f
  648. // sample string "1.Name0x7fStart Directory0x7fShortcut path(Shortcut location)0x7fRestNULL"
  649. while(*pszTemp && *pszTemp++!=0x7f);
  650. while(*pszTemp && *pszTemp++!=0x7f);
  651. if(*pszTemp) {
  652. // number of chars from beginning to second 0x7f
  653. dwCount=pszTemp - pszOldShortCut;
  654. dwLen = strlen(pszTemp);
  655. pszNewShortCut = malloc_w(dwCount+dwLen+MAX_PATH);
  656. if(pszNewShortCut && W32Map9xSpecialPath(pszTemp, pszNewShortCut+dwCount,dwLen+MAX_PATH)) {
  657. // Path needs to be corrected
  658. memcpy(pszNewShortCut,pszOldShortCut,dwCount);
  659. pShellLinkArg->pszShortCut = pszNewShortCut;
  660. }
  661. }
  662. uReturn = pfnShellLink(pShellLinkArg);
  663. pShellLinkArg->pszShortCut = pszOldShortCut;
  664. if(pszNewShortCut) {
  665. free_w(pszNewShortCut);
  666. }
  667. return uReturn;
  668. }
  669. ULONG
  670. GtCompCreateDirectoryA(PSZ pszDirPath,
  671. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  672. )
  673. {
  674. CHAR szNewDirPath[MAX_PATH];
  675. if(W32Map9xSpecialPath(pszDirPath, szNewDirPath, sizeof(szNewDirPath))) {
  676. return DPM_CreateDirectory(szNewDirPath, lpSecurityAttributes);
  677. }
  678. return DPM_CreateDirectory(pszDirPath, lpSecurityAttributes);
  679. }
  680. PSZ GtCompGetExportDirectory(PBYTE pDllBase)
  681. {
  682. PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)pDllBase;
  683. PIMAGE_NT_HEADERS pINTH;
  684. PIMAGE_EXPORT_DIRECTORY pIED;
  685. DWORD dwExportTableOffset;
  686. PSZ pImageName = NULL;
  687. if(!pDllBase) {
  688. return(NULL);
  689. }
  690. // Get the export table directory
  691. pINTH = (PIMAGE_NT_HEADERS)(pDllBase + pIDH->e_lfanew);
  692. dwExportTableOffset = pINTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  693. pIED = (PIMAGE_EXPORT_DIRECTORY)(pDllBase + dwExportTableOffset);
  694. if (pIED->Name) {
  695. pImageName = (PSZ)pDllBase+pIED->Name;
  696. }
  697. return pImageName;
  698. }
  699. HMODULE GtCompLoadLibraryA(PSZ pszDllName) {
  700. if (!WOW32_strnicmp(pszDllName,"mss32",5)) {
  701. return NULL;
  702. }
  703. return LoadLibrary(pszDllName);
  704. }
  705. VOID
  706. GtCompHookImport(
  707. PBYTE pDllBase, // base address of the DLL to change imports
  708. PSZ pszModuleName, // import func's module name
  709. DWORD pfnOldFunc, // import func pointer
  710. DWORD pfnNewFunc // new import func pointer
  711. ) {
  712. NTSTATUS Status;
  713. PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)pDllBase;
  714. PIMAGE_NT_HEADERS pINTH;
  715. PIMAGE_IMPORT_DESCRIPTOR pIID;
  716. DWORD dwImportTableOffset;
  717. DWORD dwProtect, dwProtect2;
  718. DWORD dwFuncAddr;
  719. SIZE_T dwProtectSize;
  720. if(!pDllBase) {
  721. return;
  722. }
  723. //
  724. // Get the import table.
  725. //
  726. pINTH = (PIMAGE_NT_HEADERS)(pDllBase + pIDH->e_lfanew);
  727. dwImportTableOffset = pINTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  728. if (dwImportTableOffset == 0) {
  729. // No import table found. This is probably ntdll.dll
  730. return;
  731. }
  732. pIID = (PIMAGE_IMPORT_DESCRIPTOR)(pDllBase + dwImportTableOffset);
  733. // Loop through the import table and search for the API to patch
  734. while (TRUE) {
  735. PSZ pszImportEntryModule;
  736. PIMAGE_THUNK_DATA pITDA;
  737. // Return if no first thunk (terminating condition).
  738. if (pIID->FirstThunk == 0) {
  739. break;
  740. }
  741. pszImportEntryModule = (PSZ)(pDllBase + pIID->Name);
  742. if(!WOW32_stricmp(pszImportEntryModule,pszModuleName)) {
  743. pITDA = (PIMAGE_THUNK_DATA) (pDllBase + (DWORD)pIID->FirstThunk);
  744. while(TRUE) {
  745. if(pITDA->u1.Ordinal == 0) {
  746. break;
  747. }
  748. if((DWORD)pITDA->u1.Function == pfnOldFunc) {
  749. dwProtectSize = sizeof(DWORD);
  750. dwFuncAddr = (SIZE_T)&pITDA->u1.Function;
  751. Status = NtProtectVirtualMemory(NtCurrentProcess(),
  752. (PVOID)&dwFuncAddr,
  753. &dwProtectSize,
  754. PAGE_READWRITE,
  755. &dwProtect);
  756. if(NT_SUCCESS(Status)) {
  757. pITDA->u1.Function = pfnNewFunc;
  758. dwProtectSize = sizeof(DWORD);
  759. Status = NtProtectVirtualMemory(NtCurrentProcess(),
  760. (PVOID)&dwFuncAddr,
  761. &dwProtectSize,
  762. dwProtect,
  763. &dwProtect2);
  764. }
  765. }
  766. pITDA++;
  767. }
  768. }
  769. pIID++;
  770. }
  771. }