home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / sdkrest.pak / STRUCTER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  39.9 KB  |  1,188 lines

  1. //  BDE - (C) Copyright 1995 by Borland International
  2.  
  3. #include "structer.h"
  4. #include "macro.h"
  5.  
  6. #define szCURRENTMODULE  "STRUCTER"
  7.  
  8. //=====================================================================
  9. //  This BDE example provides users a means of doing a limited Paradox and
  10. //  dBASE table restructure using Paradox for Windows ver. 5.0 ObjectPAL.  The 
  11. //  ObjectPAL procedures created are: AddField, DeleteField, ModifyField,
  12. //  and MoveField.  You only need to use one procedure for an entire
  13. //  restructure.
  14. //
  15. //  You can change field order, names, types, and sizes on local tables or on
  16. //  tables where the user has all rights to its directory.  You can also add
  17. //  or delete fields and/or pack the table.  Table properties are maintained
  18. //  (i.e. Validity Checks, Table Lookup, Secondary Indexes, etc.).
  19. //
  20. //  Because you can already re-key a table with ObjectPAL, primary key
  21. //  operations are not done in this DLL.  If adding, dropping, or copying
  22. //  (moving) a field in the the key you will need to remove the key with
  23. //  ObjectPAL (delete .PX), restructure with this DLL, and then reindex
  24. //  using ObjectPAL.  You can modify a field in a primary key without
  25. //  removing the key.
  26. //
  27. //  Also, because of the complexity of table encryption (passwords) this
  28. //  example only supports tables with no passwords.
  29. //
  30. //
  31. //  This is a Paradox Uses block:
  32. //
  33. //  Uses structer
  34. //
  35. //      DeleteField(tablePath cptr, tableName cptr, FieldName cptr,
  36. //                  PackOrNoPack cptr, returnStringBuffer cptr)
  37. //
  38. //      MoveField(tablePath cptr, tableName cptr,
  39. //                NewFieldPosition cword, CurrentFieldName cptr,
  40. //                PackOrNoPack cptr, returnStringBuffer cptr)
  41. //
  42. //      AddField(tablePath cptr, tableName cptr, NewFieldPosition
  43. //               cword, FieldName cptr, FieldType cptr, FieldSize cword,
  44. //               PackOrNoPack cptr, returnStringBuffer cptr)
  45. //
  46. //      ModifyField(tablePath cptr, tableName cptr,
  47. //                  FieldName cptr, NewFieldName cptr, FieldType cptr,
  48. //                  FieldSize cword, PackOrNoPack cptr, 
  49. //                  returnStringBuffer cptr)
  50. //
  51. //  endUses
  52. //
  53. //
  54. //  Return value: (returnStringBuffer) "Restructure successful." or an error.
  55. //                Using the return value is optional.
  56. //
  57. //
  58. //  And some typical methods:
  59. //
  60. //  Var ; on the form level
  61. //      returnStringBuffer String
  62. //  endVar
  63. //
  64. //  method open(var eventInfo Event)
  65. //      ; requires a 129 byte buffer:
  66. //      returnStringBuffer = space(129)
  67. //  endmethod
  68. //
  69. //  method mouseDown(var eventInfo MouseEvent)
  70. //      DeleteField(workingdir(), "test.dbf", "Company", "PACK",
  71. //                  returnStringBuffer)
  72. //      message(returnStringBuffer)
  73. //  endmethod
  74. //
  75. //  method mouseDown(var eventInfo MouseEvent)
  76. //      MoveField(workingdir(), "test", 2, "Phone", "NOPACK",
  77. //                returnStringBuffer)
  78. //      message(returnStringBuffer)
  79. //  endmethod
  80. //
  81. //  method mouseDown(var eventInfo MouseEvent)
  82. //      AddField(workingdir(), "test", 2, "autoincre", "+", 0, "PACK",
  83. //               returnStringBuffer)
  84. //      message(returnStringBuffer)
  85. //  endmethod
  86. //
  87. //  method mouseDown(var eventInfo MouseEvent)
  88. //      ModifyField(workingdir(), "test", "Company", "Company Name", "A",
  89. //                  50, "NOPACK", returnStringBuffer)
  90. //      message(returnStringBuffer)
  91. //  endmethod
  92. //
  93. //
  94. //  Arguments used with DeleteField:
  95. //
  96. //  1st and 2nd argument: the table Path and the table name (.db is optional,
  97. //                                                           and .dbf is
  98. //                                                           required)
  99. //  3th argument: the current field name
  100. //  4th argument: specify "PACK" or "NOPACK" (anything but "PACK" does not 
  101. //                                            pack the table)
  102. //  5th argument: return value
  103. //
  104. //  Arguments used with MoveField:
  105. //
  106. //  1st and 2nd argument: the table Path and the table name
  107. //  3rd argument: the new field position
  108. //  4th argument: the current field name
  109. //  5th argument: specify "PACK" or "NOPACK"
  110. //  6th argument: return value
  111. //
  112. //
  113. //  Arguments used with AddField and ModifyField:
  114. //
  115. //  1st and 2nd argument: the table Path and the table name
  116. //  3rd argument: the new field position
  117. //  4th argument: the current field name
  118. //  5th argument: the new field type:
  119. //
  120. //    Paradox types:               dBASE types:
  121. //    "A" = Alpha                  "C" = Character
  122. //    "N" = Number                 "F" = Float
  123. //    "$" = Money                  "N" = Number
  124. //    "S" = Short                  "D" = Date
  125. //    "I" = Long Integer           "L" = Logical
  126. //    "#" = BCD                    "M" = Memo
  127. //    "D" = Date                   "O" = OLE
  128. //    "T" = Time                   "B" = Binary
  129. //    "@" = Timestamp
  130. //    "M" = Memo
  131. //    "F" = Formatted Memo
  132. //    "G" = Graphic
  133. //    "O" = OLE
  134. //    "L" = Logical
  135. //    "+" = Autoincrement
  136. //    "B" = Binary
  137. //    "Y" = Bytes
  138. //
  139. //  6th argument: Field size
  140. //    Needs a valid number.  If a type requires no size, then use 0.
  141. //  7th argument: specify "PACK" or "NOPACK"
  142. //  8th argument: return value
  143. //
  144. //
  145. //  Other notes:
  146. //
  147. //    Follow the standard rules for all field types (i.e. you can
  148. //    convert existing number, short, and long integer fields to
  149. //    autoincrement fields if the field is the table's single-field
  150. //    primary index (key).  Use correct field sizes (0 for no size).)
  151. //
  152. //    Changes get ignored outside of these rules and give various BDE
  153. //    errors such as "Invalid field type" or "Invalid field descriptor".
  154. //
  155. //    Make sure that you have enough file handles (IDAPI maxfilehandles
  156. //    + 20).  Only use full, absolute paths for tablePathOrAlias. Relative
  157. //        paths are not supported.
  158. //    Using too few or too many parameters the Paradox Uses block
  159. //        WILL CAUSE A GPF!! (in Pdoxwin).
  160. //=====================================================================
  161.  
  162.  
  163.  
  164. //=====================================================================
  165. //  Function:
  166. //             AddField(pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
  167. //                      pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1,
  168. //                      pCHAR pPack, pCHAR pszRetBuffer)
  169. //
  170. //  Description:
  171. //             This example shows how to change the characteristics of a
  172. //             table, just adding one field.
  173. //
  174. //=====================================================================
  175. void FAR WINAPI _export
  176. AddField (pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
  177.           pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1, pCHAR pPack,
  178.           pCHAR pszRetBuffer)
  179. {
  180.     CHAR        szFldType[1] = {"\0"};   // for user field type code
  181.     HGLOBAL     hglbCorrectTableInfo;    // handle to TableInfo struct
  182.  
  183.     // store field type code
  184.     sprintf(szFldType, "%s", pFldType);
  185.  
  186.     // initialize buffer for return string
  187.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  188.  
  189.     // initialize handle to TableInfo struct
  190.     hglbCorrectTableInfo = NULL;
  191.  
  192.     // allocate memory for TableInfo struct
  193.     hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
  194.                             sizeof(struct TBLINFO));
  195.     if (hglbCorrectTableInfo == NULL)
  196.     {
  197.         GetString(1, pszRetBuffer); //"Out of Memory."
  198.         CLEANUP_NODISPLAY;
  199.     }
  200.  
  201.     // get return string from calling the first function
  202.     // set the new number of fields to + 1
  203.     BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 1, pszRetBuffer);
  204.     if (!strcmp(pszRetBuffer, "\0"))
  205.     {
  206.         SetFieldDescriptions(hglbCorrectTableInfo, crADD, iNewFldNum,
  207.                              pNewName, pNewName, szFldType, iUnits1,
  208.                              pszRetBuffer);
  209.     }
  210.     if (!strcmp(pszRetBuffer, "\0"))
  211.     {
  212.         EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
  213.     }
  214.  
  215. CleanUp:
  216.     if (hglbCorrectTableInfo)
  217.     {
  218.         cleanUpMemory(hglbCorrectTableInfo);
  219.     }
  220. }
  221.  
  222.  
  223.  
  224. //=====================================================================
  225. //  Function:
  226. //             DeleteField(pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
  227. //                         pCHAR pPack, pCHAR pszRetBuffer)
  228. //
  229. //  Description:
  230. //             This example shows how to change the characteristics of a
  231. //             table, just deleting one field.
  232. //
  233. //=====================================================================
  234. void FAR WINAPI _export
  235. DeleteField (pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName, pCHAR pPack,
  236.              pCHAR pszRetBuffer)
  237. {
  238.     CHAR        szFldType[1] = {"\0"};
  239.     HGLOBAL     hglbCorrectTableInfo;
  240.  
  241.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  242.  
  243.     hglbCorrectTableInfo = NULL;
  244.     hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
  245.                             sizeof(struct TBLINFO));
  246.     if (hglbCorrectTableInfo == NULL)
  247.     {
  248.         GetString(1, pszRetBuffer); //"Out of Memory."
  249.         CLEANUP_NODISPLAY;
  250.     }
  251.  
  252.     BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, -1, pszRetBuffer);
  253.     if (!strcmp(pszRetBuffer, "\0"))
  254.     {
  255.         SetFieldDescriptions(hglbCorrectTableInfo, crDROP, 0, pOldName,
  256.                              pOldName, szFldType, 0, pszRetBuffer);
  257.     }
  258.     if (!strcmp(pszRetBuffer, "\0"))
  259.     {
  260.         EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
  261.     }
  262.  
  263. CleanUp:
  264.     if (hglbCorrectTableInfo)
  265.     {
  266.         cleanUpMemory(hglbCorrectTableInfo);
  267.     }
  268. }
  269.  
  270.  
  271.  
  272. //=====================================================================
  273. //  Function:
  274. //             ModifyField(pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
  275. //                         pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1,
  276. //                         pCHAR pPack, pCHAR pszRetBuffer)
  277. //
  278. //  Description:
  279. //             This example shows how to change the characteristics of a
  280. //             table, just modifying one field.
  281. //
  282. //=====================================================================
  283. void FAR WINAPI _export
  284. ModifyField (pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
  285.              pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1, pCHAR pPack,
  286.              pCHAR pszRetBuffer)
  287. {
  288.     CHAR        szFldType[1] = {"\0"};
  289.     HGLOBAL     hglbCorrectTableInfo;
  290.  
  291.     sprintf(szFldType, "%s", pFldType);
  292.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  293.  
  294.     hglbCorrectTableInfo = NULL;
  295.     hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
  296.                             sizeof(struct TBLINFO));
  297.     if (hglbCorrectTableInfo == NULL)
  298.     {
  299.         GetString(1, pszRetBuffer); //"Out of Memory."
  300.         CLEANUP_NODISPLAY;
  301.     }
  302.  
  303.     BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 0, pszRetBuffer);
  304.     if (!strcmp(pszRetBuffer, "\0"))
  305.     {
  306.         SetFieldDescriptions(hglbCorrectTableInfo, crMODIFY, 0, pOldName,
  307.                              pNewName, szFldType, iUnits1, pszRetBuffer);
  308.     }
  309.     if (!strcmp(pszRetBuffer, "\0"))
  310.     {
  311.         EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
  312.     }
  313.  
  314. CleanUp:
  315.     if (hglbCorrectTableInfo)
  316.     {
  317.         cleanUpMemory(hglbCorrectTableInfo);
  318.     }
  319. }
  320.  
  321.  
  322.  
  323. //=====================================================================
  324. //  Function:
  325. //             MoveField(pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
  326. //                       pCHAR pOldName, pCHAR pPack, pCHAR pszRetBuffer)
  327. //
  328. //  Description:
  329. //             This example shows how to change the characteristics of a
  330. //             table, just moving one field.
  331. //
  332. //=====================================================================
  333. void FAR WINAPI _export
  334. MoveField (pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
  335.            pCHAR pOldName, pCHAR pPack, pCHAR pszRetBuffer)
  336. {
  337.     CHAR        szFldType[1] = {"\0"};
  338.     HGLOBAL     hglbCorrectTableInfo;
  339.  
  340.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  341.  
  342.     hglbCorrectTableInfo = NULL;
  343.     hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
  344.                             sizeof(struct TBLINFO));
  345.     if (hglbCorrectTableInfo == NULL)
  346.     {
  347.         GetString(1, pszRetBuffer); //"Out of Memory."
  348.         CLEANUP_NODISPLAY;
  349.     }
  350.  
  351.     BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 0, pszRetBuffer);
  352.     if (!strcmp(pszRetBuffer, "\0"))
  353.     {
  354.         SetFieldDescriptions(hglbCorrectTableInfo, crCOPY, iNewFldNum,
  355.                              pOldName, "", szFldType, 0, pszRetBuffer);
  356.     }
  357.     if (!strcmp(pszRetBuffer, "\0"))
  358.     {
  359.         EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
  360.     }
  361.  
  362. CleanUp:
  363.     if (hglbCorrectTableInfo)
  364.     {
  365.         cleanUpMemory(hglbCorrectTableInfo);
  366.     }
  367. }
  368.  
  369.  
  370.  
  371. //=====================================================================
  372. //  Function:
  373. //             BeginRestructure(HGLOBAL hglbCorrectTableInfo, pCHAR pTblDir,
  374. //                              pCHAR pTblName, int wNUMOFFIELDS,
  375. //                              pCHAR pszRetBuffer)
  376. //
  377. //  Input:
  378. //             from AddField(), DeleteField(), ModifyField(), or MoveField()
  379. //                 hglbCorrectTableInfo - handle to TableInfo struct
  380. //                 pTblDir - table directory
  381. //                 pTblName - table name
  382. //                 wNUMOFFIELDS - -1 (delete), 0 (move/modify), 1 (add)
  383. //                 pszRetBuffer - return to client
  384. //
  385. //  Return:    (pszRetBuffer) null or error string.
  386. //
  387. //  Description:
  388. //             This function allocates memory based on the new number of
  389. //             fields passed from the client, for example, Paradox.  And,
  390. //             it gets the field descriptor for an existing cursor.  The
  391. //             engine is not initialized or closed because it is in use
  392. //             by the client - Paradox for Windows.  The private directory
  393. //             has also been set by Paradox.
  394. //=====================================================================
  395. void FAR WINAPI
  396. BeginRestructure (HGLOBAL hglbCorrectTableInfo, pCHAR pTblDir, pCHAR pTblName,
  397.                   int wNUMOFFIELDS, pCHAR pszRetBuffer)
  398. {
  399.     DBIResult   rslt;
  400.     UINT16      i;                        // loop counter
  401.     CURProps    curProps;                 // table properties
  402.     struct      TBLINFO *TableInfo;       // pointer to TableInfo struct
  403.     CHAR        szTblType1[] = szPARADOX; // table type (PARADOX)
  404.     CHAR        szTblType2[] = szDBASE;   // table type (DBASE)
  405.  
  406.     // initialize return string to NULL
  407.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  408.  
  409.     // make sure we have handle to TableInfo struct
  410.     CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
  411.  
  412.     // point to TableInfo struct
  413.     TableInfo = GlobalLock (hglbCorrectTableInfo);
  414.     if (TableInfo == NULL)
  415.     {
  416.         hglbCorrectTableInfo = NULL;
  417.         GetString(1, pszRetBuffer); //"Out of Memory."
  418.         CLEANUP_NODISPLAY;
  419.     }
  420.  
  421.     // initialize TableInfo struct
  422.     TableInfo->pIdxDesc       = NULL;
  423.     TableInfo->pFldDesc       = NULL;
  424.     TableInfo->pFldDescriptor = NULL;
  425.     TableInfo->ecrFldOp       = NULL;
  426.     TableInfo->uNumFields     = 0;
  427.     TableInfo->uNewNumFields  = 0;
  428.     TableInfo->hDb            = NULL;
  429.     TableInfo->hCur           = NULL;
  430.     TableInfo->retVal         = 1;
  431.     TableInfo->bHasIndex      = 0;
  432.  
  433.     // initialize new table descriptor
  434.     memset(&TableInfo->crTblDesc, 0, sizeof(CRTblDesc));
  435.  
  436.     // set new table descriptor to table name
  437.     strcpy(TableInfo->crTblDesc.szTblName, pTblName);
  438.  
  439.     // open a database in the current session and get a database handle
  440.     CHKERR_CLEANUP(DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENEXCL,
  441.                                    NULL, 0, NULL, NULL, &TableInfo->hDb));
  442.  
  443.     // set the current directory
  444.     CHKERR_CLEANUP(DbiSetDirectory(TableInfo->hDb, pTblDir));
  445.  
  446.     // associate a cursor handle with an opened table
  447.     CHKERR_CLEANUP(DbiOpenTable(TableInfo->hDb, (pCHAR) pTblName, NULL,
  448.                                 NULL, NULL, 0, dbiREADWRITE, dbiOPENEXCL,
  449.                                 xltFIELD, FALSE, NULL, &TableInfo->hCur));
  450.  
  451.     // set field translate mode no translation
  452.     CHKERR_CLEANUP(DbiSetProp(TableInfo->hCur, curXLTMODE, xltNONE));
  453.  
  454.     // get the cursor properties for the existing table
  455.     CHKERR_CLEANUP(DbiGetCursorProps(TableInfo->hCur, &curProps));
  456.  
  457.     // if table is password protected, cancel restructure
  458.     if (curProps.bProtected)
  459.     {
  460.         GetString(12, pszRetBuffer); //"Only tables without passwords are
  461.                                  // supported."
  462.         CLEANUP_NODISPLAY;
  463.     }
  464.  
  465.     // if table is other than Paradox or dBASE, cancel restructure
  466.     if (strcmp(szTblType1, curProps.szTableType) && strcmp(szTblType2,
  467.                                                     curProps.szTableType))
  468.     {
  469.         GetString(6, pszRetBuffer); //"Only Paradox and dBASE tables are
  470.                                 // supported."
  471.         CLEANUP_NODISPLAY;
  472.     }
  473.  
  474.     // set new table descriptor to table type
  475.     strcpy(TableInfo->crTblDesc.szTblType, curProps.szTableType);
  476.  
  477.     // if table has primary key, allocate memory for existing index descriptor
  478.     if (curProps.iIndexes)
  479.     {
  480.         TableInfo->bHasIndex = 1;
  481.         TableInfo->pIdxDesc =
  482.             (IDXDesc*) malloc (curProps.iIndexes * sizeof(IDXDesc));
  483.         if (TableInfo->pIdxDesc == NULL)
  484.         {
  485.             GetString(1, pszRetBuffer); //"Out of Memory."
  486.             CLEANUP_NODISPLAY;
  487.         }
  488.     }
  489.  
  490.     // get existing number of fields
  491.     TableInfo->uNumFields = curProps.iFields;
  492.  
  493.     // get new number of fields
  494.     TableInfo->uNewNumFields = curProps.iFields + wNUMOFFIELDS;
  495.  
  496.     // allocate memory for existing field descriptor
  497.     TableInfo->pFldDesc =
  498.         (FLDDesc*) malloc (curProps.iFields * sizeof(FLDDesc));
  499.     if (TableInfo->pFldDesc == NULL)
  500.     {
  501.         GetString(1, pszRetBuffer); //"Out of Memory."
  502.         CLEANUP_NODISPLAY;
  503.     }
  504.  
  505.     // allocate memory for new field descriptor
  506.     TableInfo->pFldDescriptor =
  507.         (FLDDesc*) malloc (TableInfo->uNewNumFields * sizeof(FLDDesc));
  508.     if (TableInfo->pFldDescriptor == NULL)
  509.     {
  510.         GetString(1, pszRetBuffer); //"Out of Memory."
  511.         CLEANUP_NODISPLAY;
  512.     }
  513.  
  514.     // allocate memory for field operations array
  515.     TableInfo->ecrFldOp =
  516.         (CROpType*) malloc (TableInfo->uNewNumFields * sizeof(CROpType));
  517.     if (TableInfo->ecrFldOp == NULL)
  518.     {
  519.  
  520.         GetString(1, pszRetBuffer); //"Out of Memory."
  521.         CLEANUP_NODISPLAY;
  522.     }
  523.  
  524.     // get existing field descriptors
  525.     CHKERR_CLEANUP(DbiGetFieldDescs(TableInfo->hCur, TableInfo->pFldDesc));
  526.     CHKERR_CLEANUP(DbiSetProp(TableInfo->hCur, curXLTMODE, xltFIELD));
  527.  
  528.     // initialize new field numbers and field operations array
  529.     for (i = 0; i < TableInfo->uNewNumFields; i++)
  530.     {
  531.         TableInfo->pFldDescriptor[i].iFldNum = -1;
  532.         TableInfo->ecrFldOp[i] = NULL;
  533.     }
  534.  
  535.     TableInfo->retVal = 0;
  536.  
  537.  
  538. CleanUp:
  539.     if (hglbCorrectTableInfo)
  540.     {
  541.         GlobalUnlock(hglbCorrectTableInfo);
  542.         hglbCorrectTableInfo = NULL;
  543.     }
  544. }
  545.  
  546.  
  547.  
  548. //=====================================================================
  549. //  Function:
  550. //             SetFieldDescriptions(HGLOBAL hglbCorrectTableInfo,
  551. //                                  CROpType FieldOp, UINT16 iNewFldNum,
  552. //                                  pCHAR pOldName, pCHAR pNewName,
  553. //                                  pCHAR pFldType, UINT16 iUnits1,
  554. //                                  pCHAR pszRetBuffer)
  555. //
  556. //  Input:
  557. //             from AddField(), DeleteField(), ModifyField(), or MoveField()
  558. //                 hglbCorrectTableInfo - handle to TableInfo struct
  559. //                 FieldOp      -  crCOPY, crDROP, crADD, or crMODIFY
  560. //                 iNewFldNum   -  new position of field
  561. //                 pOldName     -  old field name
  562. //                 pNewName     -  new field name
  563. //                 pFldType     -  field type
  564. //                 iUnits1      -  field size
  565. //                 pszRetBuffer - return to client
  566. //
  567. //  Return:    (pszRetBuffer) null or error string.
  568. //
  569. //  Description:
  570. //             This function sets up the field structure for the new table.
  571. //=====================================================================
  572. void FAR WINAPI
  573. SetFieldDescriptions (HGLOBAL hglbCorrectTableInfo, CROpType FieldOp,
  574.                       UINT16 iNewFldNum, pCHAR pOldName, pCHAR pNewName,
  575.                       pCHAR pFldType, UINT16 iUnits1, pCHAR pszRetBuffer)
  576. {
  577.     UINT16      i;
  578.     UINT16      iField = 0;
  579.     UINT16      iDropped = 0;
  580.     UINT16      iCompleted= 0;
  581.     UINT16      iFieldFound = 0;
  582.     UINT16      iOrigFld;
  583.     UINT16      FieldType = 0;
  584.     struct      TBLINFO *TableInfo;
  585.  
  586.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  587.  
  588.     CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
  589.  
  590.     TableInfo = GlobalLock (hglbCorrectTableInfo);
  591.     if (TableInfo == NULL)
  592.     {
  593.         hglbCorrectTableInfo = NULL;
  594.         GetString(1, pszRetBuffer); //"Out of Memory."
  595.         CLEANUP_NODISPLAY;
  596.     }
  597.     CHKERR_NODISPLAY((TableInfo == NULL) || (TableInfo->retVal == 1))
  598.     TableInfo->retVal = 1;
  599.  
  600.     // allow any case for user input of field type
  601.     AnsiUpper(pFldType);
  602.  
  603.     // set field types for dBASE
  604.     if (!strcmp(TableInfo->crTblDesc.szTblType, szDBASE))
  605.     {
  606.         switch (pFldType[0])
  607.         {
  608.             case 'C':
  609.                 FieldType = fldDBCHAR;
  610.                 break;
  611.             case 'F':
  612.                 FieldType = fldDBFLOAT;
  613.                 break;
  614.             case 'N':
  615.                 FieldType = fldDBNUM;
  616.                 break;
  617.             case 'D':
  618.                 FieldType = fldDBDATE;
  619.                 break;
  620.             case 'L':
  621.                 FieldType = fldDBBOOL;
  622.                 break;
  623.             case 'M':
  624.                 FieldType = fldDBMEMO;
  625.                 break;
  626.             case 'O':
  627.                 FieldType = fldDBOLEBLOB;
  628.                 break;
  629.             case 'B':
  630.                 FieldType = fldDBBINARY;
  631.                 break;
  632.         }
  633.     }
  634.  
  635.     // set field types for Paradox
  636.     if (!strcmp(TableInfo->crTblDesc.szTblType, szPARADOX))
  637.     {
  638.         switch (pFldType[0])
  639.         {
  640.             case 'A':
  641.                 FieldType = fldPDXCHAR;
  642.                 break;
  643.             case 'N':
  644.                 FieldType = fldPDXNUM;
  645.                 break;
  646.             case '$':
  647.                 FieldType = fldPDXMONEY;
  648.                 break;
  649.             case 'D':
  650.                 FieldType = fldPDXDATE;
  651.                 break;
  652.             case 'S':
  653.                 FieldType = fldPDXSHORT;
  654.                 break;
  655.             case 'M':
  656.                 FieldType = fldPDXMEMO;
  657.                 break;
  658.             case 'B':
  659.                 FieldType = fldPDXBINARYBLOB;
  660.                 break;
  661.             case 'F':
  662.                 FieldType = fldPDXFMTMEMO;
  663.                 break;
  664.             case 'O':
  665.                 FieldType = fldPDXOLEBLOB;
  666.                 break;
  667.             case 'G':
  668.                 FieldType = fldPDXGRAPHIC;
  669.                 break;
  670.             case 'I':
  671.                 FieldType = fldPDXLONG;
  672.                 break;
  673.             case 'T':
  674.                 FieldType = fldPDXTIME;
  675.                 break;
  676.             case '@':
  677.                 FieldType = fldPDXDATETIME;
  678.                 break;
  679.             case 'L':
  680.                 FieldType = fldPDXBOOL;
  681.                 break;
  682.             case '+':
  683.                 FieldType = fldPDXAUTOINC;
  684.                 break;
  685.             case 'Y':
  686.                 FieldType = fldPDXBYTES;
  687.                 break;
  688.             case '#':
  689.                 FieldType = fldPDXBCD;
  690.                 break;
  691.         }
  692.     }
  693.  
  694.     // get index descriptor if a primary key exists
  695.     if (TableInfo->bHasIndex)
  696.     {
  697.         DbiGetIndexDescs(TableInfo->hCur, TableInfo->pIdxDesc);
  698.     }
  699.  
  700.     // setup in order, set field numbers to old positions.
  701.     for (i = 0; i < TableInfo->uNumFields; i++)
  702.     {
  703.  
  704.         // operation for moving fields
  705.         if (FieldOp == crCOPY)
  706.         {
  707.             // was it copied already?
  708.             if (!strcmpi(pOldName, TableInfo->pFldDesc[iNewFldNum - 1].szName))
  709.             {
  710.                 GetString(9, pszRetBuffer); //"The field was already moved."
  711.                 CLEANUP_NODISPLAY;
  712.             }
  713.  
  714.             // the existing field name is found
  715.             if (!strcmpi(TableInfo->pFldDesc[i].szName,
  716.                                    pOldName))
  717.             {
  718.  
  719.                 // the table has a primary key
  720.                 if (TableInfo->bHasIndex)
  721.                 {
  722.  
  723.                     // don't allow a copy to an existing key
  724.                     if ((((i + 1) <= TableInfo->pIdxDesc[0].iFldsInKey) ||
  725.                         (iNewFldNum <= TableInfo->pIdxDesc[0].iFldsInKey) &&
  726.                          !strcmp(TableInfo->crTblDesc.szTblType, szPARADOX)) &&
  727.                          TableInfo->pIdxDesc[0].bPrimary)
  728.                     {
  729.                         GetString(2, pszRetBuffer); //"Only modifications can
  730.                                                 // be made to primary keys."
  731.                         CLEANUP_NODISPLAY;
  732.                     }
  733.                 }
  734.  
  735.                 // is the new field number within range of the existing field
  736.                 //   descriptors?
  737.                 if (iNewFldNum < 1 || iNewFldNum > TableInfo->uNumFields)
  738.                 {
  739.                     GetString(5, pszRetBuffer); //"Invalid field descriptor."
  740.                     CLEANUP_NODISPLAY;
  741.                 }
  742.  
  743.                 // copy a field descriptor
  744.                 TableInfo->pFldDescriptor[iNewFldNum - 1] =
  745.                     TableInfo->pFldDesc[i];
  746.  
  747.                 // set field number to the old position (not to iFldNum)
  748.                 TableInfo->pFldDescriptor[iNewFldNum - 1].iFldNum = i + 1;
  749.  
  750.                 // set field operation
  751.                 TableInfo->ecrFldOp[iNewFldNum - 1] = crCOPY;
  752.  
  753.                 // done with this operation
  754.                 iFieldFound = 1;
  755.             }
  756.  
  757.             // couldn't find field name
  758.             if (i + 1 == TableInfo->uNumFields && iFieldFound == 0)
  759.             {
  760.                 GetString(5, pszRetBuffer); //"Invalid field descriptor."
  761.                 CLEANUP_NODISPLAY;
  762.             }
  763.         }
  764.  
  765.         // operation for adding fields
  766.         if (FieldOp == crADD)
  767.         {
  768.             // is the new field number out of range?
  769.             if (iNewFldNum - 1 > TableInfo->uNumFields)
  770.             {
  771.                 GetString(10, pszRetBuffer); //"The new field number is out of
  772.                                          // range."
  773.                 CLEANUP_NODISPLAY;
  774.             }
  775.  
  776.             // was the field added already?
  777.             for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
  778.                  iFieldFound++)
  779.             {
  780.                 if (!strcmpi(pOldName, TableInfo->pFldDesc[iFieldFound].szName))
  781.                 {
  782.                     GetString(4, pszRetBuffer); //"The field was already added."
  783.                     CLEANUP_NODISPLAY;
  784.  
  785.                 }
  786.             }
  787.  
  788.             if (TableInfo->bHasIndex)
  789.             {
  790.                 if (iNewFldNum <= TableInfo->pIdxDesc[0].iFldsInKey &&
  791.                     !strcmp(TableInfo->crTblDesc.szTblType, szPARADOX) &&
  792.                     TableInfo->pIdxDesc[0].bPrimary)
  793.                 {
  794.                     GetString(2, pszRetBuffer); //"Only modifications can be made
  795.                                             // to primary keys."
  796.                     CLEANUP_NODISPLAY;
  797.                 }
  798.             }
  799.  
  800.             // set field numbers to zero for added fields
  801.             TableInfo->pFldDescriptor[iNewFldNum - 1].iFldNum  = 0;
  802.  
  803.             strcpy(TableInfo->pFldDescriptor[iNewFldNum - 1]
  804.                                              .szName, pOldName);
  805.             TableInfo->pFldDescriptor[iNewFldNum - 1].iFldType = FieldType;
  806.             TableInfo->pFldDescriptor[iNewFldNum - 1].iSubType = 0;
  807.             TableInfo->pFldDescriptor[iNewFldNum - 1].iUnits1  = iUnits1;
  808.             TableInfo->pFldDescriptor[iNewFldNum - 1].iUnits2  = 0;
  809.             TableInfo->pFldDescriptor[iNewFldNum - 1].iOffset  = 0;
  810.             TableInfo->pFldDescriptor[iNewFldNum - 1].iLen     = 0;
  811.             TableInfo->pFldDescriptor[iNewFldNum - 1].iNullOffset = 0;
  812.             TableInfo->pFldDescriptor[iNewFldNum - 1].efldvVchk   =
  813.                                                       fldvNOCHECKS;
  814.             TableInfo->pFldDescriptor[iNewFldNum - 1].efldrRights =
  815.                                                       fldrREADWRITE;
  816.             TableInfo->ecrFldOp[iNewFldNum - 1] = crADD;
  817.         }
  818.  
  819.         // operation for modifying field names, types, or sizes
  820.         if (FieldOp == crMODIFY)
  821.         {
  822.  
  823.             // quit loop if this operation is finished
  824.             if (iCompleted == 1)
  825.             {
  826.                 break;
  827.             }
  828.  
  829.             for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
  830.                  iFieldFound++)
  831.             {
  832.                 if (!strcmpi(pOldName, TableInfo->pFldDesc[iFieldFound].szName))
  833.                 {
  834.                     TableInfo->pFldDescriptor[iFieldFound] =
  835.                           TableInfo->pFldDesc[iFieldFound];
  836.                     TableInfo->pFldDescriptor[iFieldFound].iFldNum =
  837.                                                            iFieldFound + 1;
  838.                     strcpy(TableInfo->pFldDescriptor[iFieldFound].szName,
  839.                                                                   pNewName);
  840.                     TableInfo->pFldDescriptor[iFieldFound].iFldType = FieldType;
  841.                     TableInfo->pFldDescriptor[iFieldFound].iSubType = 0;
  842.                     TableInfo->pFldDescriptor[iFieldFound].iUnits1 = iUnits1;
  843.                     TableInfo->pFldDescriptor[iFieldFound].iUnits2  = 0;
  844.                     TableInfo->pFldDescriptor[iFieldFound].iOffset  = 0;
  845.                     TableInfo->pFldDescriptor[iFieldFound].iLen     = 0;
  846.                     TableInfo->pFldDescriptor[iFieldFound].iNullOffset = 0;
  847.                     TableInfo->pFldDescriptor[iFieldFound].efldvVchk   =
  848.                                                               fldvNOCHECKS;
  849.                     TableInfo->pFldDescriptor[iFieldFound].efldrRights =
  850.                                                               fldrREADWRITE;
  851.                     TableInfo->ecrFldOp[iFieldFound] = crMODIFY;
  852.                     iCompleted = 1;
  853.                     break;
  854.                 }
  855.                 if (iFieldFound + 1 == TableInfo->uNumFields)
  856.                 {
  857.                     GetString(7, pszRetBuffer); //"The field name can't be found."
  858.                     CLEANUP_NODISPLAY;
  859.                 }
  860.             }
  861.         }
  862.  
  863.         // operation for deleting fields - deletes by skipping a field
  864.         //   descriptor copy
  865.         // does nothing except check if field was already dropped
  866.         if (FieldOp == crDROP)
  867.         {
  868.             // was it dropped already?
  869.             for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
  870.                  iFieldFound++)
  871.             {
  872.                 if (!strcmpi(TableInfo->pFldDesc[iFieldFound].szName, pOldName))
  873.                 {
  874.                     if (TableInfo->bHasIndex)
  875.                     {
  876.                         if ((iFieldFound + 1) <= TableInfo->pIdxDesc[0].
  877.                              iFldsInKey && !strcmp(TableInfo->crTblDesc.
  878.                              szTblType, szPARADOX)&& TableInfo->pIdxDesc[0].
  879.                              bPrimary)
  880.                         {
  881.                             GetString(2, pszRetBuffer); //"Only modifications can
  882.                                                     // be made to primary keys."
  883.                             CLEANUP_NODISPLAY;
  884.                         }
  885.                     }
  886.                     iDropped = 1;
  887.                 }
  888.  
  889.                 if ((iFieldFound + 1 == TableInfo->uNumFields) && iDropped == 0)
  890.                 {
  891.                     GetString(8, pszRetBuffer); //"The field was already deleted."
  892.                     CLEANUP_NODISPLAY;
  893.                 }
  894.             }
  895.         }
  896.     }
  897.  
  898.     // fill in blank field descriptors
  899.     for (i = 0; i < TableInfo->uNewNumFields; i++)
  900.     {
  901.  
  902.         // check for blank field (preassigned -1u - max of possible ranges)
  903.         if (TableInfo->pFldDescriptor[i].iFldNum == -1u)
  904.         {
  905.             for (iOrigFld = iField; iOrigFld < TableInfo->uNumFields;
  906.                  iOrigFld++)
  907.             {
  908.                 iField++;
  909.                 if (strcmpi(TableInfo->pFldDesc[iOrigFld].szName, pOldName))
  910.                 {
  911.                     TableInfo->pFldDescriptor[i] =
  912.                         TableInfo->pFldDesc[iOrigFld];
  913.  
  914.                     // set field number to the old position (not the iFldNum)
  915.                     TableInfo->pFldDescriptor[i].iFldNum = iOrigFld + 1;
  916.                     TableInfo->ecrFldOp[i] = crCOPY;
  917.                     break;
  918.                 }
  919.             }
  920.         }
  921.     }
  922.     TableInfo->retVal = 0;
  923.  
  924. CleanUp:
  925.     if (hglbCorrectTableInfo)
  926.     {
  927.         GlobalUnlock(hglbCorrectTableInfo);
  928.         hglbCorrectTableInfo = NULL;
  929.     }
  930. }
  931.  
  932.  
  933.  
  934. //=====================================================================
  935. //  Function:
  936. //             EndRestructure(HGLOBAL hglbCorrectTableInfo, pCHAR pPack,
  937. //                            pCHAR pszRetBuffer)
  938. //
  939. //  Input:
  940. //             from AddField(), DeleteField(), ModifyField(), or MoveField()
  941. //                 hglbCorrectTableInfo - handle to TableInfo struct
  942. //                 pPack                - "PACK" or "NOPACK"
  943. //                 pCHAR pszRetBuffer   - return to client
  944. //
  945. //  Return:    null or error string.
  946. //
  947. //  Description:
  948. //             This function gets creates a new table descriptor image
  949. //             and calls IDAPI to do the actual restructure.
  950. //=====================================================================
  951. void FAR WINAPI
  952. EndRestructure (HGLOBAL hglbCorrectTableInfo, pCHAR pPack,
  953.                 pCHAR pszRetBuffer)
  954. {
  955.     DBIResult   rslt;
  956.     DBIPATH     szKeyViol;
  957.     struct      TBLINFO *TableInfo;
  958.  
  959.     GetString(11, szKeyViol); // Key violation table name
  960.     memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
  961.  
  962.     CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
  963.  
  964.     TableInfo = GlobalLock (hglbCorrectTableInfo);
  965.     if (TableInfo == NULL)
  966.     {
  967.         hglbCorrectTableInfo = NULL;
  968.         GetString(1, pszRetBuffer); //"Out of Memory."
  969.         CLEANUP_NODISPLAY;
  970.     }
  971.     CHKERR_NODISPLAY((TableInfo == NULL) || (TableInfo->retVal == 1))
  972.     TableInfo->retVal = 1;
  973.  
  974.     // allow any case for user input of pack operation
  975.     AnsiUpper(pPack);
  976.  
  977.     // set default to no table pack
  978.     TableInfo->crTblDesc.bPack = FALSE;
  979.  
  980.     if (!strcmpi(pPack, "PACK"))
  981.     {
  982.         TableInfo->crTblDesc.bPack = TRUE;
  983.     }
  984.  
  985.     if (!strcmpi(pPack, "NOPACK"))
  986.     {
  987.         TableInfo->crTblDesc.bPack = FALSE;
  988.     }
  989.  
  990.     // copy information to new table descriptor
  991.     TableInfo->crTblDesc.iFldCount = TableInfo->uNewNumFields;
  992.     TableInfo->crTblDesc.pecrFldOp = TableInfo->ecrFldOp;
  993.     TableInfo->crTblDesc.pfldDesc  = TableInfo->pFldDescriptor;
  994.  
  995.     // allows DbiDoRestructure to get an exclusive lock on the table
  996.     CHKERR_CLEANUP(DbiCloseCursor(&TableInfo->hCur));
  997.     TableInfo->hCur = NULL;
  998.  
  999.     // call to BDE to restructure the table
  1000.     CHKERR_CLEANUP(DbiDoRestructure(TableInfo->hDb, 1, &TableInfo->crTblDesc,
  1001.                    NULL, szKeyViol, NULL, FALSE));
  1002.  
  1003.     TableInfo->retVal = 0;
  1004.  
  1005. CleanUp:
  1006.     if (hglbCorrectTableInfo)
  1007.     {
  1008.         GlobalUnlock(hglbCorrectTableInfo);
  1009.         hglbCorrectTableInfo = NULL;
  1010.     }
  1011.     if (!strcmp(pszRetBuffer, "\0"))
  1012.     {
  1013.         GetString(13, pszRetBuffer); // "Restructure successful."
  1014.     }
  1015. }
  1016.  
  1017.  
  1018.  
  1019. //=====================================================================
  1020. //  Function:
  1021. //             DBIError(HGLOBAL hglbCorrectTableInfo, DBIResult retVal,
  1022. //                      pCHAR pszRetBuffer)
  1023. //
  1024. //  Input:
  1025. //             from macro.h:
  1026. //                 hglbCorrectTableInfo - handle to TableInfo struct
  1027. //                 retVal               - BDE return
  1028. //                 pszRetBuffer         - Buffer to contain the error string
  1029. //
  1030. //  Return:    a DBIResult value.
  1031. //
  1032. //  Description:
  1033. //             This function gets information of where an error occurred.
  1034. //=====================================================================
  1035. DBIResult
  1036. DBIError (HGLOBAL hglbCorrectTableInfo, DBIResult retVal, pCHAR pszRetBuffer)
  1037. {
  1038.     struct      TBLINFO *TableInfo;
  1039.  
  1040.     if (retVal == DBIERR_NONE)
  1041.     {
  1042.         return retVal;
  1043.     }
  1044.  
  1045.     CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL)
  1046.  
  1047.     TableInfo = GlobalLock (hglbCorrectTableInfo);
  1048.     if (TableInfo == NULL)
  1049.     {
  1050.         hglbCorrectTableInfo = NULL;
  1051.         CLEANUP_NODISPLAY;
  1052.     }
  1053.  
  1054.     if (retVal == DBIERR_CANTFINDODAPI)
  1055.     {
  1056.         GetString(3, pszRetBuffer); //"Cannot find IDAPI files: Check path."
  1057.         CLEANUP_DISPLAYERR(pszRetBuffer);
  1058.     }
  1059.     else
  1060.     {
  1061.         DbiGetErrorString(retVal, pszRetBuffer);
  1062.     }
  1063.  
  1064. CleanUp:
  1065.     if (hglbCorrectTableInfo)
  1066.     {
  1067.         GlobalUnlock(hglbCorrectTableInfo);
  1068.         hglbCorrectTableInfo = NULL;
  1069.     }
  1070.     return retVal;
  1071. }
  1072.  
  1073.  
  1074. //=====================================================================
  1075. //  Function:
  1076. //             cleanUpMemory(HGLOBAL hglbCorrectTableInfo);
  1077. //
  1078. //  Description:
  1079. //             Free all allocations, cursors, and tables if needed.
  1080. //=====================================================================
  1081. void
  1082. cleanUpMemory (HGLOBAL hglbCorrectTableInfo)
  1083. {
  1084.     UINT16  i;
  1085.     struct  TBLINFO *TableInfo;
  1086.  
  1087.     CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
  1088.  
  1089.     TableInfo = GlobalLock (hglbCorrectTableInfo);
  1090.     if (TableInfo == NULL)
  1091.     {
  1092.         hglbCorrectTableInfo = NULL;
  1093.         CLEANUP_NODISPLAY;
  1094.     }
  1095.  
  1096.     if (hglbCorrectTableInfo)
  1097.     {
  1098.         if (TableInfo->hCur)
  1099.         {
  1100.             DbiCloseCursor(&TableInfo->hCur);
  1101.         }
  1102.  
  1103.         if (TableInfo->hDb)
  1104.         {
  1105.             DbiCloseDatabase(&TableInfo->hDb);
  1106.         }
  1107.  
  1108.         if (TableInfo->ecrFldOp)
  1109.         {
  1110.             free(TableInfo->ecrFldOp);
  1111.         }
  1112.  
  1113.         if (TableInfo->pIdxDesc)
  1114.         {
  1115.             free(TableInfo->pIdxDesc);
  1116.         }
  1117.  
  1118.         if (TableInfo->pFldDescriptor)
  1119.         {
  1120.             free(TableInfo->pFldDescriptor);
  1121.         }
  1122.  
  1123.         if (TableInfo->pFldDesc)
  1124.         {
  1125.             free(TableInfo->pFldDesc);
  1126.         }
  1127.  
  1128.         //decrement lock count to 0.
  1129.         for (i = GlobalFlags(hglbCorrectTableInfo); i > 0; i--)
  1130.         {
  1131.             GlobalUnlock(hglbCorrectTableInfo);
  1132.         }
  1133.         GlobalFree(hglbCorrectTableInfo);
  1134.  
  1135. CleanUp:
  1136.  
  1137.     }
  1138. }
  1139.  
  1140.  
  1141.  
  1142. //=====================================================================
  1143. //  Function:
  1144. //              GetString(WORD iStringID, pCHAR pszRetBuffer)
  1145. //
  1146. //  Input:
  1147. //              iStringID   - Identifier for the string
  1148. //              pszBuffer   - Buffer to contain the error string.
  1149. //                            (Allocated by the calling function)
  1150. //
  1151. //  Description:
  1152. //             Load a string from STRUCTER.DLL.
  1153. //=====================================================================
  1154. void
  1155. GetString (WORD iStringID, pCHAR pszRetBuffer)
  1156. {
  1157.     if (pszRetBuffer)
  1158.     {
  1159.         LoadString(GetModuleHandle(szCURRENTMODULE), iStringID, pszRetBuffer,
  1160.                    DBIMAXMSGLEN - 1);
  1161.     }
  1162. }
  1163.  
  1164.  
  1165.  
  1166. #pragma argsused
  1167. BOOL WINAPI
  1168. LibMain (HINSTANCE hInstance, WORD wDataSeg,
  1169.          WORD cbHeapSize, LPSTR lpCmdLine) {
  1170.     if (cbHeapSize != 0)
  1171.     {
  1172.         UnlockData(0);
  1173.     }
  1174.     return TRUE;
  1175. }
  1176.  
  1177. int WINAPI
  1178. WEP (int nSystemExit) {
  1179.     switch (nSystemExit) {
  1180.         case WEP_SYSTEM_EXIT:
  1181.             break;
  1182.         case WEP_FREE_DLL:
  1183.             break;
  1184.     }
  1185.     return 1;
  1186. }
  1187.  
  1188.