home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / doc / misc / genthunk.txt next >
Encoding:
Text File  |  1995-07-11  |  16.3 KB  |  444 lines

  1. Windows NT Generic Thunk Overview
  2. =================================
  3.  
  4. Windows NT supports running 16-bit applications using a technology referred
  5. to as WOW (Windows on Windows NT). Each 16-bit application can be run in its
  6. own address space (VDM) or run in a shared address space (the default). The
  7. 16-bit Windows API calls are mapped to Win32 APIs in the WOW layer.
  8.  
  9. Windows NT does not allow mixing 16-bit and 32-bit code in the same process.
  10. WOW supports standard IPC mechanisms such as DDE, RPC, OLE, and named pipes,
  11. but there are occasions when it is necessary to call a routine in a Win32
  12. DLL (including Win32 APIs in the system DLLs) from a 16-bit application. This
  13. functionality is provided by WOW Generic Thunks.
  14.  
  15. When deciding whether to use existing IPC mechanisms or use Generic Thunks, it
  16. is important to consider that Generic Thunks are unique to Windows NT and code
  17. that uses them will not be portable to other Win32 platforms. Other Win32
  18. platforms support different thunking mechanisms (i.e. Universal Thunks on
  19. Win32s). The best thing to do is to isolate thunking code into DLLs which can
  20. be made platform-specific, or to detect the platform at runtime and call
  21. the appropriate APIs (see the \SCT\Samples\Interop sample for an example).
  22.  
  23. WOW Application Programming Interfaces
  24. ======================================
  25.  
  26. The following are 16-bit WOW APIs exported by KERNEL for use in Generic Thunks.
  27. The prototypes can be found in wownt16.h.
  28.  
  29. ----------
  30.  
  31. DWORD FAR PASCAL LoadLibraryEx32W(
  32.    LPCSTR lpszLibFile,
  33.    DWORD  hFile,
  34.    DWORD  dwFlags);
  35.  
  36. This API allows a 16-bit thunk DLL to load a 32-bit thunk DLL.
  37.  
  38. Parameters
  39.  
  40. This API thunks to the Win32 LoadLibraryEx(). For a complete description of
  41. the parameters, please refer to the Win32 SDK documentation.
  42.  
  43. Returns
  44.  
  45. If the call succeeds, the return value is a 32-bit DLL HINSTANCE, otherwise,
  46. it is NULL.
  47.  
  48. Comments
  49.  
  50. The 16-bit thunk DLL can then call GetProcAddress32W() to get the address of
  51. the 32-bit entry point(s) and then call the thunk(s) via CallProc32W().
  52.  
  53. ----------
  54.  
  55. BOOL FAR PASCAL FreeLibrary32W(DWORD hInst);
  56.  
  57. This API allows a 16-bit thunk DLL to free a 32-bit thunk DLL which it had
  58. previously loaded via LoadLibraryEx32W().
  59.  
  60. Parameter
  61.  
  62. This API thunks to the Win32 FreeLibrary(). For a complete description of the
  63. parameter, please refer to the Win32 SDK documentation.
  64.  
  65. Returns
  66.  
  67. If the function succeeds, the return value is TRUE, otherwise, it is FALSE.
  68.  
  69. Comments
  70.  
  71. Note that WOW does not do any cleanup of 32-bit thunk DLLs when the WOW task
  72. exits. It is up to the 16-bit thunk DLLs to free the 32-bit thunk DLLs as
  73. necessary.
  74.  
  75. ----------
  76.  
  77. DWORD FAR PASCAL GetProcAddress32W(DWORD hModule, LPCSTR lpszProc);
  78.  
  79. This API allows a 16-bit thunk DLL to get a value that corresponds to a
  80. 32-bit thunk routine.
  81.  
  82. Parameters
  83.  
  84. This API thunks to the Win32 GetProcAddress(). For a complete description of
  85. the parameters, please refer to the Win32 SDK documentation.
  86.  
  87. Returns
  88.  
  89. If the call succeeds, the return value is a 32-bit value that must be passed
  90. as a parameter to CallProc32W() or CallProcEx32W(), rather than used directly.
  91.  
  92. ----------
  93.  
  94. DWORD FAR PASCAL GetVDMPointer32W(lpAddress, fMode);
  95.  
  96. This API allows a 16-bit thunk DLL to translate a 16-bit far pointer into
  97. a 32-bit flat pointer for use by a 32-bit thunk DLL.
  98.  
  99. Parameters
  100.  
  101.    LPVOID lpAddress Valid 16:16 address, either protect or "real" mode
  102.    UNIT   fMode     1 - address is interpreted as Protect Mode address
  103.                     0 - address is interpreted as "Real" Mode Address
  104.  
  105. Returns
  106.  
  107. If the call succeeds, the return value is a 32-bit linear address. Otherwise,
  108. the function will return NULL. Note that on non-x86 platforms "real" mode
  109. address 0:0 may not point to linear 0 in memory, so always use this function
  110. and make no assumptions about memory layout.
  111.  
  112. Comments
  113.  
  114. The WOW Kernel memory manager moves segments in memory and keeps the selectors
  115. the same. However if you get the linear address, it may not be valid if the
  116. memory manager has moved memory. If you need to keep a flat pointer to
  117. a buffer for a long period (rather than doing the address conversion each time
  118. the pointer is used), then call GlobalWire() to lock the segment in low memory.
  119. On non-x86 platforms, it will not be possible to use this address directly,
  120. but the address can be useful to pass to other 32-bit thunk DLLs or as a part
  121. of a packet of data to be passed to another process.
  122.  
  123. ----------
  124.  
  125. DWORD FAR PASCAL CallProc32W( DWORD param1, DWORD param2, ... ,
  126.                               LPVOID lpProcAddress32,
  127.                               DWORD fAddressConvert, DWORD nParams);
  128.  
  129. This API is used by a 16-bit thunk DLL to call an entry point in a 32-bit DLL.
  130.  
  131. Parameters
  132.  
  133.    DWORD   param1-param32    Parameters for 32-bit procedure represented by
  134.                              lpProcAddress32
  135.  
  136.    LPVOID  lpProcAddress32   The 32-bit value corresponding to the procedure
  137.                              to be called, returned by GetProcAddress32().
  138.  
  139.    DWORD   fAddressConvert   Bit mask representing which parameters will be
  140.                              treated as 16:16 pointers and translated into
  141.                              flat linear pointers before being passed to the
  142.                              32-bit procedure
  143.  
  144.    DWORD   nParams           Number of DWORD params passed (not counting
  145.                              fAddressConvert and nParams). For functions
  146.                              that take no parameters this will be 0.
  147.  
  148. Returns
  149.  
  150. The API returns a DWORD which is the return value from the 32-bit entry point
  151. represented by lpProcAddress32. The return value can also be 0 if lpProcAddress
  152. was 0 or if nParams is greater than 32.
  153.  
  154. Comments
  155.  
  156. At minimum this routine takes 3 parameters (lpProcAddress32, fAddressConvert
  157. and nParams). It can additionally take a maximum of 32 optional parameters.
  158. These parameters must be DWORDS and must match the type that the 32-bit thunk
  159. DLL is expecting. If the appropriate bit is set in the fAddressConvert mask,
  160. the parameter will be translated from a 16:16 pointer to a 32-bit flat linear
  161. pointer. Note that the lowest bit in the mask represents param1, the second
  162. lowest bit represents param2, and so forth.
  163.  
  164. Under Windows NT version 3.1, the procedure called must be defined with the
  165. _stdcall calling convention.
  166.  
  167. WARNING: Be careful when using this API, since there is no compiler check made
  168. on the number and type of parameters, no conversions of types (all parameters
  169. passed a DWORDS and will be passed directly to the function called without
  170. conversion). No checks of 16:16 address are made (limit checks, NULL checks,
  171. correct ring level, and so forth).
  172.  
  173. Reference
  174.  
  175. See also CallProcEx32W().
  176.  
  177. ----------
  178.  
  179. DWORD FAR CallProcEx32W( DWORD nParams, DWORD fAddressConvert,
  180.                          DWORD lpProcAddress, DWORD param1, ... );
  181.  
  182. This API is used by a 16-bit thunk DLL to call an entry point in a 32-bit DLL.
  183. This function is new to Windows NT version 3.5.
  184.  
  185. Parameters
  186.  
  187. See the parameters for CallProc32W().
  188.  
  189. Comments
  190.  
  191. CallProcEx32W() is similar to CallProc32W(), but it uses the C calling
  192. convention to allow easier and more flexible prototyping.
  193.  
  194. On Windows NT version 3.5, both CallProc32W() and CallProcEx32W() accept a
  195. flag OR'd with the parameter count which indicates the calling convention of
  196. the 32-bit procedure. For example, the call to a _cdecl function that accepts
  197. 1 parameter by value would look like this:
  198.  
  199.    dwResult = CallProcEx32W( CPEX_DEST_CDECL | 1, 0, dwfn32, param1 );
  200.  
  201. while a similar call to a _stdcall function would look like this:
  202.  
  203.    dwResult = CallProcEx32W( CPEX_DEST_STDCALL | 1, 0, dwfn32, param1 );
  204.  
  205. Reference
  206.  
  207. See also CallProc32W().
  208.  
  209. -------------------------------------------------------------------------------
  210.  
  211. The following are 32-bit WOW APIs exported by WOW32.DLL.
  212.  
  213. ----------
  214.  
  215. LPVOID WINAPI WOWGetVDMPointer(DWORD vp, DWORD dwBytes, BOOL fProtectedMode);
  216.  
  217. Convert a 16:16 address to the equivalent flat address.
  218.  
  219. Parameters
  220.  
  221.    vp               Valid 16:16 address
  222.  
  223.    dwBytes          Size of block pointed to by vp
  224.  
  225.    fProtectedMode   1 - upper 16 bits are treated as a selector in the local
  226.                         descriptor table
  227.                     0 - upper 16 bits are treated as a real-mode segment value
  228.  
  229. Returns
  230.  
  231. If the API is successful, the return value the 32-bit address. The return value
  232. is NULL if the selector is invalid.
  233.  
  234. Comments
  235.  
  236. Limit checking is not performed in the retail build of Windows NT. It is
  237. performed in the checked (debug) build of WOW32.DLL, which will cause NULL to
  238. be returned when the limit is exceeded by the supplied offset.
  239.  
  240. ----------
  241.  
  242. LPVOID WINAPI WOWGetVDMPointerFix(DWORD vp, 
  243.                                   DWORD dwBytes,
  244.                                   BOOL fProtectedMode);
  245. VOID WINAPI WOWGetVDMPointerUnfix(DWORD vp);
  246.  
  247.  
  248. The WOWGetVDMPointerFix is functionally equivalent to WOWGetVDMPointer on 
  249. Windows NT.  However, on future releases of Windows this function
  250. will call GlobalFix before returning the flat address, so that the 16-bit 
  251. memory will not move around in linear space.  WOWGetVDMPointerUnFix will
  252. GlobalUnFix the memory and return.
  253.  
  254. The reason for this is that while the 32-bit code called through Generic
  255. Thunks is executing on Windows NT, no other 16-bit code will execute in that
  256. VDM. As a result, the 16-bit memory will not move around in linear
  257. (32-bit) memory.  However, this will not be the case on all platforms
  258. that support these APIs.
  259.  
  260. Please note that Windows NT 3.5 does not GlobalFix the memory when you use
  261. this call so if your thunks use callbacks (WOWCallback16 and WOWCallback16Ex)
  262. then it is possible that the 16-bit memory will move around in linear space on
  263. Windows NT during the callback. In that case you should either GlobalFix the 
  264. memory before calling the thunk or discard all flat pointers and call 
  265. WOWGetVDMPointer after returning from the callback.
  266.  
  267. Also, if you use any of the WOWGlobalAlloc16 family of APIs, its possible that
  268. any 32-bit pointers that you have to 16-bit memory may become invalidated as the
  269. 16-bit heap is shuffled during the callback.
  270.  
  271. ----------
  272.  
  273. WORD  WINAPI WOWGlobalAlloc16(WORD wFlags, DWORD cb);
  274. WORD  WINAPI WOWGlobalFree16(WORD hMem);
  275. DWORD WINAPI WOWGlobalLock16(WORD hMem);
  276. BOOL  WINAPI WOWGlobalUnlock16(WORD hMem);
  277.  
  278. These APIs thunk to the 16-bit side and call the Win16 versions of 
  279. these APIs.
  280.  
  281. ----------
  282.  
  283. DWORD WINAPI WOWGlobalAllocLock16(WORD wFlags, DWORD cb, WORD *phMem);
  284. WORD  WINAPI WOWGlobalUnlockFree16(DWORD vpMem);
  285. DWORD WINAPI WOWGlobalLockSize16(WORD hMem, PDWORD pcb);
  286.  
  287. These APIs combine several common Win16 operations into one call
  288. across the thunk.
  289.  
  290. ----------
  291.  
  292. VOID WINAPI WOWYield16(VOID);
  293. VOID WINAPI WOWDirectedYield16(WORD htask16);
  294.  
  295. These APIs, like the WOWGlobalAlloc16 family of APIs, thunk down to the
  296. Win16 forms of these APIs to allow other tasks to run while the thunk
  297. is doing a lengthy operation.  Note that 16-bit blocks of memory that have
  298. not been GlobalFix'd may move in memory as a result of this call.
  299.  
  300. ----------
  301.  
  302. DWORD WINAPI WOWCallback16(DWORD vpfn16, DWORD dwParam);
  303.  
  304. Used in 32-bit code called from 16-bit code via Generic Thunks to call back
  305. to the 16-bit side (Generic Callback).
  306.  
  307. Parameters
  308.  
  309.    vpfn16   Pointer to 16-bit callback routine, which is passed from the
  310.             16-bit side
  311.  
  312.    dwParam  Parameter for the 16-bit callback routine
  313.  
  314. Returns
  315.  
  316. The value comes from the callback routine. If the callback routine returns a
  317. WORD instead of a DWORD, the upper 16 bits of the return value are undefined.
  318. If the callback routine has no return value, the entire return value of this
  319. API is undefined.
  320.  
  321. Comments
  322.  
  323. The 16-bit function to be called must be declared with one of the following
  324. types:
  325.  
  326.    LONG FAR PASCAL CallbackRoutine(DWORD dwParam);
  327.  
  328.    -or-
  329.  
  330.    LONG FAR PASCAL CallbackRoutine(VOID FAR *vp);
  331.  
  332. depending on whether the parameter is a pointer or not.
  333.  
  334. NOTE: If you are passing a pointer, you'll need to get the pointer using
  335. either WOWGlobalAlloc16() or WOWGlobalAllocLock16() (see wownt32.h).
  336.  
  337. ----------
  338.  
  339. BOOL WINAPI WOWCallback16Ex(
  340.               DWORD  vpfn16,
  341.               DWORD  dwFlags,
  342.               DWORD  cbArgs,
  343.               PVOID  pArgs,
  344.               PDWORD pdwRetCode
  345.               );
  346.  
  347. Used in 32-bit code called from 16-bit code via Generic Thunks to call back
  348. to the 16-bit side (Generic Callback).
  349.  
  350. Parameters
  351.  
  352.    vpfn16      Pointer to 16-bit callback routine, which is passed from the
  353.                16-bit side
  354.  
  355.    dwFlags     WCB16_PASCAL - to call a _pascal callback routine (default)
  356.                WCB16_CDECL  - to call a _cdecl callback routine
  357.  
  358.    cbArgs      Count of bytes in arguments (used to properly clean 16-bit stack)
  359.  
  360.    pArgs       Arguments for the callback routine
  361.  
  362.    pdwRetCode  The return code from the callback routine
  363.  
  364. Returns
  365.  
  366. If cbArgs is larger than the WCB16_MAX_ARGS which the system supports, the
  367. return value is FALSE and GetLastError() returns ERROR_INVALID_PARAMETER.
  368. Otherwise, the return value is TRUE and the DWORD pointed to by pdwRetCode
  369. contains the return code from the callback routine. If the callback routine
  370. returns a WORD, the HIWORD of the return code is undefined and should be
  371. ignored by using LOWORD(dwRetCode).
  372.  
  373. Comments
  374.  
  375. WOWCallback16Ex() allows any combination of arguments up to WCB16_MAX_CBARGS
  376. bytes total to be passed to the 16-bit callback routine. Regardless of the
  377. value of cbArgs, WCB16_MAX_CBARGS bytes will always be copied from pArgs to the
  378. 16-bit stack. If pArgs is less than WCB16_MAX_CBARGS bytes from the end of a
  379. page and the next page is inaccessible, WOWCallback16Ex() will incur an access
  380. violation.
  381.  
  382. The arguments pointed to by pArgs must be in the correct order for the callback
  383. routine's calling convention. For example, to call the PASCAL routine
  384. SetWindowText()
  385.  
  386.    LONG FAR PASCAL SetWindowText(HWND hwnd, LPCSTR lpsz);
  387.  
  388. pArgs would point to an array of words:
  389.  
  390.    WORD SetWindowTextArgs[] = {OFFSETOF(lpsz), SELECTOROF(lpsz), hwnd};
  391.  
  392. In other words, the arguments are placed in the array in reverse order, with
  393. the least significant word first for DWORDs and offset first for FAR pointers.
  394.  
  395. To call the CDECL routine wsprintf()
  396.  
  397.    LPSTR lpszFormat = "%d %s";
  398.    int _cdecl wsprintf(lpsz, lpszFormat, nValue. lpszString);
  399.  
  400. pArgs would point to the array:
  401.  
  402.    WORD wsprintfArgs[] = {OFFSETOF(lpsz), SELECTOROF(lpsz),
  403.                           OFFSETOF(lpszFormat), SELECTOROF(lpszFormat),
  404.                           nValue,
  405.                           OFFSETOF(lpszString), SELECTOROF(lpszString)};
  406.  
  407. In other words, the arguments are placed in the array in the order listed in
  408. the function prototype with the least significant word first for DWORDs and
  409. offset first for FAR pointers.
  410.  
  411. ----------
  412.  
  413. HANDLE WINAPI WOWHandle32 (WORD, WOW_HANDLE_TYPE);
  414. WORD WINAPI WOWHandle16 (HANDLE, WOW_HANDLE_TYPE);
  415.  
  416. These APIs (and the associated macros) are used to map a
  417. 16-bit handle to a 32-bit handle (and vice-versa).  These
  418. APIs should be used in lieu of any private knowledge of
  419. the relationship between a Win16 handle and a Win32 handle.
  420.  
  421. The reason is that the relationship between a Win16 handle
  422. and a Win32 handle can change (and has done so between
  423. Windows NT 3.1 and Windows NT 3.5).  We expect that they
  424. may change in the future.
  425.  
  426. These APIs use the WOW_HANDLE_TYPE to indicate the type of
  427. handle being translated.  Types supported include:
  428. HWND, HMENU, HDWP, HDROP, HDC, HFONT, HMETAFILE, HRGN,
  429. HBITMAP, HBRUSH, HPALETTE, HPEN, HACCEL, HTASK, FULLHWND
  430.  
  431. The WOW_HANDLE_TYPE corresponding to each of these is of
  432. the form WOW_TYPE_<handle>, e.g. WOW_TYPE_HWND.
  433.  
  434. Also, there are macros in WOWNT32.H to use to map handles between
  435. Win16 and Win32.  For example, to map a Win16 HWND to a Win32
  436. HWND, you would use the HWND_32 macro (e.g. hWnd32 = HWND_32(hWnd16)).
  437.  
  438. A "full" hWnd is a hWnd that a Win32 app would see (and therefore can
  439. be used in comparisons with 32-bit hWnds received from Win32 APIs.) 
  440. The other hWnd type has a different value but is recognized by the 
  441. system.  Please do not make assumptions about the relationship between
  442. the 16-bit hWnd, the 32-bit Hwnd, and the 32-bit Full hWnd.  This
  443. relationship has changed in the past (for performance reasons) and it
  444. may change again in the future.