home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / propvu / bldprop.cpp next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  72.7 KB  |  2,066 lines

  1. /*******************************************************************/
  2. /*
  3.  -  BldProp.cpp
  4.  -  Copyright (C) 1995 Microsoft Corporation
  5.  -
  6.  *  Purpose:
  7.  *      Contains member functions for CBldPropDlg
  8.  *      This MFC Dialog is used to build up a lpsPropTagArray
  9.  *      for the LPMAPIPROP functions lpObj->DeleteProps()
  10.  *      lpObj->GetProps(), or a lpsPropValueArray for
  11.  *      lpObj->SetProps().  The property viewer DLL uses
  12.  *      this function to build up these property arrays
  13.  *      by selecting Property IDs, Property Types, and
  14.  *      Property Data to build in the PropValue Arrays
  15.  *      and/or PropTag Arrays.  You are able to view the
  16.  *      currently selected arrays, and add/delete from the 
  17.  *      selected arrays.
  18.  */
  19. /*******************************************************************/
  20.  
  21. #undef  CINTERFACE      // C++ calling convention for mapi calls
  22.  
  23. #ifdef WIN32
  24. #ifdef _WIN95
  25. #define _INC_OLE
  26. #endif
  27. #define INC_OLE2
  28. #define INC_RPC
  29. #endif
  30.  
  31. #include <afxwin.h>
  32. #include <windowsx.h>
  33. #include <string.h>
  34.  
  35. #ifdef WIN16
  36. #include <compobj.h>
  37. #endif
  38.  
  39. #ifdef WIN32
  40. #include <objbase.h>
  41. #include <objerror.h>
  42. #ifdef _WIN95
  43. #include <ole2.h>
  44. #endif
  45. #endif
  46.  
  47. #ifdef WIN16
  48. #include <mapiwin.h>
  49. #endif
  50. #include <mapix.h>
  51. #include <strtbl.h>
  52. #include <misctool.h>
  53. #include <pvalloc.h>
  54. #include "resource.h"
  55. #include "propvu.h"  
  56. #include "bldprop.h"
  57.  
  58. /******************* Set Property Message Map *********************/
  59.  
  60. BEGIN_MESSAGE_MAP(CBldPropDlg, CModalDialog)
  61.  
  62.     ON_LBN_SELCHANGE(   IDC_SP_PROPTAGS,                OnSelectPropTagLB)
  63.     ON_EN_CHANGE(       IDC_SP_PROPID,                  OnChangePropIDHexLB)
  64.     ON_COMMAND(         IDC_SP_ADD,                     OnAdd)
  65.     ON_COMMAND(         IDC_SP_DELETE,                  OnDelete)
  66.     ON_COMMAND(         IDC_SP_CALL,                    OnCall)
  67.     ON_COMMAND(         IDC_SP_REMOVEALL,               OnRemoveAll)
  68.     ON_COMMAND(         IDC_SP_ADD_ALL_MAPITAGS,        OnAddAllMapiTags)
  69.     ON_COMMAND(         IDC_SP_ADD_ALL_CURRENT,         OnAddAllCurrent)
  70.     ON_COMMAND(         IDC_STOREPROPS,                 OnDumpPropValsToFile)
  71.     ON_CBN_SELCHANGE(   IDC_SP_PROPTYPE,                OnSelectPropTypeCB)
  72.     
  73.  
  74. END_MESSAGE_MAP()
  75.  
  76. /*******************************************************************/
  77. /**************************** SETPROPS *****************************/
  78.  
  79.  
  80.  
  81. void CBldPropDlg::OnAddAllMapiTags()
  82. {
  83.     ULONG               ulMax           = 0;
  84.     ULONG               idx             = 0;
  85.     LPSPropValue        lpspva          = NULL;
  86.     ULONG               ulPropTag       = 0;
  87.  
  88.     ulMax =   GetRowCount("PropTags");
  89.  
  90.     
  91.     if(m_fIsPropValueArray)
  92.     {
  93.         if( (ulMax + m_ulNewValues) >= MAX_SET_PROPS  )
  94.             return;
  95.  
  96.         // add one of each mapi tag type
  97.         for(idx = 0; idx < ulMax ; idx++)
  98.         {
  99.  
  100.             lpspva = (LPSPropValue) PvAlloc(sizeof(SPropValue));
  101.             memset(lpspva,0,(size_t)sizeof(SPropValue));
  102.  
  103.             lpspva->ulPropTag = GetRowID("PropTags",idx);
  104.  
  105.             switch(PROP_TYPE(lpspva->ulPropTag))
  106.             {
  107.  
  108.  
  109.                 //$  LOOK RETHINK THIS NOW !!!!
  110.  
  111.  
  112.  
  113.  
  114.                 // DONT ADD PROPTAGS OF THESE THESE TYPES TO LIST
  115.                 case PT_UNSPECIFIED:
  116.                 case PT_CLSID:
  117.                 case PT_OBJECT:
  118.                 case PT_UNICODE:
  119.  
  120.                 case PT_MV_I2:
  121.                 case PT_MV_LONG:
  122.                 case PT_MV_R4:
  123.                 case PT_MV_DOUBLE:
  124.                 case PT_MV_CURRENCY:
  125.                 case PT_MV_APPTIME:
  126.                 case PT_MV_SYSTIME:
  127.                 case PT_MV_STRING8:
  128.                 case PT_MV_BINARY:
  129.                 case PT_MV_UNICODE:
  130.                 case PT_MV_CLSID:
  131.                 case PT_MV_I8:
  132.  
  133.                     // dont add to list 
  134.                     PvFree(lpspva);
  135.                     break;
  136.  
  137.  
  138.  
  139.                 // ADD PROPTAGS OF THESE TYPES TO LIST
  140.                 case PT_STRING8:
  141.                     lpspva->Value.lpszA = (LPSTR) PvAllocMore(10,lpspva);
  142.                     lstrcpy(lpspva->Value.lpszA,"JoeSmi");
  143.                     m_ulNewValues++;
  144.                     m_lppNewPropValue[m_ulNewValues -1 ] = lpspva;
  145.                     break;
  146.                 case PT_BINARY:
  147.                     lpspva->Value.bin.cb        = 3;                
  148.                     lpspva->Value.bin.lpb       = (LPBYTE) PvAllocMore(10,lpspva);
  149.                     lpspva->Value.bin.lpb[0]    = 0;
  150.                     lpspva->Value.bin.lpb[1]    = 1;
  151.                     lpspva->Value.bin.lpb[2]    = 0;
  152.                     m_ulNewValues++;                            
  153.                     m_lppNewPropValue[m_ulNewValues -1 ] = lpspva;
  154.                     break;
  155.                 default:        
  156.                     m_ulNewValues++;
  157.                     m_lppNewPropValue[m_ulNewValues -1 ] = lpspva;
  158.                     break;
  159.             }            
  160.         }            
  161.     }
  162.     else        // its a PropTagArray
  163.     {
  164.         if( (ulMax + m_lpNewPTA->cValues) >= MAX_SET_PROPS  )
  165.              return;
  166.  
  167.         for(idx = 0; idx < ulMax ; idx++)
  168.         {
  169.             ulPropTag = GetRowID("PropTags",idx);
  170.             
  171.             switch(PROP_TYPE(ulPropTag) )
  172.             {
  173.  
  174.                 //$  LOOK RETHINK THIS NOW !!!!
  175.  
  176.  
  177.  
  178.  
  179.                 // DONT ADD PROPTAGS OF THESE THESE TYPES TO LIST
  180.                 case PT_UNSPECIFIED:
  181.                 case PT_CLSID:
  182.                 case PT_OBJECT:
  183.                 case PT_UNICODE:
  184.  
  185.                 case PT_MV_I2:
  186.                 case PT_MV_LONG:
  187.                 case PT_MV_R4:
  188.                 case PT_MV_DOUBLE:
  189.                 case PT_MV_CURRENCY:
  190.                 case PT_MV_APPTIME:
  191.                 case PT_MV_SYSTIME:
  192.                 case PT_MV_STRING8:
  193.                 case PT_MV_BINARY:
  194.                 case PT_MV_UNICODE:
  195.                 case PT_MV_CLSID:
  196.                 case PT_MV_I8:
  197.                        break;
  198.  
  199.                 default:
  200.                     m_lpNewPTA->cValues++;
  201.                     m_lpNewPTA->aulPropTag[m_lpNewPTA->cValues - 1] = ulPropTag;
  202.                     break;
  203.             }
  204.         }   
  205.     }     
  206.  
  207.       
  208.     RedrawBuildProps();     
  209.  
  210.  
  211. }
  212.  
  213. /********************************************************************/
  214. /********************************************************************/
  215.  
  216. void CBldPropDlg::OnAddAllCurrent()
  217. {
  218.     LPSPropValue        lpPVAGetProps   = NULL;
  219.     ULONG               ulValues        = 0;
  220.     LPSPropTagArray     lpPTA           = NULL;
  221.     ULONG               idx             = 0;
  222.     LPSPropValue        lpspva          = NULL;
  223.     HRESULT             hResult         = hrSuccess;
  224.     CGetError           E;
  225.     
  226.     
  227.     if(m_fIsPropValueArray)
  228.     {
  229.  
  230.         if( HR_FAILED(hResult = m_lpSetEntry->GetProps(NULL, 0, &ulValues, &lpPVAGetProps) ) )
  231.         {
  232.             MessageBox( E.SzError("CBldPropDlg::OnAddAllCurrent   GetProps()", hResult), 
  233.                                 "Client", MBS_ERROR );
  234.             return;
  235.         }
  236.     
  237.         if( (ulValues + m_ulNewValues) >= MAX_SET_PROPS  )
  238.             return;
  239.             
  240.         // add one of each mapi tag type
  241.         for(idx = 0; idx < ulValues ; idx++)
  242.         {        
  243.             lpspva = (LPSPropValue) PvAlloc(sizeof(SPropValue));
  244.             memset(lpspva,0,(size_t)sizeof(SPropValue));
  245.  
  246.             CopyPropValue(lpspva,&(lpPVAGetProps[idx]),lpspva);
  247.  
  248.             m_ulNewValues++;                            
  249.             m_lppNewPropValue[m_ulNewValues -1 ] = lpspva;
  250.         }            
  251.     }
  252.     else        // its a PropTagArray
  253.     {
  254.  
  255.         if( HR_FAILED(hResult = m_lpSetEntry->GetPropList(0, &lpPTA) ) )
  256.         {
  257.             MessageBox( E.SzError("CBldDlg::OnAddAllCurrent()  lpEntry->GetPropList()",
  258.                 hResult), "Client", MBS_ERROR );
  259.             return;
  260.         }
  261.         if( (lpPTA->cValues + m_lpNewPTA->cValues) >= MAX_SET_PROPS  )
  262.              return;
  263.  
  264.         for(idx = 0; idx < lpPTA->cValues ; idx++)
  265.         {           
  266.             m_lpNewPTA->cValues++;
  267.             m_lpNewPTA->aulPropTag[m_lpNewPTA->cValues - 1] = lpPTA->aulPropTag[idx];
  268.         }   
  269.     }     
  270.     RedrawBuildProps();     
  271.  
  272.     if(lpPTA)
  273.         MAPIFreeBuffer(lpPTA);    
  274.  
  275.     if(lpPVAGetProps)
  276.         MAPIFreeBuffer(lpPVAGetProps);
  277. }
  278.  
  279.  
  280. /********************************************************************/
  281. /********************************************************************/
  282.  
  283. void CBldPropDlg::OnRemoveAll()
  284. {
  285.     ULONG               idx             = 0;
  286.     
  287.     if(m_fIsPropValueArray)
  288.     {
  289.         if(m_lppNewPropValue)
  290.         {
  291.             for(idx = 0 ; idx < m_ulNewValues; idx++)
  292.             {
  293.                 PvFree(m_lppNewPropValue[idx]);
  294.                 m_lppNewPropValue[idx] = NULL;
  295.             }
  296.         }
  297.         m_ulNewValues = 0;       
  298.     }
  299.     else        // its a PropTagArray
  300.     {
  301.         m_lpNewPTA->cValues = 0;
  302.     }
  303.     
  304.     RedrawBuildProps();     
  305. }
  306.  
  307.  
  308. /********************************************************************/
  309. /*
  310.  -  CBldPropDlg::
  311.  -  OnInitDialog
  312.  -
  313.  *  Purpose:
  314.  *      First routine called when an instance of a setprops dialog
  315.  *      is created.  This routine initalizes the listboxs and edit
  316.  *      controls to select the property to set chosen from the 
  317.  *      property listbox of the calling dialog(folder/attachment/message)
  318.  *
  319.  */
  320. /********************************************************************/
  321.  
  322. BOOL CBldPropDlg::OnInitDialog()
  323. {
  324.     HRESULT         hResult         = hrSuccess;
  325.     SCODE           scResult        = SUCCESS_SUCCESS;
  326.     CGetError       E;
  327.     ULONG           cColumn         = 0;
  328.     LPSPropValue    lpPropValue     = NULL;
  329.     int             iRow            = 0;
  330.     char            szBuffer[4096];
  331.     int             idx             = 0;
  332.     LONG            lSelection      = -1;
  333.     int             len             = 0;
  334.     char            szPropID[30];
  335.     ULONG           ulPropID        = 0;
  336.     DWORD           dwIndex         = 0;
  337.     ULONG           ulRowCount      = 0;
  338.     
  339.     szBuffer[0] = '\0' ; 
  340.     SetWindowText( m_Operation.GetBuffer(30) );
  341.  
  342.     SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_RESETCONTENT,0,0);
  343.     SendDlgItemMessage(IDC_SP_PROPTAGS,LB_RESETCONTENT,0,0);
  344.     dwIndex = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_SETCURSEL,(WPARAM)-1,0);
  345.     dwIndex = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_SETCURSEL,(WPARAM)-1,0);
  346.     
  347.     if( !m_lpSetEntry )
  348.     {
  349.         MessageBox( E.SzError("CBldPropDlg::OnInitDialog   lpSetEntry == NULL", hResult),
  350.                          "Client", MBS_ERROR );
  351.         goto error;
  352.     }           
  353.  
  354.     // m_lpOldPropValue holds onto state of property when enter this setprops dialog
  355.     // m_lpNewPropValue holds new propval array to set existing props with
  356.  
  357.     if(m_lpOldPropValue)
  358.     {
  359.         MAPIFreeBuffer(m_lpOldPropValue);
  360.         m_lpOldPropValue = NULL;
  361.     }
  362.  
  363.     if( HR_FAILED(hResult = m_lpSetEntry->GetProps(NULL, 0, &m_ulOldValues, &m_lpOldPropValue) ) )
  364.     {
  365.         MessageBox( E.SzError("CBldPropDlg::OnInitDialog   GetProps(Old)", hResult), 
  366.                             "Client", MBS_ERROR );
  367.         goto error;
  368.     }
  369.  
  370.     // ADD DATA TO LISTBOX OF PROP IDS
  371.     szBuffer[0] = '\0' ;
  372.     // this (UNKNOWN PROPID) is always in the 0th place in listbox    
  373.     dwIndex = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_ADDSTRING,0,(LPARAM)(void *)"AN UNKNOWN PROPID");
  374.  
  375.     ulRowCount = GetRowCount("PropIDs");
  376.     for( idx = 0; idx < ulRowCount ; idx++ )
  377.     {
  378.         if( !GetRowString("PropIDs",idx,szBuffer) )
  379.              goto error;
  380.  
  381.         dwIndex = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_ADDSTRING,0,(LPARAM)szBuffer);
  382.     }          
  383.  
  384.     // select string in listbox
  385.  
  386.     m_SelectedTag = "PR_SUBJECT";
  387.     
  388.     lSelection = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_SELECTSTRING,(WPARAM) -1,
  389.                         (LPARAM) m_SelectedTag.GetBuffer(10) );
  390.  
  391.     szBuffer[0] = '\0' ;
  392.     
  393.     // ADD DATA TO LISTBOX OF PROP TYPES, ORDER IS IMPORTANT, alphabetical !!!!
  394.     SendDlgItemMessage(IDC_SP_PROPTYPE,CB_RESETCONTENT,0,0);
  395.  
  396.     ulRowCount = GetRowCount("PropType");
  397.     for( idx = 0; idx < ulRowCount ; idx++ )
  398.     {
  399.         if( !GetRowString("PropType",idx,szBuffer) )
  400.              goto error;
  401.  
  402.         dwIndex = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_ADDSTRING,0,(LPARAM)szBuffer);
  403.  
  404.     }          
  405.  
  406.     
  407.     // now select the property type associated with the tag selected
  408.  
  409.     // set PropID edit control
  410.     // THIS MUST COME BEFORE  PROP TYPE IS SELECTED or else
  411.     // the event of change to the PropIDHex edit control will overwrite the
  412.     // selected prop type.
  413.  
  414.     m_lSelectedTag = PR_SUBJECT;      
  415.   
  416.     SendDlgItemMessage(IDC_SP_PROPID,WM_CLEAR,0,0);
  417.     wsprintf (szPropID, "%04X", PROP_ID(m_lSelectedTag));               
  418.     GetDlgItem(IDC_SP_PROPID    )->SetWindowText(szPropID);
  419.  
  420.     // this must come after the Setting of the PropID Hex field !!!!!!
  421.  
  422.     // explain why it must
  423.  
  424.     
  425.     GetString("PropType",PROP_TYPE(m_lSelectedTag),szBuffer);
  426.     lSelection = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_SELECTSTRING,(WPARAM) -1,
  427.                         (LPARAM) szBuffer );
  428.  
  429.  
  430.     SelectNewPropType( PROP_TYPE(m_lSelectedTag) );
  431.  
  432.     szBuffer[0] = '\0';
  433.  
  434.     // Set PropData edit control
  435.     SendDlgItemMessage(IDC_SP_PROPDATA,WM_CLEAR,0,0);
  436.         
  437.     for(idx = 0; idx < m_ulOldValues ; idx++)
  438.     {
  439.         if( ((ULONG) m_lSelectedTag) == ((ULONG)m_lpOldPropValue[idx].ulPropTag ) )
  440.         {
  441.             
  442.             if( PROP_TYPE(m_lSelectedTag) == PT_BINARY )
  443.             {
  444.                 char    lpszHex[9];
  445.                 ULONG   cb = 0;
  446.                 ULONG   cChars = 0;
  447.                 LPBYTE  lpb = m_lpOldPropValue[idx].Value.bin.lpb;
  448.  
  449.                 while((cb < m_lpOldPropValue[idx].Value.bin.cb) && (cChars < MAX_LOG_BUFF-16 ) )
  450.                 {
  451.                     wsprintf(lpszHex, "%02X ", *lpb);
  452.                     lstrcat(szBuffer, lpszHex);
  453.                     cChars += 3;
  454.                     lpb++;
  455.                     cb++;
  456.                 }
  457.             }
  458.             else
  459.             {
  460.                 SzGetPropValue(szBuffer,(LPSPropValue) &m_lpOldPropValue[idx]);
  461.             }
  462.             break;
  463.         }
  464.     }
  465.     GetDlgItem(IDC_SP_PROPDATA  )->SetWindowText(szBuffer);
  466.  
  467.     // if there is not already a value for selected PVA in listbox    
  468.     if(!m_lppNewPropValue)  
  469.         m_lppNewPropValue = (LPSPropValue *) PvAlloc(MAX_SET_PROPS * sizeof(LPSPropValue));
  470.     
  471.     // if it is a Prop tag array, disable the Data.
  472.     if( !m_fIsPropValueArray)
  473.     {
  474.         // is not already allocated an initialized
  475.         if(!m_lpNewPTA)
  476.         {
  477.             m_lpNewPTA = (LPSPropTagArray) PvAlloc( (MAX_SET_PROPS * sizeof(ULONG)) + sizeof(SPropTagArray));
  478.             m_lpNewPTA->cValues = 0;
  479.         }
  480.         GetDlgItem(IDC_SP_PROPDATA  )->EnableWindow(FALSE);
  481.  
  482.         SetDlgItemText(IDT_SP_PROPDISPLAY,"Selected lpsPropTagArray:");       
  483.     }       
  484.  
  485.     GetDlgItem(IDC_SP_PROPTYPEHEX)->EnableWindow(FALSE);
  486.  
  487.     // for some cases, we may already have a value inside the selected PTA,PVA
  488.     RedrawBuildProps();
  489.  
  490.     return TRUE;    
  491.  
  492. error:
  493.  
  494.     if(m_lpOldPropValue)
  495.     {
  496.         MAPIFreeBuffer(m_lpOldPropValue);
  497.         m_lpOldPropValue    = NULL;
  498.         m_ulOldValues       = 0;
  499.     }
  500.     
  501.     return FALSE;
  502.     
  503. }
  504.  
  505.  
  506.  
  507. /*******************************************************************/
  508. /*
  509.  -  CBldPropDlg::
  510.  -  RedrawBuildProps
  511.  *
  512.  *  Purpose:
  513.  *  Parameters:
  514.  *
  515.  *  Returns:
  516.  *
  517.  */
  518. /*******************************************************************/
  519.  
  520. void CBldPropDlg::RedrawBuildProps()
  521. {
  522.     char            szBuffer[1024];
  523.     int             idx             = 0;
  524.     int             rgTabStops[4];
  525.     DWORD           dwReturn        = 0;
  526.     char            szCValues[80];
  527.  
  528.     // multi value props stuff    
  529.     char            szMV[1024];    
  530.  
  531.     char            szMVSeps[]      = ";}";
  532.  
  533.  
  534.     char            *lpszToken      = NULL;
  535.     char            szTemp[30];
  536.     ULONG           ulMVRow         = 0;
  537.     ULONG           ulMVcValues     = 0;
  538.     char            *szEnd          = NULL;
  539.  
  540.     char szID[50];
  541.     char szData[512];
  542.     char szType[32];      // Assumes no PropType string longer than 31 chars
  543.  
  544.     szBuffer[0] = '\0' ;
  545.  
  546.     SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_RESETCONTENT,0,0);
  547.  
  548.     // load properties into listbox
  549.     dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_SETHORIZONTALEXTENT,
  550.                     (WPARAM) PROP_LISTBOX_HORIZONTAL_SIZE ,0 );
  551.  
  552.     rgTabStops[0] = PROP_LISTBOX_TAB1_SIZE ;
  553.     rgTabStops[1] = PROP_LISTBOX_TAB2_SIZE ;
  554.  
  555.     dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_SETTABSTOPS,
  556.                     (WPARAM) 2,(LPARAM)rgTabStops );
  557.     
  558.  
  559.     // either a PTA or PVA
  560.     
  561.     // if it is a PropValueArray
  562.     if(m_fIsPropValueArray) 
  563.     {           
  564.             
  565.         for(idx = 0; idx < m_ulNewValues; idx++)
  566.         {   
  567.             szID[0]     = '\0' ;
  568.             szData[0]   = '\0' ;
  569.             szType[0]   = '\0' ;
  570.             szBuffer[0] = '\0' ;
  571.                 
  572.             if(GetString("PropIDs", PROP_ID( (*(m_lppNewPropValue[idx])).ulPropTag), szID ) )
  573.             {
  574.                 lstrcat(szBuffer, szID );               
  575.                 lstrcat(szBuffer, "\t");
  576.             }
  577.             else
  578.             {
  579.                 wsprintf(szBuffer,"%#04X\t", PROP_ID(  (*(m_lppNewPropValue[idx])).ulPropTag) );        
  580.             }
  581.  
  582.             if( GetString("PropType", PROP_TYPE( (*(m_lppNewPropValue[idx])).ulPropTag), szType) )
  583.             {
  584.                 lstrcat(szBuffer, szType);
  585.                 lstrcat(szBuffer,"\t");
  586.             }       
  587.             else
  588.             {
  589.                 wsprintf(szType,"%#04X\t", PROP_TYPE( (*(m_lppNewPropValue[idx])).ulPropTag) );
  590.                 lstrcat(szBuffer,szType);
  591.             }
  592.  
  593.  
  594.             SzGetPropValue(szData,(LPSPropValue) m_lppNewPropValue[idx]);
  595.  
  596.             // if it is a MultiValueProperty, parse the output, and add
  597.             //   more than one row for this property
  598.             if( (PROP_TYPE( (*(m_lppNewPropValue[idx])).ulPropTag)) & MV_FLAG )
  599.             {
  600.                 // it is multi value, so strtok out the data 
  601.                 // and add a row for each data value                                                        
  602.                 ulMVRow = 0;
  603.  
  604.                 // determine number of cValues
  605.                 lpszToken   = strtok(szData,":");
  606.  
  607.                 ulMVcValues = strtoul(lpszToken,&szEnd,16);        
  608.  
  609.                 // rip out first row of multi value prop
  610.                 lpszToken = strtok(NULL,szMVSeps);
  611.                                 
  612.                 // rip out remaining rows                
  613.                 while( lpszToken != NULL )
  614.                 {
  615.                     lstrcpy(szMV,szBuffer);
  616.                     wsprintf(szTemp,"[%lu] ",ulMVRow);
  617.                     lstrcat(szMV,szTemp);
  618.                     lstrcat(szMV,lpszToken);
  619.                 
  620.                     dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_ADDSTRING,0,
  621.                             (LPARAM)szMV);
  622.                 
  623.                     lpszToken = strtok(NULL,szMVSeps);
  624.                     ulMVRow++;
  625.                 }                
  626.                 
  627.                 // if all the data was not there, fill in the remainder with bogus stub
  628.                 while( ulMVRow < ulMVcValues )
  629.                 {
  630.                     lstrcpy(szMV,szBuffer);
  631.                     wsprintf(szTemp,"[%lu] ",ulMVRow);
  632.                     lstrcat(szMV,szTemp);
  633.                     lstrcat(szMV,"<No Data Available>");
  634.                 
  635.                     dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_ADDSTRING,0,
  636.                             (LPARAM)szMV);
  637.                     ulMVRow++;                            
  638.                 }
  639.             }
  640.             else            
  641.             {
  642.                 lstrcat(szBuffer,szData);
  643.                 dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_ADDSTRING,0,
  644.                             (LPARAM)szBuffer);
  645.             }
  646.  
  647.  
  648.         }  // end of for loop of m_ulNewValues in lpNewPropValue
  649.  
  650.         wsprintf(szCValues,"Selected cValues:  %lu",m_ulNewValues);
  651.         SetDlgItemText(IDT_SP_PROPCVALUES,szCValues);       
  652.  
  653.     }
  654.     else  // it is a proptag array
  655.     {
  656.             
  657.         for(idx = 0; idx < m_lpNewPTA->cValues; idx++)
  658.         {   
  659.             szID[0]     = '\0' ;
  660.             szType[0]   = '\0' ;
  661.             szBuffer[0] = '\0' ;
  662.                 
  663.             if(GetString("PropIDs", PROP_ID(m_lpNewPTA->aulPropTag[idx]), szID ) )
  664.             {
  665.                 lstrcat(szBuffer, szID );               
  666.                 lstrcat(szBuffer, "\t");
  667.             }
  668.             else
  669.             {
  670.                 wsprintf(szBuffer,"%#04X\t", PROP_ID(m_lpNewPTA->aulPropTag[idx]) );        
  671.             }
  672.  
  673.             if( GetString("PropType", PROP_TYPE(m_lpNewPTA->aulPropTag[idx]), szType) )
  674.             {
  675.                 lstrcat(szBuffer, szType);
  676.                 lstrcat(szBuffer,"\t");
  677.             }       
  678.             else
  679.             {
  680.                 wsprintf(szType,"%#04X\t", PROP_TYPE(m_lpNewPTA->aulPropTag[idx]) );
  681.                 lstrcat(szBuffer,szType);
  682.             }
  683.             dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_ADDSTRING,0,
  684.                                 (LPARAM)szBuffer);
  685.         
  686.         }  
  687.         wsprintf(szCValues,"Selected lpsPTA->cValues:  %lu",m_lpNewPTA->cValues);
  688.         SetDlgItemText(IDT_SP_PROPCVALUES,szCValues);       
  689.         
  690.     }             
  691.  
  692.  
  693.     
  694.     dwReturn = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_SETCURSEL,(WPARAM) -1 ,0 );
  695. }
  696.  
  697. /*******************************************************************/
  698. /*
  699.  -  CBldPropDlg::
  700.  -  OnSelectPropTagLB
  701.  *
  702.  *  Purpose:
  703.  *      Upon selection of a property tag id in the listbox of available
  704.  *      proptag ids, the combo box of the proptype will correspond to
  705.  *      the default of this id and the data and ID hex value will adjust 
  706.  *      to currently selected item as well.
  707.  *
  708.  *  Parameters:
  709.  *      None
  710.  *
  711.  *  Returns:
  712.  *      Nothing
  713.  *
  714.  */
  715. /*******************************************************************/
  716.  
  717. void CBldPropDlg::OnSelectPropTagLB()
  718. {
  719.     char    szBuffer[512];
  720.     char    szPropID[30];
  721.     int     idx         = 0;
  722.     LONG    lCurSelect  = 0;
  723.     DWORD   dwIndex     = 0;
  724.  
  725.     szBuffer[0] = '\0';
  726.  
  727.     // determine which entry in listbox is selected
  728.     lCurSelect = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_GETCURSEL,0,0);
  729.  
  730.     // if select an unknown ID
  731.     if(lCurSelect == 0 )
  732.     {
  733.         // select unknown type for Type combo box
  734.         dwIndex = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_SELECTSTRING,
  735.                 (WPARAM) -1, (LPARAM)(void *) "PT_UNSPECIFIED");
  736.  
  737.         szBuffer[0] = '\0';
  738.         // Set PropData edit control
  739.         SendDlgItemMessage(IDC_SP_PROPDATA,WM_CLEAR,0,0);
  740.         GetDlgItem( IDC_SP_PROPDATA )->SetWindowText(  szBuffer );
  741.         return;   
  742.     }       
  743.  
  744.     // set proptag listbox selection
  745.     SendDlgItemMessage(IDC_SP_PROPTAGS,LB_GETTEXT,(WPARAM)lCurSelect,(LPARAM)szBuffer);
  746.     m_SelectedTag = szBuffer;
  747.  
  748.     GetID("PropTags", m_SelectedTag.GetBuffer(10),&m_lSelectedTag );
  749.         
  750.  
  751.     // set PropID edit control
  752.     SendDlgItemMessage(IDC_SP_PROPID,WM_CLEAR,0,0);
  753.     wsprintf (szPropID, "%04X", PROP_ID(m_lSelectedTag));               
  754.     GetDlgItem(IDC_SP_PROPID    )->SetWindowText(szPropID);
  755.  
  756. }
  757.  
  758.  
  759. /*******************************************************************/
  760. /*
  761.  -  CBldPropDlg::
  762.  -  SelectNewPropType
  763.  *
  764.  *  Purpose:
  765.  *
  766.  *  Parameters:
  767.  *      LONG lSelectedType
  768.  *
  769.  *  Returns:
  770.  *      Nothing
  771.  *
  772.  */
  773. /*******************************************************************/
  774.  
  775. void CBldPropDlg::SelectNewPropType(ULONG ulSelectedType)
  776. {
  777.     char    szPropType[128];
  778.     char    szDataItemDisplay[128];
  779.  
  780.     SendDlgItemMessage(IDC_SP_PROPTYPEHEX,WM_CLEAR,0,0);
  781.     wsprintf (szPropType, "%04X", ulSelectedType );             
  782.     GetDlgItem(IDC_SP_PROPTYPEHEX   )->SetWindowText(szPropType);
  783.  
  784.  
  785.     if(!m_fIsPropValueArray)
  786.     {
  787.         wsprintf(szDataItemDisplay,"Building PropTagArray, Data Not Applicable");                                
  788.         SetDlgItemText(IDT_SP_PROPDATA,szDataItemDisplay);
  789.         return;
  790.     }            
  791.     
  792.     // now set data field description of how to enter data
  793.     // depending on the type. 
  794.     
  795.     switch(ulSelectedType)
  796.     {
  797.         case PT_UNSPECIFIED:
  798.             wsprintf(szDataItemDisplay,"Prop Data: PT_UNSPECIFIED, Data Unspecified");
  799.             break;
  800.  
  801.         case PT_NULL:
  802.             wsprintf(szDataItemDisplay,"Prop Data: PT_NULL, No Data");        
  803.             break;
  804.  
  805.         case PT_I2:
  806.             wsprintf(szDataItemDisplay,"Prop Data: PT_I2, enter a short int ex. 43");                
  807.             break;
  808.  
  809.         case PT_LONG:
  810.             wsprintf(szDataItemDisplay,"Prop Data: PT_LONG, enter a long ex. 43");                        
  811.             break;
  812.  
  813.         case PT_R4:
  814.             wsprintf(szDataItemDisplay,"Prop Data: PT_R4, enter a float ex. 43.0007");                                
  815.             break;
  816.  
  817.         case PT_DOUBLE:
  818.             wsprintf(szDataItemDisplay,"Prop Data: PT_DOUBLE, enter a double ex. 435677");                                        
  819.             break;
  820.  
  821.         case PT_CURRENCY:
  822.             wsprintf(szDataItemDisplay,"Prop Data: PT_CURRENCY, enter two longs(low then high) ex. 5 78");                                                
  823.             break;
  824.  
  825.         case PT_APPTIME:
  826.             wsprintf(szDataItemDisplay,"Prop Data: PT_APPTIME, enter a double ex. 435677");                                                
  827.             break;
  828.  
  829.         case PT_ERROR:
  830.             wsprintf(szDataItemDisplay,"Prop Data: PT_ERROR, enter a textized Error code ex. MAPI_E_NO_ACCESS");                                                        
  831.             break;
  832.  
  833.         case PT_BOOLEAN:
  834.             wsprintf(szDataItemDisplay,"Prop Data: PT_BOOLEAN, enter a boolean 1 or 0");                                                                            
  835.             break;
  836.  
  837.         case PT_OBJECT:
  838.             wsprintf(szDataItemDisplay,"Prop Data: PT_OBJECT, data doesn't make sense");                                                                                    
  839.             break;
  840.  
  841.         case PT_I8:
  842.             wsprintf(szDataItemDisplay,"Prop Data: PT_I8, enter 2 DWORDs LowPart HighPart ex. 34 67");                                                                                            
  843.             break;
  844.  
  845.         case PT_SYSTIME:
  846.             wsprintf(szDataItemDisplay,"Prop Data: PT_SYSTEMTIME, Enter Y/M/D Hr:Min:Sec ex. 1995/02/08 17:55:27");                                                                                                    
  847.             break;
  848.  
  849.         case PT_STRING8:
  850.             wsprintf(szDataItemDisplay,"Prop Data: PT_STRING8, Enter string ex. Hello World");                                                                                                    
  851.             break;
  852.  
  853.         case PT_UNICODE:
  854.             wsprintf(szDataItemDisplay,"Prop Data: PT_UNICODE, Enter string ex. Hello World");                                                                                                            
  855.             break;
  856.  
  857.         case PT_CLSID:
  858.             wsprintf(szDataItemDisplay,"Prop Data: PT_CLSID, Enter Guid, currently NOT SUPPORTED");                                                                                                                    
  859.             break;
  860.  
  861.         case PT_BINARY:
  862.             wsprintf(szDataItemDisplay,"Prop Data: PT_BINARY, Enter 2 bytes,space,2 bytes... Ex. 00 01 10 11");
  863.             break;
  864.  
  865.         case PT_MV_I2:
  866.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_I2, Enter cVals: Val1; Val2;... Ex. 3: 43; 33; 12;");
  867.             break;
  868.  
  869.         case PT_MV_LONG:
  870.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_LONG, Enter cVals: Val1; Val2;... Ex. 3: 43; 33; 12;");
  871.             break;
  872.  
  873.         case PT_MV_R4:
  874.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_LONG, Enter cVals: Val1; Val2;... Ex. 3: 43.00; 33.78; 12.9001;");
  875.             break;
  876.  
  877.         case PT_MV_DOUBLE:
  878.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_DOUBLE, Enter cVals: Val1; Val2;... Ex. 3: 43; 33; 12;");
  879.             break;
  880.  
  881.         case PT_MV_CURRENCY:
  882.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_CURRENCY, Enter cVals: lo1 hi1 ; lo2 hi2;... Ex. 2: 4 3; 3 53");
  883.             break;
  884.  
  885.         case PT_MV_APPTIME:
  886.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_APPTIME, Enter cVals: Val1; Val2;... Ex. 3: 43; 33; 12;");
  887.             break;
  888.  
  889.         case PT_MV_SYSTIME:
  890.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_SYSTIME, Enter cVals: Val1; Val2; Val3 Ex. 1: 1995/2/2 1:12:30 ;");
  891.             break;
  892.  
  893.         case PT_MV_BINARY:
  894.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_BINARY, Enter cVals:Val1;Val2;Val3 Ex. 2:11 00 10;11 01;");
  895.             break;
  896.  
  897.         case PT_MV_STRING8:
  898.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_STRING8, Enter cVals: Val1; Val2;... Ex. 3: joe; smith; test;");
  899.             break;
  900.  
  901.         case PT_MV_UNICODE:
  902.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_UNICODE, Enter cVals: Val1; Val2;... Ex. 3: joe; smith; test;");
  903.             break;
  904.  
  905.         case PT_MV_CLSID:
  906.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_CLSID, Currently NOT SUPPORTED");
  907.             break;
  908.  
  909.         case PT_MV_I8:
  910.             wsprintf(szDataItemDisplay,"Prop Data: PT_MV_I8, Enter cVals: Low1 High1; Low2 High2;... Ex. 2: 4 43; 67 33; ");
  911.             break;
  912.             
  913.         default:
  914.             wsprintf(szDataItemDisplay,"Prop Data: Unknown Prop Type ");
  915.             break;
  916.     }            
  917.  
  918.     SetDlgItemText(IDT_SP_PROPDATA,szDataItemDisplay);
  919. }
  920.  
  921. /*******************************************************************/
  922. /*
  923.  -  CBldPropDlg::
  924.  -  OnSelectPropTypeCB
  925.  *
  926.  *  Purpose:
  927.  *
  928.  *  Parameters:
  929.  *      None
  930.  *
  931.  *  Returns:
  932.  *      Nothing
  933.  *
  934.  */
  935. /*******************************************************************/
  936.  
  937. void CBldPropDlg::OnSelectPropTypeCB()
  938. {
  939.     char    szBuffer[512];
  940.     LONG    lCurSelect      = 0;
  941.     LONG    lSelectedType   = 0;
  942.     
  943.     szBuffer[0] = '\0';
  944.     // determine which entry in listbox is selected
  945.     lCurSelect = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_GETCURSEL,0,0);
  946.  
  947.     // set proptag listbox selection
  948.     SendDlgItemMessage(IDC_SP_PROPTYPE,CB_GETLBTEXT,(WPARAM)lCurSelect,(LPARAM)szBuffer);
  949.         
  950.     GetID("PropType",szBuffer,&lSelectedType);
  951.  
  952.     SelectNewPropType((ULONG)lSelectedType);
  953. }
  954.  
  955.  
  956. /*******************************************************************/
  957. /*
  958.  -  CBldPropDlg::
  959.  -  OnChangePropHexLB
  960.  *
  961.  *  Purpose:
  962.  *      Select a hex value for the PROP ID and adjust the 
  963.  *      proptag listbox string values, proptype string values.
  964.  *      and the prop data accordingly
  965.  *
  966.  *  Parameters:
  967.  *      None
  968.  *
  969.  *  Returns:
  970.  *      Nothing
  971.  *
  972.  */
  973. /*******************************************************************/
  974.  
  975. void CBldPropDlg::OnChangePropIDHexLB()
  976. {
  977.     char    szBuffer[4096];
  978.     int     idx         = 0;
  979.     LONG    lCurSelect  = 0;
  980.     DWORD   dwIndex     = 0;
  981.     ULONG   ulIDVal     = 0;
  982.     LONG    len         = -1;
  983.     int     i           = 0;
  984.     LONG    lTempTag    = 0;
  985.  
  986.     // get value out of the edit control
  987.     *(WORD *)szBuffer = sizeof(szBuffer) -1;    // first char has buffer length
  988.  
  989.     len  = SendDlgItemMessage(IDC_SP_PROPID,EM_GETLINE,0,(LPARAM)(void *)szBuffer);
  990.             
  991.     szBuffer[len] = '\0';        // null terminate our buffer
  992.  
  993.     if( ! AsciiToHex(len,szBuffer, &ulIDVal ) )
  994.  
  995.     {
  996.         MessageBox("CDlg::OnSet AsciiToHex Failed", "Client", MBS_ERROR );
  997.         return;
  998.     }       
  999.  
  1000.     // find out if the hex value is in PropTag list
  1001.     if( !GetString("PropIDs",ulIDVal,szBuffer) )
  1002.     {
  1003.         // set the current selection as UNKNOWN PROPID and PROPTYPE
  1004.         dwIndex = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_SETCURSEL, 0,0);
  1005.         
  1006.         dwIndex = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_SELECTSTRING,
  1007.                 (WPARAM) -1, (LPARAM)(void *) "PT_UNSPECIFIED");
  1008.  
  1009.         szBuffer[0] = '\0';
  1010.         // Set PropData edit control
  1011.         SendDlgItemMessage(IDC_SP_PROPDATA,WM_CLEAR,0,0);
  1012.  
  1013.         SelectNewPropType( PT_UNSPECIFIED );
  1014.  
  1015.         GetDlgItem( IDC_SP_PROPDATA )->SetWindowText(  szBuffer );
  1016.  
  1017.         return;           
  1018.     }
  1019.  
  1020.                     
  1021.     // if it is NOT an UNKNOWN PROPID, adjust PropTags, PropType, and DATA
  1022.     dwIndex = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_SELECTSTRING,
  1023.                 (WPARAM) -1, (LPARAM) szBuffer);
  1024.         
  1025.     // determine which entry in listbox is selected
  1026.     lCurSelect = SendDlgItemMessage(IDC_SP_PROPTAGS,LB_GETCURSEL,0,0);
  1027.     SendDlgItemMessage(IDC_SP_PROPTAGS,LB_GETTEXT,(WPARAM)lCurSelect,
  1028.                         (LPARAM)szBuffer);
  1029.     m_SelectedTag = szBuffer;
  1030.     
  1031.     // if property exists, don't change the m_lSelectedTag   
  1032.     // only reset the m_lSelectedTag if the property does not already exist !!!!!!!!!    
  1033.  
  1034.     GetID("PropTags", m_SelectedTag.GetBuffer(5),&lTempTag );
  1035.  
  1036.     // loop through the list of existing old properties and see if it is there
  1037.  
  1038.     for( i = 0; i < m_ulOldValues ; i++)
  1039.     {
  1040.         if( (PROP_ID(m_lpOldPropValue[i].ulPropTag)) == (PROP_ID(lTempTag)) )
  1041.             break;                 
  1042.     }    
  1043.  
  1044.     // if not, set m_lSelectedTag to new computed value(default)
  1045.     if( i == m_ulOldValues )  // if it reached the end of the list without match
  1046.         m_lSelectedTag = lTempTag;    
  1047.  
  1048.     // set PropType Control Box
  1049.     GetString("PropType",PROP_TYPE(m_lSelectedTag),szBuffer);
  1050.     dwIndex = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_SELECTSTRING,
  1051.                 (WPARAM) -1, (LPARAM) szBuffer);
  1052.  
  1053.  
  1054.     // new
  1055.     SelectNewPropType( PROP_TYPE(m_lSelectedTag) );
  1056.  
  1057.     // Set PropData edit control
  1058.     SendDlgItemMessage(IDC_SP_PROPDATA,WM_CLEAR,0,0);
  1059.     szBuffer[0] = '\0';
  1060.  
  1061.     for(idx = 0; idx < m_ulOldValues ; idx++)
  1062.     {
  1063.         if( ((ULONG) m_lSelectedTag) == ((ULONG)m_lpOldPropValue[idx].ulPropTag ) )
  1064.         {
  1065.             if( PROP_TYPE(m_lSelectedTag) == PT_BINARY )
  1066.             {
  1067.                 char    lpszHex[9];
  1068.                 ULONG   cb          = 0;
  1069.                 ULONG   cChars      = 0;
  1070.                 LPBYTE  lpb         = m_lpOldPropValue[idx].Value.bin.lpb;
  1071.  
  1072.                 while((cb < m_lpOldPropValue[idx].Value.bin.cb) && (cChars < MAX_LOG_BUFF-16 ) )
  1073.                 {
  1074.                     wsprintf(lpszHex, "%02X ", *lpb);
  1075.                     lstrcat(szBuffer, lpszHex);
  1076.                     cChars += 3;
  1077.                     lpb++;
  1078.                     cb++;
  1079.                 }
  1080.             }
  1081.             else
  1082.             {
  1083.                 SzGetPropValue(szBuffer,(LPSPropValue) &m_lpOldPropValue[idx]);
  1084.             }
  1085.             break;
  1086.         }
  1087.         
  1088.     }
  1089.     GetDlgItem( IDC_SP_PROPDATA )->SetWindowText(  szBuffer );
  1090. }
  1091.  
  1092. /*******************************************************************/
  1093. /*
  1094.  -  CBldPropDlg::
  1095.  -  OnAdd
  1096.  -
  1097.  *  Purpose:
  1098.  *      Commit the SetProps on newly constructed Property
  1099.  */
  1100. /*******************************************************************/
  1101.  
  1102. #ifdef WIN16
  1103. #pragma optimize("",off)
  1104. #endif
  1105.  
  1106. void CBldPropDlg::OnAdd()
  1107. {
  1108.     char    szBuffer[512];
  1109.     LONG    lCurSelect      = 0;
  1110.     LONG    lSelectedType   = 0;
  1111.     int     idx             = 0;
  1112.     HRESULT hResult         = hrSuccess;
  1113.     SCODE   scResult        = SUCCESS_SUCCESS;
  1114.     LPSPropProblemArray     lpProblems = NULL;
  1115.     CGetError E;
  1116.     ULONG   ulPropID        = 0;
  1117.     LONG    len             = 0;
  1118.     LONG    lenBin          = 0;
  1119.     ULONG   ulVal           = 0;
  1120.     ULONG   ulIDVal         = 0;
  1121.     int     i               = 0;
  1122.     LONG    lVal            = 0;
  1123.     double  dVal            = 0;
  1124.     int     iVal            = 0;
  1125.     float   fVal            = (float) 0.0;
  1126.     int     dBytes          = 0;
  1127.     int     dCopiedBytes    = 0;
  1128.     DWORD   dwRet           = 0;
  1129.     int     dBufferLen      = 0;
  1130.     LPSPropValue    lpNewPVA = NULL;
  1131.     ULONG           ulMax           = 0;
  1132.     SYSTEMTIME FAR  *lpSysTime          = NULL;
  1133.  
  1134.     // multi value props stuff    
  1135.     char            szMVSeps[]      = ";:";
  1136.  
  1137.     LPSTR           *lppszToken     = NULL;
  1138.     char            *lpszTemp       = NULL;
  1139.     char            *lpszToken      = NULL;
  1140.     ULONG           ulMVRow         = 0;
  1141.     char            *szEnd          = NULL;
  1142.  
  1143.  
  1144.  
  1145.     //PROPTYPE
  1146.     szBuffer[0] = '\0' ;
  1147.     // get property type combo box entry
  1148.     lCurSelect = SendDlgItemMessage(IDC_SP_PROPTYPE,CB_GETCURSEL,0,0);
  1149.     SendDlgItemMessage(IDC_SP_PROPTYPE,CB_GETLBTEXT,(WPARAM)lCurSelect,
  1150.                         (LPARAM)szBuffer);
  1151.     GetID("PropType", szBuffer,&lSelectedType );    
  1152.     
  1153.     //PROPID HEX VALUE read out
  1154.     szBuffer[0] = '\0' ;
  1155.     // get value out of the edit control
  1156.     *(WORD *)szBuffer = sizeof(szBuffer) -1;    // first char has buffer length
  1157.     len  = SendDlgItemMessage(IDC_SP_PROPID,EM_GETLINE,0,(LPARAM)szBuffer);
  1158.     szBuffer[len] = '\0';        // null terminate our buffer
  1159.     // get a line of data from ID edit control
  1160.     if( ! AsciiToHex(len,szBuffer, &ulIDVal ) )
  1161.     {
  1162.         MessageBox("CDlg::OnSet AsciiToHex Failed", "Client", MBS_ERROR );
  1163.         goto Error;
  1164.     }       
  1165.  
  1166.     // if it is a PropValueArray
  1167.     if(m_fIsPropValueArray) 
  1168.     {           
  1169.         // allocate a new SPropValue and add to list(use PvAlloc)
  1170.         lpNewPVA = (LPSPropValue) PvAlloc( sizeof(SPropValue) );
  1171.         lpNewPVA[0].ulPropTag = PROP_TAG((ULONG)lSelectedType, (ULONG)ulIDVal ); 
  1172.         GetString("PropTags",lpNewPVA[0].ulPropTag,szBuffer);
  1173.  
  1174.         //PROPDATA 
  1175.         // get value out of the edit control
  1176.         *(WORD *)szBuffer = sizeof(szBuffer) -1;    // first char has buffer length
  1177.         // get a line of data from data edit control
  1178.         len = SendDlgItemMessage(IDC_SP_PROPDATA,EM_GETLINE,0,(LPARAM)szBuffer);
  1179.         szBuffer[len] = '\0' ;  // ensure end of string is null terminated from getline
  1180.  
  1181.         // determine which type of data it is and load  
  1182.         switch(lSelectedType)
  1183.         {
  1184.             // all elements of size ULONG
  1185.             //$ FUTURE this should not convert all of these to hex, it should
  1186.             //    convert to the appropriate type Decimal, SYSTEMTIME, etc.
  1187.  
  1188.             case PT_UNSPECIFIED:                       
  1189.                 break;
  1190.                 
  1191.             case PT_I2:         // short int
  1192.                 iVal = atoi(szBuffer);
  1193.                 lpNewPVA[0].Value.i = iVal;                 
  1194.                 break;        
  1195.  
  1196.             case PT_LONG:       // long
  1197.                 lVal = strtol(szBuffer,&szEnd,10);
  1198.                 lpNewPVA[0].Value.l = lVal;                 
  1199.                 break;        
  1200.  
  1201.             case PT_R4:         // float
  1202.                 fVal = (float) atof(szBuffer);
  1203.                 lpNewPVA[0].Value.flt = fVal;                   
  1204.                 break;        
  1205.  
  1206.             case PT_DOUBLE:     // double
  1207.                 dVal = strtod(szBuffer,&szEnd);
  1208.                 lpNewPVA[0].Value.dbl = dVal;                   
  1209.                 break;        
  1210.  
  1211.             case PT_CURRENCY:   // Special Currency two longs such as 3 45
  1212.                 lpszToken   = strtok(szBuffer," ");
  1213.                 lpNewPVA[0].Value.cur.Lo =  strtol(lpszToken,&szEnd,10);        
  1214.  
  1215.                 lpszToken   = strtok(NULL," ");
  1216.                 lpNewPVA[0].Value.cur.Hi =  strtol(lpszToken,&szEnd,10);        
  1217.                 break;
  1218.  
  1219.             case PT_APPTIME:    // double
  1220.                 dVal = strtod(szBuffer,&szEnd);
  1221.                 lpNewPVA[0].Value.at = dVal;                    
  1222.                 break;        
  1223.  
  1224.             case PT_BOOLEAN:    // unsigned short int
  1225.                 iVal = atoi(szBuffer);
  1226.                 lpNewPVA[0].Value.b = iVal;         
  1227.                 break;
  1228.  
  1229.             case PT_SYSTIME:    // Special FILETIME
  1230.                 
  1231.                 lpSysTime = (LPSYSTEMTIME) PvAlloc(sizeof(SYSTEMTIME) );
  1232.                 memset(lpSysTime,0,(size_t) sizeof(SYSTEMTIME) );
  1233.                 
  1234.                 lpszToken   = strtok(szBuffer,"/");
  1235.                 lpSysTime->wYear   = atoi(lpszToken);
  1236.                 lpszToken   = strtok(NULL,"/");
  1237.                 lpSysTime->wMonth  = atoi(lpszToken);
  1238.                 lpszToken   = strtok(NULL," ");
  1239.                 lpSysTime->wDay    = atoi(lpszToken);
  1240.                 lpszToken   = strtok(NULL,":");
  1241.                 lpSysTime->wHour   = atoi(lpszToken);
  1242.                 lpszToken   = strtok(NULL,":");
  1243.                 lpSysTime->wMinute = atoi(lpszToken);
  1244.                 lpszToken   = strtok(NULL," ");
  1245.                 lpSysTime->wSecond = atoi(lpszToken);
  1246.  
  1247.                 if( ! SystemTimeToFileTime(lpSysTime, &(lpNewPVA[0].Value.ft) ) )
  1248.                 {
  1249.                     MessageBox("Could not convert SystemTimeToFileTime", "Client", MBS_INFO );
  1250.                     PvFree(lpSysTime);
  1251.                     goto Error;
  1252.                 }    
  1253.  
  1254.                 PvFree(lpSysTime);
  1255.                 break;                
  1256.  
  1257.  
  1258.             case PT_STRING8:    // LPSTR
  1259.                 lpNewPVA[0].Value.lpszA = (LPSTR) PvAllocMore( len+1 ,lpNewPVA);
  1260.                 memset(lpNewPVA[0].Value.lpszA,0,(size_t)len+1);
  1261.                 lstrcpy(lpNewPVA[0].Value.lpszA, szBuffer);
  1262.                 break;                                
  1263.  
  1264.             case PT_BINARY:     // binary 00 11 00 10 01 
  1265.                 // make sure it is in the proper format for putting back in Hex
  1266.                 if (((len % 3) != 0) && (((len + 1) % 3) != 0))
  1267.                 {
  1268.                     MessageBox("Enter Binary data as follows:  00 00 10 01 11 ",
  1269.                                      "Client", MBS_ERROR );
  1270.                     goto Error;
  1271.                 }       
  1272.                 lpNewPVA[0].Value.bin.lpb = (LPBYTE) PvAllocMore( len/3 ,lpNewPVA);
  1273.                 len = (len + 1) / 3;
  1274.                 memset (lpNewPVA[0].Value.bin.lpb, 0,(size_t) len);
  1275.  
  1276.                 for (i = 0; i < len; i++)
  1277.                 {
  1278.                     if (!AsciiToHex (2, &szBuffer[i * 3],
  1279.                                 (ULONG *) & lpNewPVA[0].Value.bin.lpb[i]))
  1280.                     {
  1281.                         MessageBox("CBldPropDlg::OnSet AsciiToHex Failed", "Client", MBS_ERROR );
  1282.                         goto Error;
  1283.                     }       
  1284.                 }
  1285.                 lpNewPVA[0].Value.bin.cb = len;
  1286.                 break;
  1287.  
  1288.  
  1289.             case PT_UNICODE:
  1290.     #ifdef WIN32
  1291.                 if(szBuffer)                        
  1292.                     dBufferLen = lstrlen(szBuffer) + 1;     // the number of bytes plus the null char
  1293.  
  1294.                 // determines the number of Wide char bytes requried
  1295.                 dBytes = MultiByteToWideChar(   (UINT)      CP_ACP,            
  1296.                                                 (DWORD)     0,                 
  1297.                                                 (LPCTSTR)   szBuffer,          
  1298.                                                 (int)       dBufferLen,                                              
  1299.                                                 (LPWSTR)    NULL,
  1300.                                                 (int)       0);
  1301.                    
  1302.                 // allocate memory for the UNICODE string in the lpsPropValue               
  1303.                 // a wide character is two bytes so the amount of memory required is 2 * number of wide char bytes     
  1304.  
  1305.                 lpNewPVA[0].Value.lpszW = (LPWSTR) PvAllocMore( (dBytes * sizeof(WCHAR)),lpNewPVA ) ;
  1306.                 
  1307.                  // now actually convert the szBuffer edit control STRING8 into a UNICODE                       
  1308.                 dCopiedBytes = MultiByteToWideChar((UINT)   CP_ACP,            
  1309.                                                 (DWORD)     0,                 
  1310.                                                 (LPCTSTR)   szBuffer,          
  1311.                                                 (int)       dBufferLen,                                              
  1312.                                                 (LPWSTR)    lpNewPVA[0].Value.lpszW,    
  1313.                                                 (int)       dBytes );
  1314.                           
  1315.                 dwRet = GetLastError();
  1316.                 break;
  1317.     #endif      
  1318.                 // else it will fall down here in 16 bit
  1319.                 MessageBox("Viewer doesn't support setting PT_UNICODE on 16 bit", "Client", MBS_INFO );
  1320.                 goto Error;
  1321.  
  1322.             // SUPPORT IN  FUTURE 
  1323.             
  1324.             case PT_CLSID:      // Special LPUID
  1325.                 MessageBox("Viewer doesn't support setting PT_CLSID", "Client", MBS_INFO );
  1326.                 goto Error;
  1327.  
  1328.             case PT_I8:         // Special LARGE_INTEGER
  1329.                 lpszToken   = strtok(szBuffer," ");
  1330.                 lpNewPVA[0].Value.li.LowPart =  strtol(lpszToken,&szEnd,10);        
  1331.  
  1332.                 lpszToken   = strtok(NULL," ");
  1333.                 lpNewPVA[0].Value.li.HighPart =  strtol(lpszToken,&szEnd,10);        
  1334.                 break;
  1335.                 
  1336.             case PT_NULL:       // set not data for PT_NULL
  1337.                 break;
  1338.  
  1339.             case PT_OBJECT:     // not supported yet
  1340.                 break;
  1341.  
  1342.             case PT_ERROR:      // Special Scode (ULONG)
  1343.                 // read data, find out if recognized SCODE, if not, goto error
  1344.                 
  1345.                 if(GetID("MAPIErrors",szBuffer,&lVal) )
  1346.                     lpNewPVA[0].Value.err = lVal;
  1347.                 else
  1348.                 {                                        
  1349.                     MessageBox("Could not interpret this String as a MAPI Return code", "Client", MBS_INFO );
  1350.                     goto Error;
  1351.                 }                    
  1352.                 break;
  1353.             
  1354.             // ********** MULTI VALUE PROPERTIES
  1355.             // Generally read in as follows:  cVals: val1; val2; val3; ...                
  1356.                 
  1357.             case PT_MV_I2:      // array of short ints
  1358.     
  1359.                 ulMVRow = 0;
  1360.                 // determine count of multi values
  1361.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1362.                 lpNewPVA[0].Value.MVi.cValues =  strtoul(lpszToken,&szEnd,10);        
  1363.  
  1364.                 lpNewPVA[0].Value.MVi.lpi = (short int *) PvAllocMore(
  1365.                             (sizeof(short int) * lpNewPVA[0].Value.MVi.cValues), lpNewPVA );
  1366.  
  1367.                 // rip out first row of multi value prop
  1368.                 lpszToken = strtok(NULL,szMVSeps);
  1369.                             
  1370.                 // rip out remaining rows                
  1371.                 while( lpszToken != NULL )
  1372.                 {
  1373.                     lpNewPVA[0].Value.MVi.lpi[ulMVRow] = atoi(lpszToken);
  1374.                     lpszToken = strtok(NULL,szMVSeps);
  1375.                     ulMVRow++;
  1376.                 }                
  1377.             
  1378.                 // if all the data was not there, fill in the remainder with bogus stub
  1379.                 while( ulMVRow < lpNewPVA[0].Value.MVi.cValues )
  1380.                 {
  1381.                     lpNewPVA[0].Value.MVi.lpi[ulMVRow] = 0;
  1382.                     ulMVRow++;                            
  1383.                 }
  1384.                 break;
  1385.                 
  1386.             case PT_MV_LONG:    // array of longs
  1387.  
  1388.                 ulMVRow = 0;
  1389.                 // determine count of multi values
  1390.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1391.                 lpNewPVA[0].Value.MVl.cValues =  strtoul(lpszToken,&szEnd,10);        
  1392.  
  1393.                 lpNewPVA[0].Value.MVl.lpl = (LONG *) PvAllocMore(
  1394.                             (sizeof(LONG) * lpNewPVA[0].Value.MVl.cValues),lpNewPVA );
  1395.  
  1396.                 // rip out first row of multi value prop
  1397.                 lpszToken = strtok(NULL,szMVSeps);
  1398.                             
  1399.                 // rip out remaining rows                
  1400.                 while( lpszToken != NULL )
  1401.                 {
  1402.                     lpNewPVA[0].Value.MVl.lpl[ulMVRow] = strtol(lpszToken,&szEnd,10);
  1403.                     lpszToken = strtok(NULL,szMVSeps);
  1404.                     ulMVRow++;
  1405.                 }                
  1406.             
  1407.                 // if all the data was not there, fill in the remainder with bogus stub
  1408.                 while( ulMVRow < lpNewPVA[0].Value.MVl.cValues )
  1409.                 {
  1410.                     lpNewPVA[0].Value.MVl.lpl[ulMVRow] = 0;
  1411.                     ulMVRow++;                            
  1412.                 }
  1413.                 break;
  1414.                 
  1415.             case PT_MV_R4:
  1416.                 ulMVRow = 0;
  1417.  
  1418.                 // determine count of multi values
  1419.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1420.                 lpNewPVA[0].Value.MVflt.cValues =  strtoul(lpszToken,&szEnd,10);        
  1421.  
  1422.                 lpNewPVA[0].Value.MVflt.lpflt = (float *) PvAllocMore(
  1423.                             (sizeof(float) * lpNewPVA[0].Value.MVflt.cValues),lpNewPVA );
  1424.  
  1425.                 // rip out first row of multi value prop
  1426.                 lpszToken = strtok(NULL,szMVSeps);
  1427.                             
  1428.                 // rip out remaining rows                
  1429.                 while( lpszToken != NULL )
  1430.                 {
  1431.                     lpNewPVA[0].Value.MVflt.lpflt[ulMVRow] = (float) atof(lpszToken);
  1432.                     lpszToken = strtok(NULL,szMVSeps);
  1433.                     ulMVRow++;
  1434.                 }                
  1435.             
  1436.                 // if all the data was not there, fill in the remainder with bogus stub
  1437.                 while( ulMVRow < lpNewPVA[0].Value.MVflt.cValues )
  1438.                 {
  1439.                     lpNewPVA[0].Value.MVflt.lpflt[ulMVRow] = (float) 0.0;
  1440.                     ulMVRow++;                            
  1441.                 }
  1442.             
  1443.                 break;
  1444.                 
  1445.             case PT_MV_DOUBLE:
  1446.                 ulMVRow = 0;
  1447.  
  1448.                 // determine count of multi values
  1449.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1450.                 lpNewPVA[0].Value.MVdbl.cValues =  strtoul(lpszToken,&szEnd,10);        
  1451.  
  1452.                 lpNewPVA[0].Value.MVdbl.lpdbl = (double *) PvAllocMore(
  1453.                             (sizeof(double) * lpNewPVA[0].Value.MVdbl.cValues),lpNewPVA );
  1454.  
  1455.                 // rip out first row of multi value prop
  1456.                 lpszToken = strtok(NULL,szMVSeps);
  1457.                             
  1458.                 // rip out remaining rows                
  1459.                 while( lpszToken != NULL )
  1460.                 {
  1461.                     lpNewPVA[0].Value.MVdbl.lpdbl[ulMVRow] = (double) strtod(lpszToken,&szEnd);
  1462.                     lpszToken = strtok(NULL,szMVSeps);
  1463.                     ulMVRow++;
  1464.                 }                
  1465.             
  1466.                 // if all the data was not there, fill in the remainder with bogus stub
  1467.                 while( ulMVRow < lpNewPVA[0].Value.MVdbl.cValues )
  1468.                 {
  1469.                     lpNewPVA[0].Value.MVdbl.lpdbl[ulMVRow] = 0;
  1470.                     ulMVRow++;                            
  1471.                 }
  1472.             
  1473.                 break;
  1474.                 
  1475.  
  1476.             case PT_MV_CURRENCY:
  1477.                 ulMVRow = 0;
  1478.                 // determine count of multi values
  1479.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1480.                 lpNewPVA[0].Value.MVcur.cValues =  strtoul(lpszToken,&szEnd,10);        
  1481.  
  1482.                 lpNewPVA[0].Value.MVcur.lpcur = (CURRENCY *) PvAllocMore(
  1483.                             (sizeof(CURRENCY) * lpNewPVA[0].Value.MVcur.cValues),lpNewPVA );
  1484.  
  1485.                 lppszToken = (LPSTR *) PvAlloc(
  1486.                             (30 * sizeof(char) * lpNewPVA[0].Value.MVcur.cValues) );
  1487.  
  1488.                 memset(lpNewPVA[0].Value.MVcur.lpcur,0,
  1489.                         (size_t) (sizeof(CURRENCY) * lpNewPVA[0].Value.MVcur.cValues) );
  1490.  
  1491.                 // rip out remaining rows                
  1492.                 while( (lppszToken[ulMVRow] = strtok(NULL,";")) != NULL )
  1493.                     ulMVRow++;
  1494.  
  1495.                 for(idx = 0 ; idx < ulMVRow ; idx++)
  1496.                 {
  1497.                     lpszToken   = strtok(lppszToken[idx]," ");
  1498.                     lpNewPVA[0].Value.MVcur.lpcur[idx].Lo =  strtol(lpszToken,&szEnd,10);        
  1499.  
  1500.                     lpszToken   = strtok(NULL," ");
  1501.                     lpNewPVA[0].Value.MVcur.lpcur[idx].Hi =  strtol(lpszToken,&szEnd,10);        
  1502.                 }
  1503.  
  1504.                 break;
  1505.                 
  1506.             case PT_MV_APPTIME:
  1507.                 ulMVRow = 0;
  1508.                 // determine count of multi values
  1509.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1510.                 lpNewPVA[0].Value.MVat.cValues =  strtoul(lpszToken,&szEnd,10);        
  1511.  
  1512.                 lpNewPVA[0].Value.MVat.lpat = (double *) PvAllocMore(
  1513.                             (sizeof(double) * lpNewPVA[0].Value.MVat.cValues),lpNewPVA );
  1514.  
  1515.                 // rip out first row of multi value prop
  1516.                 lpszToken = strtok(NULL,szMVSeps);
  1517.                             
  1518.                 // rip out remaining rows                
  1519.                 while( lpszToken != NULL )
  1520.                 {
  1521.                     lpNewPVA[0].Value.MVat.lpat[ulMVRow] = (double) strtod(lpszToken,&szEnd);
  1522.                     lpszToken = strtok(NULL,szMVSeps);
  1523.                     ulMVRow++;
  1524.                 }                
  1525.             
  1526.                 // if all the data was not there, fill in the remainder with bogus stub
  1527.                 while( ulMVRow < lpNewPVA[0].Value.MVat.cValues )
  1528.                 {
  1529.                     lpNewPVA[0].Value.MVat.lpat[ulMVRow] = 0;
  1530.                     ulMVRow++;                            
  1531.                 }
  1532.                 break;
  1533.  
  1534.             case PT_MV_SYSTIME:
  1535.                 ulMVRow = 0;
  1536.                 // determine count of multi values
  1537.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1538.                 lpNewPVA[0].Value.MVft.cValues =  strtoul(lpszToken,&szEnd,10);        
  1539.  
  1540.                 lpNewPVA[0].Value.MVft.lpft = (FILETIME *) PvAllocMore(
  1541.                             (sizeof(FILETIME) * lpNewPVA[0].Value.MVft.cValues),lpNewPVA );
  1542.  
  1543.                 lppszToken = (LPSTR *) PvAlloc(
  1544.                             (30 * sizeof(char) * lpNewPVA[0].Value.MVft.cValues) );
  1545.  
  1546.                 memset(lpNewPVA[0].Value.MVft.lpft,0,
  1547.                         (size_t) (sizeof(FILETIME) * lpNewPVA[0].Value.MVft.cValues ));
  1548.  
  1549.                 // rip out remaining rows                
  1550.                 while( (lppszToken[ulMVRow] = strtok(NULL,";")) != NULL )
  1551.                     ulMVRow++;
  1552.  
  1553.                 for(idx = 0 ; idx < ulMVRow ; idx++)
  1554.                 {
  1555.                     lpSysTime = (LPSYSTEMTIME) PvAlloc(sizeof(SYSTEMTIME) );
  1556.                     memset(lpSysTime,0,(size_t) sizeof(SYSTEMTIME) );
  1557.                                        
  1558.                     lpszTemp   = strtok(lppszToken[idx],"/");
  1559.                     lpSysTime->wYear   = atoi(lpszTemp);
  1560.                     lpszTemp   = strtok(NULL,"/");
  1561.                     lpSysTime->wMonth  = atoi(lpszTemp);
  1562.                     lpszTemp   = strtok(NULL," ");
  1563.                     lpSysTime->wDay    = atoi(lpszTemp);
  1564.                     lpszTemp   = strtok(NULL,":");
  1565.                     lpSysTime->wHour   = atoi(lpszTemp);
  1566.                     lpszTemp   = strtok(NULL,":");
  1567.                     lpSysTime->wMinute = atoi(lpszTemp);
  1568.                     lpszTemp   = strtok(NULL," ");
  1569.                     lpSysTime->wSecond = atoi(lpszTemp);
  1570.  
  1571.                     if( ! SystemTimeToFileTime(lpSysTime, &(lpNewPVA[0].Value.MVft.lpft[idx]) ) )
  1572.                     {
  1573.                         MessageBox("Could not convert SystemTimeToFileTime", "Client", MBS_INFO );
  1574.                         PvFree(lpSysTime);
  1575.                         goto Error;
  1576.                     }    
  1577.  
  1578.                     PvFree(lpSysTime);
  1579.                 }
  1580.             
  1581.                 break;
  1582.                 
  1583.             case PT_MV_STRING8:
  1584.  
  1585.                 ulMVRow = 0;
  1586.                 // determine count of multi values
  1587.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1588.                 lpNewPVA[0].Value.MVszA.cValues =  strtoul(lpszToken,&szEnd,10);        
  1589.  
  1590.                 lpNewPVA[0].Value.MVszA.lppszA = (LPSTR *) PvAllocMore(
  1591.                             (sizeof(LPSTR) * lpNewPVA[0].Value.MVszA.cValues),lpNewPVA );
  1592.  
  1593.                 // rip out first row of multi value prop
  1594.                 lpszToken = strtok(NULL,szMVSeps);
  1595.                             
  1596.                 // rip out remaining rows                
  1597.                 while( lpszToken != NULL )
  1598.                 {
  1599.                     
  1600.                     lpNewPVA[0].Value.MVszA.lppszA[ulMVRow] = (LPSTR) PvAllocMore(
  1601.                                 lstrlen(lpszToken) + 1,lpNewPVA);
  1602.                     lstrcpy(lpNewPVA[0].Value.MVszA.lppszA[ulMVRow],lpszToken);
  1603.  
  1604.                     lpszToken = strtok(NULL,szMVSeps);
  1605.                     ulMVRow++;
  1606.                 }                
  1607.             
  1608.                 // if all the data was not there, fill in the remainder with bogus stub
  1609.                 while( ulMVRow < lpNewPVA[0].Value.MVszA.cValues )
  1610.                 {
  1611.                     lpNewPVA[0].Value.MVszA.lppszA[ulMVRow] = (LPSTR) PvAllocMore(
  1612.                                 30 * sizeof(char),lpNewPVA);
  1613.  
  1614.  
  1615.                     lstrcpy(lpNewPVA[0].Value.MVszA.lppszA[ulMVRow], "Unknown");
  1616.  
  1617.                     ulMVRow++;                            
  1618.                 }
  1619.                 break;
  1620.  
  1621.                
  1622.             case PT_MV_BINARY:
  1623.  
  1624.                 ulMVRow = 0;
  1625.                  // determine count of multi values
  1626.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1627.                 lpNewPVA[0].Value.MVbin.cValues =  strtoul(lpszToken,&szEnd,10);        
  1628.  
  1629.                 lpNewPVA[0].Value.MVbin.lpbin = (SBinary *) PvAllocMore(
  1630.                             (sizeof(SBinary) * lpNewPVA[0].Value.MVbin.cValues),lpNewPVA );
  1631.  
  1632.                 // rip out first row of multi value prop
  1633.                 lpszToken = strtok(NULL,szMVSeps);
  1634.                             
  1635.                 // rip out remaining rows                
  1636.                 while( lpszToken != NULL )
  1637.                 {
  1638.                     lenBin = strlen(lpszToken);
  1639.  
  1640.                     // make sure it is in the proper format for putting back in Hex
  1641.                     if (((lenBin % 3) != 0) && (((lenBin + 1) % 3) != 0))
  1642.                     {
  1643.                         MessageBox("Enter Binary data as follows:  00 00 10 01 11 ",
  1644.                                          "Client", MBS_ERROR );
  1645.                         goto Error;
  1646.                     }       
  1647.                     lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].lpb = (LPBYTE) PvAllocMore( lenBin/3 ,lpNewPVA);
  1648.                     lenBin = (lenBin + 1) / 3;
  1649.                     memset (lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].lpb, 0,(size_t) lenBin);
  1650.  
  1651.                     for (i = 0; i < lenBin; i++)
  1652.                     {
  1653.                         if (!AsciiToHex (2, &lpszToken[i * 3],
  1654.                                     (ULONG *) & lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].lpb[i]))
  1655.                         {
  1656.                             MessageBox("CBldPropDlg::OnSet AsciiToHex Failed", "Client", MBS_ERROR );
  1657.                             goto Error;
  1658.                         }       
  1659.                     }
  1660.                     lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].cb = lenBin;
  1661.                     
  1662.                     lpszToken = strtok(NULL,szMVSeps);
  1663.                     ulMVRow++;
  1664.                 }                
  1665.             
  1666.                 // if all the data was not there, fill in the remainder with bogus stub
  1667.                 while( ulMVRow < lpNewPVA[0].Value.MVbin.cValues )
  1668.                 {
  1669.                     lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].lpb = (BYTE *) PvAllocMore(
  1670.                                 30 * sizeof(BYTE),lpNewPVA);
  1671.  
  1672.                     memset(lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].lpb,0,(size_t)10*sizeof(BYTE));
  1673.                     lpNewPVA[0].Value.MVbin.lpbin[ulMVRow].cb = 10;
  1674.  
  1675.                     ulMVRow++;                            
  1676.                 }
  1677.                 break;
  1678.             
  1679.             case PT_MV_UNICODE:
  1680.  
  1681.     #ifdef WIN32
  1682.                  ulMVRow = 0;
  1683.                  // determine count of multi values
  1684.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1685.                 lpNewPVA[0].Value.MVszW.cValues =  strtoul(lpszToken,&szEnd,10);        
  1686.  
  1687.  
  1688.                 lpNewPVA[0].Value.MVszW.lppszW = (LPWSTR *) PvAllocMore(
  1689.                             (sizeof(LPWSTR) * lpNewPVA[0].Value.MVszW.cValues),lpNewPVA );
  1690.  
  1691.                 // rip out first row of multi value prop
  1692.                 lpszToken = strtok(NULL,szMVSeps);
  1693.                             
  1694.                 // rip out remaining rows                
  1695.                 while( lpszToken != NULL )
  1696.                 {
  1697.  
  1698.                     if(lpszToken)                        
  1699.                         dBufferLen = lstrlen(lpszToken) + 1;     // the number of bytes plus the null char
  1700.  
  1701.                     // determines the number of Wide char bytes requried
  1702.                     dBytes = MultiByteToWideChar(   (UINT)      CP_ACP,            
  1703.                                                     (DWORD)     0,                 
  1704.                                                     (LPCTSTR)   lpszToken,          
  1705.                                                     (int)       dBufferLen,                                              
  1706.                                                     (LPWSTR)    NULL,
  1707.                                                     (int)       0);
  1708.                        
  1709.                     // allocate memory for the UNICODE string in the lpsPropValue               
  1710.                     // a wide character is two bytes so the amount of memory required is 2 * number of wide char bytes     
  1711.      
  1712.                     lpNewPVA[0].Value.MVszW.lppszW[ulMVRow] = 
  1713.                             (LPWSTR) PvAllocMore( (dBytes * sizeof(WCHAR)),lpNewPVA ) ;
  1714.                     
  1715.                      // now actually convert the lpszToken edit control STRING8 into a UNICODE                      
  1716.                     dCopiedBytes = MultiByteToWideChar((UINT)   CP_ACP,            
  1717.                                                     (DWORD)     0,                 
  1718.                                                     (LPCTSTR)   lpszToken,          
  1719.                                                     (int)       dBufferLen,                                              
  1720.                                                     (LPWSTR)    lpNewPVA[0].Value.MVszW.lppszW[ulMVRow],    
  1721.                                                     (int)       dBytes );
  1722.                               
  1723.                     dwRet = GetLastError();
  1724.  
  1725.                     lpszToken = strtok(NULL,szMVSeps);
  1726.  
  1727.                     ulMVRow++;
  1728.                 }                
  1729.             
  1730.                 // if all the data was not there, fill in the remainder with bogus stub
  1731.                 while( ulMVRow < lpNewPVA[0].Value.MVszW.cValues )
  1732.                 {
  1733.                     lpNewPVA[0].Value.MVszW.lppszW[ulMVRow] = (LPWSTR) PvAllocMore(
  1734.                                 30 * sizeof(WCHAR),lpNewPVA);
  1735.  
  1736.                      // now actually convert the lpszToken edit control STRING8 into a UNICODE                      
  1737.                     dCopiedBytes = MultiByteToWideChar((UINT)   CP_ACP,            
  1738.                                                     (DWORD)     0,                 
  1739.                                                     (LPCTSTR)   "UnKnown",          
  1740.                                                     (int)       20,                                              
  1741.                                                     (LPWSTR)    lpNewPVA[0].Value.MVszW.lppszW[ulMVRow],    
  1742.                                                     (int)       dBytes );
  1743.                               
  1744.                     dwRet = GetLastError();
  1745.  
  1746.                     ulMVRow++;                            
  1747.                 }
  1748.                 break;
  1749.     #endif      
  1750.                 // else it will fall down here in 16 bit
  1751.                 MessageBox("Viewer doesn't support setting PT_MV_UNICODE on 16 bit", "Client", MBS_INFO );
  1752.                 goto Error;
  1753.  
  1754.  
  1755.  
  1756.                 // SUPPORT IN  FUTURE 
  1757.                          
  1758.             case PT_MV_CLSID:
  1759.                 MessageBox("Viewer doesn't support setting PT_MV_CLSID", "Client", MBS_INFO );            
  1760.                 goto Error;
  1761.                 
  1762.             case PT_MV_I8:
  1763.                 ulMVRow = 0;
  1764.                 // determine count of multi values
  1765.                 lpszToken   = strtok(szBuffer,szMVSeps);
  1766.                 lpNewPVA[0].Value.MVli.cValues =  strtoul(lpszToken,&szEnd,10);        
  1767.  
  1768.                 lpNewPVA[0].Value.MVli.lpli = (LARGE_INTEGER *) PvAllocMore(
  1769.                             (sizeof(LARGE_INTEGER) * lpNewPVA[0].Value.MVli.cValues),lpNewPVA );
  1770.  
  1771.                 lppszToken = (LPSTR *) PvAlloc(
  1772.                             (30 * sizeof(char) * lpNewPVA[0].Value.MVli.cValues) );
  1773.  
  1774.                 memset(lpNewPVA[0].Value.MVli.lpli,0,
  1775.                         (size_t) (sizeof(LARGE_INTEGER) * lpNewPVA[0].Value.MVli.cValues ));
  1776.  
  1777.                 // rip out remaining rows                
  1778.                 while( (lppszToken[ulMVRow] = strtok(NULL,";")) != NULL )
  1779.                     ulMVRow++;
  1780.  
  1781.                 for(idx = 0 ; idx < ulMVRow ; idx++)
  1782.                 {
  1783.                     lpszToken   = strtok(lppszToken[idx]," ");
  1784.                     lpNewPVA[0].Value.MVli.lpli[idx].LowPart =  strtol(lpszToken,&szEnd,10);        
  1785.  
  1786.                     lpszToken   = strtok(NULL," ");
  1787.                     lpNewPVA[0].Value.MVli.lpli[idx].HighPart =  strtol(lpszToken,&szEnd,10);        
  1788.                 }
  1789.  
  1790.                 break;
  1791.                 
  1792.             default:
  1793.                 MessageBox("[Error] UNKNOWN PROPERTY TYPE", "Client", MBS_INFO );                        
  1794.                 goto Error;
  1795.         }
  1796.  
  1797.         m_ulNewValues++;
  1798.         m_lppNewPropValue[m_ulNewValues - 1] = lpNewPVA;
  1799.         
  1800.     }
  1801.     else  // its a Prop Tag Array
  1802.     {
  1803.         //Move NEW TAG from ID and TYPE
  1804.  
  1805.         m_lpNewPTA->cValues++;
  1806.         m_lpNewPTA->aulPropTag[m_lpNewPTA->cValues - 1] = 
  1807.                         PROP_TAG((ULONG)lSelectedType, (ULONG)ulIDVal ); 
  1808.     
  1809.     }     
  1810.       
  1811.     RedrawBuildProps();     
  1812.     
  1813.     return;
  1814.     
  1815. Error: 
  1816.  
  1817.     if(lpNewPVA)
  1818.     {
  1819.         PvFree(lpNewPVA);
  1820.         lpNewPVA = NULL;
  1821.     }
  1822. }
  1823.  
  1824. #ifdef WIN16
  1825. #pragma optimize("",on)
  1826. #endif
  1827.  
  1828.  
  1829. /*******************************************************************/
  1830. /*                        
  1831.  -  CBldPropDlg::
  1832.  -  OnCall
  1833.  -
  1834.  *  Purpose:
  1835.  *      Calls SetProps on lpsPropValue array built up in m_lpNewPropValue
  1836.  *      and closes dialog
  1837.  */
  1838. /*******************************************************************/
  1839.  
  1840. void CBldPropDlg::OnCall()
  1841. {
  1842.     ULONG       idx;
  1843.     
  1844.     // build the lpSelected PropValue
  1845.  
  1846.     // ASSERT m_lppNewPropValue != NULL and m_ulNewValue !=0
  1847.     if(((!m_lppNewPropValue) || (m_ulNewValues==0)) && (!m_lpNewPTA))
  1848.         goto End;        
  1849.  
  1850.     m_lpspvaSelected = (LPSPropValue) PvAlloc(m_ulNewValues * sizeof(SPropValue) );
  1851.     
  1852.     for(idx = 0 ; idx < m_ulNewValues; idx++)
  1853.     {
  1854.         CopyPropValue(  &(m_lpspvaSelected[idx]),
  1855.                         (LPSPropValue) m_lppNewPropValue[idx],
  1856.                         m_lpspvaSelected);
  1857.         
  1858.             
  1859.         PvFree(m_lppNewPropValue[idx]);
  1860.         m_lppNewPropValue[idx] = NULL;
  1861.     }
  1862.     PvFree(m_lppNewPropValue);
  1863.     m_lppNewPropValue = NULL;
  1864.     
  1865.     if(m_lpNewPTA) 
  1866.     {
  1867.         if(m_lpNewPTA->cValues == 0)
  1868.         {
  1869.             PvFree(m_lpNewPTA);
  1870.             m_lpNewPTA = NULL;
  1871.         }
  1872.     }
  1873.     
  1874.     m_fCall = TRUE;
  1875.  
  1876. End:
  1877.  
  1878.     EndDialog(IDCANCEL);
  1879. }
  1880.  
  1881.  
  1882. /*******************************************************************/
  1883. /*
  1884.  -  CBldPropDlg::
  1885.  -  ~CBldPropDlg
  1886.  -
  1887.  *  Purpose:
  1888.  *      Destructor for class CBldPropDlg. Releases and Frees memory
  1889.  *      allocated in this class
  1890.  *
  1891.  */
  1892. /*******************************************************************/
  1893.  
  1894. CBldPropDlg::~CBldPropDlg()
  1895. {
  1896.     ULONG   idx;
  1897.  
  1898.     if(m_lpOldPropValue)
  1899.     {
  1900.         MAPIFreeBuffer(m_lpOldPropValue);
  1901.         m_lpOldPropValue = NULL;
  1902.     }
  1903.  
  1904.     if(m_lppNewPropValue)
  1905.     {
  1906.         for(idx = 0 ; idx < m_ulNewValues; idx++)
  1907.         {
  1908.             PvFree(m_lppNewPropValue[idx]);
  1909.             m_lppNewPropValue[idx] = NULL;
  1910.         }
  1911.         PvFree(m_lppNewPropValue);
  1912.         m_lppNewPropValue = NULL;
  1913.     }
  1914.     
  1915.     // lpsPropValue to pass back to user
  1916.     PvFree(m_lpspvaSelected);
  1917.     m_lpspvaSelected = NULL;
  1918.     
  1919.     if(m_lpNewPTA)
  1920.     {
  1921.         PvFree(m_lpNewPTA);
  1922.         m_lpNewPTA = NULL;
  1923.     }
  1924.      
  1925. /*******************************************************************/
  1926. /*
  1927.  -  CBldPropDlg::
  1928.  -  OnDelete
  1929.  *
  1930.  *  Purpose:
  1931.  *      Allow user to Help a message with a Help note
  1932.  *
  1933.  *  Parameters:
  1934.  *      None
  1935.  *
  1936.  *  Returns:
  1937.  *      Nothing
  1938.  *
  1939.  *  Note: listbox's are zero based, meaning the 1st element is 
  1940.  *          in 0th index
  1941.  *
  1942.  */ 
  1943. /*******************************************************************/
  1944.  
  1945. void CBldPropDlg::OnDelete()
  1946. {
  1947.     LONG            lCurSelect      = 0;
  1948.     LPSPropValue    lppvaDelete     = NULL;
  1949.     ULONG           ulMax           = 0;
  1950.  
  1951.     // get property type combo box entry
  1952.     lCurSelect = SendDlgItemMessage(IDC_SP_PROPDISPLAY,LB_GETCURSEL,0,0);
  1953.     if(lCurSelect == LB_ERR)
  1954.     {
  1955.         MessageBox("Please Select a Property from Listbox of Selected List to delete", 
  1956.                     "OnDelete", MBS_ERROR );
  1957.         return;
  1958.     }    
  1959.  
  1960.     // if it is a PropValueArray
  1961.     if(m_fIsPropValueArray) 
  1962.     {           
  1963.         if(m_ulNewValues == 0)
  1964.             return;
  1965.             
  1966.         lppvaDelete                   = m_lppNewPropValue[lCurSelect];    
  1967.         m_lppNewPropValue[lCurSelect] = m_lppNewPropValue[m_ulNewValues - 1];
  1968.  
  1969.         if(lppvaDelete)
  1970.         {
  1971.             PvFree(lppvaDelete);
  1972.             lppvaDelete = NULL;
  1973.         }        
  1974.         m_ulNewValues--;
  1975.     }
  1976.     else  // its a Prop Tag Array
  1977.     {                
  1978.         if(m_lpNewPTA->cValues == 0)
  1979.             return;
  1980.  
  1981.         // zero based index, get numvalues - 1 for max
  1982.         ulMax = m_lpNewPTA->cValues - 1;
  1983.  
  1984.         m_lpNewPTA->aulPropTag[lCurSelect] = m_lpNewPTA->aulPropTag[ulMax];      
  1985.         m_lpNewPTA->cValues--;    
  1986.     }     
  1987.   
  1988.     RedrawBuildProps();     
  1989.     
  1990.     return;
  1991.    
  1992.     
  1993. }
  1994.  
  1995.  
  1996. /*******************************************************************/
  1997. /*
  1998.  -  CBldPropDlg::
  1999.  -  OnDumpPropValsToFile
  2000.  *
  2001.  *  Purpose:
  2002.  *      Store PropValues in object to file
  2003.  */
  2004. /*******************************************************************/
  2005.  
  2006. void CBldPropDlg::OnDumpPropValsToFile()
  2007. {
  2008.     char                szTag[80];
  2009.     char                szFileName[80];
  2010.     CStorePropValDlg    StoreProp(this);
  2011.     LPTSTR              lpszTemp;
  2012.     LPSPropValue        lpspvaTemp = NULL;
  2013.     ULONG               idx;        
  2014.         
  2015.     // find file to open
  2016.     lpszTemp = getenv("MAPITEST");
  2017.  
  2018.     if(lpszTemp)
  2019.         strcpy(szFileName, lpszTemp);
  2020.     else
  2021.         strcpy(szFileName, "c:\\mapitest");
  2022.  
  2023.     strcat(szFileName, "\\data\\propvu.txt");
  2024.  
  2025.     // create the tag with braces around it
  2026.     strcpy(szTag,"[BLDPROP00001]");
  2027.  
  2028.     StoreProp.m_TagID       = szTag;
  2029.     StoreProp.m_FileName    = szFileName;
  2030.     
  2031.     if( StoreProp.DoModal() == IDOK )
  2032.     {    
  2033.         // if it is a prop tag array 
  2034.         if(m_lpNewPTA)
  2035.         {   
  2036.             WritePropTagArray(  StoreProp.m_szFileName,
  2037.                             StoreProp.m_szTagID,
  2038.                             m_lpNewPTA);
  2039.         }
  2040.         else        
  2041.         {      
  2042.             // build selectd list, and dump to file
  2043.             lpspvaTemp = (LPSPropValue) PvAlloc(m_ulNewValues * sizeof(SPropValue) );
  2044.     
  2045.             for(idx = 0 ; idx < m_ulNewValues; idx++)
  2046.             {
  2047.                 CopyPropValue(  &(lpspvaTemp[idx]),
  2048.                                 (LPSPropValue) m_lppNewPropValue[idx],
  2049.                                 lpspvaTemp);
  2050.             }
  2051.             
  2052.               
  2053.             WritePropValArray( StoreProp.m_szFileName,
  2054.                             StoreProp.m_szTagID,
  2055.                             m_ulNewValues,
  2056.                             lpspvaTemp,
  2057.                             StoreProp.m_ulFlags);
  2058.             if(lpspvaTemp)
  2059.                 PvFree(lpspvaTemp);                            
  2060.         }                            
  2061.     }
  2062.     
  2063. }
  2064.  
  2065.