home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / spiwrap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.3 KB  |  641 lines

  1. //--------------------------------------------------------------------
  2. //  spiwrap.c
  3. //
  4. //  Created: 11/20/97
  5. //  Author:  Matt Kendall
  6. //
  7. //  Copyright (C) 1997 Full Circle Software All Rights Reserved
  8. //
  9. //  Dynamically Load Spiral API
  10. //
  11. //--------------------------------------------------------------------
  12. #include <windows.h>
  13. #include <stdarg.h>
  14.  
  15. #include "fullsoft.h"
  16.  
  17. #define FC_WRAPPER_VERSION                             2
  18. #define FC_WRAPPER_MINIMUM_ACCEPTABLE_LIBRARY_VERSION  1
  19.  
  20. #if !defined(_WINDOWS)
  21. #error This is a Windows only file
  22. #endif // _WINDOWS
  23.  
  24. #if !defined(_WIN32) && !defined(_WIN16)
  25. #define _WIN16
  26. #endif // ! _WIN32 && ! _WIN16
  27.  
  28. #if defined(_WIN32)
  29. #define DEFINE_CALLNAME(s) const char sz##s[] = #s
  30. #else // ! _WIN32
  31. #define DEFINE_CALLNAME(s) const char sz##s[] = "_"#s
  32. void FreeOrphanFCLoads() ;
  33. #endif // ! _WIN32
  34.  
  35. void FCUnloadLibrary() ;
  36. BOOL FCIsValidFullsoftLibrary(const char *) ;
  37.  
  38. typedef FC_ERROR (FCAPI __cdecl *t_FCInitialize)( void ) ;
  39.  
  40. typedef FC_ERROR (FCAPI __cdecl *t_FCCreateKey)(
  41.     FC_KEY key,
  42.     FC_DATA_TYPE type,
  43.     FC_UINT32 first_count,
  44.     FC_UINT32 last_count,
  45.     FC_UINT32 max_element_size) ;
  46.  
  47. typedef FC_ERROR (FCAPI __cdecl *t_FCCreatePersistentKey)(
  48.     FC_KEY key,
  49.     FC_DATA_TYPE type,
  50.     FC_UINT32 first_count,
  51.     FC_UINT32 last_count,
  52.     FC_UINT32 max_element_size) ;
  53.  
  54. typedef FC_ERROR (FCAPI __cdecl *t_FCAddDataToKey)(
  55.     FC_KEY key,
  56.     FC_PVOID buffer,
  57.     FC_UINT32 data_length) ;
  58.  
  59. typedef FC_ERROR (FCAPI __cdecl *t_FCAddIntToKey)(
  60.     FC_KEY key,
  61.     FC_UINT32 data) ;
  62.  
  63. typedef FC_ERROR (FCAPI __cdecl *t_FCAddStringToKey)(
  64.     FC_KEY key,
  65.     FC_STRING string) ;
  66.  
  67. typedef FC_ERROR (FCAPI __cdecl *t_FCRegisterMemory)(
  68.     FC_KEY key,
  69.     FC_DATA_TYPE type,
  70.     FC_PVOID buffer,
  71.     FC_UINT32 length,
  72.     FC_UINT32 dereference_count,
  73.     FC_CONTEXT context) ;
  74.  
  75. typedef FC_ERROR (FCAPI __cdecl *t_FCUnregisterMemory)(
  76.     FC_CONTEXT context) ;
  77.  
  78. typedef FC_ERROR (FCAPI __cdecl  *t_FCAddDateToKey)(
  79.     FC_KEY key,
  80.     FC_DATE date) ;
  81.  
  82. typedef FC_ERROR (FCAPI __cdecl *t_FCSetCounter)(
  83.     FC_KEY key,
  84.     FC_UINT32 value) ;
  85.  
  86. typedef FC_ERROR (FCAPI __cdecl *t_FCIncrementCounter)(
  87.     FC_KEY key,
  88.     FC_UINT32 value) ;
  89.  
  90. typedef FC_ERROR (FCAPI __cdecl *t_FCTrigger)( FC_TRIGGER trigger ) ;
  91.  
  92. typedef FC_ERROR (FCAPI __cdecl *t_FCTriggerInternal)(
  93.     FC_TRIGGER szTrigger,
  94.     FC_UINT32 eip,
  95.     FC_UINT32 esp,
  96.     FC_UINT32 ebp) ;
  97.  
  98. typedef void (FCAPI __cdecl *t_FCTraceInternal)(FC_STRING fmt,void FAR *) ;
  99.  
  100. typedef void (FCAPI __cdecl *t_FCAssertInternal)(unsigned long) ;
  101.  
  102. typedef FC_ERROR (FCAPI __cdecl *t_FCCleanup)( void ) ;
  103.  
  104. typedef int  (FCAPI __cdecl *t_FCOrphanLoadCount)() ;
  105.  
  106. typedef void (FCAPI __cdecl *t_FCAssertParamInternal)(FC_UINT32 pc,FC_UINT32 mask,FC_UINT32 level ) ;
  107.  
  108. typedef void (FCAPI __cdecl *t_FCTraceParamInternal)(FC_UINT32 mask,FC_UINT32 level,FC_STRING fmt,void FAR *args ) ;
  109.  
  110. typedef FC_UINT32 (FCAPI __cdecl *t_FCLibraryVersion)( FC_UINT32 wrap_version ) ;
  111.  
  112. typedef FC_ERROR  (FCAPI __cdecl *t_FCInitializeInternal)( FC_UINT32 wrap_version ) ;
  113.  
  114. DEFINE_CALLNAME( FCInitialize ) ;
  115. DEFINE_CALLNAME( FCCreateKey ) ;
  116. DEFINE_CALLNAME( FCCreatePersistentKey ) ;
  117. DEFINE_CALLNAME( FCAddDataToKey ) ;
  118. DEFINE_CALLNAME( FCAddIntToKey ) ;
  119. DEFINE_CALLNAME( FCAddStringToKey ) ;
  120. DEFINE_CALLNAME( FCRegisterMemory ) ;
  121. DEFINE_CALLNAME( FCUnregisterMemory ) ;
  122. DEFINE_CALLNAME( FCAddDateToKey ) ;
  123. DEFINE_CALLNAME( FCSetCounter ) ;
  124. DEFINE_CALLNAME( FCIncrementCounter ) ;
  125. DEFINE_CALLNAME( FCTrigger ) ;
  126. DEFINE_CALLNAME( FCTriggerInternal ) ;
  127. DEFINE_CALLNAME( FCTraceInternal ) ;
  128. DEFINE_CALLNAME( FCAssertInternal ) ;
  129. DEFINE_CALLNAME( FCCleanup ) ;
  130. DEFINE_CALLNAME( FCOrphanLoadCount ) ;
  131. DEFINE_CALLNAME( FCAssertParamInternal ) ;
  132. DEFINE_CALLNAME( FCTraceParamInternal ) ;
  133. DEFINE_CALLNAME( FCLibraryVersion ) ;
  134. DEFINE_CALLNAME( FCInitializeInternal ) ;
  135.  
  136. t_FCInitialize pfnFCInitialize ;
  137. t_FCCreateKey pfnFCCreateKey ;
  138. t_FCCreatePersistentKey pfnFCCreatePersistentKey ;
  139. t_FCAddDataToKey pfnFCAddDataToKey ;
  140. t_FCAddIntToKey pfnFCAddIntToKey ;
  141. t_FCAddStringToKey pfnFCAddStringToKey ;
  142. t_FCAddDateToKey pfnFCAddDateToKey ;
  143. t_FCSetCounter pfnFCSetCounter ;
  144. t_FCIncrementCounter pfnFCIncrementCounter ;
  145. t_FCRegisterMemory pfnFCRegisterMemory ;
  146. t_FCUnregisterMemory pfnFCUnregisterMemory ;
  147. t_FCTrigger pfnFCTrigger ;
  148.  
  149. // undocumented dll functions
  150. t_FCTraceInternal pfnFCTraceInternal ;
  151. t_FCAssertInternal pfnFCAssertInternal ;
  152. t_FCCleanup pfnFCCleanup ;
  153. t_FCAssertParamInternal pfnFCAssertParamInternal ;
  154. t_FCTraceParamInternal pfnFCTraceParamInternal ;
  155. t_FCLibraryVersion pfnFCLibraryVersion ;
  156. t_FCInitializeInternal pfnFCInitializeInternal ;
  157. t_FCTriggerInternal pfnFCTriggerInternal ;
  158.  
  159. static HMODULE gMod = NULL;
  160.  
  161. void ExitFunction( void );
  162. void ExitFunction( void )
  163. {
  164.     if( pfnFCCleanup!=NULL ) {
  165.         pfnFCCleanup() ;
  166.     }
  167.     if( gMod!=NULL ) {
  168.         FreeLibrary( gMod ) ;
  169.     }
  170. }
  171.  
  172. FC_ERROR FCAPI
  173. FCInitialize() {
  174.     FC_UINT32 dwLibraryVersion ;
  175.     char szFullsoftLibrary[MAX_PATH] ;
  176.     char *p,*pEnd,*pLastSlash ;
  177.     HMODULE hMod;
  178.  
  179. #if defined(_WIN16)
  180.     // If Spiral crashed in Win16 than "spiral.dll" will be left in memory with
  181.     // a bogus reference count.  The following routine identifies this and
  182.     // cleans up
  183.     FreeOrphanFCLoads() ;
  184. #endif // _WIN16
  185.  
  186.     if ( atexit(ExitFunction) != 0 ) {
  187.         return FC_ERROR_CANT_INITIALIZE;
  188.     }
  189.  
  190.     // Build up a fully qualified path to FULLSOFT.DLL
  191.     GetModuleFileName( GetModuleHandle(NULL) , szFullsoftLibrary , MAX_PATH ) ;
  192.     pEnd = szFullsoftLibrary+MAX_PATH ;
  193.     pLastSlash = szFullsoftLibrary ;
  194.     for( p = szFullsoftLibrary ; (p<pEnd) && *p ; p++ ) {
  195.         if( *p=='\\' ) {
  196.             pLastSlash = p ;
  197.         }
  198.     }
  199.     if( *pLastSlash=='\\' ) {
  200.         pLastSlash++ ;
  201.     }
  202.     strcpy(pLastSlash,"FULLSOFT.DLL") ;
  203.  
  204.     // Check for our copyright string in FULLSOFT.DLL
  205.     if( FCIsValidFullsoftLibrary(szFullsoftLibrary)==FALSE ) {
  206.         return FC_ERROR_CANT_INITIALIZE ;
  207.     }
  208.  
  209.     // Load the library
  210.     hMod = LoadLibrary(szFullsoftLibrary) ;
  211. #if defined(_WIN32)
  212.     if( hMod==NULL ) {
  213.         return FC_ERROR_CANT_INITIALIZE ;
  214.     }
  215. #else // !_WIN32
  216.     if( hMod<HINSTANCE_ERROR ) {
  217.         hMod = NULL ;
  218.         return FC_ERROR_CANT_INITIALIZE ;
  219.     }
  220. #endif // !_WIN32
  221.  
  222.     gMod = hMod;
  223.  
  224.     pfnFCInitialize = (t_FCInitialize)GetProcAddress(hMod,szFCInitialize) ;
  225.     pfnFCCreateKey = (t_FCCreateKey)GetProcAddress(hMod, szFCCreateKey) ;
  226.     pfnFCCreatePersistentKey = (t_FCCreatePersistentKey)GetProcAddress(hMod, szFCCreatePersistentKey) ;
  227.     pfnFCAddDataToKey = (t_FCAddDataToKey)GetProcAddress(hMod, szFCAddDataToKey) ;
  228.     pfnFCAddIntToKey = (t_FCAddIntToKey)GetProcAddress(hMod, szFCAddIntToKey) ;
  229.     pfnFCAddStringToKey = (t_FCAddStringToKey)GetProcAddress(hMod, szFCAddStringToKey) ;
  230.     pfnFCAddDateToKey = (t_FCAddDateToKey)GetProcAddress(hMod, szFCAddDateToKey) ;
  231.     pfnFCSetCounter = (t_FCSetCounter)GetProcAddress(hMod, szFCSetCounter) ;
  232.     pfnFCIncrementCounter = (t_FCIncrementCounter)GetProcAddress(hMod, szFCIncrementCounter) ;
  233.     pfnFCRegisterMemory = (t_FCRegisterMemory)GetProcAddress(hMod, szFCRegisterMemory) ;
  234.     pfnFCUnregisterMemory = (t_FCUnregisterMemory)GetProcAddress(hMod, szFCUnregisterMemory) ;
  235.     pfnFCTrigger = (t_FCTrigger)GetProcAddress(hMod, szFCTrigger) ;
  236.     
  237.     pfnFCTraceInternal = (t_FCTraceInternal)GetProcAddress(hMod, szFCTraceInternal) ;
  238.     pfnFCAssertInternal = (t_FCAssertInternal)GetProcAddress(hMod, szFCAssertInternal) ;
  239.     pfnFCCleanup = (t_FCCleanup)GetProcAddress(hMod,szFCCleanup) ;
  240.     pfnFCAssertParamInternal = (t_FCAssertParamInternal)GetProcAddress(hMod,szFCAssertParamInternal) ;
  241.     pfnFCTraceParamInternal = (t_FCTraceParamInternal)GetProcAddress(hMod,szFCTraceParamInternal)  ;
  242.     pfnFCLibraryVersion = (t_FCLibraryVersion)GetProcAddress(hMod,szFCLibraryVersion) ;
  243.     pfnFCInitializeInternal = (t_FCInitializeInternal)GetProcAddress(hMod,szFCInitializeInternal) ;
  244.     pfnFCTriggerInternal = (t_FCTriggerInternal)GetProcAddress(hMod, szFCTriggerInternal) ;
  245.  
  246.     // Get the library version and ensure it is compatible
  247.     if( pfnFCLibraryVersion==NULL ) {
  248.         FCUnloadLibrary() ;
  249.         return FC_ERROR_CANT_INITIALIZE ;
  250.     }
  251.     dwLibraryVersion = pfnFCLibraryVersion( FC_WRAPPER_VERSION ) ;
  252.     if( dwLibraryVersion<FC_WRAPPER_MINIMUM_ACCEPTABLE_LIBRARY_VERSION ) {
  253.         FCUnloadLibrary() ;
  254.         return FC_ERROR_CANT_INITIALIZE ;
  255.     }
  256.  
  257.     // If we were able to load and locate the library's initialize routine
  258.     // call it now
  259.     if( pfnFCInitialize==NULL ) {
  260.         FCUnloadLibrary() ;
  261.         return FC_ERROR_CANT_INITIALIZE ;
  262.     } else {
  263.         return pfnFCInitializeInternal(FC_WRAPPER_VERSION) ;
  264.     }
  265. }
  266.  
  267. FC_ERROR FCAPI
  268. FCCreateKey(
  269.     FC_KEY key,
  270.     FC_DATA_TYPE type,
  271.     FC_UINT32 first_count,
  272.     FC_UINT32 last_count,
  273.     FC_UINT32 max_element_size) 
  274. {
  275.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  276.     if( pfnFCCreateKey!=NULL ) {
  277.         err = pfnFCCreateKey(key,type,first_count,last_count,max_element_size) ;
  278.     }
  279.     return err ;
  280. }
  281.  
  282. FC_ERROR FCAPI
  283. FCCreatePersistentKey(
  284.     FC_KEY key,
  285.     FC_DATA_TYPE type,
  286.     FC_UINT32 first_count,
  287.     FC_UINT32 last_count,
  288.     FC_UINT32 max_element_size) 
  289. {
  290.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  291.     if( pfnFCCreateKey!=NULL ) {
  292.         err = pfnFCCreatePersistentKey(key,type,first_count,last_count,max_element_size) ;
  293.     }
  294.     return err ;
  295. }
  296.  
  297. FC_ERROR FCAPI
  298. FCAddDataToKey(
  299.     FC_KEY key,
  300.     FC_PVOID buffer,
  301.     FC_UINT32 data_length) 
  302. {
  303.     if( pfnFCAddDataToKey!=NULL ) {
  304.         pfnFCAddDataToKey(key,buffer,data_length) ;
  305.     }
  306.     return FC_ERROR_OK ;
  307. }
  308.  
  309. FC_ERROR FCAPI
  310. FCAddIntToKey(
  311.     FC_KEY key,
  312.     FC_UINT32 data)
  313. {
  314.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  315.     if( pfnFCAddIntToKey!=NULL ) {
  316.         err = pfnFCAddIntToKey(key,data) ;
  317.     }
  318.     return err ;
  319. }
  320.  
  321. FC_ERROR FCAPI
  322. FCAddStringToKey(
  323.     FC_KEY key,
  324.     FC_STRING string) 
  325. {
  326.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  327.     if( pfnFCAddStringToKey!=NULL ) {
  328.         err = pfnFCAddStringToKey(key,string) ;
  329.     }
  330.     return err ;
  331. }
  332.  
  333. FC_ERROR FCAPI
  334. FCRegisterMemory(
  335.     FC_KEY key,
  336.     FC_DATA_TYPE type,
  337.     FC_PVOID buffer,
  338.     FC_UINT32 length,
  339.     FC_UINT32 dereference_count,
  340.     FC_CONTEXT context) 
  341. {
  342.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  343.     if( pfnFCRegisterMemory!=NULL ) {
  344.         pfnFCRegisterMemory(key,type,buffer,length,dereference_count,context) ;
  345.     }
  346.     return err ;
  347. }
  348.  
  349. FC_ERROR FCAPI
  350. FCUnregisterMemory( FC_CONTEXT context ) {
  351.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  352.     if( pfnFCUnregisterMemory!=NULL ) {
  353.         pfnFCUnregisterMemory(context) ;
  354.     }
  355.     return err ;
  356. }
  357.  
  358. FC_ERROR FCAPI
  359. FCAddDateToKey(
  360.     FC_KEY key,
  361.     FC_DATE date)
  362. {
  363.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  364.     if( pfnFCAddDateToKey!=NULL ) {
  365.         err = pfnFCAddDateToKey(key,date) ;
  366.     }
  367.     return err ;
  368. }
  369.  
  370. FC_ERROR FCAPI
  371. FCSetCounter(
  372.     FC_KEY key,
  373.     FC_UINT32 value)
  374. {
  375.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  376.     if( pfnFCSetCounter!=NULL ) {
  377.         err = pfnFCSetCounter(key,value) ;
  378.     }
  379.     return err ;
  380. }
  381.  
  382. FC_ERROR FCAPI
  383. FCIncrementCounter(
  384.     FC_KEY key,
  385.     FC_UINT32 value)
  386. {
  387.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  388.     if( pfnFCIncrementCounter!=NULL ) {
  389.         err = pfnFCIncrementCounter(key,value) ;
  390.     }
  391.     return err ;
  392. }
  393.  
  394. void FCAPI FCTrace(FC_STRING fmt,...) {
  395.     if( pfnFCTraceInternal!=NULL ) {
  396.         va_list args ;
  397.         va_start(args,fmt) ;
  398.         pfnFCTraceInternal(fmt,args) ;
  399.         va_end(args) ;
  400.     }
  401. }
  402.  
  403. #if defined(_MSC_VER)
  404. #pragma optimize("",off)
  405. #else
  406. #error  Only Microsoft compiler supported.  To fix this, enter the appropriate pragma
  407. #error  here to ensure that a stack frame is generated by your compiler (or set your
  408. #error  compiler command line switches) and remove this warning
  409. #endif
  410.  
  411. #if defined(_WIN32)
  412. void FCAPI FCAssert() {
  413.     if( pfnFCAssertInternal!=NULL ) {
  414.         FC_UINT32 pc ;
  415.         _asm {
  416.             mov eax,[ebp+4] ;
  417.             mov pc,eax ;
  418.         }
  419.         pfnFCAssertInternal(pc) ;
  420.     }
  421. }
  422.  
  423. void FCAPI
  424. FCAssertParam(
  425.     FC_UINT32 mask,
  426.     FC_UINT32 level )
  427. {
  428.     if( pfnFCAssertParamInternal!=NULL ) {
  429.         FC_UINT32 pc ;
  430.         _asm {
  431.             push eax ;
  432.             mov eax,[ebp+4] ;
  433.             mov pc,eax ;
  434.             pop eax ;
  435.         }
  436.         pfnFCAssertParamInternal(pc,mask,level) ;
  437.     }
  438. }
  439.  
  440. FC_ERROR FCAPI
  441. FCTrigger(FC_TRIGGER trigger) {
  442.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  443.     FC_UINT32 dwEip,dwEsp,dwEbp ;
  444.     
  445.     // Get context for stack trace
  446.     _asm {
  447.         mov  eax, [ebp] ;
  448.         mov  dwEbp, eax ;
  449.         mov  eax,[ebp+4] ;
  450.         mov  dwEip, eax ;
  451.         mov  dwEsp, ebp ;
  452.     }
  453.  
  454.     dwEsp += 8 ; // ebp points to return address
  455.     
  456.     if( pfnFCTriggerInternal!=NULL ) {
  457.         pfnFCTriggerInternal(trigger,dwEip,dwEsp,dwEbp) ;
  458.     }
  459.     return err ;
  460. }
  461.  
  462. #endif // _WIN32
  463.  
  464. #if defined(_WIN16)
  465. void FCAPI FCAssert() {
  466.     FC_UINT32 pc ;
  467.     if( pfnFCAssertInternal!=NULL ) {
  468.         _asm {
  469.             mov  ax,[bp+4] ;
  470.             mov  word ptr pc+2, ax ;
  471.             mov  ax,[bp+2] ;
  472.             mov  word ptr pc, ax ;
  473.         }
  474.         pfnFCAssertInternal(pc) ;
  475.     }
  476. }
  477.  
  478. void FCAPI
  479. FCAssertParam(
  480.     FC_UINT32 mask,
  481.     FC_UINT32 level )
  482. {
  483.     if( pfnFCAssertParamInternal!=NULL ) {
  484.         FC_UINT32 pc ;
  485.         _asm {
  486.             mov  ax,[bp+4] ;
  487.             mov  word ptr pc+2, ax ;
  488.             mov  ax,[bp+2] ;
  489.             mov  word ptr pc, ax ;
  490.         }
  491.         pfnFCAssertParamInternal(pc,mask,level) ;
  492.     }
  493. }
  494. #endif // _WIN16
  495.  
  496. #if defined(_MSC_VER)
  497. #pragma optimize("",on)
  498. #endif // _MSC_VER
  499.  
  500. void FCAPI
  501. FCTraceParam(
  502.     FC_UINT32 mask,
  503.     FC_UINT32 level,
  504.     FC_STRING fmt, ... )
  505. {
  506.     if( pfnFCTraceParamInternal!=NULL ) {
  507.         va_list args ;
  508.         va_start(args,fmt) ;
  509.         pfnFCTraceParamInternal(mask,level,fmt,args) ;
  510.         va_end(args) ;
  511.     }
  512. }
  513.  
  514. void FCUnloadLibrary() {
  515.     if ( gMod != NULL ) {
  516.         FreeLibrary( gMod );
  517.         gMod = NULL;
  518.     }
  519.     
  520.     pfnFCInitialize = NULL ;
  521.     pfnFCCreateKey = NULL ;
  522.     pfnFCAddDataToKey = NULL ;
  523.     pfnFCAddIntToKey = NULL ;
  524.     pfnFCAddStringToKey = NULL ;
  525.     pfnFCAddDateToKey = NULL ;
  526.     pfnFCSetCounter = NULL ;
  527.     pfnFCIncrementCounter = NULL ;
  528.     pfnFCRegisterMemory = NULL ;
  529.     pfnFCTrigger = NULL ;
  530.  
  531.     pfnFCTraceInternal = NULL ;
  532.     pfnFCAssertInternal = NULL ;
  533.     pfnFCCleanup = NULL ;
  534.     pfnFCAssertParamInternal = NULL ;
  535.     pfnFCTraceParamInternal = NULL ;
  536.     pfnFCLibraryVersion = NULL ;
  537.     pfnFCInitializeInternal = NULL ;
  538. }
  539.  
  540. #if defined(_WIN16)
  541.  
  542. FC_ERROR FCAPI
  543.    FCTrigger(FC_TRIGGER trigger) {
  544.     FC_ERROR err = FC_ERROR_NOT_INITIALIZED ;
  545.  
  546.     if( pfnFCTrigger!=NULL ) {
  547.         pfnFCTrigger(trigger) ;
  548.     }
  549.     return err ;
  550. }
  551.  
  552. void FreeOrphanFCLoads() {
  553.     t_FCOrphanLoadCount FCOrphanLoadCount ;
  554.     HMODULE hMod = GetModuleHandle("FULLSOFT") ;
  555.     if( hMod!=NULL ) {
  556.         FCOrphanLoadCount = (t_FCOrphanLoadCount)GetProcAddress(hMod,szFCOrphanLoadCount) ;
  557.         if( FCOrphanLoadCount!=NULL ) {
  558.             int nOrphans = FCOrphanLoadCount() ;
  559.             for(;nOrphans;nOrphans--) {
  560.                 FreeLibrary(hMod) ;
  561.             }
  562.         }
  563.     }
  564. }
  565. #endif // _WIN16
  566.  
  567. #if defined(_WIN32)
  568.  
  569. // 'Scrambled' version of the string we expect to find in the library.
  570. const char FullsoftCopyright[]    =
  571.     { '\x50', '\xcc', '\x49', '\xcf', '\x4e', '\xc4', '\x38', '\xad',
  572.       '\x2e', '\x5b', '\x90', '\x00', '\x36', '\x63', '\xa1', '\xe7',
  573.       '\x2d', '\x72', '\xab', '\xd8', '\x2b', '\xad', '\x26', '\x9f',
  574.       '\xcc', '\x1c', '\x92', '\x11', '\x81', '\xfa', '\x6c', '\x99',
  575.       '\xf9', '\x75', '\xe8', '\x69', '\xed', '\x5b', '\xda', '\x4c',
  576.       '\x85', '\xb2', '\x08', '\x83', '\xf3', '\x2e', '\x3b' };
  577.  
  578. BOOL FCIsValidFullsoftLibrary(const char *szFile) {
  579.     BOOL fRet = FALSE ;
  580.     HANDLE hFile = INVALID_HANDLE_VALUE ;
  581.     IMAGE_DOS_HEADER idh ;
  582.     IMAGE_FILE_HEADER ifh ;
  583.     DWORD dw ;
  584.     char buffer[sizeof(FullsoftCopyright)] ;
  585.     char        ch;
  586.     char        output;
  587.     char        last = 0;
  588.     const char    *infoString ;
  589.     const char    *expectString ;
  590.     int         i ;
  591.  
  592.     hFile = CreateFile(szFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL) ;
  593.     if( hFile==INVALID_HANDLE_VALUE ) {
  594.         goto OnError ;
  595.     }
  596.  
  597.     if( ReadFile(hFile,&idh,sizeof(idh),&dw,NULL)==FALSE ) {
  598.         goto OnError ;
  599.     }
  600.  
  601.     SetFilePointer(hFile,idh.e_lfanew+sizeof(DWORD),NULL,FILE_BEGIN) ;
  602.  
  603.     if( ReadFile(hFile,&ifh,sizeof(ifh),&dw,NULL)==FALSE ) {
  604.         goto OnError ;
  605.     }
  606.  
  607.     SetFilePointer(hFile,
  608.                    ifh.SizeOfOptionalHeader + ifh.NumberOfSections * sizeof(IMAGE_SECTION_HEADER),
  609.                    NULL,FILE_CURRENT) ;
  610.  
  611.     if( ReadFile(hFile,buffer,sizeof(FullsoftCopyright),&dw,NULL)==FALSE ) {
  612.         goto OnError ;
  613.     }
  614.  
  615.     infoString = buffer ;
  616.     expectString = FullsoftCopyright ;
  617.     
  618.     // Compare against scrambled text.
  619.     for( i=0 ; i<sizeof(FullsoftCopyright) ; i++ ) {
  620.         ch = *expectString;
  621.         output = ch - last - 13;
  622.         last = ch;
  623.         if( output!=*infoString ) {
  624.             // Someone's different. Go get 'em, lawyers!
  625.             break;
  626.         }
  627.         infoString++;
  628.         expectString++;
  629.     }
  630.     if( i==sizeof(FullsoftCopyright) ) {
  631.         fRet = TRUE ;
  632.     }
  633.  
  634. OnError:
  635.     if( hFile!=INVALID_HANDLE_VALUE) {
  636.         CloseHandle( hFile ) ;
  637.     }
  638.     return fRet ;
  639. }
  640. #endif // _WIN32
  641.