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.

510 lines
12 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. thunk.c
  5. Abstract:
  6. Thunk procedures for calling 16-bit functions
  7. Revision History:
  8. Brijesh Krishnaswami (brijeshk) 05/24/99
  9. - created (imported from msinfo codebase)
  10. ********************************************************************/
  11. #include <windows.h>
  12. #include "drvdefs.h"
  13. /***************************************************************************
  14. *
  15. * @doc INTERNAL
  16. *
  17. * @func DWORD | TemplateThunk |
  18. *
  19. * Call down, passing all sorts of random parameters.
  20. *
  21. * Parameter signature is as follows:
  22. *
  23. * p = 0:32 pointer to convert to 16:16 pointer
  24. * l = a 32-bit integer
  25. * s = a 16-bit integer
  26. *
  27. * P = returns a pointer
  28. * L = returns a 32-bit integer
  29. * S = returns a 16-bit signed integer
  30. * U = returns a 16-bit unsigned integer
  31. *
  32. ***************************************************************************/
  33. #pragma warning(disable:4035) // no return value
  34. __declspec(naked) int
  35. TemplateThunk(FARPROC fp, PCSTR pszSig, ...)
  36. {
  37. BYTE rgbThunk[60]; // For private use of QT_Thunk
  38. LPVOID *ppvArg;
  39. int i;
  40. LPVOID pv;
  41. int iRc;
  42. __asm {
  43. // Function prologue
  44. push ebp;
  45. mov ebp, esp;
  46. sub esp, __LOCAL_SIZE;
  47. push ebx;
  48. push edi;
  49. push esi;
  50. }
  51. // Thunk all the parameters according to the signature
  52. ppvArg = (LPVOID)(&pszSig+1);
  53. for (i = 0; ; i++) {
  54. pv = ppvArg[i];
  55. switch (pszSig[i]) {
  56. case 'p':
  57. pv = ppvArg[i] = MapLS(pv);
  58. __asm push pv;
  59. break;
  60. case 'l':
  61. __asm push pv;
  62. break;
  63. case 's':
  64. __asm mov eax, pv;
  65. __asm push ax;
  66. break;
  67. default: goto doneThunk;
  68. }
  69. }
  70. doneThunk:;
  71. // Call the 16:16 procedure
  72. __asm {
  73. mov edx, fp;
  74. mov ebx, ebp;
  75. lea ebp, rgbThunk+64; // Required by QT_Thunk
  76. }
  77. QT_Thunk();
  78. __asm {
  79. mov ebp, ebx;
  80. shl eax, 16; // Convert DX:AX to EAX
  81. shrd eax, edx, 16;
  82. mov iRc, eax;
  83. }
  84. // Now unthunk the parameters
  85. ppvArg = (LPVOID)(&pszSig+1);
  86. for (i = 0; ; i++) {
  87. switch (pszSig[i]) {
  88. case 'p':
  89. UnMapLS(ppvArg[i]);
  90. break;
  91. case 'l':
  92. case 's':
  93. break;
  94. default: goto doneUnthunk;
  95. }
  96. }
  97. doneUnthunk:;
  98. // Thunk the return value
  99. switch (pszSig[i]) {
  100. case 'L':
  101. break;
  102. case 'U':
  103. iRc = LOWORD(iRc);
  104. break;
  105. case 'S':
  106. iRc = (short)iRc;
  107. break;
  108. case 'P':
  109. iRc = (int)MapSL((LPVOID)iRc);
  110. break;
  111. }
  112. __asm {
  113. mov eax, iRc;
  114. pop esi;
  115. pop edi;
  116. pop ebx;
  117. mov esp, ebp;
  118. pop ebp;
  119. ret;
  120. }
  121. }
  122. #pragma warning(default:4035)
  123. /***************************************************************************
  124. *
  125. * Functions we call down in Win16.
  126. *
  127. ***************************************************************************/
  128. FARPROC g_rgfpKernel[] = {
  129. (FARPROC)132, /* GetWinFlags */
  130. (FARPROC)355, /* GetWinDebugInfo */
  131. (FARPROC)169, /* GetFreeSpace */
  132. (FARPROC) 47, /* GetModuleHandle */
  133. (FARPROC) 93, /* GetCodeHandle */
  134. (FARPROC)104, /* GetCodeInfo */
  135. (FARPROC) 49, /* GetModuleFileName */
  136. (FARPROC)175, /* AllocSelector */
  137. (FARPROC)186, /* GetSelectorBase */
  138. (FARPROC)187, /* SetSelectorBase */
  139. (FARPROC)188, /* GetSelectorLimit */
  140. (FARPROC)189, /* SetSelectorLimit */
  141. (FARPROC)176, /* FreeSelector */
  142. (FARPROC) 27, /* GetModuleName */
  143. (FARPROC)167, /* GetExpWinVer */
  144. (FARPROC)184, /* GlobalDosAlloc */
  145. (FARPROC)185, /* GlobalDosFree */
  146. (FARPROC) 16, /* GlobalReAlloc */
  147. };
  148. #define g_fpGetWinFlags g_rgfpKernel[0]
  149. #define g_fpGetWinDebugInfo g_rgfpKernel[1]
  150. #define g_fpGetFreeSpace g_rgfpKernel[2]
  151. #define g_fpGetModuleHandle g_rgfpKernel[3]
  152. #define g_fpGetCodeHandle g_rgfpKernel[4]
  153. #define g_fpGetCodeInfo g_rgfpKernel[5]
  154. #define g_fpGetModuleFileName g_rgfpKernel[6]
  155. #define g_fpAllocSelector g_rgfpKernel[7]
  156. #define g_fpGetSelectorBase g_rgfpKernel[8]
  157. #define g_fpSetSelectorBase g_rgfpKernel[9]
  158. #define g_fpGetSelectorLimit g_rgfpKernel[10]
  159. #define g_fpSetSelectorLimit g_rgfpKernel[11]
  160. #define g_fpFreeSelector g_rgfpKernel[12]
  161. #define g_fpGetModuleName g_rgfpKernel[13]
  162. #define g_fpGetExpWinVer g_rgfpKernel[14]
  163. #define g_fpGlobalDosAlloc g_rgfpKernel[15]
  164. #define g_fpGlobalDosFree g_rgfpKernel[16]
  165. #define g_fpGlobalReAlloc g_rgfpKernel[17]
  166. FARPROC g_rgfpUser[] = {
  167. (FARPROC)216, /* UserSeeUserDo */
  168. (FARPROC)284, /* GetFreeSystemResources */
  169. (FARPROC)256, /* GetDriverInfo */
  170. (FARPROC)257, /* GetNextDriver */
  171. };
  172. #define g_fpUserSeeUserDo g_rgfpUser[0]
  173. #define g_fpGetFreeSystemResources g_rgfpUser[1]
  174. #define g_fpGetDriverInfo g_rgfpUser[2]
  175. #define g_fpGetNextDriver g_rgfpUser[3]
  176. /***************************************************************************
  177. *
  178. * @doc INTERNAL
  179. *
  180. * @func void | ThunkGetProcAddresses |
  181. *
  182. * Get all the necessary proc addresses.
  183. *
  184. ***************************************************************************/
  185. HINSTANCE
  186. ThunkGetProcAddresses(FARPROC *rgfp, UINT cfp, LPCTSTR ptszLibrary,
  187. BOOL fFree)
  188. {
  189. HINSTANCE hinst;
  190. hinst = LoadLibrary16(ptszLibrary);
  191. if (hinst >= (HINSTANCE)32) {
  192. UINT ifp;
  193. for (ifp = 0; ifp < cfp; ifp++) {
  194. rgfp[ifp] = GetProcAddress16(hinst, (PVOID)rgfp[ifp]);
  195. }
  196. if (fFree) {
  197. FreeLibrary16(hinst);
  198. }
  199. } else {
  200. hinst = 0;
  201. }
  202. return hinst;
  203. }
  204. /***************************************************************************
  205. *
  206. * @doc INTERNAL
  207. *
  208. * @func void | ThunkInit |
  209. *
  210. * GetProcAddress16 our brains out.
  211. *
  212. ***************************************************************************/
  213. LPVOID g_pvWin16Lock = NULL;
  214. HINSTANCE g_hinstUser;
  215. void
  216. ThunkInit(void)
  217. {
  218. if (g_pvWin16Lock == NULL)
  219. {
  220. ThunkGetProcAddresses(g_rgfpKernel, cA(g_rgfpKernel), TEXT("KERNEL"), 1);
  221. g_hinstUser = ThunkGetProcAddresses(g_rgfpUser, cA(g_rgfpUser), TEXT("USER"), 1);
  222. GetpWin16Lock(&g_pvWin16Lock);
  223. }
  224. }
  225. HMODULE16
  226. GetModuleHandle16(LPCSTR pszModule)
  227. {
  228. return (HMODULE16)TemplateThunk(g_fpGetModuleHandle, "pU", pszModule);
  229. }
  230. int
  231. GetModuleFileName16(HMODULE16 hmod, LPSTR sz, int cch)
  232. {
  233. return TemplateThunk(g_fpGetModuleFileName, "spsS", hmod, sz, cch);
  234. }
  235. int
  236. GetModuleName16(HMODULE16 hmod, LPSTR sz, int cch)
  237. {
  238. return TemplateThunk(g_fpGetModuleName, "spsS", hmod, sz, cch);
  239. }
  240. UINT
  241. AllocCodeSelector16(void)
  242. {
  243. return TemplateThunk(g_fpAllocSelector, "sU", HIWORD(g_fpAllocSelector));
  244. }
  245. DWORD
  246. GetSelectorBase16(UINT sel)
  247. {
  248. return TemplateThunk(g_fpGetSelectorBase, "sL", sel);
  249. }
  250. UINT
  251. SetSelectorBase16(UINT sel, DWORD dwBase)
  252. {
  253. return TemplateThunk(g_fpSetSelectorBase, "slU", sel, dwBase);
  254. }
  255. DWORD
  256. GetSelectorLimit16(UINT sel)
  257. {
  258. return TemplateThunk(g_fpGetSelectorLimit, "sL", sel);
  259. }
  260. UINT
  261. SetSelectorLimit16(UINT sel, DWORD dwLimit)
  262. {
  263. return TemplateThunk(g_fpSetSelectorLimit, "slU", sel, dwLimit);
  264. }
  265. UINT
  266. FreeSelector16(UINT sel)
  267. {
  268. return TemplateThunk(g_fpFreeSelector, "sU", sel);
  269. }
  270. WORD
  271. GetExpWinVer16(HMODULE16 hmod)
  272. {
  273. return (WORD)TemplateThunk(g_fpGetExpWinVer, "sS", hmod);
  274. }
  275. DWORD
  276. GlobalDosAlloc16(DWORD cb)
  277. {
  278. return (DWORD)TemplateThunk(g_fpGlobalDosAlloc, "lL", cb);
  279. }
  280. UINT
  281. GlobalDosFree16(UINT uiSel)
  282. {
  283. return (UINT)TemplateThunk(g_fpGlobalDosFree, "sS", uiSel);
  284. }
  285. /*
  286. * Kernel has thunks for GlobalAlloc, GlobalFree, but not GlobalRealloc.
  287. */
  288. WORD
  289. GlobalReAlloc16(WORD hglob, DWORD cb, UINT fl)
  290. {
  291. return (WORD)TemplateThunk(g_fpGlobalReAlloc, "slsS", hglob, cb, fl);
  292. }
  293. #define SD_ATOMNAME 0x000E
  294. UINT
  295. GetUserAtomName(UINT atom, LPSTR psz)
  296. {
  297. return (UINT)TemplateThunk(g_fpUserSeeUserDo, "sspS",
  298. SD_ATOMNAME, atom, psz);
  299. }
  300. #define SD_GETRGPHKSYSHOOKS 0x0010
  301. DWORD
  302. GetUserHookTable(void)
  303. {
  304. return (UINT)TemplateThunk(g_fpUserSeeUserDo, "sslL",
  305. SD_GETRGPHKSYSHOOKS, 0, 0);
  306. }
  307. BOOL
  308. GetDriverInfo16(WORD hDriver, DRIVERINFOSTRUCT16* pdis)
  309. {
  310. return (BOOL)TemplateThunk(g_fpGetDriverInfo, "spS", hDriver, pdis);
  311. }
  312. WORD
  313. GetNextDriver16(WORD hDriver, DWORD fdwFlag)
  314. {
  315. return (WORD)TemplateThunk(g_fpGetNextDriver, "slS", hDriver, fdwFlag);
  316. }
  317. /***************************************************************************
  318. *
  319. * @doc INTERNAL
  320. *
  321. * @func BOOL | Int86x |
  322. *
  323. * Issue a real-mode software interrupt.
  324. *
  325. * We do this by allocating a temporary code selector and
  326. * thunking to it.
  327. *
  328. *
  329. ***************************************************************************/
  330. BYTE rgbInt31[] = {
  331. 0x55, /* push bp */
  332. 0x8B, 0xEC, /* mov bp, sp */
  333. 0x57, /* push di */
  334. 0xC4, 0x7E, 0x06, /* les di, [bp+6] */
  335. 0x8B, 0x5E, 0x0A, /* mov bx, [bp+10] */
  336. 0x33, 0xC9, /* xor cx, cx */
  337. 0xB8, 0x00, 0x03, /* mov ax, 0300h */
  338. 0xCD, 0x31, /* int 31h */
  339. 0x72, 0x02, /* jc $+4 */
  340. 0x33, 0xC0, /* xor ax, ax */
  341. 0x5F, /* pop di */
  342. 0x5D, /* pop bp */
  343. 0xCA, 0x06, 0x00, /* retf 6 */
  344. };
  345. UINT
  346. Int86x(UINT intno, PRMIREGS preg)
  347. {
  348. UINT selCode = AllocCodeSelector16();
  349. UINT uiRc;
  350. if (selCode) {
  351. SetSelectorBase16(selCode, (DWORD)rgbInt31);
  352. SetSelectorLimit16(selCode, sizeof(rgbInt31));
  353. preg->ss = preg->sp = 0;
  354. uiRc = (UINT)TemplateThunk((FARPROC)MAKELONG(0, selCode),
  355. "spU", intno, preg);
  356. FreeSelector16(selCode);
  357. } else {
  358. uiRc = 0x8011; /* Descriptor unavailable */
  359. }
  360. return uiRc;
  361. }
  362. /***************************************************************************
  363. *
  364. * @doc INTERNAL : ported from msinfo 4.10 code
  365. *
  366. * @func Token_Find |
  367. *
  368. * Returns the first token in the string.
  369. *
  370. * Tokens are space or comma separated strings. Quotation marks
  371. * have no effect. We also treat semicolons as separators.
  372. * (This lets us use this routine for walking the PATH too.)
  373. *
  374. * *pptsz is modified in place to contain a pointer that can
  375. * be passed subsequently to Token_Find to pull the next token.
  376. *
  377. ***************************************************************************/
  378. LPTSTR Token_Find(LPTSTR *pptsz)
  379. {
  380. LPTSTR ptsz = *pptsz;
  381. while (*ptsz) {
  382. /*
  383. * Skip leading separators.
  384. */
  385. while (*ptsz == TEXT(' ') ||
  386. *ptsz == TEXT(',') ||
  387. *ptsz == TEXT(';')) {
  388. ptsz++;
  389. }
  390. if (*ptsz) {
  391. LPTSTR ptszStart = ptsz;
  392. /*
  393. * Skip until we see a separator.
  394. */
  395. while (*ptsz != TEXT('\0') &&
  396. *ptsz != TEXT(' ') &&
  397. *ptsz != TEXT(',') &&
  398. *ptsz != TEXT(';')) {
  399. ptsz++;
  400. }
  401. /*
  402. * Wipe out the separator, and advance ptsz past it
  403. * if there is something after it. (Don't advance
  404. * it beyond the end of the string!)
  405. */
  406. if (*ptsz) {
  407. *ptsz++ = 0;
  408. }
  409. *pptsz = ptsz;
  410. return ptszStart;
  411. } else {
  412. break;
  413. }
  414. }
  415. return 0;
  416. }
  417. #pragma warning(default:4035)