home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / repease / util.c < prev    next >
C/C++ Source or Header  |  1994-12-12  |  21KB  |  690 lines

  1. /******************************************************************************
  2.     UTIL.C
  3.     Sub Systems, Inc.
  4.     Copyright (c) 1992, Sub Systems, Inc. All Rights Reserved.
  5.     159 Main Street, #8C, Stoneham,  MA 02180, (617) 438-8901.
  6.     
  7.     FileSort and FileJoin Utilities
  8.  
  9.     This file is used only by the demo program.  This file is not needed
  10.     by the ReportEase Plus DLL.
  11.  
  12. ******************************************************************************/
  13.  
  14. #include "windows.h"
  15. #include "stdio.h"
  16. #include "stdlib.h"
  17. #include "ctype.h"
  18. #include "dos.h"
  19. #include "fcntl.h"
  20. #include "io.h"
  21. #include "signal.h"
  22. #include "string.h"
  23. #include "time.h"
  24.  
  25. /*****************************************************************************
  26.    Compiler specific include files and library translations
  27. ******************************************************************************/
  28. #if defined(__TURBOC__)
  29.    #include "alloc.h"
  30.    #include "dir.h"
  31.    #include "string.h"
  32.    #include "mem.h"
  33.    #define _memavl coreleft
  34.    #define _makepath fnmerge
  35.    #define _splitpath fnsplit
  36. #else
  37.    #include "string.h"
  38.    #include "malloc.h"
  39.    #include "memory.h"
  40. #endif
  41.  
  42. /******************************************************************************
  43.     WIN32 specific defines
  44. *******************************************************************************/
  45. #if defined (_WIN32)
  46.    #if !defined(WIN32)
  47.      #define WIN32
  48.    #endif
  49. #endif
  50. #if defined (WIN32)
  51.    #define huge
  52.    #define _export
  53. #else
  54.    #define huge huge 
  55. #endif
  56.  
  57. #include "util.h"
  58.  
  59. /******************************************************************************
  60.    Necessary Prototypes
  61. *******************************************************************************/
  62. int     JoinArrayMem(void);
  63. int     JoinExtractCommonField(struct StrJoinRec far *,int,int);
  64. int     JoinFreeMem(struct StrJoinRec far *,int);
  65. int     JoinReadFile(LPSTR,struct StrJoinRec far *);
  66. int     JoinWriteFile(LPSTR);
  67.  
  68. int     SortArrayMem(int);
  69. int     SortBuildKeys(void);
  70. int     SortReadFile(LPSTR);
  71. int     SortDoSort(void);
  72. int     SortWriteFile(LPSTR);
  73.  
  74. int     FileLines(LPSTR);
  75. int     ExtractField(LPSTR,int far *,int,char far *);
  76. void far *OurAlloc(long);
  77. void    OurFree(void far *); 
  78. int     ltrm(LPSTR);
  79. int     rtrm(LPSTR);
  80. int     strtrm(LPSTR);
  81.  
  82. /******************************************************************************
  83.    Define statements
  84. *******************************************************************************/
  85. #define TRUE 1
  86. #define FALSE 0
  87.  
  88. /******************************************************************************
  89.    Global Variables
  90. *******************************************************************************/
  91. struct StrJoinRec {
  92.        char far *rec;             /* record pointer */
  93.        char far *field;           /* common field */
  94.        } far *file1,far *file2;
  95.  
  96. struct StrSortRec {
  97.        char far *rec;                 /* record pointer */
  98.        char far *key;                 /* key pointer */
  99.        } far *item;
  100.  
  101. int TotalLines,TotalLines1,TotalLines2,key[10],TotalKeys;
  102. char SortKey[10][80];
  103.  
  104. /******************************************************************************
  105.    Main routine.
  106. *******************************************************************************/
  107. int WINAPI _export FileJoin(LPSTR InputFile1,int field1,LPSTR InputFile2, int field2, LPSTR OutputFile)
  108. {
  109.  
  110.     TotalLines1=FileLines(InputFile1);  /* find total number of lines in file1 */
  111.     TotalLines2=FileLines(InputFile2);  /* find total number of lines in file2 */
  112.  
  113.     if (TotalLines1<0 || TotalLines2<0) return FALSE;
  114.  
  115.     if (!JoinArrayMem()) return FALSE;      /* allocate memory for the line arrays */
  116.  
  117.     if (!JoinReadFile(InputFile1,file1)) return FALSE;     /* read the input file1 */
  118.     if (!JoinReadFile(InputFile2,file2)) return FALSE;     /* read the input file2 */
  119.  
  120.     if (!JoinExtractCommonField(file1,TotalLines1,field1)) return FALSE;      /* extract the common field for file 1*/
  121.     if (!JoinExtractCommonField(file2,TotalLines2,field2)) return FALSE;      /* extract the common field for file 2*/
  122.  
  123.     if (!JoinWriteFile(OutputFile)) return FALSE;          /* write the output file */
  124.  
  125.     if (!JoinFreeMem(file1,TotalLines1)) return FALSE;     // freeup memory
  126.     if (!JoinFreeMem(file2,TotalLines2)) return FALSE;
  127.  
  128.     return TRUE;
  129. }
  130.  
  131. /*****************************************************************************
  132.     WEP:
  133.     Library exit routine.
  134. ******************************************************************************/
  135. CALLBACK _export WEP(int nParameter)
  136. {
  137.     return 1;
  138. }
  139.  
  140. /****************************************************************************
  141.     JoinArrayMem:
  142.     Allocate memory for the line array.
  143. *****************************************************************************/
  144. JoinArrayMem() 
  145. {
  146.    
  147.     file1=(struct StrJoinRec far *) OurAlloc(((long)TotalLines1+1)*(long)sizeof(struct StrJoinRec));
  148.     file2=(struct StrJoinRec far *) OurAlloc(((long)TotalLines2+1)*(long)sizeof(struct StrJoinRec));
  149.     if (file1==NULL || file2==NULL) {
  150.        MessageBox(NULL,"Out of RAM for file pointers","JOIN",MB_OK);return FALSE;
  151.     }
  152.     return TRUE;
  153. }
  154.  
  155. /*****************************************************************************
  156.     JoinReadFile:
  157.     Read the file into memory.
  158. *****************************************************************************/
  159. JoinReadFile(LPSTR FileName,struct StrJoinRec far *item)
  160. {
  161.  
  162.     char line[250];
  163.     LPSTR result;
  164.     int i=0;
  165.     FILE far *iStream;
  166.  
  167.     if (NULL==(iStream=fopen(FileName,"rt"))) {
  168.        wsprintf(line,"Can not open the input file %s",(LPSTR)FileName);
  169.        MessageBox(NULL,line,"JOIN",MB_OK);
  170.        return FALSE;
  171.     }
  172.  
  173.  
  174.     NEXT_LINE:
  175.     result=fgets(line,250,iStream);
  176.     if (ferror(iStream)) {
  177.         wsprintf(line,"Error in reading the file: %s",(LPSTR)FileName);
  178.         MessageBox(NULL,line,"JOIN",MB_OK);
  179.         return FALSE;
  180.     }
  181.     
  182.     if (feof(iStream))  goto END_FILE;
  183.     
  184.     if (result==NULL) {
  185.         wsprintf(line,"Error in reading file: %s",(LPSTR)FileName);
  186.         MessageBox(NULL,line,"JOIN",MB_OK);
  187.         return FALSE;
  188.     }
  189.  
  190.     if (NULL==(item[i].rec=OurAlloc(lstrlen(line)+1))) {
  191.        MessageBox(NULL,"Cannot load the file, out of memory\n","JOIN",MB_OK);return FALSE;
  192.     }
  193.  
  194.     lstrcpy(item[i].rec,line);
  195.  
  196.     i++;
  197.  
  198.     goto NEXT_LINE;
  199.  
  200.     END_FILE:
  201.     fclose(iStream);
  202.     
  203.     return TRUE;
  204. }
  205.  
  206. /*****************************************************************************
  207.     JoinFreeMem:
  208.     Free up memory used by a file
  209. *****************************************************************************/
  210. JoinFreeMem(struct StrJoinRec far *item, int TotalLines)
  211. {
  212.     int i;
  213.  
  214.     for (i=0;i<TotalLines;i++) {
  215.        OurFree(item[i].rec);
  216.        OurFree(item[i].field);
  217.     }
  218.     OurFree(item);
  219.  
  220.     return TRUE;
  221. }
  222.  
  223. /*****************************************************************************
  224.     JoinExtractCommonField:
  225.     Extract the common field from the file records
  226. *****************************************************************************/
  227. JoinExtractCommonField(struct StrJoinRec far *file,int TotalLines,int fld)
  228. {
  229.     int line,LineIdx,CurLen,FieldNo;
  230.     char CurKey[240],KeyFound;
  231.  
  232.  
  233.     for (line=0;line<TotalLines;line++) { /* process each line */
  234.          
  235.          LineIdx=0;                       /* prepare to scan the line */
  236.          CurLen=lstrlen(file[line].rec);
  237.          if (CurLen>0 && file[line].rec[CurLen-1]==0xA) CurLen--;
  238.          KeyFound=FALSE;
  239.          FieldNo=1;
  240.  
  241.          while (TRUE) {
  242.             /* extract the fields */
  243.             if (!ExtractField(file[line].rec,&LineIdx,CurLen,CurKey)) break;
  244.             if (fld==FieldNo) {
  245.                KeyFound=TRUE;
  246.                break;
  247.             }
  248.             FieldNo++;
  249.          }
  250.          if (!KeyFound) {
  251.             wsprintf(CurKey,"Common field not found in record number: %d",line+1);
  252.             MessageBox(NULL,CurKey,NULL,MB_OK);
  253.             return FALSE;
  254.          }
  255.          
  256.          /* build the full key */
  257.          if (NULL==(file[line].field=OurAlloc(lstrlen(CurKey)+1))) {
  258.             MessageBox(NULL,"Out of Memory during Key Build","JOIN",MB_OK);return FALSE;
  259.          }
  260.  
  261.          lstrcpy(file[line].field,CurKey);
  262.     }
  263.     return TRUE;
  264. }
  265.  
  266. /******************************************************************************
  267.    FileSort:
  268.    Main Sort routine.
  269. *****************************************************************************/
  270. int WINAPI _export FileSort(LPSTR InputFile, int NumKeys, LPINT KeyTable)
  271. {
  272.  
  273.     int i;
  274.  
  275.  
  276.     // save the sort keys
  277.     TotalKeys=NumKeys;
  278.     for (i=0;i<TotalKeys;i++) key[i]=KeyTable[i];
  279.  
  280.     TotalLines=FileLines(InputFile);/* find total number of lines in the file */
  281.     if (TotalLines<0) return FALSE;
  282.  
  283.     if (!SortArrayMem(TotalLines)) return FALSE;       /* allocate memory for the line arrays */
  284.  
  285.     if (!SortReadFile(InputFile)) return FALSE;        /* read the input file */
  286.  
  287.     if (!SortBuildKeys()) return FALSE;                /* build keys */
  288.  
  289.     if (!SortDoSort()) return FALSE;                 /* sort the file in the memory */
  290.     
  291.     if (!SortWriteFile(InputFile)) return FALSE;                 /* write the output file */
  292.  
  293.     return TRUE;
  294. }
  295.  
  296. /****************************************************************************
  297.     SortArrayMem:
  298.     Allocate memory for the line array.
  299. *****************************************************************************/
  300. SortArrayMem(int TotalLines) 
  301. {
  302.    
  303.     item=(struct StrSortRec far *)OurAlloc(((long)TotalLines+1)*(long)sizeof(struct StrSortRec));
  304.     if (item==NULL) {
  305.        MessageBox(NULL,"Out of RAM for file pointers","SORT",MB_OK);return FALSE;
  306.     }
  307.     return TRUE;
  308. }
  309.  
  310. /*****************************************************************************
  311.     SortReadFile:
  312.     Read the file into memory.
  313. *****************************************************************************/
  314. SortReadFile(LPSTR InputFile)
  315. {
  316.  
  317.     char line[250],far *result;
  318.     int i=0;
  319.     FILE far *iStream;
  320.  
  321.     if (NULL==(iStream=fopen(InputFile,"rt"))) {
  322.        wsprintf(line,"Can not open the input file %s",(LPSTR)InputFile);
  323.        MessageBox(NULL,line,"SORT",MB_OK);
  324.        return FALSE;
  325.     }
  326.  
  327.  
  328.     NEXT_LINE:
  329.     result=fgets(line,250,iStream);
  330.     if (ferror(iStream)) {
  331.         wsprintf(line,"Error in reading the file: %s",(LPSTR)InputFile);
  332.         MessageBox(NULL,line,"SORT",MB_OK);
  333.         return FALSE;
  334.     }
  335.     
  336.     if (feof(iStream))  goto END_FILE;
  337.     
  338.     if (result==NULL) {
  339.         wsprintf(line,"Error in reading file: %s",(LPSTR)InputFile);
  340.         MessageBox(NULL,line,"SORT",MB_OK);
  341.         return FALSE;
  342.     }
  343.  
  344.     if (NULL==(item[i].rec=OurAlloc(strlen(line)+1))) {
  345.        MessageBox(NULL,"Cannot load the file, out of memory\n","SORT",MB_OK);return FALSE;
  346.     }
  347.  
  348.     lstrcpy(item[i].rec,line);
  349.  
  350.     i++;
  351.  
  352.     goto NEXT_LINE;
  353.  
  354.     END_FILE:
  355.     fclose(iStream);
  356.     
  357.     return TRUE;
  358. }
  359.  
  360. /*****************************************************************************
  361.     SortBuildKeys:
  362.     Build a key for each record line.
  363. *****************************************************************************/
  364. SortBuildKeys()
  365. {
  366.     int line,LineIdx,CurLen,i,FieldNo;
  367.     char KeyString[240],CurKey[240],KeysFound;
  368.  
  369.  
  370.     for (line=0;line<TotalLines;line++) { /* process each line */
  371.          
  372.          LineIdx=0;                       /* prepare to scan the line */
  373.          CurLen=lstrlen(item[line].rec);
  374.          if (CurLen>0 && item[line].rec[CurLen-1]==0xA) CurLen--;
  375.          KeysFound=0;
  376.          FieldNo=1;
  377.          for (i=0;i<TotalKeys;i++) SortKey[0][0]=0;
  378.  
  379.          while (TRUE) {
  380.             /* extract the fields */
  381.             if (!ExtractField(item[line].rec,&LineIdx,CurLen,CurKey)) break;
  382.             for (i=0;i<TotalKeys;i++) {
  383.                if (key[i]==FieldNo) {
  384.                   strcpy(SortKey[i],CurKey);
  385.                   KeysFound++;
  386.                }
  387.             }
  388.             FieldNo++;
  389.          }
  390.          if (KeysFound!=TotalKeys) {
  391.             wsprintf(KeyString,"Sort key %d not found in record number: %d",key[KeysFound],line+1);
  392.             MessageBox(NULL,KeyString,"SORT",MB_OK);
  393.             return FALSE;
  394.          }
  395.          
  396.          /* build the full key */
  397.          KeyString[0]=0;
  398.          for (i=0;i<TotalKeys;i++) strcat(KeyString,SortKey[i]);
  399.          
  400.          if (NULL==(item[line].key=OurAlloc(strlen(KeyString)+1))) {
  401.             MessageBox(NULL,"Out of Memory during Key Build","SORT",MB_OK);return FALSE;
  402.          }
  403.  
  404.          lstrcpy(item[line].key,KeyString);
  405.     }
  406.     return TRUE;
  407. }
  408.  
  409. /*****************************************************************************
  410.     SortDoSort:
  411.     Sort the file in the memory
  412. *****************************************************************************/
  413. SortDoSort()
  414. {
  415.     int i,j,SmallRecIdx;
  416.     struct StrSortRec TempItem;
  417.  
  418.     for (i=0;i<TotalLines;i++) {
  419.        SmallRecIdx=i;
  420.        for(j=i;j<TotalLines;j++) {
  421.           if (lstrcmp(item[j].key,item[SmallRecIdx].key)<0) SmallRecIdx=j;
  422.        }
  423.        if (SmallRecIdx!=i) {    /* exchange the words */
  424.            TempItem=item[i];
  425.            item[i]=item[SmallRecIdx];
  426.            item[SmallRecIdx]=TempItem;
  427.        }
  428.     }
  429.  
  430.     return TRUE;
  431. }
  432.  
  433. /*****************************************************************************
  434.     SortWriteFile:
  435.     write the output file
  436. *****************************************************************************/
  437. SortWriteFile(LPSTR InputFile)
  438. {
  439.     FILE far *oStream;
  440.     int i;
  441.     char OutputFile[128],string[300];
  442.  
  443.     for (i=0;i<129 && InputFile[i]!='.' && InputFile[i]!='\0';i++) OutputFile[i]=InputFile[i];
  444.     OutputFile[i]=0;
  445.     strcat(OutputFile,".SRT");
  446.  
  447.  
  448.     unlink(OutputFile);
  449.     if (NULL==(oStream=fopen(OutputFile,"wt"))) {
  450.        wsprintf(string,"Can not open the output file %s",(LPSTR)OutputFile);
  451.        MessageBox(NULL,string,"SORT",MB_OK);
  452.        return FALSE; 
  453.     }
  454.  
  455.     for (i=0;i<TotalLines;i++) {
  456.        lstrcpy(string,item[i].rec);
  457.        fputs(string,oStream);
  458.     }
  459.  
  460.     fclose(oStream);
  461.  
  462.     return TRUE;
  463. }
  464.  
  465. /*****************************************************************************
  466.     FileLines:
  467.     find total number of lines in the file.
  468. *****************************************************************************/
  469. FileLines(LPSTR FileName)
  470. {
  471.     char line[250];
  472.     LPSTR result;
  473.     int TotalLines=0;
  474.     FILE far *iStream;
  475.  
  476.  
  477.     if (NULL==(iStream=fopen(FileName,"rt"))) {
  478.        wsprintf(line,"Can not open the input file %s",(LPSTR)FileName);
  479.        MessageBox(NULL,line,"JOIN",MB_OK);
  480.        return -1;
  481.     }
  482.  
  483.     NEXT_LINE:
  484.     result=fgets(line,250,iStream);
  485.     if (ferror(iStream)) {
  486.         wsprintf(line,"Error in reading the file: %s",(LPSTR)FileName);
  487.         MessageBox(NULL,line,"JOIN",MB_OK);
  488.         return -1;
  489.     }
  490.     
  491.     if (feof(iStream))  goto END_FILE;
  492.     
  493.     if (result==NULL) {
  494.         wsprintf(line,"Error in reading file: %s",(LPSTR)FileName);
  495.         MessageBox(NULL,line,"JOIN",MB_OK);
  496.         return -1;
  497.     }
  498.     TotalLines++;
  499.  
  500.     if (TotalLines>30000) {
  501.         MessageBox(NULL,"Cannot sort this file larger than 30000 lines.","JOIN",MB_OK);
  502.         return -1;
  503.     }
  504.     
  505.     goto NEXT_LINE;
  506.  
  507.     END_FILE:
  508.     fclose(iStream);
  509.     
  510.     return TotalLines;
  511. }
  512.  
  513. /******************************************************************************
  514.     ExtractField:
  515.     This routine scans a text line to extract the next field.
  516.     The fields are assumed to be of character type.
  517. ******************************************************************************/
  518. ExtractField(LPSTR line,int far *idx,int LineLen,char far *CharReturn)
  519. {
  520.     char quote='"',string[240],far *ptr,SaveChar;
  521.     int  i,j,k;
  522.  
  523.     i=(*idx);
  524.     while (i<LineLen && line[i]==' ') i++;  /* go past the spaces */
  525.  
  526.     if (i>=LineLen) return FALSE;           /* past the end of the line */
  527.  
  528.     if (line[i]==quote) {
  529.        i++;                                 /* skip over the first quote */
  530.        
  531.        for (k=i;k<LineLen;k++) if (line[k]==quote) break;
  532.  
  533.        if (k==LineLen) return FALSE;
  534.  
  535.        ptr=&line[k];
  536.        
  537.        j=1;
  538.        while (ptr[j]!=',' && ptr[j]!=0) j++;/* locate the next comma */
  539.        
  540.        SaveChar=ptr[0];                     /* extract the string */
  541.        ptr[0]=0;        
  542.        lstrcpy(string,&line[i]);
  543.        ptr[0]=SaveChar;
  544.        (*idx)=i+lstrlen(string)+1+j;         /* index to the next field */       
  545.     }
  546.     else {
  547.        for (k=i;k<LineLen;k++) if (line[k]==',') break;
  548.  
  549.        if (k==LineLen) ptr=&line[LineLen];
  550.        else ptr=&line[k];
  551.  
  552.        SaveChar=ptr[0];                     /* extract the string */
  553.        ptr[0]=0;        
  554.        lstrcpy(string,&line[i]);
  555.        ptr[0]=SaveChar;
  556.        (*idx)=i+lstrlen(string)+1;           /* index to the next field */       
  557.     }
  558.  
  559.     lstrcpy(CharReturn,string);
  560.     return TRUE;
  561. }
  562.  
  563. /*****************************************************************************
  564.     JoinWriteFile:
  565.     write the output file
  566. *****************************************************************************/
  567. JoinWriteFile(LPSTR OutputFile)
  568. {
  569.     FILE far *oStream;
  570.     int i,j,CurLen;
  571.     char line[500];
  572.  
  573.     unlink(OutputFile);
  574.     if (NULL==(oStream=fopen(OutputFile,"wt"))) {
  575.        wsprintf(line,"Can not open the output file %s",(LPSTR)OutputFile);
  576.        MessageBox(NULL,line,"JOIN",MB_OK);
  577.        return FALSE; 
  578.     }
  579.  
  580.     for (i=0;i<TotalLines1;i++) {        /* process each line of the primary file */
  581.        for(j=0;j<TotalLines2;j++) {      /* match with the secondary file */
  582.           if (lstrcmp(file1[i].field,file2[j].field)==0) {
  583.              lstrcpy(line,file1[i].rec);
  584.              CurLen=lstrlen(line);
  585.              if (CurLen>0 && line[CurLen-1]==0xA) CurLen--;
  586.              line[CurLen]=',';           /* comma delimiter */
  587.              CurLen++;
  588.              line[CurLen]=0;
  589.  
  590.              if (CurLen+lstrlen(file2[j].rec)>499) {
  591.                 MessageBox(NULL,"Record too big!","JOIN",MB_OK);
  592.                 return FALSE;
  593.              }
  594.              lstrcat(line,file2[j].rec);
  595.              fputs(line,oStream);
  596.           }
  597.        }
  598.     }
  599.  
  600.     fclose(oStream);
  601.  
  602.     return TRUE;
  603. }
  604.  
  605. /*******************************************************************************
  606.    strtrm:
  607.    Trim the spaces on left & right  of the string
  608. *******************************************************************************/
  609. strtrm(LPSTR string)
  610. {
  611.     rtrm(string);
  612.     ltrm(string);
  613.     return TRUE;
  614. }
  615.  
  616. /*******************************************************************************
  617.    rtrm:
  618.    Trim the space on right side of the string
  619. *******************************************************************************/
  620. rtrm(LPSTR string)
  621. {
  622.     int i,TmpLen;
  623.     
  624.     TmpLen=lstrlen(string);
  625.     for (i=TmpLen-1;i>=0 && string[i] == ' ';i--);
  626.     string[i+1] = '\0';
  627.     
  628.     return TRUE;
  629. }
  630.  
  631. /*******************************************************************************
  632.    ltrm:
  633.    Trim the space on left side of the string
  634. *******************************************************************************/
  635. ltrm(LPSTR string)
  636. {
  637.     int i,TmpLen,BegPoint;
  638.     char TmpStr[255];
  639.     
  640.     TmpLen=lstrlen(string);
  641.     for (i=0;i < TmpLen && string[i] == ' ';i++);
  642.     BegPoint=i;
  643.     for (i=BegPoint;i<TmpLen;i++) TmpStr[i-BegPoint]=string[i];
  644.     TmpStr[TmpLen-BegPoint] = '\0';
  645.     lstrcpy(string,TmpStr);
  646.     return TRUE;
  647. }
  648.  
  649. /*******************************************************************************
  650.    OurAlloc:
  651.    This routine allocates a specified number of byte from the global heap, 
  652.    and returns a far pointer to the locked object.
  653. *******************************************************************************/
  654. void far *OurAlloc(long bytes)
  655. {
  656.     HANDLE hnd;
  657.     LPSTR result;
  658.  
  659.     if ( (NULL==(hnd=GlobalAlloc(GMEM_MOVEABLE,bytes+1))) 
  660.        || (NULL==(result=GlobalLock(hnd))) ) {
  661.        MessageBox(NULL,"Ran out of memory","JOIN",MB_OK);
  662.        return FALSE;
  663.     }
  664.     return result;
  665. }
  666.  
  667. /******************************************************************************
  668.     OurFree:
  669.     Free up the given memory object.  This object must have been allocated
  670.     using the OurAlloc routine.
  671. *******************************************************************************/
  672. void OurFree(void far *pMem) 
  673. {
  674.     HGLOBAL hMem;
  675.  
  676.     if (pMem!=NULL) {
  677.        #if defined(WIN32)
  678.           hMem=GlobalHandle(pMem);      // convert pointer to handle
  679.        #else
  680.           {
  681.           DWORD temp=GlobalHandle((UINT)(((DWORD)pMem)>>16));
  682.           hMem=(HGLOBAL)LOWORD(temp);
  683.           }
  684.        #endif
  685.  
  686.        GlobalUnlock(hMem);
  687.        GlobalFree(hMem);
  688.     }
  689. }
  690.