home *** CD-ROM | disk | FTP | other *** search
/ CICA 1993 August / CICA.cdr / cis_libs / mswin32 / 14 / utov.txt < prev    next >
Encoding:
Text File  |  1993-01-10  |  23.5 KB  |  812 lines

  1. Universal Thunk Overview
  2. ========================
  3.  
  4. Win32s has the following design goals and requirements:
  5.  
  6. o Offer a 32-bit programming model for Windows 3.1 Enhanced Mode
  7.  
  8. o Use Win32 semantics for the windowing API
  9.  
  10. o Win32s supports Win32 apps with binary compatibility (same exe format)
  11.  
  12. o Win32s provides seemless migration from 16-bit Windows to 32-bit Windows NT
  13.  
  14. Binary compatibility and the requirement to provide natural migration
  15. to Windows NT creates a portability problem for ISVs which have
  16. Windows apps that require device drivers.
  17.  
  18. Win32s cannot support the Windows NT kernel device driver model on
  19. Windows 3.1.  Therefore, the only way that Win32 apps running on
  20. Windows 3.1 can access devices is through existing drivers supported
  21. by Windows 3.1.
  22.  
  23. However, Windows NT does not support mixing 16- and 32-bit code in
  24. the same process.  This is not portable and therefore, not allowed. 
  25. There are a number of IPC mechanisms such as DDEML that would allow
  26. data to be passed between Win32 and 16-bit Windows processes, but the
  27. bandwidth is not sufficiently high for some types of applications.
  28.  
  29. Therefore, the Universal Thunk has been designed to overcome this
  30. problem. The Universal Thunk allows a Win32 application to call a
  31. routine in a 16-bit DLL.  There is also support for a 16-bit routine
  32. to callback to a 32-bit function.  The simple Win32s thunk used to
  33. implement this design also provide address translation services
  34. allowing access to flat memory from segmented code and vice versa.
  35.  
  36. This design allows a Win32 application to isolate driver specific
  37. routines in a 16-bit DLL.  The Win32 application remains portable
  38. across Windows 3.1 and Windows NT; on Windows NT the 16-bit DLL is
  39. replaced with a 32-bit DLL that communicates to devices via the
  40. Windows NT model.
  41.  
  42.  
  43. Universal Thunk Design
  44. ======================
  45.  
  46. First diagram illustrates Win32 Application using UT to access
  47. existing 16-bit service.
  48.  
  49. Win32 application is binary compatible on Windows 3.1 and Windows NT.
  50.  The Win32 DLL offers identical interfaces on Windows 3.1 and Windows
  51. NT, however unique Win32 (32-bit) DLLs are created for Windows 3.1
  52. and Windows NT.  This DLL isolates the different techniques required
  53. to access drivers and hardware on Windows 3.1 and Windows NT.
  54.  
  55. Windows 3.1
  56. -----------
  57.  
  58. +--------------+
  59. |              |
  60. |  Win32 App   |
  61. |              |
  62. +--------------+
  63.        ^
  64.        | Std. Interface                                      Existing Win3.1
  65.        v                                   16-bit DLL          DLL/Driver
  66. +--------------+       +----------+       +----------+  (1)  +----------+
  67. |              |------>|          |------>| UT16Proc |------>|          |
  68. |  Win32 DLL   |       | Win32s UT|------>| UT16Init |  (2)  |          |
  69. |fnUT32CallBack|<------|          |<------|          |<------|          |
  70. +--------------+       +----------+       +----------+       +----------+
  71.                  32-bit             16-bit
  72.                Interface          Interface
  73.  
  74. (1) Pass data from Win32 app to existing Win 3.1 DLL/driver or obtain data
  75.     from existing Win 3.1 DLL/driver. Transaction driven by Win32 application.
  76.  
  77. (2) Use callback function to transfer data from existing Win 3.1 DLL/driver
  78.     to Win32 application. Transaction driven from 16-bit side.
  79.  
  80. Windows NT
  81. ----------
  82.  
  83. Illustrates Win32 application relying on 32-bit Windows NT DLLs and drivers.
  84.  
  85.                      +--------------+
  86.                      |              |
  87.                      |  Win32 App   |
  88.                      |              |
  89.                      +--------------+
  90.                             ^
  91.                             | Std. Interface
  92.                             v
  93.                      +--------------+
  94.                      |              |
  95.                      |  Win32 DLL   |
  96.                      |              |
  97.                      +--------------+
  98.                             ^
  99.                             | Driver I/O (via Win32 API or IOCTLs)
  100.                             v
  101.                      +--------------+
  102.                      |              |
  103.                      |  Windows NT  |
  104.                      | 32-bit driver|
  105.                      |  Kernel Mode |
  106.                      |              |
  107.                      +--------------+
  108.  
  109.  
  110. ============================================================================
  111. ================ Universal Thunk API =======================================
  112. ============================================================================
  113.  
  114.  
  115. typedef DWORD (* WINAPI UT32PROC)(LPVOID lpBuff,
  116.                                   DWORD  dwUserDefined,
  117.                                   LPVOID *lpTranslationList
  118.                                  );
  119.  
  120. Prototype of 32-bit thunk to 16-bit dll.
  121.  
  122. Parameters
  123. ----------
  124.  
  125. lpBuff
  126.  
  127. pointer to general purpose memory buffer. This 32-bit pointer is
  128. translated to 16:16 form and passed to the 16-bit procedure. The
  129. segmented address provides addresiblity for object of 32KB. This
  130. parameter is optional.
  131.  
  132. dwUserDefined
  133.  
  134. available for application use.
  135.  
  136. lpTranslationList
  137.  
  138. array of pointers to pointers that should be translated to segmented
  139. form. the list is terminated by a null pointer. No validity check is
  140. performed on the address except for null check. The translation list
  141. is used internally and not passed to the 16-bit procedure. This
  142. parameter is optional.
  143.  
  144. See Also
  145. --------
  146.  
  147. UTRegister()
  148. ___________________________________________________________________________
  149.  
  150. DWORD FAR PASCAL UT16PROC(LPVOID lpBuff, DWORD  dwUserDefined );
  151.  
  152. UT16PROC name is a placeholder for the application-defined function
  153. name. The actual name must be exported by including it in the EXPORTS
  154. statement in the DLL's module-definition file.
  155.  
  156. Parameters
  157. ----------
  158.  
  159. lpBuff
  160.  
  161. pointer to general purpose memory buffer that was passed by the 32-bit code.
  162.  
  163. dwUserDefined
  164.  
  165. available for application use.
  166.  
  167. See Also
  168. --------
  169.  
  170. UTRegister()
  171.  
  172. ___________________________________________________________________________
  173.  
  174. DWORD FAR PASCAL UT16INIT( UT16CBPROC pfnUT16CallBack, LPVOID lpBuff);
  175.  
  176. UT16INIT name is a placeholder for the application-defined function
  177. name. The actual name must be exported by including it in the EXPORTS
  178. statement in the DLL's module-definition file.
  179.  
  180. Parameters
  181. ----------
  182. pfnUT16CallBack
  183.  
  184. 16-bit thunk to 32-bit callback routine, as specified at registration.
  185.  
  186.  
  187. lpBuff
  188.  
  189. pointer to general purpose memory buffer that was passed by the 32-bit code.
  190.  
  191. See Also
  192. --------
  193.  
  194. UTRegister()
  195.  
  196. ___________________________________________________________________________
  197.  
  198. DWORD WINAPI UT32CBPROC( LPVOID lpBuff, DWORD dwUserDefined );
  199.  
  200. UT32CBPROC name is a placeholder for the application-defined function
  201. name. It does not have to be exported.
  202.  
  203. Parameters
  204. ----------
  205.  
  206. lpBuff
  207.  
  208. pointer to general purpose memory buffer as passed to 16-bit callback thunk.
  209.  
  210. dwUserDefined
  211.  
  212. available for application use.
  213.  
  214. Comments
  215. --------
  216.  
  217. Memory allocated by 16-bit code and passed to 32-bit must be first
  218. fixed in memory.
  219.  
  220.  
  221. See Also
  222. --------
  223.  
  224. UTRegister()
  225. ___________________________________________________________________________
  226.  
  227. typedef DWORD FAR PASCAL (*UT16CBPROC)( LPVOID lpBuff,
  228.                                         DWORD dwUserDefined,
  229.                                         LPVOID *lpTranslationList
  230.                                       );
  231.  
  232. Prototype of 16-bit Universal Thunk Call Back procedure
  233.  
  234. Parameters
  235. ----------
  236.  
  237. lpBuff
  238.  
  239. Pointer to general purpose memory buffer. This segmented pointer is
  240. translated to flat address and passed to the 32-bit callback
  241. procedure. This parameter is optional.
  242.  
  243. dwUserDefined
  244.  
  245. available for application use.
  246.  
  247. lpTranslationList
  248.  
  249. array of pointers to pointers that should be translated to segmented
  250. form. the list is terminated by a null pointer. No validity check is
  251. performed on the address except for null check. The translation list
  252. is used internally and not passed to the 32-bit callback procedure.
  253. This parameter is optional.
  254.  
  255. See Also
  256. --------
  257.  
  258. UTRegister()
  259. ___________________________________________________________________________
  260.  
  261. BOOL UTRegister(hModule, lpsz16BITDLL, lpszInitName, lpszProcName,
  262.                 ppfn32Thunk, pfnUT32CallBack, lpBuff )
  263.  
  264. HANDLE     hModule;          // 32-bit Dll module handle
  265. LPCTSTR    lpsz16BITDLL;     // Name of DLL (i.e. "MY16BIT.DLL")
  266. LPCTSTR    lpszInitName;     // Name of exported init function
  267. LPCTSTR    lpszProcName;     // Name of exported thunk function
  268. UT32PROC * ppfn32Thunk;      // Output parameter (indirect 32-bit
  269. function pointer)
  270. FARPROC    pfnUT32CallBack;  // Address of 32-bit callback function
  271. LPVOID     lpBuff;      // Pointer to shared memory block
  272.  
  273. This routine registers a universal thunk that can be used to access
  274. 16-bit code from a Win32 application running via Win32s on Windows
  275. 3.1.  Only one UT can be created per Win32 dll.  The thunk can be
  276. destroyed by calling UTUnRegister(). UTRegister() will automatically
  277. load the 16-bit DLL specified. It then calls the init routine and
  278. provide it a 16-bit callable routine. The system creates a 32-bit
  279. thunk that can be used to call the 16-bit procedure in the 16-bit
  280. dll.
  281.  
  282. Parameters
  283. ----------
  284.  
  285. hDllInst
  286.  
  287. Handle of 32-bit dll. The universal thunk provides a mechnism to
  288. "extend" a win32 dll into win3.1. The thunk is owned by the dll and
  289. every dll is limited to have only one thunk.
  290.  
  291. lpsz16BITDLL
  292.  
  293. Points to a null-terminated string that that names the library file
  294. to be loaded. If the string does not contain a path, Win32s searches
  295. for the library using the same search mechanism as LoadLibrary on
  296. Windows 3.1.
  297.  
  298. lpszInitName
  299.  
  300. Points to a null-terminated string containing the function name, or
  301. specifies the ordinal value of the initialization function. If it is
  302. an ordinal value, the value must be in the low word and the high word
  303. must be zero. This parameter can be NULL if no initialization or
  304. callback is required.
  305.  
  306. lpszProcName
  307.  
  308. Points to a null-terminated string containing the function name, or
  309. specifies the ordinal value of the 16-bit function. If it is an
  310. ordinal value, the value must be in the low word and the high word
  311. must be zero.
  312.  
  313. ppfn32Thunk
  314.  
  315. Return value is a 32-bit function pointer (thunk to 16-bit routine)
  316. if UTRegister() is successful.  This function can be used to call the
  317. 16-bit routine indirectly.
  318.  
  319. pfnUT32CallBack
  320.  
  321. Address of the 32-bit callback routine.  Win32S creates a 16-bit
  322. callable thunk to the 32-bit function and provid it to the
  323. initialization routine.  The 32-bit routine does not need to be
  324. specified as an EXPORT function in the DEF file. No call back thunk
  325. is created if either this parameter or lpszInitName are NULL.
  326.  
  327. lpBuff
  328.  
  329. Pointer to globally allocated shared memory. Pointer is translated
  330. into 16:16 alias by Universal Thunk and is passed to the
  331. initialization routine. This parameter is optional and ignored if
  332. NULL.
  333.  
  334. Returns
  335. -------
  336.  
  337. Function returns TRUE if DLL was loaded and UT16Init() routine was
  338. successfully called or FALSE if an error occurred.  Use the
  339. GetLastError() function to obtain extended error information. 
  340. Typical errors are: ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND,
  341. ERROR_INVALID_ORDINAL, and ERROR_NOT_ENOUGH_MEMORY,
  342.  
  343.  
  344. Comments
  345. --------
  346.  
  347. Registering the Universal Thunk enables two capabilities for
  348. communicating between 32-bit and 16-bit routines.  The first
  349. capability is to allow a Win32 application to call a 16-bit routine
  350. passing data using globally shared memory. This is a Win32
  351. application initiated data transfer mechanism.
  352.  
  353. The second capability is to register a callback routine by which
  354. 16-bit code can callback into a 32-bit routine in a Win32 DLL. Again,
  355. shared global memory is used to transfer data.
  356.  
  357. The first capability is designed to allow Win32 applications to use
  358. existing Windows 3.1 device drivers.  The design requires the Win32
  359. application to poll the device driver just like a 16-bit Windows 3.1
  360. application.  The globally shared memory buffer can be used to
  361. transfer data from the device (read operation) or to the device
  362. (write operation).
  363.  
  364. The 32-bit callback routine is designed to allow Win32 applications
  365. to obtain information from 16-bit service providers.  This may be
  366. necessary until the service provider itself implements a Win32 DLL
  367. service.
  368.  
  369. The 16-bit DLL must EXPORT the initialization routine and the  sevice
  370. routine, and  use the following function prototypes:
  371.  
  372. VOID FAR PASCAL UT16Init( FARPROC pfnUT32CallBack, LPVOID lpBuff );
  373.  
  374. DWORD FAR PASCAL UT16Proc( LPVOID lpBuff, DWORD dwUserDefined );
  375.  
  376. UTRegister() will result in Win32s loading the specified DLL with
  377. normal Windows 3.1 DLL initialization occuring.  Win32s will then
  378. call the initialization routine passing this function a 16:16 thunk
  379. to the 32-bit callback function.  The initialization routine can
  380. return data in a global shared memory buffer.
  381.  
  382. The initialization routine must return non zero value to indicate
  383. successful initialization. If it fails no thunk is created.
  384.  
  385. UTRegister() returns a 32-bit thunk to the 16-bit UT16Proc().  This
  386. pointer can be used in Win32 code to call the 16-bit routine:
  387.  
  388. dwUserDefinedReturn = (*pfnUT16Proc)( pSharedMemory, dwUserDefinedSend,
  389.                                       lpTranslationList );
  390.  
  391. The Universal Thunk will translate the 32-bit linearaddress of the
  392. shared memory to a 16:16 segmented pointer, along with all the
  393. addresses listed by lpTranslationList before passing it to the 16-bit
  394. UT16Proc() routine.
  395.  
  396. The 16-bit code can call Win32 code using the callback mechanism:
  397.  
  398. dwUserDefinedReturn = (*pfnUT32CallBack)( pSharedMemory, dwUserDefinedSend,
  399.                                           lpTranslationList );
  400.  
  401. The 32-bit callback routine should be defined as follows (but does
  402. not need to be EXPORTed in the DEF file):
  403.  
  404. DWORD WINAPI UT32CBPROC( LPVOID lpBuff, DWORD dwUserDefined );
  405.  
  406. See Also
  407. --------
  408.  
  409. UTUnRegister(), LoadLibrary() (16-bit version), GetProcAddress
  410. (16-bit version)
  411.  
  412. ___________________________________________________________________________
  413.  
  414.  
  415. VOID UTUnRegister( hModule )
  416.  
  417. HANDLE hModule
  418.  
  419. Requests Win32s to call FreeLibrary() for the 16-bit DLL loaded by
  420. UTRegister().  Also, destroys the dynamically created Universal
  421. Thunk.
  422.  
  423. Returns
  424. -------
  425.  
  426. No return value.
  427.  
  428.  
  429. Comments
  430. --------
  431.  
  432. This call allows the single dynamically created Universal Thunk to be
  433. destroyed and the 16-bit DLL dereferenced.  Win32s will clean-up
  434. these resources automatically when the Win32 dll is freed (normally
  435. or abnormally).
  436.  
  437. See Also
  438. --------
  439.  
  440. UTRegister(), FreeLibrary() (16-bit version)
  441.  
  442. ___________________________________________________________________________
  443.  
  444.  
  445. Universal Thunk auxilary services
  446. =================================
  447.  
  448. The following are address translation services available for 16-bit code only.
  449.  
  450. ___________________________________________________________________________
  451.  
  452. DWORD UTSelectorOffsetToLinear( lpByte )
  453.  
  454. LPVOID  lpByte;
  455.  
  456. Translate a segmented address to flat form;
  457.  
  458. Returns
  459. -------
  460.  
  461. Equivalent flat address.
  462.  
  463. Comments
  464. --------
  465.  
  466. The base of the flat selectors used by Win32S process is not zero. 
  467. If the memory is allocated by 16-bit api it must be fixed before its
  468. address can be converted to flat form.
  469.  
  470.  
  471. See Also
  472. --------
  473. UTLinearToSelectorOffset
  474.  
  475. ___________________________________________________________________________
  476.  
  477. LPVOID UTLinearToSelectorOffset( lpByte )
  478.  
  479. DWORD  lpByte;
  480.  
  481. Translate a flat address to a segmented form.
  482.  
  483. Returns
  484. -------
  485.  
  486. Equivalent segmented address.
  487.  
  488. Comments
  489. --------
  490.  
  491. The returned address guarentees addressibility for objects up to 32K byte.
  492.  
  493. See Also
  494. --------
  495.  
  496. UTSelectorOffsetToLinear
  497.  
  498.  
  499.  
  500. Universal Thunk Implementation Notes
  501. ------------------------------------
  502.  
  503. The following information discusses implementation issues that impact
  504. application usage.
  505.  
  506. 1)
  507. Only one Universal Thunk (UT) may exist for each Win32 dll. 
  508. Additional calls to UTRegister() will fail until UTUnRegister() is
  509. called.
  510.  
  511. 2)
  512. Win32s will destroy the UT and call FreeLibrary for the 16-bit DLL when:
  513.  
  514. o UTUnRegister() is called
  515.  
  516. o The Win32 dll is freed (normally or abnormally)
  517.  
  518. 3)
  519. Memory allocated by 16-bit routines via GlobalAlloc should be fixed
  520. via GlobalFix.  It must be translated to flat address before it can
  521. be used bu 32-bit code.  Translated will be performed by the system
  522. if passed as lpBuff or by using the traslation list.  It can also be
  523. translated explicitly via UTSelectorOffsetToLinear before it can be
  524. used by 32-bit code.
  525.  
  526. 4)
  527. The 32-bit callback function should not be used by 16-bit interrupt
  528. handlers. The Win32 API does not support locking memory pages,
  529. therefore an interrupt service routine which calls back into 32-bit
  530. code cannot gurantee that the code is currently paged into memory.
  531.  
  532. 5)
  533. Exception handling can be done in 32-bit code only. Exceptions in
  534. 16-bit code will be handled by the last 32-bit exception frame.
  535.  
  536.  
  537. ============================================================================
  538. ======================= SAMPLE =============================================
  539. ============================================================================
  540.  
  541.     /*++
  542.  
  543.     Copyright (c) 1985-92, Microsoft Corporation
  544.  
  545.     Module Name:
  546.  
  547.         db.h
  548.  
  549.     Abstract:
  550.  
  551.         Win32s sample code of Universal Thunk (UT) -
  552.         this example demonstrates how existing 16bit code can provide services
  553.         to 32bit application thru a thunking layer based on the UT api.
  554.  
  555.         This header file defines the interface to the data base services.
  556.         The 32-bit interface provided by thunking is identical to the 16-bit
  557.         interface.
  558.  
  559.     --*/
  560.  
  561.  
  562.     typedef  struct {
  563.          short int  len;
  564.          char      *str;
  565.     } DB_NAME;
  566.  
  567.     typedef  struct {
  568.          short int  year;
  569.          short int  month;
  570.          short int  day;
  571.          short int  hour;
  572.          short int  minute;
  573.          short int  seconds;
  574.     } DB_TIME;
  575.  
  576.  
  577.     /*
  578.      * following services are provided by DB.DLL which is a 16bit dll.
  579.      */
  580.  
  581.  
  582.     int         DbGetVersion(void);
  583.     void        DbSetTime(DB_TIME * pTime);
  584.     short       DbAddUser(DB_NAME * pName, int Permission, short int *pId);
  585.  
  586.  
  587.     /*++
  588.  
  589.     Copyright (c) 1985-92, Microsoft Corporation
  590.  
  591.     Module Name:
  592.  
  593.         db32.c
  594.  
  595.     Abstract:
  596.  
  597.         Win32s sample code of Universal Thunk (UT) -
  598.         32bit code that provides the same services as DB.DLL by means
  599.         of thunking to 16bit dll.
  600.         This is the main source file of DB32.DLL
  601.  
  602.     --*/
  603.  
  604.  
  605.  
  606.     #include <windows.h>
  607.     #include <w32sut.h>
  608.     #include <db.h>
  609.  
  610.     UT32PROC  pUTProc=NULL;
  611.     int       cProcessesAttached = 0;
  612.  
  613.  
  614.     BOOL
  615.     DllInit(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)
  616.     {
  617.  
  618.       if ( fdwReason == DLL_PROCESS_ATTACH ) {
  619.  
  620.         /*
  621.          * Registration of UT need to be done only once for first
  622.          * attaching process.
  623.          */
  624.  
  625.         if ( cProcessesAttached++ ) {
  626.             return(TRUE);
  627.         }
  628.  
  629.         return UTRegister( hInst,        // DB32.DLL module handle
  630.                            "DB16.DLL",   // name of 16bit thunk dll
  631.                            NULL,         // no init routine
  632.                            "UTProc",     // name of 16bit dispatch routine
  633.                                          // exported from DB16.DLL
  634.                            &pUTProc,     // Global variable to
  635. receive thunk address
  636.                            NULL,         // no call back function
  637.                            NULL          // no shared memroy
  638.                          );
  639.       } else if ( fdwReason == DLL_PROCESS_DETACH ) {
  640.  
  641.           if ( --cProcessesAttached == 0 ) {
  642.               UTUnregister( hInst );
  643.           }
  644.       }
  645.  
  646.     }
  647.  
  648.     /*
  649.      * constants for dispatcher in 16bit side
  650.      */
  651.  
  652.     #define DB_SRV_GETVERSION   0
  653.     #define DB_SRV_SETTIME      1
  654.     #define DB_SRV_ADDUSER      2
  655.  
  656.  
  657.     int
  658.     DbGetVersion(void)
  659.     {
  660.  
  661.         /*
  662.          * call the 16bit dispatch thru the 32bit thunk. no parameters
  663.          * are passed.
  664.          * returned value is the service result.
  665.          */
  666.  
  667.         return( (int) (* pfnUTProc)(NULL, DB_SRV_GETVERSION, NULL) );
  668.  
  669.     }
  670.  
  671.     void
  672.     DbSetTime(DB_TIME * pTime);
  673.     {
  674.  
  675.         /*
  676.          * call the 16bit dispatch thru the 32bit thunk.
  677.          * pass one pointer to a buffer which will be translated
  678.          * to 16:16 address before passed to 16bit side.
  679.          *
  680.          */
  681.  
  682.         (* pfnUTProc)(pTime, DB_SRV_SETTIME, NULL);
  683.  
  684.     }
  685.  
  686.     int
  687.     DbAddUser(DB_NAME * pName, int Permission, short int *pId)
  688.     {
  689.  
  690.         DWORD    Args[3];           // function has three arguments
  691.         PVOID    TransList[4];      // Three pointers needs translation:
  692.                                     //     pName
  693.                                     //     pName->str
  694.                                     //     pId
  695.                                     // plus null to indicate end of list
  696.         char    *pSaveStr;
  697.         int     Ret;
  698.  
  699.         /*
  700.          * put arguments in buffer
  701.          */
  702.  
  703.         Args[0] = pName;
  704.         Args[1] = Permission;
  705.         Args[2] = pId;
  706.  
  707.         /*
  708.          * build translation list for all the flat pointers that need to
  709.          * be translated to segmented form.
  710.          */
  711.         TransList[0] = & Args[0];
  712.         TransList[1] = & pName->str;
  713.         TransList[2] = & Args[2];
  714.         TransList[3] = 0;
  715.  
  716.         /*
  717.          * save the original pointer in the NAME struct so it can be restored
  718.          * after the call to the thunk.
  719.          * This is required only if the caller of the service expects the
  720.          * structure to be left unmodified.
  721.          */
  722.  
  723.         pSaveStr = pName->str;
  724.  
  725.         /*
  726.          * call the 16bit dispatch thru the 32bit thunk.
  727.          * pass arguments in buffer along with list of addresses
  728.          * that need to be translated equivalent segmented format.
  729.          *
  730.          */
  731.  
  732.         Ret = (int) (* pfnUTProc)(Args, DB_SRV_ADDUSER, TransList);
  733.  
  734.         /*
  735.          * restore flat pointer
  736.          */
  737.         pName->str = pSaveStr;
  738.  
  739.         return(Ret);
  740.     }
  741.  
  742.  
  743.  
  744.  
  745.     /*++
  746.  
  747.     Copyright (c) 1985-92, Microsoft Corporation
  748.  
  749.     Module Name:
  750.  
  751.         db16.c
  752.  
  753.     Abstract:
  754.  
  755.         Win32s sample code of Universal Thunk (UT) -
  756.         services dispatcher in 16bit side.
  757.         This is the main source file of DB16.DLL.
  758.  
  759.     --*/
  760.  
  761.  
  762.     #include <windows.h>
  763.     #include <w32sut.h>
  764.     #include <db.h>
  765.  
  766.  
  767.     /*
  768.      * constants for dispatcher in 16bit side
  769.      */
  770.  
  771.     #define DB_SRV_GETVERSION   0
  772.     #define DB_SRV_SETTIME      1
  773.     #define DB_SRV_ADDUSER      2
  774.  
  775.  
  776.     /*
  777.      * 16bit dispatcher function.
  778.      * exported by DB16.DLL
  779.      */
  780.  
  781.     DWORD FAR PASCAL
  782.     UTProc(LPVOID lpBuf, DWORD dwFunc)
  783.     {
  784.  
  785.         /*
  786.          * call 16bit DB services based on the function Id.
  787.          */
  788.  
  789.         switch (dwFunc) {
  790.  
  791.         case DB_SRV_GETVERSION:
  792.             return( (DWORD) DbGetVersion() );
  793.  
  794.         case DB_SRV_SETTIME:
  795.             DbSetTime((DB_TIME *) lpBuf);
  796.             return;
  797.  
  798.         case DB_SRV_ADDUSER:
  799.             return( (DWORD) DbAddUser( (DWORD *)lpBuf [0] ,
  800.                                        (DWORD *)lpBuf [1] ,
  801.                                        (DWORD *)lpBuf [2]
  802.                                      )
  803.                   );
  804.  
  805.         }
  806.  
  807.         return( 0 );
  808.     }
  809.  
  810.  
  811. ++++++++++++++++++++++++++  E N D ++++++++++++++++++++++++++++++++++++++++++
  812.