home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / ADSDK.ZIP / Samples / General / ADQI / helper.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-08  |  16.9 KB  |  877 lines

  1. #include "stdafx.h"
  2. #include "helper.h"
  3.  
  4.  
  5.  
  6. extern ADSIIF  adsiIfs[];
  7.  
  8. HRESULT  VariantToStringList(  VARIANT& refvar, CStringList& refstringlist)
  9. {
  10.     HRESULT hr = S_OK;
  11.     long start, end;
  12.     USES_CONVERSION;
  13.  
  14.     if ( !(V_VT(&refvar) &  VT_ARRAY)  ) // Single Value
  15.     {
  16.         if ( V_VT(&refvar) == VT_DISPATCH )
  17.         {
  18.             // Find out which interfaces it supports
  19.             IUnknown *pQI;
  20.             int xx=0;
  21.             CString s;
  22.             while( !IsEqualIID( *adsiIfs[xx].pIID, IID_NULL ) )
  23.             {
  24.                    hr = V_DISPATCH(&refvar)->QueryInterface( *adsiIfs[xx].pIID, (void**) &pQI );
  25.                    if ( SUCCEEDED(hr) )
  26.                    {
  27.                         s = ARROW_SYMBOL;
  28.                         s += adsiIfs[xx].szIf;
  29.                         refstringlist.AddHead( s );
  30.                         pQI->Release();
  31.                    }
  32.                    xx++;
  33.             }
  34.             return S_OK;
  35.  
  36.  
  37.         }
  38.         else if ( V_VT(&refvar) != VT_BSTR )
  39.         {
  40.             
  41.             hr = VariantChangeType( &refvar, &refvar,0, VT_BSTR );
  42.  
  43.             if( FAILED(hr) )
  44.             {
  45.                 return hr;
  46.             }
  47.  
  48.         }
  49.         
  50.  
  51.         refstringlist.AddHead( OLE2T(V_BSTR(&refvar)) );
  52.         return hr;
  53.     }
  54.     
  55.  
  56.     SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  57.  
  58.     //
  59.     // Figure out the dimensions of the array.
  60.     //
  61.  
  62.     hr = SafeArrayGetLBound( saAttributes, 1, &start );
  63.         if( FAILED(hr) )
  64.                 return hr;
  65.  
  66.     hr = SafeArrayGetUBound( saAttributes, 1, &end );
  67.         if( FAILED(hr) )
  68.                 return hr;
  69.  
  70.     VARIANT SingleResult;
  71.     VariantInit( &SingleResult );
  72.  
  73.     //
  74.     // Process the array elements.
  75.     //
  76.  
  77.     for ( long idx = start; idx <= end; idx++   ) 
  78.     {
  79.  
  80.         hr = SafeArrayGetElement( saAttributes, &idx, &SingleResult );
  81.         if( FAILED(hr) )
  82.         {
  83.             return hr;
  84.         }
  85.  
  86.         if ( V_VT(&SingleResult) != VT_BSTR )
  87.         {
  88.  
  89.             
  90.             if ( V_VT(&SingleResult) == VT_NULL )
  91.             {
  92.                 V_VT(&SingleResult ) = VT_BSTR;
  93.                 V_BSTR(&SingleResult ) = SysAllocString(L"0");
  94.             }
  95.             else
  96.             {
  97.                 hr = VariantChangeType( &SingleResult, &SingleResult,0, VT_BSTR );
  98.  
  99.                 if( FAILED(hr) )
  100.                 {
  101.                     return hr;
  102.                 }
  103.             }
  104.         }
  105.  
  106.  
  107.  
  108.          refstringlist.AddHead( OLE2T(V_BSTR(&SingleResult)) );
  109.         VariantClear( &SingleResult );
  110.     }
  111.  
  112.     return S_OK;
  113. } // VariantToStringList()
  114.  
  115.  
  116.  
  117. HRESULT OctetVariantToString(  VARIANT& refvar, CString &sResult)
  118. {
  119.     HRESULT hr = S_OK;
  120.     CString s;
  121.     long start, end;
  122.     USES_CONVERSION;
  123.  
  124.     if ( !(V_VT(&refvar) &  VT_ARRAY)  ) // Single Value
  125.     {
  126.         return E_UNEXPECTED;
  127.     }
  128.     
  129.  
  130.     SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  131.  
  132.     //
  133.     // Figure out the dimensions of the array.
  134.     //
  135.  
  136.     hr = SafeArrayGetLBound( saAttributes, 1, &start );
  137.     if( FAILED(hr) )
  138.            return hr;
  139.  
  140.     hr = SafeArrayGetUBound( saAttributes, 1, &end );
  141.     if( FAILED(hr) )
  142.             return hr;
  143.  
  144.     VARIANT SingleResult;
  145.     VariantInit( &SingleResult );
  146.  
  147.     //
  148.     // Process the array elements.
  149.     //
  150.     sResult.Empty();
  151.     for ( long idx = start; idx <= end; idx++   ) 
  152.     {
  153.  
  154.         hr = SafeArrayGetElement( saAttributes, &idx, &SingleResult );
  155.         if( FAILED(hr) )
  156.         {
  157.             return hr;
  158.         }
  159.  
  160.         if ( V_VT(&SingleResult) == VT_I1 )
  161.         {
  162.             s.Format("%02X", V_I1(&SingleResult));
  163.             sResult += s;
  164.             VariantClear( &SingleResult );
  165.         }
  166.     }
  167.  
  168.     return S_OK;
  169. } // VariantToStringList()
  170.  
  171.  
  172.  
  173.  
  174.  
  175. HRESULT StringListToVariant( VARIANT& refvar, const CStringList& refstringlist)
  176. {
  177.     HRESULT hr = S_OK;
  178.     int cCount = refstringlist.GetCount();
  179.  
  180.     SAFEARRAYBOUND rgsabound[1];
  181.     rgsabound[0].lLbound = 0;
  182.     rgsabound[0].cElements = cCount;
  183.  
  184.     SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  185.     if (NULL == psa)
  186.         return E_OUTOFMEMORY;
  187.  
  188.     VariantClear( &refvar );
  189.     V_VT(&refvar) = VT_VARIANT|VT_ARRAY;
  190.     V_ARRAY(&refvar) = psa;
  191.  
  192.     VARIANT SingleResult;
  193.     VariantInit( &SingleResult );
  194.     V_VT(&SingleResult) = VT_BSTR;
  195.     POSITION pos = refstringlist.GetHeadPosition();
  196.     long i;
  197.     for (i = 0; i < cCount, pos != NULL; i++)
  198.     {
  199.         V_BSTR(&SingleResult) = T2BSTR((LPCTSTR)refstringlist.GetNext(pos));
  200.         hr = SafeArrayPutElement(psa, &i, &SingleResult);
  201.         if( FAILED(hr) )
  202.             return hr;
  203.     }
  204.     if (i != cCount || pos != NULL)
  205.         return E_UNEXPECTED;
  206.  
  207.     return hr;
  208. } // StringListToVariant()
  209.  
  210.  
  211. void StringToStringList( CString s, CStringList &sList )
  212. {
  213.     int idx;
  214.     CString sAttr;
  215.  
  216.     //////////////////////////////////////////
  217.     // Parse and put them in the string list
  218.     //////////////////////////////////////////
  219.     idx = s.Find(_T(","));
  220.     while( idx != -1 )
  221.     {
  222.            sAttr = s.Mid(0, idx );
  223.            sAttr.TrimLeft(); sAttr.TrimRight();
  224.            if ( !sAttr.IsEmpty() )
  225.            {
  226.              sList.AddTail( sAttr );
  227.            }
  228.            s = s.Mid( idx + 1 );
  229.            idx = s.Find(_T(","));
  230.     }
  231.     s.TrimLeft(); s.TrimRight();
  232.     if ( !s.IsEmpty() )      
  233.     {
  234.         sList.AddTail( s );
  235.     }
  236.  
  237.  
  238. }
  239.  
  240.  
  241. void StringListToString( CStringList &sList, CString &s )
  242. {
  243.     POSITION pos;
  244.     int idx=0;
  245.     CString sTemp;
  246.  
  247.  
  248.     pos = sList.GetHeadPosition();
  249.     s.Empty();
  250.     while( pos != NULL )
  251.     {
  252.         if ( idx )
  253.         {
  254.             s += _T(" #");
  255.             s += sList.GetAt(pos);
  256.         }
  257.         else
  258.         {
  259.             s += sList.GetAt(pos);
  260.         }
  261.         
  262.         sList.GetNext(pos);
  263.         idx++;
  264.  
  265.     }
  266.  
  267. }
  268.  
  269.  
  270.  
  271. void ADsToStringList(ADSVALUE *pValues, DWORD dwNumber, CStringList &sList )
  272. {
  273.     CString sTemp;
  274.  
  275.     sList.RemoveAll();
  276.  
  277.  
  278.     USES_CONVERSION;
  279.  
  280.     for (DWORD x=0; x < dwNumber; x++) 
  281.     {
  282.             if ( pValues->dwType == ADSTYPE_INVALID )
  283.             {
  284.                 continue;
  285.             }
  286.  
  287.             
  288.             sTemp.Empty();
  289.  
  290.             switch( pValues->dwType ) 
  291.             {
  292.             case ADSTYPE_DN_STRING         :
  293.                 sTemp.Format(
  294.                 "%s",
  295.                 OLE2T(pValues->DNString)
  296.                 );
  297.                 break;
  298.  
  299.             case ADSTYPE_CASE_EXACT_STRING :
  300.                 sTemp.Format(
  301.                 "%s",
  302.                 OLE2T(pValues->CaseExactString)
  303.                 );
  304.                 break;
  305.  
  306.             case ADSTYPE_CASE_IGNORE_STRING:
  307.             
  308.                 sTemp.Format(
  309.                 "%s",
  310.                 OLE2T(pValues->CaseIgnoreString)
  311.                 );
  312.                 
  313.             break;
  314.  
  315.             case ADSTYPE_PRINTABLE_STRING  :
  316.                 sTemp.Format(
  317.                 "%s",
  318.                 pValues->PrintableString
  319.                 );
  320.                 break;
  321.  
  322.             case ADSTYPE_NUMERIC_STRING    :
  323.                 sTemp.Format(
  324.                 "%s",
  325.                 pValues->NumericString
  326.                 );
  327.                 break;
  328.     
  329.             case ADSTYPE_OBJECT_CLASS    :
  330.                 sTemp.Format(
  331.                 "%s",
  332.                 pValues->ClassName
  333.                 );
  334.                 break;
  335.     
  336.             case ADSTYPE_BOOLEAN           :
  337.                 sTemp.Format(
  338.                 "%s",
  339.                 (DWORD) pValues->Boolean ? 
  340.                 "TRUE" : "FALSE"
  341.                 );
  342.                 break;
  343.     
  344.             case ADSTYPE_INTEGER           :
  345.                 sTemp.Format(
  346.                 "%d",
  347.                 (DWORD) pValues->Integer 
  348.                 );
  349.                 break;
  350.     
  351.             case ADSTYPE_OCTET_STRING      :
  352.                 {
  353.                     CString sOctet;
  354.                     CString sPrint;
  355.                     CString sChar;
  356.  
  357.                     
  358.             
  359.                     BYTE  b;
  360.                     for ( DWORD idx=0; idx<pValues->OctetString.dwLength; idx++) 
  361.                     {
  362.                         b = ((BYTE *)pValues->OctetString.lpValue)[idx];
  363.                         sOctet.Format(
  364.                        "%02X ",
  365.                         b
  366.                         );
  367.                         if ( idx != 0 && ((idx % 16)  == 0) )
  368.                         {
  369.                             sTemp += "\t";
  370.                             sTemp += sPrint;
  371.                             sList.AddTail( sTemp );
  372.                             sTemp.Empty();
  373.                             sPrint.Empty();
  374.                         }
  375.  
  376.                         if ( !isprint(b) )
  377.                         {
  378.                             sPrint += _T(".");
  379.                         }
  380.                         else
  381.                         {
  382.                             sChar.Format("%c", b );
  383.                             sPrint += sChar;
  384.                             
  385.                         }
  386.  
  387.                     
  388.                         sTemp += sOctet;
  389.  
  390.                     }
  391.                     
  392.                     if ( !sPrint.IsEmpty() )
  393.                     {
  394.                         DWORD dwMod;
  395.                        // Figure out the remaining 16 bytes aligment
  396.                        // for display
  397.                        dwMod = 16 - (idx % 16);
  398.                        for( idx=0;idx < dwMod; idx++ )
  399.                        {
  400.                           sTemp += _T("Xx ");
  401.                        }
  402.                        sTemp += _T("\t");
  403.                        sTemp += sPrint;                       
  404.                     }
  405.                     
  406.                 }
  407.                 break;
  408.     
  409.             case ADSTYPE_LARGE_INTEGER     :
  410.                 if     ( pValues->LargeInteger.HighPart )
  411.                 {
  412.                     sTemp.Format("%ld%ld", pValues->LargeInteger.HighPart, pValues->LargeInteger.LowPart );
  413.                 }
  414.                 else
  415.                 {
  416.                     sTemp.Format("%ld", pValues->LargeInteger.LowPart );
  417.                 }
  418.                 
  419.                 break;
  420.     
  421.             case ADSTYPE_UTC_TIME          :
  422.                 sTemp.Format(
  423.                     "%02d/%02d/%04d %02d:%02d:%02d", pValues->UTCTime.wMonth, pValues->UTCTime.wDay, pValues->UTCTime.wYear,
  424.                      pValues->UTCTime.wHour, pValues->UTCTime.wMinute, pValues->UTCTime.wSecond 
  425.                     );
  426.                 break;
  427.  
  428.             case ADSTYPE_PROV_SPECIFIC     :
  429.                 sTemp.Format(
  430.                     "(provider specific value) "
  431.                     );
  432.                 break;
  433.  
  434.  
  435.             case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  436.                 {
  437.                     sTemp.Format(_T("%sIADsSecurityDescriptor"), ARROW_SYMBOL );
  438.                 }
  439.                 break;
  440.     
  441.             }
  442.             
  443.             pValues++;
  444.  
  445.             
  446.             sList.AddTail( sTemp );
  447.         
  448.     }
  449.  
  450.  
  451.  }
  452.  
  453.  
  454.  
  455. void PopulateListBoxFromStringList( CListBox &list, CStringList &sList )
  456. {
  457.     POSITION pos;
  458.  
  459.  
  460.  
  461.     pos = sList.GetHeadPosition();
  462.     while( pos != NULL )
  463.     {
  464.         list.AddString( sList.GetAt(pos));
  465.         sList.GetNext(pos);
  466.     }
  467.  
  468. }
  469.  
  470.  
  471. void PopulateComboBoxFromStringList( CComboBox &list, CStringList &sList )
  472. {
  473.     POSITION pos;
  474.  
  475.  
  476.  
  477.     pos = sList.GetHeadPosition();
  478.     while( pos != NULL )
  479.     {
  480.         list.AddString( sList.GetAt(pos));
  481.         sList.GetNext(pos);
  482.     }
  483.  
  484. }
  485.  
  486.  
  487. HRESULT ReportError( HRESULT hr )
  488. {
  489.     AfxMessageBox( GetErrorMessage(hr) );
  490.     return hr;
  491. }
  492.  
  493.  
  494.  
  495. HRESULT  VariantToPtrList(  VARIANT& refvar, CPtrList & refptrlist)
  496. {
  497.     HRESULT hr = S_OK;
  498.     long start, end;
  499.  
  500.     if ( !(V_VT(&refvar) &  VT_ARRAY)  )
  501.     {
  502.                 
  503.         if ( V_VT(&refvar) != VT_DISPATCH )
  504.         {
  505.             return E_FAIL;
  506.         }
  507.         else
  508.         {
  509.            refptrlist.AddHead( V_DISPATCH(&refvar) );
  510.  
  511.         }
  512.  
  513.     }
  514.  
  515.     SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  516.  
  517.     //
  518.     // Figure out the dimensions of the array.
  519.     //
  520.  
  521.     hr = SafeArrayGetLBound( saAttributes, 1, &start );
  522.         if( FAILED(hr) )
  523.                 return hr;
  524.  
  525.     hr = SafeArrayGetUBound( saAttributes, 1, &end );
  526.         if( FAILED(hr) )
  527.                 return hr;
  528.  
  529.     VARIANT SingleResult;
  530.     VariantInit( &SingleResult );
  531.  
  532.     //
  533.     // Process the array elements.
  534.     //
  535.  
  536.     for ( long idx = start; idx <= end; idx++   ) 
  537.     {
  538.  
  539.         hr = SafeArrayGetElement( saAttributes, &idx, &SingleResult );
  540.         if( FAILED(hr) )
  541.         {
  542.             return hr;
  543.         }
  544.  
  545.         if ( V_VT(&SingleResult) != VT_DISPATCH )
  546.         {
  547.             return E_UNEXPECTED;
  548.         }
  549.  
  550.  
  551.         refptrlist.AddHead( V_DISPATCH(&SingleResult) );
  552.     }
  553.  
  554.     return S_OK;
  555. } // VariantToStringList()
  556.  
  557.  
  558.  
  559. HRESULT PropertyValueToString( LONG lADsType, IADsPropertyValue *pValue, CString &sValue )
  560. {
  561.     BSTR bstr = NULL;
  562.     LONG l;
  563.     VARIANT var;
  564.     HRESULT hr = S_OK;
  565.     sValue.Empty();
  566.  
  567.     VariantInit(&var);
  568.     switch( lADsType )
  569.     {
  570.     case ADSTYPE_DN_STRING:
  571.          hr = pValue->get_DNString( &bstr );
  572.          sValue = bstr;
  573.         break;
  574.  
  575.     case ADSTYPE_CASE_EXACT_STRING:
  576.         hr = pValue->get_CaseExactString( &bstr );
  577.         sValue = bstr;
  578.         break;
  579.  
  580.     case ADSTYPE_CASE_IGNORE_STRING:
  581.          hr = pValue->get_CaseIgnoreString( &bstr );
  582.          sValue = bstr;
  583.         break;
  584.  
  585.     case ADSTYPE_PRINTABLE_STRING:
  586.          hr = pValue->get_PrintableString( &bstr );
  587.          sValue = bstr;
  588.         break;
  589.  
  590.     case ADSTYPE_NUMERIC_STRING:
  591.         hr = pValue->get_NumericString( &bstr );
  592.         sValue = bstr;
  593.         break;
  594.  
  595.     case ADSTYPE_BOOLEAN:
  596.          hr = pValue->get_Boolean( &l );
  597.          sValue = l ? _T("TRUE") : _T("FALSE");
  598.         break;
  599.  
  600.     case ADSTYPE_INTEGER:
  601.           hr = pValue->get_Integer( &l );
  602.          sValue.Format("%ld", l );
  603.         break;
  604.  
  605.  
  606.     case ADSTYPE_OCTET_STRING: 
  607.          hr = pValue->get_OctetString( &var );
  608.          if ( SUCCEEDED(hr) )
  609.          {
  610.             CString s;
  611.             hr =  OctetVariantToString( var, s);
  612.             if ( SUCCEEDED(hr) )
  613.             {
  614.                 sValue = s;
  615.             }
  616.          }
  617.  
  618.         break;
  619.  
  620.  
  621.     case ADSTYPE_UTC_TIME:
  622.         {
  623.             DATE date;
  624.             hr = pValue->get_UTCTime(&date);
  625.  
  626.  
  627.         }
  628.         break;
  629.  
  630.     case ADSTYPE_LARGE_INTEGER:
  631.         sValue.Format(_T("%sIADsLargeInteger"), ARROW_SYMBOL );
  632.         break;
  633.  
  634.     case ADSTYPE_PROV_SPECIFIC:
  635.         sValue = _T("Provider Specific");
  636.         break;
  637.  
  638.     case ADSTYPE_CASEIGNORE_LIST:
  639.         hr = pValue->get_CaseIgnoreString(&bstr);
  640.         sValue = bstr;
  641.         break;
  642.  
  643.     case ADSTYPE_OCTET_LIST:
  644.         sValue.Format(_T("%sIADsOctetString"), ARROW_SYMBOL );
  645.         break;
  646.  
  647.     case ADSTYPE_PATH:
  648.         sValue.Format(_T("%sIADsPath"), ARROW_SYMBOL );
  649.         break;
  650.  
  651.     case ADSTYPE_POSTALADDRESS:
  652.         sValue.Format(_T("%sIADsPostalAddress"), ARROW_SYMBOL );
  653.         break;
  654.  
  655.     case ADSTYPE_TIMESTAMP:
  656.         sValue.Format(_T("%sIADsTimestamp"), ARROW_SYMBOL );
  657.         break;
  658.  
  659.     case ADSTYPE_BACKLINK:
  660.         sValue.Format(_T("%sIADsBackLink"), ARROW_SYMBOL );
  661.         break;
  662.  
  663.     case ADSTYPE_TYPEDNAME:
  664.         sValue.Format(_T("%sIADsTypedName"), ARROW_SYMBOL );
  665.         break;
  666.  
  667.     case ADSTYPE_HOLD:
  668.         sValue.Format(_T("%sIADsHold"), ARROW_SYMBOL );
  669.         break;
  670.  
  671.     case ADSTYPE_NETADDRESS:
  672.         sValue.Format(_T("%sIADsNetAddress"), ARROW_SYMBOL );
  673.         break;
  674.  
  675.     case ADSTYPE_REPLICAPOINTER:
  676.         sValue.Format(_T("%sIADsReplicaPointer"), ARROW_SYMBOL );
  677.         break;
  678.  
  679.     case ADSTYPE_FAXNUMBER:
  680.         sValue.Format(_T("%sIADsFaxNumber"), ARROW_SYMBOL );
  681.         break;
  682.  
  683.     case ADSTYPE_EMAIL:
  684.         sValue.Format(_T("%sIADsEmail"), ARROW_SYMBOL );
  685.         break;
  686.  
  687.     case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  688.         sValue.Format(_T("%sIADsSecurityDescriptor"), ARROW_SYMBOL );
  689.         break;
  690.  
  691.     case ADSTYPE_UNKNOWN:
  692.          sValue = _T("Unknown");
  693.          break;
  694.  
  695.     }
  696.  
  697.     if ( bstr )
  698.     {
  699.         SysFreeString( bstr );
  700.     }
  701.  
  702.     VariantClear(&var);
  703.     pValue->Release();
  704.     return hr;
  705. }
  706.  
  707.  
  708.  
  709.  
  710.  
  711. CString GetErrorMessage( HRESULT hr )
  712. {
  713.     BOOL bRet;
  714.     CString s;
  715.     LPTSTR lpBuffer=NULL;
  716.  
  717.     if ( SUCCEEDED(hr) )
  718.     {
  719.         return _T("Success");
  720.     }
  721.  
  722.     
  723.     if ( hr & 0x00005000) // standard ADSI Errors 
  724.     {
  725.         s = GetADSIError(hr);
  726.     }
  727.     else if ( HRESULT_FACILITY(hr)==FACILITY_WIN32 )
  728.     {
  729.  
  730.  
  731.         /////////////////////////////////////////////
  732.         //
  733.         // Retrieve the Win32 Error message
  734.         //
  735.         /////////////////////////////////////////////////
  736.  
  737.         bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  738.                              NULL,  hr,
  739.                              MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  740.                              (LPTSTR) &lpBuffer, 0, NULL);
  741.  
  742.         if ( !bRet )
  743.         {
  744.             s.Format(_T("Error %X"), hr );
  745.         }
  746.  
  747.         if ( lpBuffer )
  748.         {
  749.             s = lpBuffer;
  750.             LocalFree( lpBuffer );
  751.         }
  752.     }
  753.     else // Non Win32 Error
  754.     {
  755.         s.Format("%X", hr );
  756.     }
  757.  
  758.     //////////////////////////////////////////////////////////////////
  759.     //
  760.     // Extended error message may be occured. 
  761.     //
  762.     // IADs, IADsContainer, IDirectoryObject or IDirectorySearch may return
  763.     // this extended error message
  764.     //
  765.     ////////////////////////////////////////////////////////////////////
  766.  
  767.     if ( (hr & 0x00005000) ||  //adsi
  768.          (hr & 0x00007000) )   // and win32
  769.     {
  770.         WCHAR szBuffer[MAX_PATH];
  771.         WCHAR szName[MAX_PATH];
  772.         DWORD dwError;
  773.     
  774.  
  775.         hr = ADsGetLastError( &dwError, szBuffer, (sizeof(szBuffer)/sizeof(WCHAR))-1,
  776.                               szName, (sizeof(szName)/sizeof(WCHAR))-1 );
  777.     
  778.     
  779.         if ( SUCCEEDED(hr) && dwError != ERROR_INVALID_DATA  && wcslen(szBuffer))
  780.         {
  781.             USES_CONVERSION;
  782.             s += _T("  -- Extended Error:");
  783.             s += OLE2T(szName);
  784.             s += _T(" : ");
  785.             s += OLE2T( szBuffer );
  786.         }
  787.     }
  788.  
  789.  
  790.     return s;
  791. }
  792.  
  793. ADSERRMSG adsErr[] = 
  794. {
  795.     ADDADSERROR(E_ADS_BAD_PATHNAME),
  796.     ADDADSERROR(E_ADS_INVALID_DOMAIN_OBJECT),
  797.     ADDADSERROR(E_ADS_INVALID_USER_OBJECT),
  798.     ADDADSERROR(E_ADS_INVALID_COMPUTER_OBJECT),
  799.     ADDADSERROR(E_ADS_UNKNOWN_OBJECT),
  800.     ADDADSERROR(E_ADS_PROPERTY_NOT_SET),
  801.     ADDADSERROR(E_ADS_PROPERTY_NOT_SUPPORTED),
  802.     ADDADSERROR(E_ADS_PROPERTY_INVALID),
  803.     ADDADSERROR(E_ADS_BAD_PARAMETER),
  804.     ADDADSERROR(E_ADS_OBJECT_UNBOUND),
  805.     ADDADSERROR(E_ADS_PROPERTY_NOT_MODIFIED),
  806.     ADDADSERROR(E_ADS_PROPERTY_MODIFIED),
  807.     ADDADSERROR(E_ADS_CANT_CONVERT_DATATYPE),
  808.     ADDADSERROR(E_ADS_PROPERTY_NOT_FOUND),
  809.     ADDADSERROR(E_ADS_OBJECT_EXISTS),
  810.     ADDADSERROR(E_ADS_SCHEMA_VIOLATION),
  811.     ADDADSERROR(E_ADS_COLUMN_NOT_SET),
  812.     ADDADSERROR(E_ADS_INVALID_FILTER),
  813.     ADDADSERROR(0),
  814. };
  815.  
  816.  
  817. /////////////////////////////////////////////
  818. //
  819. // Error message specific to ADSI 
  820. //
  821. ////////////////////////////////////////////
  822. CString GetADSIError( HRESULT hr )
  823. {
  824.     CString s;
  825.  
  826.  
  827.     if ( hr & 0x00005000 )
  828.     {
  829.         int idx=0;
  830.         while (adsErr[idx].hr != 0 )
  831.         {
  832.             if ( adsErr[idx].hr == hr )
  833.             {
  834.                 return adsErr[idx].pszError;
  835.             }
  836.             idx++;
  837.         }
  838.     }
  839.  
  840.     return _T("");
  841.   
  842.  
  843. }
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850. #if _ATL_VER <= 0x0200 
  851.  
  852. LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
  853. {
  854.     _ASSERTE(lpa != NULL);
  855.     _ASSERTE(lpw != NULL);
  856.     // verify that no illegal character present
  857.     // since lpw was allocated based on the size of lpa
  858.     // don't worry about the number of chars
  859.     lpw[0] = '\0';
  860.     MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);
  861.     return lpw;
  862. }
  863.  
  864. LPSTR WINAPI AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
  865. {
  866.     _ASSERTE(lpw != NULL);
  867.     _ASSERTE(lpa != NULL);
  868.     // verify that no illegal character present
  869.     // since lpa was allocated based on the size of lpw
  870.     // don't worry about the number of chars
  871.     lpa[0] = '\0';
  872.     WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL);
  873.     return lpa;
  874. }
  875.  
  876. #endif 
  877.