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.

467 lines
12 KiB

  1. /*****************************************************************************
  2. *
  3. * DiThunk.c
  4. *
  5. * Copyright (c) 1996-1997 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Template thunks for Windows 95 device manager.
  10. *
  11. * Contents:
  12. *
  13. * Thunk_Init
  14. * Thunk_Term
  15. *
  16. *****************************************************************************/
  17. #include "dinputpr.h"
  18. #include "dithunk.h"
  19. /*****************************************************************************
  20. *
  21. * The sqiffle for this file.
  22. *
  23. *****************************************************************************/
  24. #define sqfl sqflThunk
  25. KERNELPROCADDR g_kpa;
  26. #pragma BEGIN_CONST_DATA
  27. /*
  28. * Careful! This must match KERNELPROCADDR ...
  29. */
  30. static LPCSTR c_rgpszKernel32[] = {
  31. (LPVOID) 35, /* LoadLibrary16 */
  32. (LPVOID) 36, /* FreeLibrary16 */
  33. (LPVOID) 37, /* GetProcAddress16 */
  34. "MapLS",
  35. "UnMapLS",
  36. "MapSL",
  37. "MapSLFix",
  38. "UnMapSLFixArray",
  39. "QT_Thunk",
  40. };
  41. /***************************************************************************
  42. *
  43. * @doc INTERNAL
  44. *
  45. * @func DWORD | TemplateThunk |
  46. *
  47. * Call down, passing all sorts of random parameters.
  48. *
  49. * Parameter signature is as follows:
  50. *
  51. * p = 0:32 pointer to convert to 16:16 pointer
  52. *
  53. * l = a 32-bit integer
  54. *
  55. * s = a 16-bit integer
  56. *
  57. *
  58. * P = returns a pointer
  59. *
  60. * L = returns a 32-bit integer
  61. *
  62. * S = returns a 16-bit signed integer
  63. *
  64. * U = returns a 16-bit unsigned integer
  65. *
  66. ***************************************************************************/
  67. #pragma warning(disable:4035) /* no return value (duh) */
  68. #ifdef WIN95
  69. #ifdef SLOW_BUT_READABLE
  70. __declspec(naked) int
  71. TemplateThunk(FARPROC fp, PCSTR pszSig, ...)
  72. {
  73. BYTE rgbThunk[60]; /* For private use of QT_Thunk */
  74. LPVOID *ppvArg;
  75. int i;
  76. LPVOID pv;
  77. int iRc;
  78. __asm {
  79. /* Function prologue */
  80. push ebp;
  81. mov ebp, esp;
  82. sub esp, __LOCAL_SIZE;
  83. push ebx;
  84. push edi;
  85. push esi;
  86. }
  87. /* Thunk all the parameters according to the signature */
  88. ppvArg = (LPVOID)(&pszSig+1);
  89. for (i = 0; ; i++) {
  90. pv = ppvArg[i];
  91. switch (pszSig[i]) {
  92. case 'p':
  93. pv = ppvArg[i] = MapLS(pv);
  94. __asm push pv;
  95. break;
  96. case 'l':
  97. __asm push pv;
  98. break;
  99. case 's':
  100. __asm mov eax, pv;
  101. __asm push ax;
  102. break;
  103. default: goto doneThunk;
  104. }
  105. }
  106. doneThunk:;
  107. /* Call the 16:16 procedure */
  108. __asm {
  109. mov edx, fp;
  110. mov ebx, ebp;
  111. lea ebp, rgbThunk+64; /* Required by QT_Thunk */
  112. }
  113. g_kpa.QT_Thunk();
  114. __asm {
  115. mov ebp, ebx;
  116. shl eax, 16; /* Convert DX:AX to EAX */
  117. shrd eax, edx, 16;
  118. mov iRc, eax;
  119. }
  120. /* Now unthunk the parameters */
  121. ppvArg = (LPVOID)(&pszSig+1);
  122. for (i = 0; ; i++) {
  123. switch (pszSig[i]) {
  124. case 'p':
  125. UnMapLS(ppvArg[i]);
  126. break;
  127. case 'l':
  128. case 's':
  129. break;
  130. default: goto doneUnthunk;
  131. }
  132. }
  133. doneUnthunk:;
  134. /* Thunk the return value */
  135. switch (pszSig[i]) {
  136. case 'L':
  137. break;
  138. case 'U':
  139. iRc = LOWORD(iRc);
  140. break;
  141. case 'S':
  142. iRc = (short)iRc;
  143. break;
  144. case 'P':
  145. iRc = (int)MapSL((LPVOID)iRc);
  146. break;
  147. }
  148. __asm {
  149. mov eax, iRc;
  150. pop esi;
  151. pop edi;
  152. pop ebx;
  153. mov esp, ebp;
  154. pop ebp;
  155. ret;
  156. }
  157. }
  158. #else /* Fast but illegible */
  159. __declspec(naked) int
  160. TemplateThunk(FARPROC fp, PCSTR pszSig, ...)
  161. {
  162. __asm {
  163. /* Function prologue */
  164. push ebp;
  165. mov ebp, esp;
  166. sub esp, 60; /* QT_Thunk needs 60 bytes */
  167. push ebx;
  168. push edi;
  169. push esi;
  170. /* Thunk all the parameters according to the signature */
  171. lea esi, pszSig+4; /* esi -> next arg */
  172. mov ebx, pszSig; /* ebx -> signature string */
  173. thunkLoop:;
  174. mov al, [ebx];
  175. inc ebx; /* al = pszSig++ */
  176. cmp al, 'p'; /* Q: Pointer? */
  177. jz thunkPtr; /* Y: Do the pointer */
  178. cmp al, 'l'; /* Q: Long? */
  179. jz thunkLong; /* Y: Do the long */
  180. cmp al, 's'; /* Q: Short? */
  181. jnz thunkDone; /* N: Done */
  182. /* Y: Do the short */
  183. lodsd; /* eax = *ppvArg++ */
  184. push ax; /* Push the short */
  185. jmp thunkLoop;
  186. thunkPtr:
  187. lodsd; /* eax = *ppvArg++ */
  188. push eax;
  189. call dword ptr g_kpa.MapLS; /* Map it */
  190. mov [esi][-4], eax; /* Save it for unmapping */
  191. push eax;
  192. jmp thunkLoop;
  193. thunkLong:
  194. lodsd; /* eax = *ppvArg++ */
  195. push eax;
  196. jmp thunkLoop;
  197. thunkDone:
  198. /* Call the 16:16 procedure */
  199. mov edx, fp;
  200. call dword ptr g_kpa.QT_Thunk;
  201. shl eax, 16; /* Convert DX:AX to EDX */
  202. shld edx, eax, 16;
  203. /* Translate the return code according to the signature */
  204. mov al, [ebx][-1]; /* Get return code type */
  205. cmp al, 'P'; /* Pointer? */
  206. jz retvalPtr; /* Y: Do the pointer */
  207. cmp al, 'S'; /* Signed? */
  208. jz retvalSigned; /* Y: Do the signed short */
  209. cmp al, 'U'; /* Unsigned? */
  210. mov edi, edx; /* Assume long or void */
  211. jnz retvalOk; /* N: Then long or void */
  212. movzx edi, dx; /* Sign-extend short */
  213. jmp retvalOk;
  214. retvalPtr:
  215. push edx; /* Pointer */
  216. call dword ptr g_kpa.MapSL; /* Map it up */
  217. jmp retvalOk;
  218. retvalSigned: /* Signed */
  219. movsx edi, dx; /* Sign-extend short */
  220. jmp retvalOk;
  221. retvalOk: /* Return value in EDI */
  222. /* Now unthunk the parameters */
  223. lea esi, pszSig+4; /* esi -> next arg */
  224. mov ebx, pszSig; /* ebx -> signature string */
  225. unthunkLoop:;
  226. mov al, [ebx];
  227. inc ebx; /* al = pszSig++ */
  228. cmp al, 'p'; /* Pointer? */
  229. jz unthunkPtr; /* Y: Do the pointer */
  230. cmp al, 'l'; /* Long? */
  231. jz unthunkSkip; /* Y: Skip it */
  232. cmp al, 's'; /* Short? */
  233. jnz unthunkDone; /* N: Done */
  234. unthunkSkip:
  235. lodsd; /* eax = *ppvArg++ */
  236. jmp unthunkLoop;
  237. unthunkPtr:
  238. lodsd; /* eax = *ppvArg++ */
  239. push eax;
  240. call dword ptr g_kpa.UnMapLS;/* Unmap it */
  241. jmp unthunkLoop;
  242. unthunkDone:
  243. /* Done */
  244. mov eax, edi;
  245. pop esi;
  246. pop edi;
  247. pop ebx;
  248. mov esp, ebp;
  249. pop ebp;
  250. ret;
  251. }
  252. }
  253. #endif
  254. #else // Not X86
  255. int __cdecl TemplateThunk(FARPROC fp, PCSTR pszSig, ...)
  256. {
  257. return 0;
  258. }
  259. #endif
  260. #pragma BEGIN_CONST_DATA
  261. /***************************************************************************
  262. *
  263. * @doc INTERNAL
  264. *
  265. * @func FARPROC | GetProcOrd |
  266. *
  267. * GetProcAddress on a DLL by ordinal.
  268. *
  269. * Win95 does not let you GetProcAddress on KERNEL32 by ordinal,
  270. * so we need to do it the evil way.
  271. *
  272. * @parm HINSTANCE | hinstDll |
  273. *
  274. * The instance handle of the DLL we want to get the ordinal
  275. * from. The only DLL you need to use this function for is
  276. * KERNEL32.
  277. *
  278. * @parm UINT | ord |
  279. *
  280. * The ordinal you want to retrieve.
  281. *
  282. ***************************************************************************/
  283. #define poteExp(pinth) (&(pinth)->OptionalHeader. \
  284. DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT])
  285. FARPROC NTAPI
  286. GetProcOrd(HINSTANCE hinstDll, UINT ord)
  287. {
  288. FARPROC fp;
  289. /*
  290. * Make sure the MZ header is good.
  291. */
  292. PIMAGE_DOS_HEADER pidh = (LPVOID)hinstDll;
  293. if (!IsBadReadPtr(pidh, sizeof(*pidh)) &&
  294. pidh->e_magic == IMAGE_DOS_SIGNATURE) {
  295. /*
  296. * Make sure the PE header is good.
  297. */
  298. PIMAGE_NT_HEADERS pinth = pvAddPvCb(pidh, pidh->e_lfanew);
  299. if (!IsBadReadPtr(pinth, sizeof(*pinth)) &&
  300. pinth->Signature == IMAGE_NT_SIGNATURE) {
  301. /*
  302. * Make sure the export table is good and the ordinal
  303. * is within range.
  304. */
  305. PIMAGE_EXPORT_DIRECTORY pedt =
  306. pvAddPvCb(pidh, poteExp(pinth)->VirtualAddress);
  307. if (!IsBadReadPtr(pedt, sizeof(*pedt)) &&
  308. (ord - pedt->Base) < pedt->NumberOfFunctions) {
  309. PDWORD peat = pvAddPvCb(pidh, (DWORD)pedt->AddressOfFunctions);
  310. fp = (FARPROC)pvAddPvCb(pidh, peat[ord - pedt->Base]);
  311. if ((DWORD)cbSubPvPv(fp, peat) >= poteExp(pinth)->Size) {
  312. /* fp is valid */
  313. } else { /* Note: We don't support forwarding */
  314. fp = 0;
  315. }
  316. } else {
  317. fp = 0;
  318. }
  319. } else {
  320. fp = 0;
  321. }
  322. } else {
  323. fp = 0;
  324. }
  325. return fp;
  326. }
  327. /***************************************************************************
  328. *
  329. * @doc INTERNAL
  330. *
  331. * @func BOOL | GetKernelProcAddresses |
  332. *
  333. * Get all the necessary proc addresses from Kernel.
  334. *
  335. ***************************************************************************/
  336. BOOL EXTERNAL
  337. Thunk_GetKernelProcAddresses(void)
  338. {
  339. DllEnterCrit();
  340. if (g_kpa.QT_Thunk == 0) {
  341. HINSTANCE hinstK32 = GetModuleHandle(TEXT("KERNEL32"));
  342. if (hinstK32) {
  343. int i;
  344. FARPROC *rgfpKpa = (LPVOID)&g_kpa;
  345. for (i = 0; i < cA(c_rgpszKernel32); i++) {
  346. if (HIWORD((UINT_PTR)c_rgpszKernel32[i])) {
  347. rgfpKpa[i] = GetProcAddress(hinstK32, c_rgpszKernel32[i]);
  348. } else {
  349. rgfpKpa[i] = GetProcOrd(hinstK32, (UINT)(UINT_PTR)c_rgpszKernel32[i]);
  350. }
  351. if (!rgfpKpa[i]) break; /* Aigh! */
  352. }
  353. }
  354. }
  355. DllLeaveCrit();
  356. return (BOOL)(UINT_PTR)g_kpa.QT_Thunk;
  357. }
  358. /***************************************************************************
  359. *
  360. * @doc INTERNAL
  361. *
  362. * @func HINSTANCE | ThunkGetProcAddresses |
  363. *
  364. * Get all the necessary proc addresses.
  365. *
  366. ***************************************************************************/
  367. HINSTANCE EXTERNAL
  368. Thunk_GetProcAddresses(FARPROC *rgfp, LPCSTR *rgpsz,
  369. UINT cfp, LPCSTR pszLibrary)
  370. {
  371. HINSTANCE hinst;
  372. hinst = g_kpa.LoadLibrary16(pszLibrary);
  373. if (hinst >= (HINSTANCE)32) {
  374. UINT ifp;
  375. for (ifp = 0; ifp < cfp; ifp++) {
  376. rgfp[ifp] = g_kpa.GetProcAddress16(hinst, rgpsz[ifp]);
  377. if (!rgfp[ifp]) {
  378. g_kpa.FreeLibrary16(hinst);
  379. hinst = 0;
  380. break;
  381. }
  382. }
  383. } else {
  384. hinst = 0;
  385. }
  386. return hinst;
  387. }