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.

847 lines
23 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. bReturn = GetVersionExA(lpVersionInfo);
  168. // WHISTLER RAID BUG 366613
  169. // Business Plan Pro was failing to install because of a version problem.
  170. // Added compatibility flag for version lie to fix the problem. Solution is
  171. // to add/change the string pointed to by the szCSVersion param to "Service Pack 2"
  172. if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SP2CSDVERSIONLIE)
  173. {
  174. LOGDEBUG(LOG_WARNING,("GtCompGetVersionExA: Service Pack 2 version lie applied\n"));
  175. memcpy(lpVersionInfo->szCSDVersion, szServicePack, sizeof(szServicePack));
  176. }
  177. // WHISTLER RAID BUG 401998
  178. if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_PLATFORMVERSIONLIE)
  179. {
  180. LOGDEBUG(LOG_WARNING,("GtCompGetVersionExA: Platform version lie applied\n"));
  181. lpVersionInfo->dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
  182. }
  183. return bReturn;
  184. }
  185. ULONG FASTCALL WK32LoadLibraryEx32W(PVDMFRAME pFrame)
  186. {
  187. PSZ psz1;
  188. HINSTANCE hinstance;
  189. PLOADLIBRARYEX32W16 parg16;
  190. #ifdef i386
  191. BYTE FpuState[108];
  192. // Save the 487 state
  193. _asm {
  194. lea ecx, [FpuState]
  195. fsave [ecx]
  196. }
  197. #endif
  198. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  199. GETVDMPTR(parg16->lpszLibFile,0,psz1);
  200. //
  201. // Make sure the Win32 current directory matches this task's.
  202. //
  203. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  204. hinstance = LoadLibraryEx(psz1, (HANDLE)parg16->hFile, parg16->dwFlags);
  205. #ifdef WX86
  206. //
  207. // If load failed it might be an x86 binary on risc.
  208. // try it thru Wx86
  209. //
  210. if (!hinstance) {
  211. LONG LastError;
  212. NTSTATUS Status;
  213. ANSI_STRING AnsiString;
  214. UNICODE_STRING UniString;
  215. //
  216. // Prserve the LastError, if wx86 can't handle it, we will restore it
  217. // so caller won't see any difference.
  218. //
  219. LastError = GetLastError();
  220. if (InitWx86System()) {
  221. RtlInitString(&AnsiString, psz1);
  222. if (AreFileApisANSI()) {
  223. Status = RtlAnsiStringToUnicodeString(&UniString, &AnsiString, TRUE);
  224. }
  225. else {
  226. Status = RtlOemStringToUnicodeString(&UniString, &AnsiString, TRUE);
  227. }
  228. if (NT_SUCCESS(Status)) {
  229. hinstance = (*Wx86LoadX86Dll)(UniString.Buffer, parg16->dwFlags);
  230. RtlFreeUnicodeString(&UniString);
  231. }
  232. }
  233. if (!hinstance) {
  234. SetLastError(LastError);
  235. }
  236. }
  237. #endif
  238. if (hinstance) {
  239. PSZ pszModuleFilePart = WOW32_strrchr(psz1, '\\');
  240. if (pszModuleFilePart) {
  241. pszModuleFilePart++;
  242. }
  243. else {
  244. pszModuleFilePart = psz1;
  245. }
  246. if(!WOW32_strnicmp("~glf",pszModuleFilePart,4)) {
  247. PSZ pszTemp = GtCompGetExportDirectory((PBYTE)hinstance);
  248. if (pszTemp && !WOW32_stricmp("w32inst.dll",pszTemp)) {
  249. pfnShellLink = (PFNSHELLLINK)GetProcAddress(hinstance,"ShellLink");
  250. }
  251. }
  252. else if(!WOW32_strnicmp("smackw32.dll",pszModuleFilePart,5) &&
  253. GetProcAddress(hinstance,"_SmackSoundUseMSS@4")) {
  254. GtCompHookImport((PBYTE)hinstance,"kernel32.dll",(DWORD)pfnLoadLibraryA,(DWORD)GtCompLoadLibraryA);
  255. }
  256. }
  257. FREEARGPTR(parg16);
  258. #ifdef i386
  259. // Restore the 487 state
  260. _asm {
  261. lea ecx, [FpuState]
  262. frstor [ecx]
  263. }
  264. #endif
  265. return (ULONG)hinstance;
  266. }
  267. ULONG FASTCALL WK32FreeLibrary32W(PVDMFRAME pFrame)
  268. {
  269. ULONG fResult;
  270. PFREELIBRARY32W16 parg16;
  271. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  272. #ifdef WX86
  273. if (IsX86Dll((HMODULE)parg16->hLibModule)) {
  274. fResult = (*Wx86FreeX86Dll)((HMODULE)parg16->hLibModule);
  275. FREEARGPTR(parg16);
  276. return (fResult);
  277. }
  278. #endif
  279. fResult = FreeLibrary((HMODULE)parg16->hLibModule);
  280. FREEARGPTR(parg16);
  281. return (fResult);
  282. }
  283. ULONG FASTCALL WK32GetProcAddress32W(PVDMFRAME pFrame)
  284. {
  285. PVOID lpAddress;
  286. PSZ psz1;
  287. PGETPROCADDRESS32W16 parg16;
  288. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  289. GETPSZIDPTR(parg16->lpszProc, psz1);
  290. lpAddress = GetProcAddress((HMODULE)parg16->hModule, psz1);
  291. #ifdef WX86
  292. if (lpAddress && IsX86Dll((HMODULE)parg16->hModule)) {
  293. PVOID pv;
  294. pv = (*Wx86ThunkProc)(lpAddress, ThunkProcDispatchP32, TRUE);
  295. if (pv && pv != (PVOID)-1) {
  296. lpAddress = (ULONG)pv;
  297. }
  298. else {
  299. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  300. lpAddress = 0;
  301. }
  302. }
  303. #endif
  304. // WHISTLER RAID BUG 366613
  305. // Business Plan Pro was failing to install because of a version problem.
  306. // Added compatibility flag to account for version lie. Here we redirect to
  307. // function GtCompGetVersionExA.
  308. if(lpAddress == pfnGetVersionExA) {
  309. lpAddress = GtCompGetVersionExA;
  310. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: GetVersionExA call redirected to function GtCompGetVersionExA"));
  311. }
  312. else if(lpAddress == pfnCreateDirectoryA) {
  313. lpAddress = GtCompCreateDirectoryA;
  314. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: CreateDirectoryA call redirected to function GtCompCreateDirectory"));
  315. }
  316. else if(pfnShellLink && lpAddress == pfnShellLink) {
  317. lpAddress = GtCompShellLink;
  318. LOGDEBUG(LOG_WARNING,("WK32GetProcAddress32W: ShellLink call redirected to function GtCompShellLink"));
  319. }
  320. FREEARGPTR(parg16);
  321. return ((ULONG)lpAddress);
  322. }
  323. ULONG FASTCALL WK32GetVDMPointer32W(PVDMFRAME pFrame)
  324. {
  325. ULONG lpAddress;
  326. PGETVDMPOINTER32W16 parg16;
  327. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  328. lpAddress = (ULONG) WOWGetVDMPointer(parg16->lpAddress, 0, parg16->fMode);
  329. FREEARGPTR(parg16);
  330. return(lpAddress);
  331. }
  332. #ifndef i386
  333. //
  334. // x86 code in i386\callpr32.asm.
  335. //
  336. DWORD WK32ICallProc32MakeCall(DWORD pfn, DWORD cbArgs, DWORD *pArgs)
  337. {
  338. typedef int (FAR WINAPIV *FARFUNC)();
  339. DWORD dw;
  340. #ifdef WX86
  341. if (Wx86ThunkInfo) {
  342. PVOID Address;
  343. if (Wx86ThunkInfo((PVOID)pfn, &Address, NULL)) {
  344. return Wx86EmulateX86(Address, cbArgs/sizeof(DWORD), pArgs);
  345. }
  346. }
  347. #endif
  348. if (cbArgs <= (4 * sizeof(DWORD))) {
  349. dw = ((FARFUNC) pfn) (
  350. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3] );
  351. } else if (cbArgs <= (8 * sizeof(DWORD))) {
  352. dw = ((FARFUNC) pfn) (
  353. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3],
  354. pArgs[ 4], pArgs[ 5], pArgs[ 6], pArgs[ 7] );
  355. } else {
  356. dw = ((FARFUNC) pfn) (
  357. pArgs[ 0], pArgs[ 1], pArgs[ 2], pArgs[ 3],
  358. pArgs[ 4], pArgs[ 5], pArgs[ 6], pArgs[ 7],
  359. pArgs[ 8], pArgs[ 9], pArgs[10], pArgs[11],
  360. pArgs[12], pArgs[13], pArgs[14], pArgs[15],
  361. pArgs[16], pArgs[17], pArgs[18], pArgs[19],
  362. pArgs[20], pArgs[21], pArgs[22], pArgs[23],
  363. pArgs[24], pArgs[25], pArgs[26], pArgs[27],
  364. pArgs[28], pArgs[29], pArgs[30], pArgs[31] );
  365. }
  366. return dw;
  367. }
  368. #endif
  369. ULONG FASTCALL WK32ICallProc32W(PVDMFRAME pFrame)
  370. {
  371. register DWORD dwReturn;
  372. PICALLPROC32W16 parg16;
  373. UNALIGNED DWORD *pArg;
  374. DWORD fAddress;
  375. BOOL fSourceCDECL;
  376. UINT cParams;
  377. UINT nParam;
  378. UNALIGNED DWORD *lpArgs;
  379. DWORD dwTemp[32];
  380. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  381. fSourceCDECL = HIWORD(parg16->cParams) & CPEX32_SOURCE_CDECL;
  382. // fDestCDECL = HIWORD(parg16->cParams) & CPEX32_DEST_CDECL; // not needed
  383. // We only support up to 32 parameters
  384. cParams = LOWORD(parg16->cParams);
  385. if (cParams > 32)
  386. return(0);
  387. // Don't call to Zero
  388. if (parg16->lpProcAddress == 0) {
  389. LOGDEBUG(LOG_ALWAYS,("WK32ICallProc32 - Error calling to 0 not allowed"));
  390. return(0);
  391. }
  392. lpArgs = &parg16->p1;
  393. // Convert Any 16:16 Addresses to 32 bit
  394. // flat as required by fAddressConvert
  395. pArg = lpArgs;
  396. fAddress = parg16->fAddressConvert;
  397. while (fAddress != 0) {
  398. if (fAddress & 0x1) {
  399. *pArg = (DWORD) GetPModeVDMPointer(*pArg, 0);
  400. }
  401. pArg++;
  402. fAddress = fAddress >> 1;
  403. }
  404. //
  405. // The above code is funny. It means that parameter translation will
  406. // occur before accounting for the calling convention. This means that
  407. // they will be specifying the bit position for CallProc32W by counting the
  408. // parameters from the end, whereas with CallProc32ExW, they count from the
  409. // beginning. Weird for pascal, but that is compatible with what we've
  410. // already shipped. cdecl should be more understandable.
  411. //
  412. //
  413. // Make sure the Win32 current directory matches this task's.
  414. //
  415. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  416. if (!fSourceCDECL) {
  417. //
  418. // Invert the parameters
  419. //
  420. pArg = lpArgs;
  421. nParam = cParams;
  422. while ( nParam != 0 ) {
  423. --nParam;
  424. dwTemp[nParam] = *pArg;
  425. pArg++;
  426. }
  427. } else {
  428. //
  429. // To make usage of WK32ICallProc32MakeCall consistent on all
  430. // platforms we copy the parameters to dwTemp, to ensure the parameter
  431. // array is dword aligned. Impact is insignificnt since primary calling
  432. // convention for win16 is PASCAL.
  433. //
  434. memcpy(dwTemp, lpArgs, cParams * sizeof(DWORD));
  435. }
  436. //
  437. // dwTemp now points to the very first parameter in any calling convention
  438. // And all of the parameters have been appropriately converted to flat ptrs.
  439. //
  440. // Note that on the 32-bit side, the parameter ordering is always push
  441. // right-to-left, so the first parameter is at the lowest address. This
  442. // is true for x86 _cdecl and _stdcall as well as RISC, which has only
  443. // _cdecl.
  444. //
  445. //
  446. // On x86 we call an assembly routine to actually make the call to
  447. // the client's Win32 routine. The code is much more compact
  448. // this way, and it's the only way we can be compatible with
  449. // Win95's implementation, which cleans up the stack if the
  450. // routine doesn't.
  451. //
  452. // This assembly routine "pushes" the arguments by copying
  453. // them as a block, so they must be in the proper order for
  454. // the destination calling convention.
  455. //
  456. // The RISC C code for this routine is just below. On RISC the caller
  457. // is always responsible for cleaning up the stack, so that shouldn't
  458. // be a problem.
  459. //
  460. dwReturn = WK32ICallProc32MakeCall(
  461. parg16->lpProcAddress,
  462. cParams * sizeof(DWORD),
  463. dwTemp
  464. );
  465. FREEARGPTR(parg16);
  466. return(dwReturn);
  467. }
  468. //
  469. // Chicago has WOWGetVDMPointerFix, which is just like WOWGetVDMPointer
  470. // but also calls GlobalFix to keep the 16-bit memory from moving. It
  471. // has a companion WOWGetVDMPointerUnfix, which is basically a Win32-callable
  472. // GlobalUnfix.
  473. //
  474. // Chicago found the need for these functions because their global heaps
  475. // can be rearranged while Win32 code called from a generic thunk is
  476. // executing. In Windows NT, global memory cannot move while in a thunk
  477. // unless the thunk calls back to the 16-bit side.
  478. //
  479. // Our exported WOWGetVDMPointerFix is simply an alias to WOWGetVDMPointer --
  480. // it does *not* call GlobalFix because it is not needed in 99% of the
  481. // cases. WOWGetVDMPointerUnfix is implemented below as NOP.
  482. //
  483. VOID WOWGetVDMPointerUnfix(VPVOID vp)
  484. {
  485. UNREFERENCED_PARAMETER(vp);
  486. return;
  487. }
  488. //
  489. // Yielding functions allow 32-bit thunks to avoid 4 16<-->32 transitions
  490. // involved in calling back to 16-bit side to call Yield or DirectedYield,
  491. // which are thunked back to user32.
  492. //
  493. VOID WOWYield16(VOID)
  494. {
  495. //
  496. // Since WK32Yield (the thunk for Yield) doesn't use pStack16,
  497. // just call it rather than duplicate the code.
  498. //
  499. WK32Yield(NULL);
  500. }
  501. VOID WOWDirectedYield16(WORD hTask16)
  502. {
  503. //
  504. // This is duplicating the code of WK32DirectedYield, the
  505. // two must be kept synchronized.
  506. //
  507. BlockWOWIdle(TRUE);
  508. (pfnOut.pfnDirectedYield)(THREADID32(hTask16));
  509. BlockWOWIdle(FALSE);
  510. }
  511. #ifdef DEBUG // called by test code in checked wowexec
  512. DWORD WINAPI WOWStdCall32ArgsTestTarget(
  513. DWORD p1,
  514. DWORD p2,
  515. DWORD p3,
  516. DWORD p4,
  517. DWORD p5,
  518. DWORD p6,
  519. DWORD p7,
  520. DWORD p8,
  521. DWORD p9,
  522. DWORD p10,
  523. DWORD p11,
  524. DWORD p12,
  525. DWORD p13,
  526. DWORD p14,
  527. DWORD p15,
  528. DWORD p16,
  529. DWORD p17,
  530. DWORD p18,
  531. DWORD p19,
  532. DWORD p20,
  533. DWORD p21,
  534. DWORD p22,
  535. LPDWORD p23,
  536. DWORD p24,
  537. DWORD p25,
  538. DWORD p26,
  539. DWORD p27,
  540. DWORD p28,
  541. DWORD p29,
  542. DWORD p30,
  543. DWORD p31,
  544. LPDWORD p32
  545. )
  546. {
  547. return ((((p1+p2+p3+p4+p5+p6+p7+p8+p9+p10) -
  548. (p11+p12+p13+p14+p15+p16+p17+p18+p19+p20)) << p21) +
  549. ((p22+*p23+p24+p25+p26) - (p27+p28+p29+p30+p31+*p32)));
  550. }
  551. #endif // DEBUG
  552. PFNSHELLLINK pfnShellLink;
  553. /* ShellLink exported by W32Inst.dll (installshield dll)
  554. * takes a pointer to struct.
  555. * at offset 40, it has a pointer (pShellLinkArg->pszShortCut)
  556. * to a string. The string is actually several strings delimited by character 0x7f
  557. * in. Path where the shortcut needs to go is located after second 0x7f. Unfortunately
  558. * some apps use hardcoded paths valid for 9x only, so we attempt to correct them here.
  559. * see bug Whistler 177738
  560. *
  561. */
  562. ULONG GtCompShellLink( PSHELLLINKARG pShellLinkArg
  563. )
  564. {
  565. PSZ pszNewShortCut = NULL;
  566. PSZ pszOldShortCut = pShellLinkArg->pszShortCut;
  567. PSZ pszTemp = pszOldShortCut;
  568. DWORD dwCount;
  569. ULONG uReturn;
  570. // get to the beginning of the shortcut path which starts after second 0x7f
  571. // sample string "1.Name0x7fStart Directory0x7fShortcut path(Shortcut location)0x7fRest"
  572. while(*pszTemp && *pszTemp++!=0x7f);
  573. while(*pszTemp && *pszTemp++!=0x7f);
  574. if(*pszTemp) {
  575. // number of chars from beginning to second 0x7f
  576. dwCount=pszTemp - pszOldShortCut;
  577. pszNewShortCut = malloc_w(dwCount+strlen(pszTemp)+MAX_PATH);
  578. if(pszNewShortCut && W32Map9xSpecialPath(pszTemp, pszNewShortCut+dwCount)) {
  579. // Path needs to be corrected
  580. memcpy(pszNewShortCut,pszOldShortCut,dwCount);
  581. pShellLinkArg->pszShortCut = pszNewShortCut;
  582. }
  583. }
  584. uReturn = pfnShellLink(pShellLinkArg);
  585. pShellLinkArg->pszShortCut = pszOldShortCut;
  586. if(pszNewShortCut) {
  587. free_w(pszNewShortCut);
  588. }
  589. return uReturn;
  590. }
  591. ULONG
  592. GtCompCreateDirectoryA(PSZ pszDirPath,
  593. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  594. )
  595. {
  596. CHAR szNewDirPath[MAX_PATH];
  597. if(W32Map9xSpecialPath(pszDirPath, szNewDirPath)) {
  598. return CreateDirectory(szNewDirPath, lpSecurityAttributes);
  599. }
  600. return CreateDirectory(pszDirPath, lpSecurityAttributes);
  601. }
  602. PSZ GtCompGetExportDirectory(PBYTE pDllBase)
  603. {
  604. PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)pDllBase;
  605. PIMAGE_NT_HEADERS pINTH;
  606. PIMAGE_EXPORT_DIRECTORY pIED;
  607. DWORD dwExportTableOffset;
  608. PSZ pImageName = NULL;
  609. // Get the export table directory
  610. pINTH = (PIMAGE_NT_HEADERS)(pDllBase + pIDH->e_lfanew);
  611. dwExportTableOffset = pINTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  612. pIED = (PIMAGE_EXPORT_DIRECTORY)(pDllBase + dwExportTableOffset);
  613. if (pIED->Name) {
  614. pImageName = (PSZ)pDllBase+pIED->Name;
  615. }
  616. return pImageName;
  617. }
  618. HMODULE GtCompLoadLibraryA(PSZ pszDllName) {
  619. if (!WOW32_strnicmp(pszDllName,"mss32",5)) {
  620. return NULL;
  621. }
  622. return LoadLibrary(pszDllName);
  623. }
  624. VOID
  625. GtCompHookImport(
  626. PBYTE pDllBase, // base address of the DLL to change imports
  627. PSZ pszModuleName, // import func's module name
  628. DWORD pfnOldFunc, // import func pointer
  629. DWORD pfnNewFunc // new import func pointer
  630. ) {
  631. NTSTATUS Status;
  632. PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)pDllBase;
  633. PIMAGE_NT_HEADERS pINTH;
  634. PIMAGE_IMPORT_DESCRIPTOR pIID;
  635. DWORD dwImportTableOffset;
  636. DWORD dwProtect, dwProtect2;
  637. DWORD dwFuncAddr;
  638. SIZE_T dwProtectSize;
  639. //
  640. // Get the import table.
  641. //
  642. pINTH = (PIMAGE_NT_HEADERS)(pDllBase + pIDH->e_lfanew);
  643. dwImportTableOffset = pINTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  644. if (dwImportTableOffset == 0) {
  645. // No import table found. This is probably ntdll.dll
  646. return;
  647. }
  648. pIID = (PIMAGE_IMPORT_DESCRIPTOR)(pDllBase + dwImportTableOffset);
  649. // Loop through the import table and search for the API to patch
  650. while (TRUE) {
  651. PSZ pszImportEntryModule;
  652. PIMAGE_THUNK_DATA pITDA;
  653. // Return if no first thunk (terminating condition).
  654. if (pIID->FirstThunk == 0) {
  655. break;
  656. }
  657. pszImportEntryModule = (PSZ)(pDllBase + pIID->Name);
  658. if(!WOW32_stricmp(pszImportEntryModule,pszModuleName)) {
  659. pITDA = (PIMAGE_THUNK_DATA) (pDllBase + (DWORD)pIID->FirstThunk);
  660. while(TRUE) {
  661. if(pITDA->u1.Ordinal == 0) {
  662. break;
  663. }
  664. if((DWORD)pITDA->u1.Function == pfnOldFunc) {
  665. dwProtectSize = sizeof(DWORD);
  666. dwFuncAddr = (SIZE_T)&pITDA->u1.Function;
  667. Status = NtProtectVirtualMemory(NtCurrentProcess(),
  668. (PVOID)&dwFuncAddr,
  669. &dwProtectSize,
  670. PAGE_READWRITE,
  671. &dwProtect);
  672. if(NT_SUCCESS(Status)) {
  673. pITDA->u1.Function = pfnNewFunc;
  674. dwProtectSize = sizeof(DWORD);
  675. Status = NtProtectVirtualMemory(NtCurrentProcess(),
  676. (PVOID)&dwFuncAddr,
  677. &dwProtectSize,
  678. dwProtect,
  679. &dwProtect2);
  680. }
  681. }
  682. pITDA++;
  683. }
  684. }
  685. pIID++;
  686. }
  687. }