home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / misc / misctool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  85.8 KB  |  2,807 lines

  1. /*
  2.  -  M I S C T O O L S . C
  3.  -
  4.  *  Copyright (C) 1995 Microsoft Corporation
  5.  *  Purpose:
  6.  *      Contains utilities to support the sample applications.
  7.  */
  8.  
  9.  
  10. #ifdef WIN32
  11. #ifdef _WIN95
  12. #define _INC_OLE
  13. #endif
  14. #define INC_OLE2
  15. #define INC_RPC
  16. #endif
  17.  
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22.  
  23. #ifdef WIN16
  24. #include <compobj.h>
  25. #endif
  26.  
  27. #ifdef WIN32
  28. #include <objbase.h>
  29. #include <objerror.h>
  30. #ifdef _WIN95
  31. #include <ole2.h>
  32. #endif
  33. #endif
  34.  
  35. #include <mapiwin.h>
  36. #include <mapix.h>
  37.  
  38. // for EMS entryids in IsEntryID()
  39. // #incldue <nonmapi.h>
  40.  
  41. #include <stdlib.h>
  42. #include <strtbl.h>
  43. #include <pvalloc.h>
  44. #include <misctool.h>
  45.  
  46. #ifdef WIN16
  47. #include <time.h>
  48. #endif
  49.  
  50. #define MAX_LOG_BUFF    255
  51.  
  52. // size of character string assoicated with binary byte of data  0x44 is space, 0, x, 2 bytes data
  53. #define BINARY_CHAR_SIZE     5  
  54.  
  55. typedef int EC;
  56. /*
  57.  -  EcStringFromFile
  58.  -
  59.  *  Purpose:
  60.  *      Read a file into a string (Allocates needed memory)
  61.  *
  62.  *  Parameters:
  63.  *      lpsz                - Pointer returned with read in string
  64.  *      lpszFileName        - File to be read into string
  65.  *      lpv                 - Void pointer to chain memory to (optional)
  66.  *
  67.  *  Returns:
  68.  *      0 if successful
  69.  *      non 0 if failure
  70.  *
  71.  */
  72.  
  73. EC EcStringFromFile(LPSTR *lppsz, LPSTR lpszFileName, LPVOID lpv)
  74. {
  75.     EC      ec = 0;
  76.  
  77. #ifdef WIN32
  78.  
  79.     HANDLE  hFile;
  80.     DWORD   cHOFileSize;         //High Order 32 bits of File Size
  81.     DWORD   cLOFileSize;         //Low Order 32 bits of File Size
  82.     DWORD   cBytesRead;
  83.  
  84.     hFile = CreateFile(lpszFileName, GENERIC_READ, 0, NULL,OPEN_EXISTING,
  85.                        FILE_ATTRIBUTE_NORMAL, NULL);
  86.     if(hFile == INVALID_HANDLE_VALUE)
  87.     {
  88.         ec = 1;
  89.         goto err;
  90.     }
  91.  
  92.     cLOFileSize = GetFileSize(hFile,&cHOFileSize);
  93.     if((cLOFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
  94.     {
  95.         ec = 2;
  96.         goto err;
  97.     }
  98.  
  99.     if(lpv)
  100.         *lppsz = (LPSTR)PvAllocMore(cLOFileSize+1, lpv);
  101.     else
  102.         *lppsz = (LPSTR)PvAlloc(cLOFileSize+1);
  103.  
  104.     if(!ReadFile(hFile, *lppsz, cLOFileSize, &cBytesRead, NULL))
  105.     {
  106.         ec = 3;
  107.         goto err;
  108.     }
  109.  
  110.     (*lppsz)[cLOFileSize] = '\0';
  111.  
  112. err:
  113.     CloseHandle(hFile);
  114.  
  115. #endif
  116.  
  117.     return ec;
  118.  
  119. }
  120. /*
  121.  -  EcBinaryFromFile
  122.  -
  123.  *  Purpose:
  124.  *      Read a file into a string (Allocates needed memory)
  125.  *
  126.  *  Parameters:
  127.  *      lpsz                - Pointer returned with read in string
  128.  *      lpszFileName        - File to be read into string
  129.  *      lpv                 - Void pointer to chain memory to (optional)
  130.  *
  131.  *  Returns:
  132.  *      0 if successful
  133.  *      non 0 if failure
  134.  *
  135.  */
  136.  
  137. EC EcBinaryFromFile(LPSBinary lpsbin, LPSTR lpszFileName, LPVOID lpv)
  138. {
  139.  
  140.  
  141.     EC      ec = 0;
  142.  
  143. #ifdef WIN32
  144.  
  145.     HANDLE  hFile;
  146.     DWORD   cHOFileSize;         //High Order 32 bits of File Size
  147.     DWORD   cLOFileSize;         //Low Order 32 bits of File Size
  148.     DWORD   cBytesRead;
  149.  
  150.     hFile = CreateFile(lpszFileName, GENERIC_READ, 0, NULL,OPEN_EXISTING,
  151.                        FILE_ATTRIBUTE_NORMAL, NULL);
  152.     if(hFile == INVALID_HANDLE_VALUE)
  153.     {
  154.         ec = 1;
  155.         goto err;
  156.     }
  157.  
  158.     cLOFileSize = GetFileSize(hFile,&cHOFileSize);
  159.     if((cLOFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
  160.     {
  161.         ec = 2;
  162.         goto err;
  163.     }
  164.  
  165.     if(lpv)
  166.         lpsbin->lpb = (LPBYTE)PvAllocMore(cLOFileSize, lpv);
  167.     else
  168.         lpsbin->lpb = (LPBYTE)PvAlloc(cLOFileSize);
  169.  
  170.     if(!ReadFile(hFile, (LPSTR)lpsbin->lpb, cLOFileSize, &cBytesRead, NULL))
  171.     {
  172.         ec = 3;
  173.         goto err;
  174.     }
  175.  
  176.     lpsbin->cb = cLOFileSize;
  177.  
  178. err:
  179.     CloseHandle(hFile);
  180.  
  181. #endif
  182.  
  183.     return ec;
  184.  
  185. }
  186.  
  187.  
  188. /***********************************************************************/
  189. /*
  190.  -  SzGetEntryID
  191.  -
  192.  *  Purpose:
  193.  *      Converts a LPENTRYID struct to a printable string as
  194.  *      best we can for a given data type.
  195.  *
  196.  *  Parameters:
  197.  *      lpsz        - destination string buffer
  198.  *      lp          - pointer to entryid
  199.  *      cb          - length of binary data contained in entryid array
  200.  *
  201.  *  Returns:
  202.  *      lpsz        - Stringized version of the entry id
  203.  *
  204.  */
  205. /***********************************************************************/
  206.  
  207. LPTSTR SzGetEntryID(LPTSTR lpsz,LPENTRYID lp, ULONG cb)
  208. {
  209.     char    lpszHex[9];
  210.     ULONG   ulTotal = 0;
  211.     ULONG   ulCount = 0;
  212.     LPBYTE  lpbData = lp->ab;
  213.     LPBYTE  lpbFlags = lp->abFlags;
  214.     ULONG   i;
  215.  
  216.     wsprintf(lpsz,"cb == %lu, *ab == ",cb);
  217.  
  218.     ulTotal += strlen(lpsz);
  219.  
  220.     // put flags in char form from binary
  221.     for(i=0 ; i < 4 ; i++)
  222.     {
  223.         wsprintf(lpszHex,"%02X ",lpbFlags[i]);
  224.         lstrcat(lpsz,lpszHex);
  225.         ulTotal += 3;
  226.     }
  227.  
  228.     cb = cb - 4;        // to ensure proper length of data entryid
  229.  
  230.     // put data in char form from binary
  231.     while( (ulCount < cb) && (ulTotal < (MAX_LOG_BUFF - 20) ) )
  232.     {
  233.         wsprintf(lpszHex, "%02X ", *lpbData);
  234.         lstrcat(lpsz, lpszHex);
  235.         ulTotal += 3;
  236.         lpbData++;
  237.         ulCount++;
  238.     }
  239.  
  240.     if( (cb * 3) > (MAX_LOG_BUFF) - 20  )
  241.     {
  242.         lstrcat(lpsz, " }etc");
  243.     }
  244.  
  245.     return(lpsz);
  246. }
  247.  
  248. /*
  249.  -  SzGetPropValue
  250.  -
  251.  *  Purpose:
  252.  *      Converts a PropValue struct to a printable string as
  253.  *      best we can for a given data type.
  254.  *
  255.  *  Parameters:
  256.  *      lpsz        - destination string buffer
  257.  *      lpPV        - pointer to a PropValue data struct
  258.  *
  259.  *  Returns:
  260.  *      lpsz        - Stringized version of the property value
  261.  *
  262.  */
  263.  
  264. LPSTR SzGetPropValue(LPSTR lpsz, LPSPropValue lpPV)
  265. {
  266.     SYSTEMTIME FAR  *lpSysTime          = NULL;
  267.     int             dBytes              = 0;
  268.     BOOL            fFlag               = FALSE;
  269.     DWORD           dwRet               = 0;
  270.     int             dSizeUnicode        = 0;
  271.     LPCSTR          szDefaultChar       = NULL;
  272.     BOOL far *      lpfDefaultCharUsed  = NULL;
  273.     ULONG           idx;
  274.     ULONG           cChars              = 0;
  275.     char            szMV[MAX_LOG_BUFF];
  276.  
  277.  
  278.     switch(PROP_TYPE(lpPV->ulPropTag))
  279.     {
  280.         case PT_I2:
  281.             wsprintf(lpsz, "%hd", lpPV->Value.i);
  282.             break;
  283.  
  284.         case PT_LONG:
  285.             wsprintf(lpsz, "%ld", lpPV->Value.l);
  286.             break;
  287.  
  288.         case PT_R4:
  289.             sprintf(lpsz, "%e", lpPV->Value.flt);
  290.             break;
  291.  
  292.         case PT_DOUBLE:
  293.             sprintf(lpsz, "%le", lpPV->Value.dbl);
  294.             break;
  295.  
  296.         case PT_CURRENCY:
  297.             wsprintf(lpsz, "%ld %ld", lpPV->Value.cur.Lo, lpPV->Value.cur.Hi);
  298.             break;
  299.  
  300.         case PT_APPTIME:
  301.             sprintf(lpsz, "%le", lpPV->Value.at);
  302.             break;
  303.  
  304.         case PT_BOOLEAN:
  305.             wsprintf(lpsz, "%u", lpPV->Value.b);
  306.             break;
  307.  
  308.         case PT_SYSTIME:
  309.             lpSysTime = (LPSYSTEMTIME) PvAlloc(sizeof(SYSTEMTIME) );
  310.  
  311.             FileTimeToSystemTime( (FILETIME FAR *) &lpPV->Value.ft,(SYSTEMTIME FAR *)lpSysTime);
  312.  
  313.             wsprintf(lpsz,"%4d/%02d/%02d  %02d:%02d:%02d",
  314.                         lpSysTime->wYear,
  315.                         lpSysTime->wMonth,
  316.                         lpSysTime->wDay,
  317.                         lpSysTime->wHour,
  318.                         lpSysTime->wMinute,
  319.                         lpSysTime->wSecond);
  320.  
  321.             PvFree(lpSysTime);
  322.             break;
  323.  
  324.         case PT_STRING8:
  325.             if(lpPV->Value.lpszA)
  326.             {
  327.                 if(!_memccpy(lpsz, lpPV->Value.lpszA, '\0', MAX_LOG_BUFF-1))
  328.                 {
  329.                     lpsz[MAX_LOG_BUFF] = '\0';
  330.                 }
  331.             }
  332.             else
  333.             {
  334.                 lstrcpy(lpsz, "(null)");
  335.             }
  336.             break;
  337.  
  338.         case PT_BINARY:
  339.             {
  340.                 char    lpszHex[9];
  341.                 ULONG   cb = 0;
  342.                 LPBYTE  lpb = lpPV->Value.bin.lpb;
  343.                 cChars = 0;
  344.  
  345.                 wsprintf(lpsz, "cb: %3lu\t*pb: ", lpPV->Value.bin.cb);
  346.                 cChars += strlen(lpsz);
  347.  
  348.                 while((cb < lpPV->Value.bin.cb) && (cChars < MAX_LOG_BUFF-16 ) )
  349.                 {
  350.                     wsprintf(lpszHex, "%02X ", *lpb);
  351.                     lstrcat(lpsz, lpszHex);
  352.                     cChars += 3;
  353.                     lpb++;
  354.                     cb++;
  355.                 }
  356.  
  357.                 if( ((lpPV->Value.bin.cb)*3) > (MAX_LOG_BUFF)-16 )
  358.                 {
  359.                     lstrcat(lpsz, " }etc");
  360.                 }
  361.  
  362.             }
  363.             break;
  364.  
  365.         case PT_UNICODE:
  366.  
  367. #ifdef WIN32
  368.  
  369.             dBytes = WideCharToMultiByte(   (UINT)      CP_ACP,             // code page
  370.                                             (DWORD)     0,                  // perf/mapping flags
  371.                                             (LPCWSTR)   lpPV->Value.lpszW,  // Unicode string
  372.                                             (int)       -1 ,                // length of unicode string assume NULL terminated
  373.                                             (LPSTR)     lpsz,               // String 8 string
  374.                                             (int)       MAX_LOG_BUFF -1,     // length in bytes of string 8 string
  375.                                             (LPCSTR)    szDefaultChar,      // default char to use(NULL)
  376.                                             (BOOL far *)    lpfDefaultCharUsed);// default characters used (NULL)
  377.  
  378.             dwRet = GetLastError();
  379.  
  380. #endif
  381.  
  382.             break;
  383.  
  384.  
  385.         case PT_I8:
  386.             wsprintf(lpsz, "%ld %ld", lpPV->Value.li.LowPart, lpPV->Value.li.HighPart);
  387.             break;
  388.  
  389.         case PT_CLSID:
  390.             SzIIDToString(lpsz, lpPV->Value.lpguid);
  391.             break;
  392.  
  393.         case PT_NULL:
  394.             lstrcpy(lpsz, "<NULL>");
  395.             break;
  396.  
  397.         case PT_OBJECT:
  398.             lstrcpy(lpsz, "<MAPITEST: YOUR OBJECT HERE>");
  399.             break;
  400.  
  401.         case PT_ERROR:
  402.             GetString("MAPIErrors", (ULONG)lpPV->Value.err, lpsz);
  403.             break;
  404.  
  405.         case PT_UNSPECIFIED:
  406.             lstrcpy(lpsz, "(unspecified)");
  407.             break;
  408.  
  409.  
  410.  
  411.         /*********** MULIT VALUE PROPERTIES ********/
  412.  
  413.         // format is as follows:
  414.         // cValues : val1 ;; val2 ;; val3 ;; }etc
  415.  
  416.         case PT_MV_I2:
  417.             cChars = 0;
  418.             wsprintf(lpsz, "%lu :",lpPV->Value.MVi.cValues);
  419.  
  420.             for(idx = 0 ; idx < lpPV->Value.MVi.cValues ; idx++ )
  421.             {
  422.                 wsprintf(szMV,"%hd ;;",lpPV->Value.MVi.lpi[idx] );
  423.                 lstrcat(lpsz,szMV);
  424.  
  425.                 cChars = lstrlen(lpsz);
  426.  
  427.                 if( cChars > (MAX_LOG_BUFF)-16 )
  428.                 {
  429.                     lstrcat(lpsz, " }etc");
  430.                     break;
  431.                 }
  432.             }
  433.             break;
  434.  
  435.         case PT_MV_LONG:
  436.             cChars = 0;
  437.             wsprintf(lpsz, "%lu :",lpPV->Value.MVl.cValues);
  438.  
  439.             for(idx = 0 ; idx < lpPV->Value.MVl.cValues ; idx++ )
  440.             {
  441.                 wsprintf(szMV,"%ld ;;",lpPV->Value.MVl.lpl[idx] );
  442.                 lstrcat(lpsz,szMV);
  443.  
  444.                 cChars = lstrlen(lpsz);
  445.  
  446.                 if( cChars > (MAX_LOG_BUFF)-16 )
  447.                 {
  448.                     lstrcat(lpsz, " }etc");
  449.                     break;
  450.                 }
  451.             }
  452.             break;
  453.  
  454.         case PT_MV_R4:
  455.             cChars = 0;
  456.             wsprintf(lpsz, "%lu :",lpPV->Value.MVflt.cValues);
  457.  
  458.             for(idx = 0 ; idx < lpPV->Value.MVflt.cValues ; idx++ )
  459.             {
  460.                 sprintf(szMV,"%e ;;",lpPV->Value.MVflt.lpflt[idx] );
  461.                 lstrcat(lpsz,szMV);
  462.  
  463.                 cChars = lstrlen(lpsz);
  464.  
  465.                 if( cChars > (MAX_LOG_BUFF)-16 )
  466.                 {
  467.                     lstrcat(lpsz, " }etc");
  468.                     break;
  469.                 }
  470.             }
  471.             break;
  472.  
  473.         case PT_MV_DOUBLE:
  474.             cChars = 0;
  475.             wsprintf(lpsz, "%lu :",lpPV->Value.MVdbl.cValues);
  476.  
  477.             for(idx = 0 ; idx < lpPV->Value.MVdbl.cValues ; idx++ )
  478.             {
  479.                 sprintf(szMV,"%le ;;",lpPV->Value.MVdbl.lpdbl[idx] );
  480.                 lstrcat(lpsz,szMV);
  481.  
  482.                 cChars = lstrlen(lpsz);
  483.  
  484.                 if( cChars > (MAX_LOG_BUFF)-16 )
  485.                 {
  486.                     lstrcat(lpsz, " }etc");
  487.                     break;
  488.                 }
  489.             }
  490.             break;
  491.  
  492.         case PT_MV_CURRENCY:
  493.             cChars = 0;
  494.             wsprintf(lpsz, "%lu :",lpPV->Value.MVcur.cValues);
  495.  
  496.             for(idx = 0 ; idx < lpPV->Value.MVcur.cValues ; idx++ )
  497.             {
  498.                 wsprintf(szMV,"%ld %ld ;;",
  499.                         lpPV->Value.MVcur.lpcur[idx].Lo,
  500.                         lpPV->Value.MVcur.lpcur[idx].Hi );
  501.  
  502.                 lstrcat(lpsz,szMV);
  503.  
  504.                 cChars = lstrlen(lpsz);
  505.  
  506.                 if( cChars > (MAX_LOG_BUFF)-16 )
  507.                 {
  508.                     lstrcat(lpsz, " }etc");
  509.                     break;
  510.                 }
  511.             }
  512.             break;
  513.  
  514.         case PT_MV_APPTIME:
  515.             cChars = 0;
  516.             wsprintf(lpsz, "%lu :",lpPV->Value.MVat.cValues);
  517.  
  518.             for(idx = 0 ; idx < lpPV->Value.MVat.cValues ; idx++ )
  519.             {
  520.                 sprintf(szMV,"%le ;;",lpPV->Value.MVat.lpat[idx] );
  521.                 lstrcat(lpsz,szMV);
  522.  
  523.                 cChars = lstrlen(lpsz);
  524.  
  525.                 if( cChars > (MAX_LOG_BUFF)-16 )
  526.                 {
  527.                     lstrcat(lpsz, " }etc");
  528.                     break;
  529.                 }
  530.             }
  531.  
  532.             break;
  533.  
  534.         case PT_MV_SYSTIME:
  535.             cChars = 0;
  536.             // this has only one : on purpose, since two : is harder to strtok
  537.             //  since there is a colon in between hour:Minute:second
  538.             wsprintf(lpsz, "%lu :",lpPV->Value.MVft.cValues);
  539.  
  540.             for(idx = 0 ; idx < lpPV->Value.MVft.cValues ; idx++ )
  541.             {
  542.                 lpSysTime = (LPSYSTEMTIME) PvAlloc(sizeof(SYSTEMTIME) );
  543.  
  544.                 FileTimeToSystemTime( (FILETIME FAR *) &lpPV->Value.MVft.lpft[idx],(SYSTEMTIME FAR *)lpSysTime);
  545.  
  546.                 wsprintf(szMV,"%4d/%02d/%02d  %02d:%02d:%02d ;;",
  547.                         lpSysTime->wYear,
  548.                         lpSysTime->wMonth,
  549.                         lpSysTime->wDay,
  550.                         lpSysTime->wHour,
  551.                         lpSysTime->wMinute,
  552.                         lpSysTime->wSecond);
  553.  
  554.                 lstrcat(lpsz,szMV);
  555.  
  556.                 PvFree(lpSysTime);
  557.  
  558.                 cChars = lstrlen(lpsz);
  559.  
  560.                 if( cChars > (MAX_LOG_BUFF)-16 )
  561.                 {
  562.                     lstrcat(lpsz, " }etc");
  563.                     break;
  564.                 }
  565.             }
  566.             break;
  567.  
  568.         case PT_MV_STRING8:
  569.             cChars = 0;
  570.             wsprintf(lpsz, "%lu :",lpPV->Value.MVszA.cValues);
  571.  
  572.             for(idx = 0 ; idx < lpPV->Value.MVszA.cValues ; idx++ )
  573.             {
  574.                 if(lpPV->Value.MVszA.lppszA[idx])
  575.                     wsprintf(szMV,"%s ;;", lpPV->Value.MVszA.lppszA[idx] );
  576.                 else
  577.                     wsprintf(szMV,"%s ;;", "(NULL)" );
  578.  
  579.                 lstrcat(lpsz,szMV);
  580.  
  581.                 cChars = lstrlen(lpsz);
  582.  
  583.                 if( cChars > (MAX_LOG_BUFF)-16 )
  584.                 {
  585.                     lstrcat(lpsz, " }etc");
  586.                     break;
  587.                 }
  588.             }
  589.  
  590.             break;
  591.  
  592.         case PT_MV_BINARY:
  593.             cChars = 0;
  594.             wsprintf(lpsz, "%lu :",lpPV->Value.MVbin.cValues);
  595.  
  596.             for(idx = 0 ; idx < lpPV->Value.MVbin.cValues ; idx++ )
  597.             {
  598.                 char    lpszHex[9];
  599.                 ULONG   cb          = 0;
  600.                 LPBYTE  lpb         = lpPV->Value.MVbin.lpbin[idx].lpb;
  601.  
  602.                 wsprintf(szMV, "cb: %3lu\t*pb: ", lpPV->Value.MVbin.lpbin[idx].cb);
  603.                 lstrcat(lpsz,szMV);
  604.                 cChars = lstrlen(lpsz);
  605.  
  606.                 while((cb < lpPV->Value.MVbin.lpbin[idx].cb) && (cChars < MAX_LOG_BUFF-16 ) )
  607.                 {
  608.                     wsprintf(lpszHex, "%02X ", *lpb);
  609.                     lstrcat(lpsz, lpszHex);
  610.                     cChars += 3;
  611.                     lpb++;
  612.                     cb++;
  613.                 }
  614.  
  615.                 lstrcat(lpsz," ;;");
  616.  
  617.                 cChars = lstrlen(lpsz);
  618.  
  619.                 if( cChars > (MAX_LOG_BUFF)-16 )
  620.                 {
  621.                     lstrcat(lpsz, " }etc");
  622.                     break;
  623.                 }
  624.             }
  625.  
  626.             break;
  627.  
  628.  
  629.         case PT_MV_UNICODE:
  630. #ifdef WIN32
  631.             cChars = 0;
  632.             wsprintf(lpsz, "%lu :",lpPV->Value.MVszW.cValues);
  633.  
  634.             for(idx = 0 ; idx < lpPV->Value.MVszW.cValues ; idx++ )
  635.             {
  636.  
  637.                 dBytes = WideCharToMultiByte((UINT)     CP_ACP,                         // code page
  638.                                             (DWORD)     0,                              // perf/mapping flags
  639.                                             (LPCWSTR)   lpPV->Value.MVszW.lppszW[idx],  // Unicode string
  640.                                             (int)       -1,                             // length of unicode string assumed to Be NULL terimiated
  641.                                             (LPSTR)     szMV,                           // String 8 string
  642.                                             (int)       MAX_LOG_BUFF -1,                // length in bytes of string 8 string(max)
  643.                                             (LPCSTR)    szDefaultChar,                  // default char to use(NULL)
  644.                                             (BOOL far *)    lpfDefaultCharUsed);            // default characters used (NULL)
  645.  
  646.                 dwRet = GetLastError();
  647.  
  648.                 lstrcat(lpsz,szMV);
  649.  
  650.                 lstrcat(lpsz," ;;");
  651.  
  652.                 cChars = lstrlen(lpsz);
  653.  
  654.                 if( cChars > (MAX_LOG_BUFF)-16 )
  655.                 {
  656.                     lstrcat(lpsz, " }etc");
  657.                     break;
  658.                 }
  659.             }
  660. #endif
  661.             break;
  662.  
  663.  
  664.         case PT_MV_CLSID:
  665.             cChars = 0;
  666.             wsprintf(lpsz, "%lu :",lpPV->Value.MVguid.cValues);
  667.  
  668.             for(idx = 0 ; idx < lpPV->Value.MVguid.cValues ; idx++ )
  669.             {
  670.                 SzIIDToString(szMV,   &(lpPV->Value.MVguid.lpguid[idx]) );
  671.                 lstrcat(lpsz,szMV);
  672.  
  673.                 cChars = lstrlen(lpsz);
  674.  
  675.                 if( cChars > (MAX_LOG_BUFF)-16 )
  676.                 {
  677.                     lstrcat(lpsz, " }etc");
  678.                     break;
  679.                 }
  680.             }
  681.             break;
  682.  
  683.         case PT_MV_I8:
  684.             cChars = 0;
  685.             wsprintf(lpsz, "%lu :",lpPV->Value.MVli.cValues);
  686.  
  687.             for(idx = 0 ; idx < lpPV->Value.MVli.cValues ; idx++ )
  688.             {
  689.                 wsprintf(szMV,"%ld %ld ;;",
  690.                         lpPV->Value.MVli.lpli[idx].LowPart,
  691.                         lpPV->Value.MVli.lpli[idx].HighPart );
  692.                 lstrcat(lpsz,szMV);
  693.  
  694.                 cChars = lstrlen(lpsz);
  695.  
  696.                 if( cChars > (MAX_LOG_BUFF)-16 )
  697.                 {
  698.                     lstrcat(lpsz, " }etc");
  699.                     break;
  700.                 }
  701.             }
  702.             break;
  703.  
  704.         default:
  705.             wsprintf(lpsz, "%lu == UNKNOWN PROP TYPE", PROP_TYPE(lpPV->ulPropTag) );
  706.             break;
  707.     }
  708.  
  709.     return lpsz;
  710. }
  711.  
  712.  
  713. /*
  714.  -  SzIIDToString
  715.  -
  716.  *  Purpose:
  717.  *      Converts a IID to a string for display purposes.
  718.  *
  719.  *  Parameters:
  720.  *      lpsz        - Destination string of conversion
  721.  *      lpiid        - Pointer to the IID to be converted
  722.  *
  723.  *  Returns:
  724.  *      lpsz        - Pointer to string buffer passed in
  725.  *
  726.  *  Functions that pass in a LPSTR should make sure it is at least
  727.  *  37 bytes long.
  728.  */
  729.  
  730. LPSTR SzIIDToString(LPSTR lpsz, LPIID lpiid)
  731. {
  732.     int     i;
  733.     char    ch;
  734.  
  735.     if(lpiid)
  736.     {
  737.         wsprintf(lpsz, "%08lX %04X %04X  ", lpiid->Data1, lpiid->Data2, lpiid->Data3);
  738.  
  739.         for(i = 0; i < 8; i++)
  740.         {
  741.             lpsz[i*2+20] = ((ch=((lpiid->Data4[i] & 0xF0) >> 4)) < 10 ? ch+0x30 : ch+0x37);
  742.             lpsz[i*2+21] = ((ch=(lpiid->Data4[i] & 0x0F)) < 10 ? ch+0x30 : ch+0x37);
  743.         }
  744.  
  745.         lpsz[i*2+20] = '\0';
  746.     }
  747.     else
  748.         lstrcpy(lpsz, "(null)");
  749.  
  750.     return lpsz;
  751. }
  752.  
  753.  
  754. /*
  755.  -  CopyPropValue
  756.  -
  757.  *  Purpose:
  758.  *      Copies the contents of one PropValue into another.
  759.  *      This function does a member for member copy - freeing
  760.  *      and allocating memory for the data as appropriate.
  761.  *      Currently, Multi-Value properties are not supported.
  762.  *      If dev. does than we will.
  763.  *
  764.  *  Parameters:
  765.  *      lpspv1          - Pointer to the destination PropValue
  766.  *      lpspv2          - Pointer to the source PropValue
  767.  *      lpv             - Void pointer to a parent in a memory chain (optional)
  768.  *
  769.  *  Returns:
  770.  *      Void.
  771.  *
  772.  */
  773.  
  774. void CopyPropValue(LPSPropValue lpspv1, LPSPropValue lpspv2, LPVOID lpv)
  775. {
  776.     ULONG idx;
  777.     int             dSizeUnicode1        = 0;
  778.  
  779.     lpspv1->ulPropTag  = lpspv2->ulPropTag;
  780.     lpspv1->dwAlignPad = lpspv2->dwAlignPad;
  781.  
  782.     /* switch() through all PT_'s and set values appropriately */
  783.  
  784.     switch(PROP_TYPE(lpspv2->ulPropTag))
  785.     {
  786.         case PT_I2:
  787.             lpspv1->Value.i = lpspv2->Value.i;
  788.             break;
  789.  
  790.         case PT_LONG:
  791.             lpspv1->Value.l = lpspv2->Value.l;
  792.             break;
  793.  
  794.         case PT_R4:
  795.             lpspv1->Value.flt = lpspv2->Value.flt;
  796.             break;
  797.  
  798.         case PT_DOUBLE:
  799.             lpspv1->Value.dbl = lpspv2->Value.dbl;
  800.             break;
  801.  
  802.         case PT_CURRENCY:
  803.             lpspv1->Value.cur.Lo = lpspv2->Value.cur.Lo;
  804.             lpspv1->Value.cur.Hi = lpspv2->Value.cur.Hi;
  805.             break;
  806.  
  807.         case PT_APPTIME:
  808.             lpspv1->Value.at = lpspv2->Value.at;
  809.             break;
  810.  
  811.         case PT_BOOLEAN:
  812.             lpspv1->Value.b = lpspv2->Value.b;
  813.             break;
  814.  
  815.         case PT_SYSTIME:
  816.             lpspv1->Value.ft.dwLowDateTime = lpspv2->Value.ft.dwLowDateTime;
  817.             lpspv1->Value.ft.dwHighDateTime = lpspv2->Value.ft.dwHighDateTime;
  818.             break;
  819.  
  820.         case PT_STRING8:
  821.             if(lpv)
  822.                 lpspv1->Value.lpszA = (LPTSTR)PvAllocMore(lstrlen(lpspv2->Value.lpszA) + 1, lpv);
  823.             else
  824.                 lpspv1->Value.lpszA = (LPTSTR)PvAlloc(lstrlen(lpspv2->Value.lpszA) + 1);
  825.  
  826.             lstrcpy(lpspv1->Value.lpszA, lpspv2->Value.lpszA);
  827.             break;
  828.  
  829.         case PT_BINARY:
  830.             lpspv1->Value.bin.cb = lpspv2->Value.bin.cb;
  831.  
  832.             if(lpspv2->Value.bin.cb)
  833.             {
  834.                 ULONG   cb;
  835.                 LPBYTE  lpb1;
  836.                 LPBYTE  lpb2;
  837.  
  838.                 cb  = lpspv2->Value.bin.cb;
  839.  
  840.                 if(lpv)
  841.                     lpspv1->Value.bin.lpb = (LPBYTE)PvAllocMore(cb, lpv);
  842.                 else
  843.                     lpspv1->Value.bin.lpb = (LPBYTE)PvAlloc(cb);
  844.  
  845.                 lpb1 = lpspv1->Value.bin.lpb;
  846.                 lpb2 = lpspv2->Value.bin.lpb;
  847.  
  848.                 while(cb--)
  849.                     *lpb1++ = *lpb2++;
  850.             }
  851.             else
  852.                 lpspv1->Value.bin.lpb = NULL;
  853.  
  854.             break;
  855.  
  856.         case PT_UNICODE:
  857.  
  858. #ifdef WIN32
  859.             dSizeUnicode1 = (wcslen(lpspv2->Value.lpszW) * sizeof(WCHAR)) + 2;
  860.  
  861.             if(lpv)
  862.                 lpspv1->Value.lpszW = (LPWSTR)PvAllocMore(dSizeUnicode1, lpv);
  863.             else
  864.                 lpspv1->Value.lpszW = (LPWSTR)PvAlloc(dSizeUnicode1);
  865.  
  866.             memcpy(lpspv1->Value.lpszW,lpspv2->Value.lpszW,(size_t)dSizeUnicode1);
  867. #endif
  868.             break;
  869.  
  870.  
  871.             break;
  872.  
  873.         case PT_CLSID:
  874.             if(!lpspv1->Value.lpguid)
  875.             {
  876.                 if(lpv)
  877.                     lpspv1->Value.lpguid = (LPGUID)PvAllocMore(sizeof(GUID), lpv);
  878.                 else
  879.                     lpspv1->Value.lpguid = (LPGUID)PvAlloc(sizeof(GUID));
  880.             }
  881.  
  882.             CopyGuid(lpspv1->Value.lpguid, lpspv2->Value.lpguid);
  883.             break;
  884.  
  885.         /* Multi-Valued Properties go here!!! */
  886.  
  887.         case PT_MV_I2:
  888.             if(lpv)
  889.                 lpspv1->Value.MVi.lpi = (short int *) PvAllocMore(
  890.                                          (sizeof(short int) * lpspv2->Value.MVi.cValues) , lpv );
  891.             else
  892.                 lpspv1->Value.MVi.lpi = (short int *) PvAlloc(
  893.                             (sizeof(short int) * lpspv2->Value.MVi.cValues) );
  894.  
  895.             lpspv1->Value.MVi.cValues = lpspv2->Value.MVi.cValues;
  896.  
  897.             memcpy(lpspv1->Value.MVi.lpi,lpspv2->Value.MVi.lpi,(size_t)
  898.                    (sizeof(short int) * lpspv2->Value.MVi.cValues) );
  899.  
  900.             break;
  901.  
  902.         case PT_MV_LONG:
  903.             if(lpv)
  904.                 lpspv1->Value.MVl.lpl = (LONG *) PvAllocMore(
  905.                                          (sizeof(LONG) * lpspv2->Value.MVl.cValues) , lpv );
  906.             else
  907.                 lpspv1->Value.MVl.lpl = (LONG *) PvAlloc(
  908.                             (sizeof(LONG) * lpspv2->Value.MVl.cValues) );
  909.  
  910.             lpspv1->Value.MVl.cValues = lpspv2->Value.MVl.cValues;
  911.  
  912.             memcpy(lpspv1->Value.MVl.lpl,lpspv2->Value.MVl.lpl,(size_t)
  913.                    (sizeof(LONG) * lpspv2->Value.MVl.cValues) );
  914.  
  915.             break;
  916.  
  917.         case PT_MV_R4:
  918.             if(lpv)
  919.                 lpspv1->Value.MVflt.lpflt = (float *) PvAllocMore(
  920.                                          (sizeof(float) * lpspv2->Value.MVflt.cValues) , lpv );
  921.             else
  922.                 lpspv1->Value.MVflt.lpflt = (float *) PvAlloc(
  923.                             (sizeof(float) * lpspv2->Value.MVflt.cValues) );
  924.  
  925.             lpspv1->Value.MVflt.cValues = lpspv2->Value.MVflt.cValues;
  926.  
  927.             memcpy(lpspv1->Value.MVflt.lpflt,lpspv2->Value.MVflt.lpflt,(size_t)
  928.                    (sizeof(float) * lpspv2->Value.MVflt.cValues) );
  929.  
  930.             break;
  931.  
  932.         case PT_MV_DOUBLE:
  933.             if(lpv)
  934.                 lpspv1->Value.MVdbl.lpdbl = (double *) PvAllocMore(
  935.                                          (sizeof(double) * lpspv2->Value.MVdbl.cValues) , lpv );
  936.             else
  937.                 lpspv1->Value.MVdbl.lpdbl = (double *) PvAlloc(
  938.                             (sizeof(double) * lpspv2->Value.MVdbl.cValues) );
  939.  
  940.             lpspv1->Value.MVdbl.cValues = lpspv2->Value.MVdbl.cValues;
  941.  
  942.             memcpy(lpspv1->Value.MVdbl.lpdbl,lpspv2->Value.MVdbl.lpdbl,(size_t)
  943.                    (sizeof(double) * lpspv2->Value.MVdbl.cValues) );
  944.  
  945.             break;
  946.  
  947.         case PT_MV_CURRENCY:
  948.             if(lpv)
  949.                 lpspv1->Value.MVcur.lpcur = (CURRENCY *) PvAllocMore(
  950.                                          (sizeof(CURRENCY) * lpspv2->Value.MVcur.cValues) , lpv );
  951.             else
  952.                 lpspv1->Value.MVcur.lpcur = (CURRENCY *) PvAlloc(
  953.                             (sizeof(CURRENCY) * lpspv2->Value.MVcur.cValues) );
  954.  
  955.             lpspv1->Value.MVcur.cValues = lpspv2->Value.MVcur.cValues;
  956.  
  957.             memcpy(lpspv1->Value.MVcur.lpcur,lpspv2->Value.MVcur.lpcur,(size_t)
  958.                    (sizeof(CURRENCY) * lpspv2->Value.MVcur.cValues) );
  959.  
  960.             break;
  961.  
  962.         case PT_MV_APPTIME:
  963.             if(lpv)
  964.                 lpspv1->Value.MVat.lpat = (double *) PvAllocMore(
  965.                                          (sizeof(double) * lpspv2->Value.MVat.cValues) , lpv );
  966.             else
  967.                 lpspv1->Value.MVat.lpat = (double *) PvAlloc(
  968.                             (sizeof(double) * lpspv2->Value.MVat.cValues) );
  969.  
  970.             lpspv1->Value.MVat.cValues = lpspv2->Value.MVat.cValues;
  971.  
  972.             memcpy(lpspv1->Value.MVat.lpat,lpspv2->Value.MVat.lpat,(size_t)
  973.                    (sizeof(double) * lpspv2->Value.MVat.cValues) );
  974.  
  975.             break;
  976.  
  977.         case PT_MV_SYSTIME:
  978.             if(lpv)
  979.                 lpspv1->Value.MVft.lpft = (FILETIME *) PvAllocMore(
  980.                                          (sizeof(FILETIME) * lpspv2->Value.MVft.cValues) , lpv );
  981.             else
  982.                 lpspv1->Value.MVft.lpft = (FILETIME *) PvAlloc(
  983.                             (sizeof(FILETIME) * lpspv2->Value.MVft.cValues) );
  984.  
  985.             lpspv1->Value.MVft.cValues = lpspv2->Value.MVft.cValues;
  986.  
  987.             memcpy(lpspv1->Value.MVft.lpft,lpspv2->Value.MVft.lpft,(size_t)
  988.                    (sizeof(FILETIME) * lpspv2->Value.MVft.cValues) );
  989.  
  990.             break;
  991.  
  992.         case PT_MV_STRING8:
  993.             if(lpv)
  994.                 lpspv1->Value.MVszA.lppszA = (LPSTR *) PvAllocMore(
  995.                                          (sizeof(LPSTR) * lpspv2->Value.MVszA.cValues) , lpv );
  996.             else
  997.                 lpspv1->Value.MVszA.lppszA = (LPSTR *) PvAlloc(
  998.                             (sizeof(LPSTR) * lpspv2->Value.MVszA.cValues) );
  999.  
  1000.             lpspv1->Value.MVszA.cValues = lpspv2->Value.MVszA.cValues;
  1001.  
  1002.             for(idx = 0 ;idx < lpspv2->Value.MVszA.cValues ; idx++)
  1003.             {
  1004.  
  1005.                 if(lpv)
  1006.                 {
  1007.                     lpspv1->Value.MVszA.lppszA[idx] =
  1008.                         (LPTSTR) PvAllocMore(lstrlen(lpspv2->Value.MVszA.lppszA[idx]) + 1,
  1009.                         lpv);
  1010.                 }
  1011.                 else
  1012.                 {
  1013.                     lpspv1->Value.MVszA.lppszA[idx] =
  1014.                          (LPTSTR) PvAllocMore(lstrlen(lpspv2->Value.MVszA.lppszA[idx]) + 1,
  1015.                            lpspv1->Value.MVszA.lppszA);
  1016.                 }
  1017.                 lstrcpy(lpspv1->Value.MVszA.lppszA[idx] , lpspv2->Value.MVszA.lppszA[idx] );
  1018.             }
  1019.             break;
  1020.  
  1021.         case PT_MV_UNICODE:
  1022. #ifdef WIN32
  1023.  
  1024.             if(lpv)
  1025.                 lpspv1->Value.MVszW.lppszW = (LPWSTR *) PvAllocMore(
  1026.                                          (sizeof(LPWSTR) * lpspv2->Value.MVszW.cValues) , lpv );
  1027.             else
  1028.                 lpspv1->Value.MVszW.lppszW = (LPWSTR *) PvAlloc(
  1029.                             (sizeof(LPWSTR) * lpspv2->Value.MVszW.cValues) );
  1030.  
  1031.             lpspv1->Value.MVszW.cValues = lpspv2->Value.MVszW.cValues;
  1032.  
  1033.             for(idx = 0 ;idx < lpspv2->Value.MVszW.cValues ; idx++)
  1034.             {
  1035.  
  1036.                 dSizeUnicode1 = (wcslen(lpspv2->Value.lpszW) * sizeof(WCHAR)) + 2;
  1037.  
  1038.                 if(lpv)
  1039.                     lpspv1->Value.MVszW.lppszW[idx] = (LPWSTR) PvAllocMore(dSizeUnicode1,lpv);
  1040.                 else
  1041.                     lpspv1->Value.MVszW.lppszW[idx] =
  1042.                          (LPWSTR) PvAllocMore(dSizeUnicode1,lpspv1->Value.MVszW.lppszW);
  1043.  
  1044.                 memcpy( lpspv1->Value.MVszW.lppszW[idx],
  1045.                         lpspv2->Value.MVszW.lppszW[idx],
  1046.                         (size_t)dSizeUnicode1);
  1047.             }
  1048. #endif
  1049.             break;
  1050.  
  1051.         case PT_MV_BINARY:
  1052.             if(lpv)
  1053.                 lpspv1->Value.MVbin.lpbin = (SBinary *) PvAllocMore(
  1054.                                          (sizeof(SBinary) * lpspv2->Value.MVbin.cValues) , lpv );
  1055.             else
  1056.                 lpspv1->Value.MVbin.lpbin = (SBinary *) PvAlloc(
  1057.                             (sizeof(SBinary) * lpspv2->Value.MVbin.cValues) );
  1058.  
  1059.             lpspv1->Value.MVbin.cValues = lpspv2->Value.MVbin.cValues;
  1060.  
  1061.             for(idx = 0; idx < lpspv1->Value.MVbin.cValues ; idx++)
  1062.             {
  1063.                 lpspv1->Value.MVbin.lpbin[idx].cb = lpspv2->Value.MVbin.lpbin[idx].cb;
  1064.  
  1065.                 if(lpspv2->Value.MVbin.lpbin[idx].cb)
  1066.                 {
  1067.                     ULONG   cb;
  1068.                     LPBYTE  lpb1;
  1069.                     LPBYTE  lpb2;
  1070.  
  1071.                     cb  = lpspv2->Value.MVbin.lpbin[idx].cb;
  1072.  
  1073.                     if(lpv)
  1074.                         lpspv1->Value.MVbin.lpbin[idx].lpb = (LPBYTE)PvAllocMore(cb, lpv);
  1075.                     else
  1076.                         lpspv1->Value.MVbin.lpbin[idx].lpb = (LPBYTE)PvAlloc(cb);
  1077.  
  1078.                     lpb1 = lpspv1->Value.MVbin.lpbin[idx].lpb;
  1079.                     lpb2 = lpspv2->Value.MVbin.lpbin[idx].lpb;
  1080.  
  1081.                     while(cb--)
  1082.                         *lpb1++ = *lpb2++;
  1083.                 }
  1084.                 else
  1085.                     lpspv1->Value.MVbin.lpbin[idx].lpb = NULL;
  1086.  
  1087.             }
  1088.             break;
  1089.  
  1090.         case PT_MV_CLSID:
  1091.             if(lpv)
  1092.                 lpspv1->Value.MVguid.lpguid = (GUID *) PvAllocMore(
  1093.                                          (sizeof(GUID) * lpspv2->Value.MVguid.cValues) , lpv );
  1094.             else
  1095.                 lpspv1->Value.MVguid.lpguid = (GUID *) PvAlloc(
  1096.                             (sizeof(GUID) * lpspv2->Value.MVguid.cValues) );
  1097.  
  1098.             lpspv1->Value.MVguid.cValues = lpspv2->Value.MVguid.cValues;
  1099.  
  1100.             memcpy(lpspv1->Value.MVguid.lpguid,lpspv2->Value.MVguid.lpguid,(size_t)
  1101.                    (sizeof(GUID) * lpspv2->Value.MVguid.cValues) );
  1102.  
  1103.             break;
  1104.  
  1105.         case PT_MV_I8:
  1106.             if(lpv)
  1107.                 lpspv1->Value.MVli.lpli = (LARGE_INTEGER *) PvAllocMore(
  1108.                                          (sizeof(LARGE_INTEGER) * lpspv2->Value.MVli.cValues) , lpv );
  1109.             else
  1110.                 lpspv1->Value.MVli.lpli = (LARGE_INTEGER *) PvAlloc(
  1111.                             (sizeof(LARGE_INTEGER) * lpspv2->Value.MVli.cValues) );
  1112.  
  1113.             lpspv1->Value.MVli.cValues = lpspv2->Value.MVli.cValues;
  1114.  
  1115.             memcpy(lpspv1->Value.MVli.lpli,lpspv2->Value.MVli.lpli,(size_t)
  1116.                    (sizeof(LARGE_INTEGER) * lpspv2->Value.MVli.cValues) );
  1117.  
  1118.             break;
  1119.  
  1120.         default:
  1121.             lpspv1->Value.x = lpspv2->Value.x;
  1122.             break;
  1123.     }
  1124. }
  1125.  
  1126.  
  1127. /*
  1128.  -  MakePropValue
  1129.  -
  1130.  *  Purpose:
  1131.  *      Given a pointer to an SPropValue struct, a PropTag, and a
  1132.  *      string, make a prop value.  This is made to be compatible
  1133.  *      with the TableData text file format.  The lpv parameter
  1134.  *      is used to indicate that the memory should be allocated
  1135.  *      with MAPIAllocateMore().  lpv is passed in as the parent
  1136.  *      memory buffer to link to.
  1137.  *
  1138.  *  Parameters:
  1139.  *      lpspv       - Pointer to the destination prop value struct
  1140.  *      ulTag       - Property Tag identifying this property
  1141.  *      lpsz        - Stringized version of the data
  1142.  *      lpv         - Void pointer to a parent in a memory chain
  1143.  *
  1144.  *  WARNING:
  1145.  *      This may call strtok on lpsz. Strtok has the side effect of modifying
  1146.  *      the original string. So whatever lpsz points to may get modified.
  1147.  *
  1148.  *  Returns:
  1149.  *      BOOL    TRUE if successful, FALSE if not
  1150.  *
  1151.  */
  1152.  
  1153. BOOL MakePropValue(LPSPropValue lpspv, ULONG ulTag, LPSTR lpsz, LPVOID lpv)
  1154. {
  1155.     ULONG   idx = 0;
  1156.     BOOL    fRet = FALSE;
  1157.     ULONG   i, cVals;
  1158.     LPSTR   lpszF, lpszB;
  1159.     char    szTok[4096];
  1160.     char            *lpszToken      = NULL;
  1161.     SYSTEMTIME FAR  *lpSysTime  = NULL;
  1162.     LONG    l                   = 0;
  1163.  
  1164.     lpspv->ulPropTag = ulTag;
  1165.  
  1166.     switch(PROP_TYPE(ulTag))
  1167.     {
  1168.         case PT_I2:
  1169.             lpspv->Value.i = (short int)atoi(lpsz);
  1170.             break;
  1171.  
  1172.         case PT_LONG:
  1173.             lpspv->Value.l = strtol(lpsz, NULL, 0);
  1174.             break;
  1175.  
  1176.         case PT_R4:
  1177.             lpspv->Value.flt = (float)atof(lpsz);
  1178.             break;
  1179.  
  1180.         case PT_DOUBLE:
  1181.             lpspv->Value.dbl = strtod(lpsz, NULL);
  1182.             break;
  1183.  
  1184.         case PT_APPTIME:
  1185.             lpspv->Value.at = strtod(lpsz, NULL);
  1186.             break;
  1187.  
  1188.         case PT_ERROR:              
  1189.             if(GetID("MAPIErrors",lpsz, &l ) )
  1190.                 lpspv->Value.err = l;
  1191.             else  // throw in dummy value
  1192.                 lpspv->Value.err = S_OK;
  1193.             break;
  1194.  
  1195.         case PT_BOOLEAN:              //Convert String to ULONG
  1196.             lpspv->Value.b = ((USHORT)strtoul(lpsz, NULL, 10));
  1197.             break;
  1198.  
  1199.         case PT_CURRENCY:
  1200.         {
  1201.               char c;
  1202. #ifdef WIN32
  1203.               lpspv->Value.cur.Hi = strtol(&lpsz[4], NULL, 0 );
  1204.               c = lpsz[4];
  1205.               lpsz[4] = 0;
  1206.               lpspv->Value.cur.Lo = strtol(lpsz,  NULL,   0 );
  1207.               lpsz[4] = c;
  1208. #endif
  1209. #ifdef WIN16
  1210.               lpspv->Value.cur.Hi = strtol(&lpsz[4], NULL, 0 );
  1211.               c = lpsz[4];
  1212.               lpsz[4] = 0;
  1213.               lpspv->Value.cur.Lo = strtol(lpsz,  NULL,   0 );
  1214.               lpsz[4] = c;
  1215. #endif
  1216.         }
  1217.               break;
  1218.  
  1219.         case PT_SYSTIME:
  1220.             // The text format for this is <number> <number> where the two
  1221.             // numbers are seperated by a space or tab
  1222.  
  1223.             lpSysTime = (LPSYSTEMTIME) PvAlloc(sizeof(SYSTEMTIME) );
  1224.             memset(lpSysTime,0,(size_t) sizeof(SYSTEMTIME) );
  1225.             
  1226.             lpszToken   = strtok(lpsz,"/");
  1227.             lpSysTime->wYear   = atoi(lpszToken);
  1228.             lpszToken   = strtok(NULL,"/");
  1229.             lpSysTime->wMonth  = atoi(lpszToken);
  1230.             lpszToken   = strtok(NULL," ");
  1231.             lpSysTime->wDay    = atoi(lpszToken);
  1232.             lpszToken   = strtok(NULL,":");
  1233.             lpSysTime->wHour   = atoi(lpszToken);
  1234.             lpszToken   = strtok(NULL,":");
  1235.             lpSysTime->wMinute = atoi(lpszToken);
  1236.             lpszToken   = strtok(NULL," ");
  1237.             lpSysTime->wSecond = atoi(lpszToken);
  1238.  
  1239.             if( ! SystemTimeToFileTime(lpSysTime, &(lpspv->Value.ft) ) )
  1240.             {
  1241.                 PvFree(lpSysTime);
  1242.                 goto Cleanup;
  1243.             }    
  1244.  
  1245.             PvFree(lpSysTime);
  1246.             break;                
  1247.  
  1248.         case PT_BINARY:
  1249.             if (*lpsz != '~')
  1250.             {
  1251.                 LPBYTE lpb;
  1252.                 // it is 5  because the format for the binary data is as follows:
  1253.                 //  0x01 0x11 0xFF
  1254.                 ULONG   cb  = lstrlen(lpsz)/BINARY_CHAR_SIZE;
  1255.  
  1256.                 // lpszF is Front pointer to string parsing
  1257.                 // lpszB is Backk pointer to string parsing
  1258.                 lstrcpy(szTok, lpsz);
  1259.                 lpszF = lpszB = &szTok[0];
  1260.  
  1261.                 // determine length of binary data, if not null term, add 1 to count
  1262.                 if(lstrlen(lpsz)%BINARY_CHAR_SIZE != 0)
  1263.                     cb++;
  1264.  
  1265.                 if(lpv)
  1266.                     lpb = (LPBYTE)PvAllocMore(cb, lpv);
  1267.                 else
  1268.                     lpb = (LPBYTE)PvAlloc(cb);
  1269.  
  1270.                 lpspv->Value.bin.lpb    =  lpb;
  1271.                 lpspv->Value.bin.cb     =  cb;
  1272.  
  1273.                 // travers the binary data, and parse out the space in between
  1274.                 //  the hex values, with lpszB searching for next space or null
  1275.                 while(*lpszB)
  1276.                 {
  1277.  
  1278.                     while(*lpszB != ' ' && *lpszB != '\t' && *lpszB != '\0')
  1279.                         lpszB++;
  1280.  
  1281.                     if(*lpszB)
  1282.                     {
  1283.                         *lpszB = '\0';
  1284.                         lpszB++;
  1285.                     }
  1286.  
  1287.                     // strtoul() requries string to be in the following
  1288.                     // format to read the data as hex instead of string.
  1289.                     //  0x01 0x11 0xFF
  1290.                     //  with the prepending 0x before all numbers
  1291.                     *lpb++ = (BYTE)strtoul(lpszF, NULL, 0);
  1292.                     lpszF = lpszB;
  1293.                 }
  1294.             }
  1295.             else
  1296.                 EcBinaryFromFile(&lpspv->Value.bin, &lpsz[1], lpv);
  1297.  
  1298.             break;
  1299.  
  1300.         case PT_STRING8:
  1301.             if (*lpsz != '~')
  1302.             {
  1303.                 if(lpv)
  1304.                     lpspv->Value.lpszA = (LPSTR)PvAllocMore(lstrlen(lpsz)+1,
  1305.                                                             lpv);
  1306.                 else
  1307.                     lpspv->Value.lpszA = (LPSTR)PvAlloc(lstrlen(lpsz)+1);
  1308.  
  1309.                 lstrcpy(lpspv->Value.lpszA, lpsz);
  1310.             }
  1311.             else
  1312.                 EcStringFromFile(&lpspv->Value.lpszA, &lpsz[1], lpv);
  1313.             break;
  1314.  
  1315.         case PT_UNICODE:
  1316.             String8ToUnicode(lpsz,&lpspv->Value.lpszW,lpv);
  1317.             break;
  1318.  
  1319.         case PT_CLSID:
  1320.             if(lpv)
  1321.                 lpspv->Value.lpguid = (LPGUID)PvAllocMore(sizeof(GUID), lpv);
  1322.             else
  1323.                 lpspv->Value.lpguid = (LPGUID)PvAlloc(sizeof(GUID));
  1324.  
  1325.             lstrcpy(szTok, lpsz);
  1326.             lpszF = lpszB = &szTok[0];
  1327.  
  1328.             while(*lpszB != ' ' && *lpszB != '\t')
  1329.                 lpszB++;
  1330.  
  1331.             *lpszB = '\0';
  1332.             lpszB++;
  1333.  
  1334.             lpspv->Value.lpguid->Data1 = strtoul(lpszF, NULL, 0);
  1335.  
  1336.             lpszF = lpszB;
  1337.  
  1338.             while(*lpszB != ' ' && *lpszB != '\t')
  1339.                 lpszB++;
  1340.  
  1341.             *lpszB = '\0';
  1342.             lpszB++;
  1343.  
  1344.             lpspv->Value.lpguid->Data2 = (USHORT)strtoul(lpszF, NULL, 0);
  1345.  
  1346.             lpszF = lpszB;
  1347.  
  1348.             while(*lpszB != ' ' && *lpszB != '\t')
  1349.                 lpszB++;
  1350.  
  1351.             *lpszB = '\0';
  1352.             lpszB++;
  1353.  
  1354.             lpspv->Value.lpguid->Data3 = (USHORT)strtoul(lpszF, NULL, 0);
  1355.  
  1356.             lpszF = lpszB;
  1357.  
  1358.             for(idx = 0; idx < 8; idx++)
  1359.                  lpspv->Value.lpguid->Data4[idx] = lpszF[idx];
  1360.             break;
  1361.  
  1362.         case PT_I8:
  1363. //$ NYI
  1364.             // Ideas for how to handle this:
  1365.             // 1. Handle it like PT_SYSTIME where the two parts of the number are
  1366.             //      separated by space or tab
  1367.             // 2. Try to read in the whole number and if it overflows the low part
  1368.             //      then start on the high part
  1369.             break;
  1370.  
  1371.         /**********************************************/
  1372.         /***** Multi-Valued Properties go here!!! *****/
  1373.         /**********************************************/
  1374.  
  1375.         case PT_MV_I2:
  1376.             if ( lpszF = strtok(lpsz, ":") )
  1377.             {
  1378.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1379.                 {
  1380.                     lpspv->Value.MVi.cValues = cVals;
  1381.  
  1382.                     // Allocate array
  1383.                     if (lpv)
  1384.                         lpspv->Value.MVi.lpi = (short int FAR *)PvAllocMore(
  1385.                             sizeof(short int) * cVals, lpv);
  1386.                     else
  1387.                         lpspv->Value.MVi.lpi = (short int FAR *)PvAlloc(
  1388.                             sizeof(short int) * cVals);
  1389.  
  1390.                     for (i = 0; i < cVals; i++)
  1391.                     {
  1392.                         if ( lpszF = strtok(NULL, ";") )
  1393.                             lpspv->Value.MVi.lpi[i] = (short int)atoi(lpszF);
  1394.                         else
  1395.                             goto Cleanup;
  1396.                     }
  1397.                 }
  1398.                 else
  1399.                     goto Cleanup;
  1400.             }
  1401.             break;
  1402.  
  1403.         case PT_MV_LONG:
  1404.             if ( lpszF = strtok(lpsz, ":") )
  1405.             {
  1406.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1407.                 {
  1408.                     lpspv->Value.MVl.cValues = cVals;
  1409.  
  1410.                     // Allocate array
  1411.                     if (lpv)
  1412.                         lpspv->Value.MVl.lpl = (LONG FAR *)PvAllocMore(
  1413.                             sizeof(LONG) * cVals, lpv);
  1414.                     else
  1415.                         lpspv->Value.MVl.lpl = (LONG FAR *)PvAlloc(
  1416.                             sizeof(LONG) * cVals);
  1417.  
  1418.                     for (i = 0; i < cVals; i++)
  1419.                     {
  1420.                         if ( lpszF = strtok(NULL, ";") )
  1421.                             lpspv->Value.MVl.lpl[i] = (LONG)strtol(lpszF, NULL, 0);
  1422.                         else
  1423.                             goto Cleanup;
  1424.                     }
  1425.                 }
  1426.                 else
  1427.                     goto Cleanup;
  1428.             }
  1429.             break;
  1430.  
  1431.         case PT_MV_R4:
  1432.             if ( lpszF = strtok(lpsz, ":") )
  1433.             {
  1434.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1435.                 {
  1436.                     lpspv->Value.MVflt.cValues = cVals;
  1437.  
  1438.                     // Allocate array
  1439.                     if (lpv)
  1440.                         lpspv->Value.MVflt.lpflt = (float FAR *)PvAllocMore(
  1441.                             sizeof(float) * cVals, lpv);
  1442.                     else
  1443.                         lpspv->Value.MVflt.lpflt = (float FAR *)PvAlloc(
  1444.                             sizeof(float) * cVals);
  1445.  
  1446.                     for (i = 0; i < cVals; i++)
  1447.                     {
  1448.                         if ( lpszF = strtok(NULL, ";") )
  1449.                             lpspv->Value.MVflt.lpflt[i] = (float)atof(lpszF);
  1450.                         else
  1451.                             goto Cleanup;
  1452.                     }
  1453.                 }
  1454.                 else
  1455.                     goto Cleanup;
  1456.             }
  1457.             break;
  1458.  
  1459.         case PT_MV_DOUBLE:
  1460.             if ( lpszF = strtok(lpsz, ":") )
  1461.             {
  1462.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1463.                 {
  1464.                     lpspv->Value.MVdbl.cValues = cVals;
  1465.  
  1466.                     // Allocate array
  1467.                     if (lpv)
  1468.                         lpspv->Value.MVdbl.lpdbl = (double FAR *)PvAllocMore(
  1469.                             sizeof(double) * cVals, lpv);
  1470.                     else
  1471.                         lpspv->Value.MVdbl.lpdbl = (double FAR *)PvAlloc(
  1472.                             sizeof(double) * cVals);
  1473.  
  1474.                     for (i = 0; i < cVals; i++)
  1475.                     {
  1476.                         if ( lpszF = strtok(NULL, ";") )
  1477.                             lpspv->Value.MVdbl.lpdbl[i] = (double)strtod(lpszF, NULL);
  1478.                         else
  1479.                             goto Cleanup;
  1480.                     }
  1481.                 }
  1482.                 else
  1483.                     goto Cleanup;
  1484.             }
  1485.             break;
  1486.  
  1487.         case PT_MV_CURRENCY:
  1488.             if ( lpszF = strtok(lpsz, ":") )
  1489.             {
  1490.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1491.                 {
  1492.                     lpspv->Value.MVcur.cValues = cVals;
  1493.  
  1494.                     // Allocate array
  1495.                     if (lpv)
  1496.                         lpspv->Value.MVcur.lpcur = (CURRENCY FAR *)PvAllocMore(
  1497.                             sizeof(CURRENCY) * cVals, lpv);
  1498.                     else
  1499.                         lpspv->Value.MVcur.lpcur = (CURRENCY FAR *)PvAlloc(
  1500.                             sizeof(CURRENCY) * cVals);
  1501.  
  1502.                     for (i = 0; i < cVals; i++)
  1503.                     {
  1504.                         if ( lpszF = strtok(NULL, ";") )
  1505.                         {
  1506.                             char c;
  1507.                             #ifdef WIN32
  1508.                             lpspv->Value.MVcur.lpcur[i].Hi = strtol(&lpsz[4], NULL, 0 );
  1509.                             c = lpsz[4];
  1510.                             lpsz[4] = 0;
  1511.                             lpspv->Value.MVcur.lpcur[i].Lo = strtol(lpsz,  NULL,   0 );
  1512.                             lpsz[4] = c;
  1513.                             #endif
  1514.                             #ifdef WIN16
  1515.                             lpspv->Value.MVcur.lpcur[i].Hi = strtol(&lpsz[4], NULL, 0 );
  1516.                             c = lpsz[4];
  1517.                             lpsz[4] = 0;
  1518.                             lpspv->Value.MVcur.lpcur[i].Lo = strtol(lpsz,  NULL,   0 );
  1519.                             lpsz[4] = c;
  1520.                             #endif
  1521.                         }
  1522.                         else
  1523.                             goto Cleanup;
  1524.                     }
  1525.                 }
  1526.                 else
  1527.                     goto Cleanup;
  1528.             }
  1529.             break;
  1530.  
  1531.         case PT_MV_APPTIME:
  1532.             if ( lpszF = strtok(lpsz, ":") )
  1533.             {
  1534.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1535.                 {
  1536.                     lpspv->Value.MVat.cValues = cVals;
  1537.  
  1538.                     // Allocate array
  1539.                     if (lpv)
  1540.                         lpspv->Value.MVat.lpat = (double FAR *)PvAllocMore(
  1541.                             sizeof(double) * cVals, lpv);
  1542.                     else
  1543.                         lpspv->Value.MVat.lpat = (double FAR *)PvAlloc(
  1544.                             sizeof(double) * cVals);
  1545.  
  1546.                     for (i = 0; i < cVals; i++)
  1547.                     {
  1548.                         if ( lpszF = strtok(NULL, ";") )
  1549.                             lpspv->Value.MVat.lpat[i] = (double)strtod(lpszF, NULL);
  1550.                         else
  1551.                             goto Cleanup;
  1552.                     }
  1553.                 }
  1554.                 else
  1555.                     goto Cleanup;
  1556.             }
  1557.             break;
  1558.  
  1559.         case PT_MV_SYSTIME:
  1560.             // The text format for a single systime is <number> <number> where
  1561.             // the two numbers are seperated by a space or tab
  1562.             if ( lpsz = strtok(lpsz, ":") )
  1563.             {
  1564.                 if ( cVals = strtoul(lpsz, NULL, 0) )
  1565.                 {
  1566.                     lpspv->Value.MVft.cValues = cVals;
  1567.  
  1568.                     // Allocate array
  1569.                     if (lpv)
  1570.                         lpspv->Value.MVft.lpft = (FILETIME FAR *)PvAllocMore(
  1571.                             sizeof(FILETIME) * cVals, lpv);
  1572.                     else
  1573.                         lpspv->Value.MVft.lpft = (FILETIME FAR *)PvAlloc(
  1574.                             sizeof(FILETIME) * cVals);
  1575.  
  1576.                     for (i = 0; i < cVals; i++)
  1577.                     {
  1578.                         if ( lpsz = strtok(NULL, ";") )
  1579.                         {
  1580.                             lstrcpy(szTok, lpsz);
  1581.                             lpszF = lpszB = &szTok[0];
  1582.  
  1583.                             while(*lpszB != ' ' && *lpszB != '\t')
  1584.                                 lpszB++;
  1585.  
  1586.                             *lpszB = '\0';
  1587.                             lpszB++;
  1588.  
  1589.                             lpspv->Value.MVft.lpft[i].dwHighDateTime = strtoul(lpszF, NULL, 0);
  1590.  
  1591.                             lpszF = lpszB;
  1592.  
  1593.                             while(*lpszB != ' ' && *lpszB != '\t' && *lpszB != '\0')
  1594.                                 lpszB++;
  1595.  
  1596.                             *lpszB = '\0';
  1597.  
  1598.                             lpspv->Value.MVft.lpft[i].dwLowDateTime = strtoul(lpszF, NULL, 0);
  1599.                         }
  1600.                         else
  1601.                             goto Cleanup;
  1602.                     }
  1603.                 }
  1604.                 else
  1605.                     goto Cleanup;
  1606.             }
  1607.             break;
  1608.  
  1609.         case PT_MV_BINARY:
  1610.             if ( lpszF = strtok(lpsz, ":") )
  1611.             {
  1612.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1613.                 {
  1614.                     lpspv->Value.MVbin.cValues = cVals;
  1615.  
  1616.                     // Allocate array
  1617.                     if (lpv)
  1618.                         lpspv->Value.MVbin.lpbin = (SBinary FAR *)PvAllocMore(
  1619.                             sizeof(SBinary) * cVals, lpv);
  1620.                     else
  1621.                         lpspv->Value.MVbin.lpbin = (SBinary FAR *)PvAlloc(
  1622.                             sizeof(SBinary) * cVals);
  1623.  
  1624.                     for (i = 0; i < cVals; i++)
  1625.                     {
  1626.                         if ( lpsz = strtok(NULL, ";") )
  1627.                         {
  1628.                             if (*lpsz != '~')
  1629.                             {
  1630.                                 LPBYTE lpb;
  1631.                                 // it is 5  because the format for the binary data is as follows:
  1632.                                 //  0x01 0x11 0xFF
  1633.                                 ULONG   cb  = lstrlen(lpsz)/BINARY_CHAR_SIZE;
  1634.  
  1635.                                 // lpszF is Front pointer to string parsing
  1636.                                 // lpszB is Backk pointer to string parsing
  1637.                                 lstrcpy(szTok, lpsz);
  1638.                                 lpszF = lpszB = &szTok[0];
  1639.  
  1640.                                 // determine length of binary data, if not null term, add 1 to count
  1641.                                 if(lstrlen(lpsz)%BINARY_CHAR_SIZE != 0)
  1642.                                     cb++;
  1643.  
  1644.                                 if(lpv)
  1645.                                     lpb = (LPBYTE)PvAllocMore(cb, lpv);
  1646.                                 else
  1647.                                     lpb = (LPBYTE)PvAlloc(cb);
  1648.  
  1649.                                 lpspv->Value.MVbin.lpbin[i].lpb    =  lpb;
  1650.                                 lpspv->Value.MVbin.lpbin[i].cb     =  cb;
  1651.  
  1652.                                 // travers the binary data, and parse out the space in between
  1653.                                 //  the hex values, with lpszB searching for next space or null
  1654.                                 while(*lpszB)
  1655.                                 {
  1656.  
  1657.                                     while(*lpszB != ' ' && *lpszB != '\t' && *lpszB != '\0')
  1658.                                         lpszB++;
  1659.  
  1660.                                     if(*lpszB)
  1661.                                     {
  1662.                                         *lpszB = '\0';
  1663.                                         lpszB++;
  1664.                                     }
  1665.  
  1666.                                     // strtoul() requries string to be in the following
  1667.                                     // format to read the data as hex instead of string.
  1668.                                     //  0x01 0x11 0xFF
  1669.                                     //  with the prepending 0x before all numbers
  1670.                                     *lpb++ = (BYTE)strtoul(lpszF, NULL, 0);
  1671.                                     lpszF = lpszB;
  1672.                                 }
  1673.                             }
  1674.                             else
  1675.                                 EcBinaryFromFile(&lpspv->Value.MVbin.lpbin[i], &lpsz[1], lpv);
  1676.                         }
  1677.                         else
  1678.                             goto Cleanup;
  1679.                     }
  1680.                 }
  1681.                 else
  1682.                     goto Cleanup;
  1683.             }
  1684.             break;
  1685.  
  1686.         case PT_MV_STRING8:
  1687.             if ( lpszF = strtok(lpsz, ":") )
  1688.             {
  1689.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1690.                 {
  1691.                     lpspv->Value.MVszA.cValues = cVals;
  1692.  
  1693.                     // Allocate array of string pointers
  1694.                     if (lpv)
  1695.                         lpspv->Value.MVszA.lppszA = (LPSTR FAR *)PvAllocMore(
  1696.                             sizeof(LPSTR) * cVals, lpv);
  1697.                     else
  1698.                         lpspv->Value.MVszA.lppszA = (LPSTR FAR *)PvAlloc(
  1699.                             sizeof(LPSTR) * cVals);
  1700.  
  1701.                     // Parse strings
  1702.                     for (i = 0; i < cVals; i++)
  1703.                     {
  1704.                         if ( lpszF = strtok(NULL, ";") )
  1705.                         {
  1706.                             if (*lpszF != '~')
  1707.                             {
  1708.                                 if(lpv)
  1709.                                     lpspv->Value.MVszA.lppszA[i] = (LPSTR)
  1710.                                         PvAllocMore(lstrlen(lpszF)+1, lpv);
  1711.                                 else
  1712.                                     lpspv->Value.MVszA.lppszA[i] = (LPSTR)
  1713.                                         PvAlloc(lstrlen(lpszF)+1);
  1714.  
  1715.                                 lstrcpy(lpspv->Value.MVszA.lppszA[i], lpszF);
  1716.                             }
  1717.                             else
  1718.                                 EcStringFromFile( &lpspv->Value.MVszA.lppszA[i],
  1719.                                                   &lpszF[1], lpv);
  1720.                         }
  1721.                         else
  1722.                             goto Cleanup;
  1723.                     }
  1724.                 }
  1725.                 else
  1726.                     goto Cleanup;
  1727.             }
  1728.             break;
  1729.  
  1730.         case PT_MV_UNICODE:
  1731. //$ NYI
  1732.  
  1733.             if ( lpszF = strtok(lpsz, ":") )
  1734.             {
  1735.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1736.                 {
  1737.                     lpspv->Value.MVszW.cValues = cVals;
  1738.  
  1739.                     // Allocate array of string pointers
  1740.                     if (lpv)
  1741.                         lpspv->Value.MVszW.lppszW = (LPWSTR FAR *)PvAllocMore(
  1742.                             sizeof(LPWSTR) * cVals, lpv);
  1743.                     else
  1744.                         lpspv->Value.MVszW.lppszW = (LPWSTR FAR *)PvAlloc(
  1745.                             sizeof(LPWSTR) * cVals);
  1746.  
  1747.                     // Parse strings
  1748.                     for (i = 0; i < cVals; i++)
  1749.                     {
  1750.                         if ( lpszF = strtok(NULL, ";") )
  1751.                         {
  1752.                             lpspv->Value.MVszW.lppszW[i] = NULL;
  1753. /*
  1754.                             if (*lpszF != '~')
  1755.                             {
  1756.                                 if(lpv)
  1757.                                     lpspv->Value.MVszW.lppszW[i] = (LPWSTR)
  1758.                                         PvAllocMore(lstrlen(lpszF)+1, lpv);
  1759.                                 else
  1760.                                     lpspv->Value.MVszW.lppszW[i] = (LPWSTR)
  1761.                                         PvAlloc(lstrlen(lpszF)+1);
  1762.  
  1763.                                 lstrcpy(lpspv->Value.MVszW.lppszW[i], lpszF);
  1764.                             }
  1765.                             else
  1766.                                 EcStringFromFile( &lpspv->Value.MVszW.lppszW[i],
  1767.                                                   &lpszF[1], lpv);
  1768. */
  1769.                         }
  1770.                         else
  1771.                             goto Cleanup;
  1772.                     }
  1773.                 }
  1774.                 else
  1775.                     goto Cleanup;
  1776.             }
  1777.             break;
  1778.  
  1779.         case PT_MV_CLSID:
  1780.             if ( lpszF = strtok(lpsz, ":") )
  1781.             {
  1782.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1783.                 {
  1784.                     lpspv->Value.MVguid.cValues = cVals;
  1785.  
  1786.                     // Allocate array
  1787.                     if (lpv)
  1788.                         lpspv->Value.MVguid.lpguid = (LPGUID)PvAllocMore(
  1789.                             sizeof(GUID) * cVals, lpv);
  1790.                     else
  1791.                         lpspv->Value.MVguid.lpguid = (LPGUID)PvAlloc(
  1792.                             sizeof(GUID) * cVals);
  1793.  
  1794.                     for (i = 0; i < cVals; i++)
  1795.                     {
  1796.                         if ( lpszF = strtok(NULL, ";") )
  1797.                         {
  1798.                             lstrcpy(szTok, lpsz);
  1799.                             lpszF = lpszB = &szTok[0];
  1800.  
  1801.                             while(*lpszB != ' ' && *lpszB != '\t')
  1802.                                 lpszB++;
  1803.  
  1804.                             *lpszB = '\0';
  1805.                             lpszB++;
  1806.  
  1807.                             lpspv->Value.MVguid.lpguid[i].Data1 = strtoul(lpszF, NULL, 0);
  1808.  
  1809.                             lpszF = lpszB;
  1810.  
  1811.                             while(*lpszB != ' ' && *lpszB != '\t')
  1812.                                 lpszB++;
  1813.  
  1814.                             *lpszB = '\0';
  1815.                             lpszB++;
  1816.  
  1817.                             lpspv->Value.MVguid.lpguid[i].Data2 = (USHORT)strtoul(lpszF, NULL, 0);
  1818.  
  1819.                             lpszF = lpszB;
  1820.  
  1821.                             while(*lpszB != ' ' && *lpszB != '\t')
  1822.                                 lpszB++;
  1823.  
  1824.                             *lpszB = '\0';
  1825.                             lpszB++;
  1826.  
  1827.                             lpspv->Value.MVguid.lpguid[i].Data3 = (USHORT)strtoul(lpszF, NULL, 0);
  1828.  
  1829.                             lpszF = lpszB;
  1830.  
  1831.                             for(idx = 0; idx < 8; idx++)
  1832.                                  lpspv->Value.MVguid.lpguid[i].Data4[idx] = lpszF[idx];
  1833.                         }
  1834.                         else
  1835.                             goto Cleanup;
  1836.                     }
  1837.                 }
  1838.                 else
  1839.                     goto Cleanup;
  1840.             }
  1841.             break;
  1842.  
  1843.         case PT_MV_I8:
  1844. //$ NYI
  1845.             // Ideas to handle this:
  1846.             // 1. Handle it like PT_SYSTIME where the two parts of the number are
  1847.             //      separated by space or tab
  1848.             // 2. Try to read in the whole number and if it overflows the low part
  1849.             //      then start on the high part
  1850.  
  1851. /*
  1852.             if ( lpszF = strtok(lpsz, ":") )
  1853.             {
  1854.                 if ( cVals = strtoul(lpszF, NULL, 0) )
  1855.                 {
  1856.                     lpspv->Value.MVli.cValues = cVals;
  1857.  
  1858.                     // Allocate array
  1859.                     lpspv->Value.MVli.lpli = (LARGE_INTEGER FAR *)PvAllocMore(
  1860.                         sizeof(LARGE_INTEGER) * cVals, lpv);
  1861.  
  1862.                     for (i = 0; i < cVals; i++)
  1863.                     {
  1864.                         if ( lpszF = strtok(NULL, ";") )
  1865.                             lpspv->Value.MVli.lpli[i] = (LARGE_INTEGER)atof(lpszF);
  1866.                         else
  1867.                             goto Cleanup;
  1868.                     }
  1869.                 }
  1870.                 else
  1871.                     goto Cleanup;
  1872.             }
  1873. */
  1874.             break;
  1875.  
  1876.  
  1877.         case PT_UNSPECIFIED:
  1878.         case PT_NULL:
  1879.         case PT_OBJECT:
  1880.         default:
  1881.             lpspv->Value.x = 0L;
  1882.             break;
  1883.     }
  1884.  
  1885.     fRet = TRUE;
  1886.  
  1887.  
  1888. Cleanup:
  1889.  
  1890.     return(fRet);
  1891.  
  1892. }
  1893.  
  1894.  
  1895. /*
  1896.  -  CopyGuid
  1897.  -
  1898.  *  Purpose:
  1899.  *      Copies the contents of one GUID into another.
  1900.  *
  1901.  *  Parameters:
  1902.  *      lpg1        - Pointer to destination GUID
  1903.  *      lpg2        - Pointer to source GUID
  1904.  *
  1905.  *  Returns:
  1906.  *      Void.
  1907.  *
  1908.  */
  1909.  
  1910. void CopyGuid(LPGUID lpg1, LPGUID lpg2)
  1911. {
  1912.     int i = 0;
  1913.  
  1914.     if(!lpg1 || !lpg2)
  1915.         return;
  1916.  
  1917.     lpg1->Data1 = lpg2->Data1;
  1918.     lpg1->Data2 = lpg2->Data2;
  1919.     lpg1->Data3 = lpg2->Data3;
  1920.  
  1921.     for(; i < 8; i++)
  1922.         lpg1->Data4[i] = lpg2->Data4[i];
  1923.  
  1924.     return;
  1925. }
  1926.  
  1927.  
  1928.  
  1929. /*
  1930.  -  FreeRowSet(LPSRowSet)
  1931.  -
  1932.  *  Purpose:
  1933.  *      Free all the rows in a rowset then the rowset itself
  1934.  *
  1935.  *  Parameters:
  1936.  *      lpRows    - pointer to rows to free
  1937.  *
  1938.  *  Returns:
  1939.  *      BOOL Pass/Fail  - Pass == 1 FAIL == 0
  1940.  *
  1941.  */
  1942.  
  1943. BOOL FreeRowSet(LPSRowSet lpRows)
  1944. {
  1945.     ULONG   n;
  1946.     BOOL    fRet    = FALSE;
  1947.  
  1948.     if(lpRows)
  1949.     {
  1950.         for( n = 0 ; n < lpRows->cRows ; n++)
  1951.         {
  1952.             if( MAPIFreeBuffer(lpRows->aRow[n].lpProps ) )
  1953.             {
  1954.                 goto end;
  1955.             }
  1956.         }
  1957.         if( MAPIFreeBuffer(lpRows) )
  1958.         {
  1959.             goto end;
  1960.         }
  1961.     }
  1962.     fRet = TRUE;
  1963. end:
  1964.     return(fRet);
  1965. }
  1966.  
  1967. /***********************************************************************
  1968.  *  Purpose:
  1969.  *      Determine if Prop Tag is an EntryID
  1970.  *
  1971.  *  Parameters:
  1972.  *      [in]
  1973.  *          ulPropTag   - PropTag to determine if entryid or not
  1974.  *
  1975.  *  Returns:
  1976.  *      TRUE it is an entryid, false otherwise
  1977.  *
  1978.  ***********************************************************************/
  1979.  
  1980. BOOL    FIsEntryID(ULONG ulPropTag)
  1981. {
  1982.     if(ulPropTag == PR_ENTRYID)    
  1983.         return(TRUE);
  1984.  
  1985.     if(ulPropTag == PR_STORE_ENTRYID)    
  1986.         return(TRUE);
  1987.  
  1988.     if(ulPropTag == PR_COMMON_VIEWS_ENTRYID)    
  1989.         return(TRUE);
  1990.  
  1991.     if(ulPropTag == PR_FINDER_ENTRYID)    
  1992.         return(TRUE);
  1993.  
  1994.     if(ulPropTag == PR_HEADER_FOLDER_ENTRYID)    
  1995.         return(TRUE);
  1996.  
  1997.     if(ulPropTag == PR_IDENTITY_ENTRYID)    
  1998.         return(TRUE);
  1999.  
  2000.     if(ulPropTag == PR_IPM_OUTBOX_ENTRYID)    
  2001.         return(TRUE);
  2002.  
  2003.     if(ulPropTag == PR_IPM_SENTMAIL_ENTRYID)    
  2004.         return(TRUE);
  2005.  
  2006.     if(ulPropTag == PR_IPM_SUBTREE_ENTRYID)    
  2007.         return(TRUE);
  2008.  
  2009.     if(ulPropTag == PR_IPM_WASTEBASKET_ENTRYID)    
  2010.         return(TRUE);
  2011.  
  2012.     if(ulPropTag == PR_ORIGINAL_AUTHOR_ENTRYID)    
  2013.         return(TRUE);
  2014.  
  2015.     if(ulPropTag == PR_ORIGINAL_ENTRYID)    
  2016.         return(TRUE);
  2017.  
  2018.     if(ulPropTag == PR_ORIGINAL_SENDER_ENTRYID)    
  2019.         return(TRUE);
  2020.  
  2021.     if(ulPropTag == PR_ORIGINAL_SENT_REPRESENTING_ENTRYID)    
  2022.         return(TRUE);
  2023.  
  2024.     if(ulPropTag == PR_OWN_STORE_ENTRYID)    
  2025.         return(TRUE);
  2026.  
  2027.     if(ulPropTag == PR_PARENT_ENTRYID)    
  2028.         return(TRUE);
  2029.  
  2030.     if(ulPropTag == PR_RCVD_REPRESENTING_ENTRYID)    
  2031.         return(TRUE);
  2032.  
  2033.     if(ulPropTag == PR_READ_RECEIPT_ENTRYID)    
  2034.         return(TRUE);
  2035.  
  2036.     if(ulPropTag == PR_RECEIVED_BY_ENTRYID)    
  2037.         return(TRUE);
  2038.  
  2039.     if(ulPropTag == PR_REPORT_ENTRYID)    
  2040.         return(TRUE);
  2041.  
  2042.     if(ulPropTag == PR_SENDER_ENTRYID)    
  2043.         return(TRUE);
  2044.  
  2045.     if(ulPropTag == PR_SENT_REPRESENTING_ENTRYID)    
  2046.         return(TRUE);
  2047.  
  2048.     if(ulPropTag == PR_SENTMAIL_ENTRYID)    
  2049.         return(TRUE);
  2050.  
  2051.     if(ulPropTag == PR_VIEWS_ENTRYID)    
  2052.         return(TRUE);
  2053.  
  2054.  
  2055.     return(FALSE);
  2056.                 
  2057. }
  2058.  
  2059.  
  2060.  
  2061. static char szBinaryTestData[] = "0xDD 0xEE 0xAA 0xFF";
  2062. #define BINARY_TEST_FLAG_SIZE      4
  2063.  
  2064.  
  2065. /***********************************************************************
  2066.  *
  2067.  -  WritePropValArray
  2068.  -
  2069.  *  Purpose:
  2070.  *      Store a LPSPropValue Array in a file under a tag specified
  2071.  *
  2072.  *  Parameters:
  2073.  *      [in]
  2074.  *       lpszFilename   - name of the file to store prop value in
  2075.  *       lpszTag        - name of Tag Identifier in file delimited by [ ]
  2076.  *                          ex.  [FLD0001]
  2077.  *       cValues        - number of prop values in array
  2078.  *       lpspva         - prop value array to store in text format in file
  2079.  *       ulFlags        - used for determining things like whether to
  2080.  *                          dump actual binary data or not.(see enumerations
  2081.  *                          above.  i.e. DUMP_BINARY_DATA.
  2082.  *
  2083.  *  Returns:
  2084.  *      nothing
  2085.  *
  2086.  *    #define DUMP_BINARY_DATA        0x0001
  2087.  *    #define WRITE_NEW_DATA_ONLY     0x0010
  2088.  *
  2089.  ***********************************************************************/
  2090.  
  2091. // size of szBuffer for each data item to write to file
  2092. #define BUFFSIZE          4096
  2093.  
  2094.  
  2095. void WritePropValArray( LPSTR           lpszFileName,
  2096.                         LPSTR           lpszTag,
  2097.                         ULONG           cValues,
  2098.                         LPSPropValue    lpspva,
  2099.                         ULONG           ulFlags)    // defaults to 0 if not given
  2100. {
  2101.     ULONG   idx;
  2102.     char    szBuffer[BUFFSIZE];
  2103.     char    szLine1[2048];  // limitation of 2k of prop tags
  2104.     char    szLine2[20000];  // limitation of 12k of prop data, now has binary data
  2105.     FILE    *pFile              = NULL;
  2106.     int     len1                = 0;
  2107.     int     len2                = 0;
  2108.  
  2109.  
  2110.     // assert valid parameters
  2111.     if((lpszFileName == NULL) || (cValues == 0) || (lpszTag == NULL))
  2112.         return;
  2113.  
  2114.     // if set, only write data that has unique tag...ie. one that is not
  2115.     // already in the file.  If if exists in file already, then don't write data
  2116.     if( ulFlags & WRITE_NEW_DATA_ONLY)    
  2117.     {
  2118.         // if tag already in file, don't write anything now.
  2119.         pFile = fopen(lpszFileName, "r+");
  2120.         if (pFile == NULL)
  2121.             goto WriteInFile;
  2122.             
  2123.         // if this tag already in data file, don't write new data 
  2124.         if ( FSeekTag(pFile, lpszTag) )
  2125.         {
  2126.             fprintf(pFile,"Tag %s FOUND IN file %s\n",lpszTag,lpszFileName);
  2127.             fclose(pFile);
  2128.             return;
  2129.         }
  2130.  
  2131.         if (pFile)
  2132.         {
  2133.             fclose(pFile);
  2134.             pFile = NULL;
  2135.         }
  2136.  
  2137.     }
  2138.  
  2139. WriteInFile:
  2140.  
  2141.     // else not in file, write it out
  2142.     
  2143.     // determine within range of arrays
  2144.  
  2145.     // these are initialized so strcat works correctly
  2146.     szBuffer[0] = '\0';
  2147.     szLine1[0]  = '\0';
  2148.     szLine2[0]  = '\0';
  2149.  
  2150.     // in case the first data is a empty string, we need to 
  2151.     // buffer with one space for special case because read routines
  2152.     // will not parse a beginning comma.
  2153.     strcat(szLine2," ");
  2154.  
  2155.     // for every value in lpspva, convert to correct format to put in file
  2156.     for(idx = 0; idx < cValues ; idx++)
  2157.     {
  2158.         // get Prop tag, put in string for 1st line
  2159.         // append ", " to end of prop tag unless it's the last
  2160.         if( !GetString("PropIDs",PROP_ID(lpspva[idx].ulPropTag) , szBuffer) )
  2161.             wsprintf(szBuffer,"0x%08X",lpspva[idx].ulPropTag);      // id not found, use hex tag
  2162.  
  2163.         strcat(szLine1,szBuffer);
  2164.         strcat(szLine1,", ");
  2165.  
  2166.         // if error, then flag for Read routine later with <PT_ERROR>
  2167.         if(PROP_TYPE(lpspva[idx].ulPropTag) == PT_ERROR)
  2168.             strcat(szLine2,"<PT_ERROR>");
  2169.         
  2170.  
  2171.         // USUALLY PT_BINARY are like PR_ENTRYIDs and not
  2172.         //   comparsable byte for byte, so merely store tag
  2173.         //   and dummy data that is a flag it came from my
  2174.         //   store routine, and in the comparison, we need
  2175.         //   to look for this flag as a condition that we shouldn't
  2176.         //   campare byte for byte the PT_BINARY data
  2177.  
  2178.         if( PROP_TYPE(lpspva[idx].ulPropTag) == PT_BINARY)
  2179.         {
  2180.             // dump dummy stub value 0xDD 0xEE 0xAA 0xFF
  2181.             // OR dump actual binary data
  2182.             // in following format:  0x56 0x44 0x00 0x02 0x33
  2183.             // OR data is too big to log all of it > 204 == 1024/5          
  2184.             if( (!(ulFlags & DUMP_BINARY_DATA)) || (FIsEntryID(lpspva[idx].ulPropTag)) || (lpspva[idx].Value.bin.cb > (BUFFSIZE/BINARY_CHAR_SIZE)) )
  2185.             {
  2186.                 wsprintf(szBuffer,"%s",szBinaryTestData);
  2187.             }
  2188.             else  // we want to write the binary data to file
  2189.             {
  2190.                 char    lpszHex[9];
  2191.                 ULONG   cb              = 0;
  2192.                 int     cChars          = 0;
  2193.                 LPBYTE  lpb             = lpspva[idx].Value.bin.lpb;
  2194.  
  2195.                 szBuffer[0]             = '\0';
  2196.  
  2197.                 // while still bytes to copy and within buffer limit    
  2198.                 // buffer limit == szBuffer == 1024 bytes, 5 characters per byte of
  2199.                 // data, our limit == 1024 / 5 == 204 bytes stored in file per property
  2200.                 // if it is larger than 204 bytes, we should log 0xDD 0xEE 0xAA 0xFF
  2201.                 while((cb < lpspva[idx].Value.bin.cb) && (cChars < BUFFSIZE ) )
  2202.                 {
  2203.                     wsprintf(lpszHex, " 0x%02X", *lpb);
  2204.                     lstrcat(szBuffer, lpszHex);
  2205.                     cChars += BINARY_CHAR_SIZE;   // looks like 0x34 0x44 0x55, each taking space, 0, x, 2 bytes data == 5 spaces
  2206.                     lpb++;
  2207.                     cb++;
  2208.                 }
  2209.             }
  2210.         }
  2211.         else
  2212.         {
  2213.             if( !SzGetPropValue(szBuffer, &(lpspva[idx]) ) )
  2214.                 return;
  2215.         }
  2216.         strcat(szLine2,szBuffer);
  2217.         strcat(szLine2,", ");
  2218.  
  2219.     }
  2220.  
  2221.     // take off the last comma and space from both lines
  2222.     len1 = lstrlen(szLine1);
  2223.     szLine1[len1 - 2] = '\0';
  2224.  
  2225.     len2 = lstrlen(szLine2);
  2226.     szLine2[len2 - 2] = '\0';
  2227.  
  2228.     pFile = fopen(lpszFileName, "a");
  2229.     if (pFile == NULL)
  2230.         return;
  2231.  
  2232.     // fprintf Tag, proptags, propdata
  2233.     fprintf(pFile,"%s\n",lpszTag);
  2234.     fprintf(pFile,"%s\n",szLine1);
  2235.     fprintf(pFile,"%s\n",szLine2);
  2236.     fprintf(pFile,"\n");
  2237.  
  2238.     if (pFile)
  2239.         fclose(pFile);
  2240.  
  2241.  
  2242.  
  2243. }
  2244.  
  2245.  
  2246.  
  2247. /***********************************************************************
  2248.  *
  2249.  -  WritePropTagArray
  2250.  -
  2251.  *  Purpose:
  2252.  *      Store a LPSPropTagArray in a file under a tag specified
  2253.  *
  2254.  *  Parameters:
  2255.  *      [in]
  2256.  *       lpszFilename   - name of the file to store prop value in
  2257.  *       lpszTag        - name of Tag Identifier in file delimited by [ ]
  2258.  *                          ex.  [FLD0001]
  2259.  *       lpspva         - prop tag array to store in text format in file
  2260.  *
  2261.  *  Returns:
  2262.  *      nothing
  2263.  *
  2264.  *  Example:
  2265.  *      StorePropTag("C:\\MAPITEST\\DATA\\PROPVU.TXT",
  2266.  *                     "[FLD00001]"
  2267.  *                     lpsPTA);
  2268.  *
  2269.  ***********************************************************************/
  2270.  
  2271. void WritePropTagArray( LPSTR           lpszFileName,
  2272.                         LPSTR           lpszTag,
  2273.                         LPSPropTagArray lpspta)
  2274. {
  2275.     ULONG   idx;
  2276.     char    szBuffer[256];
  2277.     char    szLine1[2048];  // limitation of 2k of prop tags
  2278.     FILE    *pFile              = NULL;
  2279.     int     len1                = 0;
  2280.  
  2281.     // assert valid parameters
  2282.     if((lpszFileName == NULL) || (lpspta == NULL) || (lpszTag == NULL))
  2283.             return;
  2284.  
  2285.     // these are initialized so strcat works correctly
  2286.     szBuffer[0] = '\0';
  2287.     szLine1[0]  = '\0';
  2288.  
  2289.     // for every value in lpspva, convert to correct format to put in file
  2290.     for(idx = 0; idx < lpspta->cValues ; idx++)
  2291.     {
  2292.         // get Prop tag, put in string for 1st line
  2293.         // append ", " to end of prop tag unless it's the last
  2294.         if( !GetString("PropIDs",PROP_ID(lpspta->aulPropTag[idx]) , szBuffer) )
  2295.             wsprintf(szBuffer,"0x%08X",lpspta->aulPropTag[idx]);        // id not found, use hex
  2296.         strcat(szLine1,szBuffer);
  2297.         strcat(szLine1,", ");
  2298.     }
  2299.  
  2300.     // take off the last comma and space from both lines
  2301.     len1 = lstrlen(szLine1);
  2302.     szLine1[len1 - 2] = '\0';
  2303.  
  2304.     pFile = fopen(lpszFileName, "a");
  2305.     if (pFile == NULL)
  2306.         return;
  2307.  
  2308.     // fprintf Tag, proptags, propdata
  2309.     fprintf(pFile,"%s\n",lpszTag);
  2310.     fprintf(pFile,"%s\n",szLine1);
  2311.     fprintf(pFile,"\n");
  2312.  
  2313.     if (pFile)
  2314.         fclose(pFile);
  2315.  
  2316. }
  2317.  
  2318.  
  2319. /***********************************************************************
  2320.  *
  2321.  -  WriteProblemArray
  2322.  -
  2323.  *  Purpose:
  2324.  *      Store a LPSPropProblemArray in a file under a tag specified
  2325.  *
  2326.  *  Parameters:
  2327.  *      [in]
  2328.  *       lpszFilename   - name of the file to store prop value in
  2329.  *       lpszTag        - name of Tag Identifier in file delimited by [ ]
  2330.  *                          ex.  [FLD0001]
  2331.  *       lpProblem      - problem array to put in file lpszFilename under lpszTag
  2332.  *
  2333.  *  Returns:
  2334.  *      nothing
  2335.  *
  2336.  *  Example:
  2337.  *      StorePropValue("C:\\MAPITEST\\DATA\\PROPVU.TXT",
  2338.  *                     "[FLD00001]"
  2339.  *                     lpProblem);
  2340.  *
  2341.  ***********************************************************************/
  2342.  
  2343. void WriteProblemArray( LPSTR               lpszFileName,
  2344.                         LPSTR               lpszTag,
  2345.                         LPSPropProblemArray lpProblem)
  2346. {
  2347.     ULONG   idx;
  2348.     char    szBuffer[256];
  2349.     char    szLine1[256];   // limitation of 256 for indexes
  2350.     char    szLine2[2048];  // limitation of 2k for proptags
  2351.     char    szLine3[2048];  // limitation of 2k for error codes
  2352.     FILE    *pFile              = NULL;
  2353.     int     len1                = 0;
  2354.     int     len2                = 0;
  2355.     int     len3                = 0;
  2356.  
  2357.     // assert valid parameters
  2358.     if((lpszFileName == NULL) || (lpProblem == NULL) || (lpszTag == NULL))
  2359.         return;
  2360.  
  2361.     // these are initialized so strcat works correctly
  2362.     szBuffer[0] = '\0';
  2363.     szLine1[0]  = '\0';
  2364.     szLine2[0]  = '\0';
  2365.     szLine3[0]  = '\0';
  2366.  
  2367.     // for every value in lpspva, convert to correct format to put in file
  2368.     for(idx = 0; idx < lpProblem->cProblem ; idx++)
  2369.     {
  2370.         // INDEX
  2371.         wsprintf(szBuffer,"%lu, ",lpProblem->aProblem[idx].ulIndex);
  2372.         strcat(szLine1,szBuffer);
  2373.  
  2374.         // PROPTAG
  2375.         if( !GetString("PropIDs",PROP_ID(lpProblem->aProblem[idx].ulPropTag) , szBuffer) )
  2376.             wsprintf(szBuffer,"0x%08X",lpProblem->aProblem[idx].ulPropTag); // id not found, use hex tag
  2377.  
  2378.         strcat(szLine2,szBuffer);
  2379.         strcat(szLine2,", ");
  2380.  
  2381.  
  2382.         // MAPI ERROR
  2383.         GetString("MAPIErrors",lpProblem->aProblem[idx].scode , szBuffer);
  2384.         strcat(szLine3,szBuffer);
  2385.         strcat(szLine3,", ");
  2386.     }
  2387.  
  2388.     // take off the last comma and space from both lines
  2389.     len1 = lstrlen(szLine1);
  2390.     szLine1[len1 - 2] = '\0';
  2391.  
  2392.     len2 = lstrlen(szLine2);
  2393.     szLine2[len2 - 2] = '\0';
  2394.  
  2395.     len3 = lstrlen(szLine3);
  2396.     szLine3[len3 - 2] = '\0';
  2397.  
  2398.     pFile = fopen(lpszFileName, "a");
  2399.     if (pFile == NULL)
  2400.         return;
  2401.  
  2402.     // fprintf Tag, proptags, propdata
  2403.     fprintf(pFile,"%s\n",lpszTag);
  2404.     fprintf(pFile,"%s\n",szLine1);
  2405.     fprintf(pFile,"%s\n",szLine2);
  2406.     fprintf(pFile,"%s\n",szLine3);
  2407.     fprintf(pFile,"\n");
  2408.  
  2409.     if (pFile)
  2410.         fclose(pFile);
  2411. }
  2412.  
  2413.  
  2414.  
  2415. /*******************************************************************
  2416.  *
  2417.  -  GetLPIID
  2418.  -
  2419.  *  Purpose:
  2420.  *      Returns the appropiate interface ID for the type of object that
  2421.  *      is passed in.
  2422.  *
  2423.  *  Parameters:
  2424.  *      lpObj   - object pointer to get LPIID for
  2425.  *
  2426.  *  Comments:
  2427.  *      Must call PvFree on the LPIID returned once you're through with it.
  2428.  *
  2429.  *  Returns:
  2430.  *      LPIID - a pointer to the interface ID, NULL if not successful
  2431.  *
  2432.  *******************************************************************/
  2433.  
  2434. LPIID GetLPIID( LPMAPIPROP  lpObj )
  2435. {
  2436.     LPSPropTagArray     lpPropTagArray      = NULL;
  2437.     LPSPropValue        lpPropValArray      = NULL;
  2438.     LPIID               lpTmpIID            = NULL;
  2439.     ULONG               cValues;
  2440.  
  2441.     // Get the object type
  2442.     lpPropTagArray = (LPSPropTagArray) PvAlloc(
  2443.                                   sizeof(LPSPropTagArray) +sizeof(ULONG));
  2444.     lpPropTagArray->cValues = 1;
  2445.     lpPropTagArray->aulPropTag[0] = PR_OBJECT_TYPE;
  2446.     #ifdef MAPI_IF_CPP
  2447.     if ( lpObj->GetProps( lpPropTagArray, 0, &cValues, &lpPropValArray) )
  2448.     #else
  2449.     if ( lpObj->lpVtbl->GetProps( lpObj, lpPropTagArray, 0, &cValues, &lpPropValArray) )
  2450.     #endif
  2451.         goto Cleanup;
  2452.  
  2453.     lpTmpIID = (LPIID) PvAlloc(sizeof(IID));
  2454.  
  2455.     // Switch based on the object type
  2456.     switch(lpPropValArray->Value.l)
  2457.     {
  2458.         case MAPI_STORE:                // Message Store
  2459.             *lpTmpIID = IID_IMsgStore;
  2460.             break;
  2461.  
  2462.         case MAPI_ADDRBOOK:             // Address Book
  2463.             *lpTmpIID = IID_IAddrBook;
  2464.             break;
  2465.  
  2466.         case MAPI_FOLDER:               // Folder
  2467.             *lpTmpIID = IID_IMAPIFolder;
  2468.             break;
  2469.  
  2470.         case MAPI_ABCONT:               // Address Book Container
  2471.             *lpTmpIID = IID_IABContainer;
  2472.             break;
  2473.  
  2474.         case MAPI_MESSAGE:              // Message
  2475.             *lpTmpIID = IID_IMessage;
  2476.             break;
  2477.  
  2478.         case MAPI_MAILUSER:             // Individual Recipient
  2479.             *lpTmpIID = IID_IMailUser;
  2480.             break;
  2481.  
  2482.         case MAPI_ATTACH:               // Attachment
  2483.             *lpTmpIID = IID_IAttachment;
  2484.             break;
  2485.  
  2486.         case MAPI_DISTLIST:             // Distribution List Recipient
  2487.             *lpTmpIID = IID_IDistList;
  2488.             break;
  2489.  
  2490.         case MAPI_STATUS:               // Status
  2491.             *lpTmpIID = IID_IMAPIStatus;
  2492.             break;
  2493.  
  2494.         case MAPI_SESSION:              // Session
  2495.             *lpTmpIID = IID_IMAPISession;
  2496.             break;
  2497.  
  2498.         default:                        // Default to unknown
  2499.             *lpTmpIID = IID_IUnknown;
  2500.     }
  2501.  
  2502.  
  2503. Cleanup:
  2504.     if (lpPropTagArray)
  2505.         PvFree(lpPropTagArray);
  2506.  
  2507.     if (lpPropValArray)
  2508.         MAPIFreeBuffer(lpPropValArray);
  2509.  
  2510.     return(lpTmpIID);
  2511. }
  2512.  
  2513.  
  2514. /*******************************************************************
  2515.  *
  2516.  -  String8ToUnicode
  2517.  -
  2518.  *  Purpose:
  2519.  *      Converts a String8 string to a Unicode double byte
  2520.  *      string.  Use PvFree to free memory allocated for
  2521.  *      the Unicode string lppWideChar.  Since UNICODE support
  2522.  *      does not currently exist on 16 bit Windows, this function
  2523.  *      is only compiled on 32 bit version
  2524.  *
  2525.  *  Parameters:
  2526.  *      szMultiByte     - String8 string to comvert to Unicode
  2527.  *      lppWideChar     - address of pointer that takes the converted
  2528.  *                          string in Unicode form.  Free this
  2529.  *                          memory with PvFree();
  2530.  *      lpvParent       - parent to chain memory to, if NULL then
  2531.  *                          it doesn't chain the memory
  2532.  *  Returns:
  2533.  *      void
  2534.  *
  2535.  *******************************************************************/
  2536.  
  2537. void String8ToUnicode( LPSTR        szMultiByte,
  2538.                        LPWSTR       *lppWideChar,
  2539.                        void FAR     *lpvParent)     // = NULL if not given
  2540. {
  2541.     int             dBytes          = 0;
  2542.     int             dCopiedBytes    = 0;
  2543.     DWORD           dwRet           = 0;
  2544.     int             dBufferLen      = 0;
  2545.     int i = 0;
  2546.  
  2547.     if(szMultiByte)
  2548.         dBufferLen = lstrlen(szMultiByte) + 1;     // the number of bytes plus the null char
  2549.  
  2550. #ifdef WIN32
  2551.     // determines the number of Wide char bytes requried
  2552.     dBytes = MultiByteToWideChar(   (UINT)      CP_ACP,
  2553.                                     (DWORD)     0,
  2554.                                     (LPCTSTR)   szMultiByte,
  2555.                                     (int)       dBufferLen,
  2556.                                     (LPWSTR)    NULL,
  2557.                                     (int)       0);
  2558.  
  2559.     if (lpvParent)
  2560.         *lppWideChar = (LPWSTR) PvAllocMore( (dBytes * sizeof(WCHAR)), lpvParent );
  2561.     else
  2562.         *lppWideChar = (LPWSTR) PvAlloc( dBytes * sizeof(WCHAR) );
  2563.  
  2564.     // now actually convert the STRING8 into a UNICODE
  2565.     dCopiedBytes = MultiByteToWideChar( (UINT)      CP_ACP,
  2566.                                         (DWORD)     0,
  2567.                                         (LPCTSTR)   szMultiByte,
  2568.                                         (int)       dBufferLen,
  2569.                                         (LPWSTR)    *lppWideChar,
  2570.                                         (int)       dBytes );
  2571.  
  2572.     dwRet = GetLastError();
  2573.  
  2574. #else // WIN16
  2575.     // This is a hack for 16bit. Some MAPI calls such as GetIDsFromNames take
  2576.     // unicode strings in both 32bit & 16bit versions. Under 16 bit it just
  2577.     // treats the string as an array of WORD (WORD = 2 bytes). So here I'm
  2578.     // just promoting each byte of the string8 to a WORD. This will work for
  2579.     // English, but probably won't work for other languages. There are no
  2580.     // routines yet to do this for other languages that I know of.
  2581.     dBytes = sizeof(WCHAR) * dBufferLen;
  2582.  
  2583.     if (lpvParent)
  2584.         *lppWideChar = (LPWSTR) PvAllocMore( dBytes, lpvParent );
  2585.     else
  2586.         *lppWideChar = (LPWSTR) PvAlloc( dBytes );
  2587.  
  2588.     for (i = 0; i < dBufferLen; i++ )
  2589.     {
  2590.         *lppWideChar[i] = (WCHAR) szMultiByte[i];
  2591.     }
  2592. #endif
  2593. }
  2594.  
  2595.  
  2596.  
  2597. /*******************************************************************/
  2598. /*
  2599.  -  AsciiToHex
  2600.  -
  2601.  *  Purpose:
  2602.  *      Converts ascii string in hex format to hex number
  2603.  *
  2604.  *  Parameters:
  2605.  *      len             - length of ascii string to convert
  2606.  *      pch             - pointer to array of characters to convert
  2607.  *      &lpulOut        - hex string returned to calling app
  2608.  *
  2609.  *  Returns:
  2610.  *      BOOLEAN         - TRUE if successful, FALSE if fail conversion
  2611.  *
  2612.  */
  2613. /*******************************************************************/
  2614.  
  2615. BOOL PASCAL AsciiToHex (ULONG len, char *pch, ULONG * lpulOut)
  2616. {
  2617.     char ch;
  2618.     ULONG i;
  2619.  
  2620.     for (i = len; i > 0; i--)
  2621.     {
  2622.         ch = pch[i - 1];
  2623.  
  2624.         if (ch >= 'a' && ch <= 'f')
  2625.  
  2626.             ch = 10 + (ch - 'a');
  2627.  
  2628.         else if (ch >= 'A' && ch <= 'F')
  2629.  
  2630.             ch = 10 + (ch - 'A');
  2631.  
  2632.         else if (ch >= '0' && ch <= '9')
  2633.  
  2634.             ch = ch - '0';
  2635.         else
  2636.             return FALSE;
  2637.  
  2638.         *lpulOut += ((ULONG) ch) << (4 * (len - i));
  2639.     }
  2640.     return TRUE;
  2641. }
  2642.  
  2643.  
  2644.  
  2645. /*
  2646.  -  SzGetPropTag
  2647.  -
  2648.  *  Purpose:
  2649.  *      Converts a Property Tag to a 'Type' label and an ID value
  2650.  *      and stores the result in a character array.
  2651.  *
  2652.  *  Parameters:
  2653.  *      lpsz        - pointer to character string
  2654.  *      ulPropTag   - a property tag to be converted
  2655.  *
  2656.  *  Returns:
  2657.  *      LPSTR       - return the address of the destination string
  2658.  *
  2659.  */
  2660.  
  2661. LPSTR SzGetPropTag(LPSTR lpsz, ULONG ulPropTag)
  2662. {
  2663.     char rgch[32];      // Assumes no PropType string longer than 31 chars
  2664.     char rgch1[50];
  2665.  
  2666.  
  2667.     wsprintf(lpsz,"\t");
  2668.     GetString("PropIDs", PROP_ID(ulPropTag), rgch1);
  2669.  
  2670.     lstrcat(lpsz, rgch1);
  2671.  
  2672.     lstrcat(lpsz, " :\t");
  2673.  
  2674.     if( GetString("PropType", PROP_TYPE(ulPropTag), rgch) )
  2675.     {
  2676.         lstrcat(lpsz, rgch);
  2677.     }
  2678.     else
  2679.     {
  2680.         lstrcat(lpsz, "not found");
  2681.     }
  2682.  
  2683.     lstrcat(lpsz, "\t");
  2684.  
  2685.     return lpsz;
  2686. }
  2687.  
  2688.  
  2689.  
  2690. /*
  2691.  -  SzTextizeProp
  2692.  *
  2693.  *  Purpose:
  2694.  *      Textize the property tag and value of a property together
  2695.  *      in one string.
  2696.  *
  2697.  *  Arguments:
  2698.  *      lpszRet         - Allocated buffer to fill in.
  2699.  *      lpProp          - Pointer to property value to textize.
  2700.  *
  2701.  *  Returns:
  2702.  *      lpszRet         - Pointer to beginning of string in lpszRet.
  2703.  */
  2704.  
  2705. LPSTR SzTextizeProp(LPSTR lpszRet, LPSPropValue lpProp)
  2706. {
  2707.     char rgch[256];
  2708.  
  2709.     SzGetPropTag(lpszRet, lpProp->ulPropTag);
  2710.     lstrcat(lpszRet, " = " );
  2711.     return lstrcat(lpszRet, SzGetPropValue(rgch, lpProp));
  2712. }
  2713.  
  2714.  
  2715.  
  2716. /*
  2717.  -  MakeGuid
  2718.  -
  2719.  *  Purpose:
  2720.  *      Construct a GUID from the parameters passed in.
  2721.  *
  2722.  *  Parameters:
  2723.  *      lpg         - Pointer to GUID to assign
  2724.  *      ul          - Data1
  2725.  *      w1          - Data2
  2726.  *      w2          - Data3
  2727.  *      b1 - b8     - Data4[0] - Data4[7]
  2728.  *
  2729.  *  Returns:
  2730.  *      Void.
  2731.  *
  2732.  */
  2733.  
  2734. void MakeGuid(LPGUID lpg, ULONG ul, WORD w1, WORD w2, BYTE b1,
  2735.                                                       BYTE b2,
  2736.                                                       BYTE b3,
  2737.                                                       BYTE b4,
  2738.                                                       BYTE b5,
  2739.                                                       BYTE b6,
  2740.                                                       BYTE b7,
  2741.                                                       BYTE b8)
  2742. {
  2743.     if(!lpg)
  2744.         return;
  2745.  
  2746.     lpg->Data1 = ul;
  2747.     lpg->Data2 = w1;
  2748.     lpg->Data3 = w2;
  2749.     lpg->Data4[0] = b1;
  2750.     lpg->Data4[1] = b2;
  2751.     lpg->Data4[2] = b3;
  2752.     lpg->Data4[3] = b4;
  2753.     lpg->Data4[4] = b5;
  2754.     lpg->Data4[5] = b6;
  2755.     lpg->Data4[6] = b7;
  2756.     lpg->Data4[7] = b8;
  2757. }
  2758.  
  2759.  
  2760.  
  2761. /***********************************************************************
  2762.  -  FSeekTag
  2763.  -
  2764.  *  Purpose:
  2765.  *      Looks for the tag string in the given text file which should already
  2766.  *      be open. It positions the file pointer to the next line after the
  2767.  *      tag string.
  2768.  *
  2769.  *  Parameters:
  2770.  *      [in]
  2771.  *       pFile          - pointer to open file, opened with fopen
  2772.  *       lpszTag        - string to search for
  2773.  *
  2774.  *  Returns:
  2775.  *      TRUE if successful, FALSE if not
  2776.  *
  2777.  *  Example:
  2778.  *      FSeekTag( pFile, "[FLDTREE_TEMPLATE]" )
  2779.  *
  2780.  ***********************************************************************/
  2781.  
  2782. BOOL FSeekTag( FILE *pFile, LPTSTR lpszTag )
  2783. {
  2784.     char szBuffer[MAX_PATH];
  2785.  
  2786.     // seek to beginning of file, so order in file of Blocks/Tags is
  2787.     //   not important
  2788.     //   fseek returns 0 for success, nonzero for fail
  2789.     //   seek to beginning and 0 bytes offset from beginning
  2790.     if( fseek(pFile,0,SEEK_SET) )
  2791.         return(FALSE);
  2792.  
  2793.     while ( !feof( pFile ) )
  2794.     {
  2795.         // Get the next line
  2796.         if ( fgets( szBuffer, MAX_PATH, pFile ) == NULL )
  2797.             return(FALSE);
  2798.  
  2799.         // Check if this line contains lpszTag
  2800.         else if ( strstr( szBuffer, lpszTag ) != NULL)
  2801.             return(TRUE);
  2802.     }
  2803.  
  2804.     // Didn't find the tag
  2805.     return(FALSE);
  2806. }
  2807.