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.

252 lines
6.1 KiB

  1. /*++
  2. * intthunk.c
  3. *
  4. * WOW v5.0
  5. *
  6. * Copyright 1996, Microsoft Corporation. All Rights Reserved.
  7. *
  8. * WOW32.C
  9. * WOW32 16-bit API support
  10. *
  11. * History:
  12. * Created 7-Dec-96 DaveHart
  13. *
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "wowit.h"
  18. MODNAME(intthunk.c);
  19. extern DWORD WK32ICallProc32MakeCall(DWORD pfn, DWORD cbArgs, VOID *pArgs);
  20. //
  21. // On x86 we don't bother aligning pointers to DWORDs
  22. // passed to APIs. Perhaps we shouldn't for Alpha?
  23. //
  24. #ifdef _X86_
  25. #define ALIGNDWORDS 0
  26. #else
  27. #define ALIGNDWORDS 1
  28. #endif
  29. ULONG FASTCALL InterpretThunk(PVDMFRAME pFrame, DWORD dwIntThunkID)
  30. {
  31. PINT_THUNK_TABLEENTRY pit = &IntThunkTable[ dwIntThunkID ];
  32. CONST BYTE * pbInstr = pit->pbInstr;
  33. DWORD dwArgs32[MAX_IT_ARGS];
  34. PDWORD pdwArg32 = dwArgs32;
  35. #if ALIGNDWORDS
  36. BOOL fAlignedUsed = FALSE;
  37. DWORD adwAligned[MAX_IT_ARGS];
  38. PDWORD pdwAligned = adwAligned;
  39. DWORD avpAligned[MAX_IT_ARGS];
  40. PDWORD pvpAligned = avpAligned;
  41. #endif
  42. WORD UNALIGNED *pwArg16 = (WORD UNALIGNED *) ((PBYTE)&pFrame->bArgs + pFrame->cbArgs - 2);
  43. DWORD dwReturn;
  44. DWORD dw;
  45. WOW32ASSERTMSGF(dwIntThunkID <= ITID_MAX,
  46. ("WOW32 InterpretThunk error ID %d out of range (%d max).\n",
  47. dwIntThunkID, ITID_MAX));
  48. while ( ! (*pbInstr & IT_RETMASK)) {
  49. switch (*pbInstr) {
  50. case IT_WORD:
  51. *pdwArg32 = *pwArg16;
  52. break;
  53. case IT_INT:
  54. *pdwArg32 = INT32(*pwArg16);
  55. break;
  56. case IT_DWORD:
  57. *pdwArg32 = *(DWORD UNALIGNED *) --pwArg16;
  58. break;
  59. case IT_LPDWORD:
  60. #if ALIGNDWORDS
  61. if (! fAlignedUsed) {
  62. fAlignedUsed = TRUE;
  63. RtlZeroMemory(avpAligned, sizeof avpAligned);
  64. }
  65. *pvpAligned = *(DWORD UNALIGNED *) --pwArg16;
  66. if (*pvpAligned) {
  67. *pdwArg32 = (DWORD) pdwAligned;
  68. *pdwAligned = *(DWORD UNALIGNED *) GetPModeVDMPointer(*pvpAligned, 4);
  69. } else {
  70. *pdwArg32 = 0;
  71. }
  72. break;
  73. #else
  74. //
  75. // If we aren't aligning DWORDs use the generic
  76. // pointer code.
  77. //
  78. /* FALL THROUGH TO IT_PTR */
  79. #endif
  80. case IT_PTR:
  81. dw = *(DWORD UNALIGNED *) --pwArg16;
  82. do_IT_PTR_with_dw:
  83. *pdwArg32 = (DWORD) GetPModeVDMPointer(dw, 0);
  84. break;
  85. case IT_PTRORATOM:
  86. dw = *(DWORD UNALIGNED *) --pwArg16;
  87. if (HIWORD(dw)) {
  88. goto do_IT_PTR_with_dw;
  89. }
  90. *pdwArg32 = dw; // atom
  91. break;
  92. case IT_HGDI:
  93. *pdwArg32 = (DWORD) GDI32( (HAND16) *pwArg16 );
  94. break;
  95. case IT_HUSER:
  96. *pdwArg32 = (DWORD) USER32( (HAND16) *pwArg16 );
  97. break;
  98. case IT_COLOR:
  99. dw = *(DWORD UNALIGNED *) --pwArg16;
  100. *pdwArg32 = COLOR32(dw);
  101. break;
  102. case IT_HINST:
  103. *pdwArg32 = (DWORD) HINSTRES32( (HAND16) *pwArg16 );
  104. break;
  105. case IT_HICON:
  106. *pdwArg32 = (DWORD) HICON32( (HAND16) *pwArg16 );
  107. break;
  108. case IT_HCURS:
  109. *pdwArg32 = (DWORD) HCURSOR32( (HAND16) *pwArg16 );
  110. break;
  111. case IT_16ONLY:
  112. //
  113. // This is for params that appear on 16-bit side but not 32-bit side,
  114. // for example the hinstOwner passed to CopyImage in Win16 but not in Win32.
  115. //
  116. pdwArg32--;
  117. break;
  118. case IT_32ONLY:
  119. //
  120. // This is for params that appear on 32-bit side but not 16-bit side,
  121. // we pass zero for the 32-bit argument.
  122. //
  123. *pdwArg32 = 0;
  124. pwArg16++;
  125. break;
  126. default:
  127. WOW32ASSERTMSGF(FALSE, ("WOW32 InterpretThunk error unknown opcode 0x%x.\n", *pbInstr));
  128. }
  129. pwArg16--;
  130. pdwArg32++;
  131. pbInstr++;
  132. #if ALIGNDWORDS
  133. pdwAligned++;
  134. pvpAligned++;
  135. #endif
  136. WOW32ASSERT((pbInstr - pit->pbInstr) <= (MAX_IT_ARGS + 1));
  137. }
  138. //
  139. // Call API
  140. //
  141. dwReturn = WK32ICallProc32MakeCall(
  142. (DWORD) pit->pfnAPI,
  143. (PBYTE) pdwArg32 - (PBYTE) dwArgs32,
  144. dwArgs32
  145. );
  146. #ifdef DEBUG
  147. pFrame = NULL; // Memory movement may have occurred.
  148. #endif
  149. //
  150. // If we passed aligned DWORD pointers, copy the values back.
  151. //
  152. #if ALIGNDWORDS
  153. if (fAlignedUsed) {
  154. pdwAligned = adwAligned;
  155. pvpAligned = avpAligned;
  156. while (pvpAligned < (PDWORD)((PBYTE)avpAligned + sizeof avpAligned)) {
  157. if (*pvpAligned) {
  158. *(DWORD UNALIGNED *) GetPModeVDMPointer(*pvpAligned, 4) = *pdwAligned;
  159. }
  160. pdwAligned++;
  161. pvpAligned++;
  162. }
  163. }
  164. #endif
  165. //
  166. // Thunk return value using last instruction opcode
  167. //
  168. WOW32ASSERT(*pbInstr & IT_RETMASK);
  169. switch (*pbInstr) {
  170. case IT_DWORDRET:
  171. // dwReturn is correct
  172. break;
  173. case IT_WORDRET:
  174. dwReturn = GETWORD16(dwReturn);
  175. break;
  176. case IT_INTRET:
  177. dwReturn = (DWORD) GETINT16(dwReturn);
  178. break;
  179. case IT_HGDIRET:
  180. dwReturn = GDI16( (HAND32) dwReturn );
  181. break;
  182. case IT_HUSERRET:
  183. dwReturn = USER16( (HAND32) dwReturn );
  184. break;
  185. case IT_ZERORET:
  186. dwReturn = 0;
  187. break;
  188. case IT_HICONRET:
  189. dwReturn = GETHICON16( (HAND32) dwReturn );
  190. break;
  191. case IT_HCURSRET:
  192. dwReturn = GETHCURSOR16( (HAND32) dwReturn );
  193. break;
  194. case IT_ONERET:
  195. dwReturn = 1;
  196. break;
  197. case IT_HPRNDWPRET:
  198. dwReturn = GetPrn16( (HAND32) dwReturn );
  199. break;
  200. default:
  201. WOW32ASSERTMSGF(FALSE, ("WOW32 InterpretThunk error unknown return opcode 0x%x.\n", *pbInstr));
  202. }
  203. return dwReturn;
  204. }