home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / ADSDK.ZIP / Samples / ActiveDir / AddGroup / vc / main.cpp < prev   
Encoding:
C/C++ Source or Header  |  1999-01-13  |  21.3 KB  |  713 lines

  1.  
  2. #define INC_OLE2
  3. #define UNICODE 1
  4. #define _WIN32_DCOM
  5.  
  6. #include <windows.h>
  7. #include <winuser.h>
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <malloc.h>
  13. #include <winldap.h>
  14.  
  15. #include <activeds.h>
  16. #include <assert.h>
  17.  
  18.  
  19. ////////////////////////////////////////////////////////////////////////////////////////////////////
  20. // String for usage information
  21. WCHAR * pwszUsage = L"Adds new group under the passed container.\n"
  22.                     L"Usage:\n"
  23.                     L"AddGroup <Path of container>\n" 
  24.                     L"              ADsPath of the container for placing the new group\n"
  25.                     L"         <NT 5 Group Name> \n"
  26.                     L"              This is the name for the new group\n"
  27.                     L"         <Downlevel NT 4 Sam Account name>\n"
  28.                     L"              Cannot exceed 20 characters and must be globally unique\n"
  29.                     L"         \nOptional:\n"
  30.                     L"         <Group Type>\n" 
  31.                     L"              Possible values: 'global' or 'local' or 'universal'\n"
  32.                     L"         <Security >\n"
  33.                     L"             Possible values: 'Security' or 'NoSecurity' \n"
  34.                     L"             If security is specified, new group will be created with \n"
  35.                     L"             ADS_GROUP_TYPE_SECURITY_ENABLED.If parameter is not supplied,\n"
  36.                     L"             new group will be created with ADS_GROUP_TYPE_SECURITY_ENABLED\n";
  37.  
  38.  
  39. ////////////////////////////////////////////////////////////////////////////////////////////////////
  40. // Module level global variables
  41. BSTR bsADsPathContainer;
  42. BSTR bsNT5GroupName;
  43. BSTR bsSamAcctName;
  44. int iGroupType;
  45.  
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////
  47. // Forward Declarations
  48. BOOL ParseCommandLine( int argc, wchar_t *argv[ ]);
  49. HRESULT CreateGroup(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,
  50.                     IDirectoryObject ** ppDirObjRet,int iGroupType);
  51. void PrintIADSObject(IADs * pIADs);
  52. void CheckADHRESULT(HRESULT passedhr,LPOLESTR pwReason);
  53. WCHAR * CrackADError(HRESULT hResult);
  54.  
  55.  
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////
  57. // main()
  58.  
  59. /* Note: Using the UNICODE version of main().
  60.    this removes the need for the sample to include
  61.    UNICODE-ANSI conversion routines
  62. */
  63. void wmain( int argc, wchar_t *argv[ ])
  64. {
  65.  
  66.     if (!ParseCommandLine(argc,argv))
  67.         return;
  68.  
  69.     // Initialize COM
  70.     CoInitialize(0);
  71.  
  72.     HRESULT hr;
  73.     IDirectoryObject * pDirObjectContainer = NULL;
  74.     IDirectoryObject * pDirObjRet = NULL;
  75.  
  76.     // Bind to the container passed 
  77.     hr = ADsGetObject(  bsADsPathContainer, IID_IDirectoryObject,(void **)&pDirObjectContainer);
  78.     
  79.     if (SUCCEEDED(hr))
  80.     {
  81.         // Call the helper funtion to create the group
  82.         hr = CreateGroup(pDirObjectContainer, bsNT5GroupName,bsSamAcctName,
  83.                          &pDirObjRet,iGroupType);
  84.         
  85.         if (SUCCEEDED(hr))
  86.         {
  87.             _putws(L"\n New Group created with the following properties:");
  88.             
  89.             IADs * pIADsNewGoup = NULL;
  90.             
  91.             // Group succeeded- now get an IADs interface to it 
  92.             // and print some properties
  93.             hr = pDirObjRet->QueryInterface(IID_IADs,(void**)&pIADsNewGoup);
  94.  
  95.             if (SUCCEEDED(hr))
  96.             {
  97.                 PrintIADSObject(pIADsNewGoup);
  98.                             
  99.                 pIADsNewGoup->Release();
  100.                 pIADsNewGoup = NULL;
  101.             }
  102.             else
  103.                 CheckADHRESULT(hr,L"QueryInterface() - New group for IADs");
  104.             pDirObjRet->Release();
  105.             pDirObjRet = NULL;    
  106.         }
  107.         else
  108.             CheckADHRESULT(hr,L"CreateGroup()");
  109.         
  110.         pDirObjectContainer->Release();
  111.         pDirObjectContainer = NULL;    
  112.     }
  113.     else
  114.         CheckADHRESULT(hr,L"ADsGetObject()");
  115.  
  116.     CoUninitialize();
  117.  }
  118.  
  119.  
  120. ////////////////////////////////////////////////////////////////////////////////////////////////////
  121. /*
  122.     ParseCommandLine()- Parses command line and sets module level globals
  123.     
  124.     Parameters:
  125.  
  126.         int argc            - Number of Arguments
  127.         wchar_t *argv[ ]    - Array of arguments
  128.  
  129.     Returns:
  130.         TRUE if Command line was successfully parsed
  131. */    
  132.  
  133. BOOL ParseCommandLine( int argc, wchar_t *argv[ ])
  134. {
  135.     if (argc < 4 || argc >6)
  136.     {
  137.         _putws(pwszUsage);
  138.         return FALSE;
  139.     }
  140.     // if we have at least 3 arguments (the first is the EXE name)
  141.     // Save them
  142.     if (argc >= 4)
  143.     {
  144.         bsADsPathContainer  = SysAllocString(argv[1]);
  145.         bsNT5GroupName      = SysAllocString(argv[2]);
  146.         bsSamAcctName       = SysAllocString(argv[3]);
  147.     }
  148.     
  149.     // was the group type passed in?
  150.     if (argc >=5)
  151.     {
  152.         if (_wcsicmp(L"global",argv[4])==0)
  153.             iGroupType = ADS_GROUP_TYPE_GLOBAL_GROUP;
  154.         
  155.         else if (_wcsicmp(L"local",argv[4])==0)
  156.             iGroupType = ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP;
  157.  
  158.         else if (_wcsicmp(L"universal",argv[4])==0)
  159.             iGroupType = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
  160.  
  161.         else
  162.         {
  163.             _putws(L"!! Incorrect Group Type Parameter !!");                
  164.             _putws(pwszUsage);
  165.             return FALSE;
  166.         }
  167.     }
  168.      else   // Default to Global 
  169.         iGroupType = ADS_GROUP_TYPE_GLOBAL_GROUP;
  170.  
  171.     // was security enabled passed in?
  172.     if (argc ==6)
  173.     {
  174.         if (_wcsicmp(L"security",argv[5])==0)
  175.             iGroupType |= ADS_GROUP_TYPE_SECURITY_ENABLED;
  176.         
  177.         // else if the parameter there is NOT nosecurity- error
  178.         else if (!(_wcsicmp(L"nosecurity",argv[4])==0))
  179.         {
  180.             _putws(L"!! Incorrect security Parameter !!");                
  181.             _putws(pwszUsage);
  182.             return FALSE;
  183.         }
  184.     
  185.     }
  186.     else    // Default to security 
  187.         iGroupType |= ADS_GROUP_TYPE_SECURITY_ENABLED;
  188.         
  189.     return TRUE;
  190. }
  191.  
  192. ////////////////////////////////////////////////////////////////////////////////////////////////////
  193. /*  CreateGroup()   - Function for creating a basic group
  194.     
  195.     Parameters
  196.  
  197.         IDirectoryObject *pDirObject    -   Parent Directory Object for the new group
  198.         LPWSTR pwCommonName             -   Common Name for the new group
  199.         IDirectoryObject ** ppDirObjRet -   Pointer to the Pointer which will receive the new Group
  200.         int iGroupType                  -   Bitflags for new group:
  201.                                                                     ADS_GROUP_TYPE_GLOBAL_GROUP, 
  202.                                                                     ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, 
  203.                                                                     ADS_GROUP_TYPE_UNIVERSAL_GROUP, 
  204.                                                                     ADS_GROUP_TYPE_SECURITY_ENABLED 
  205. */
  206. HRESULT CreateGroup(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IDirectoryObject ** ppDirObjRet,int iGroupType)
  207. {
  208.     assert(pDirObject);
  209.     if (wcslen(pwSamAcctName) >20)
  210.     {
  211.         MessageBox(NULL,L"SamAccountName CANNOT be bigger than 20 characters",L"Error: CreateSimpleGroup()",MB_ICONSTOP);
  212.         assert(0);
  213.         return E_FAIL;
  214.     }
  215.  
  216.     HRESULT    hr;
  217.     ADSVALUE   sAMValue;
  218.     ADSVALUE   classValue;
  219.     ADSVALUE   groupType;
  220.  
  221.     LPDISPATCH pDisp;
  222.     WCHAR       pwCommonNameFull[1024];
  223.     
  224.     ADS_ATTR_INFO  attrInfo[] = 
  225.     {  
  226.        { L"objectClass", ADS_ATTR_UPDATE, 
  227.                            ADSTYPE_CASE_IGNORE_STRING, &classValue, 1 },
  228.        {L"sAMAccountName", ADS_ATTR_UPDATE, 
  229.                            ADSTYPE_CASE_IGNORE_STRING, &sAMValue, 1},
  230.        {L"groupType", ADS_ATTR_UPDATE, 
  231.                            ADSTYPE_CASE_IGNORE_STRING, &groupType, 1}
  232.     };
  233.  
  234.     DWORD dwAttrs = sizeof(attrInfo)/sizeof(ADS_ATTR_INFO); 
  235.  
  236.     classValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
  237.     classValue.CaseIgnoreString = L"group";
  238.    
  239.     sAMValue.dwType=ADSTYPE_CASE_IGNORE_STRING;
  240.     sAMValue.CaseIgnoreString = pwSamAcctName;
  241.  
  242.     groupType.dwType=ADSTYPE_INTEGER;
  243.     groupType.Integer =  iGroupType;
  244.     
  245.     wsprintfW(pwCommonNameFull,L"CN=%s",pwCommonName);
  246.      
  247.     hr = pDirObject->CreateDSObject( pwCommonNameFull,  attrInfo, 
  248.                                 dwAttrs, &pDisp );
  249.     if (SUCCEEDED(hr))
  250.     {
  251.         hr = pDisp->QueryInterface(IID_IDirectoryObject,(void**) ppDirObjRet);
  252.  
  253.         pDisp->Release();
  254.         pDisp = NULL;
  255.     }
  256.     return hr;
  257. }
  258.  
  259.  
  260. ////////////////////////////////////////////////////////////////////////////////////////////////////
  261. /*  
  262.     PrintIADSObject()       -   Calls all the methods on a IADs object 
  263.                                 and prints them the console window
  264.     Parameters
  265.     
  266.         IADs * pIADs        - IADs Interface from which to retrieve attribute values
  267. */
  268. void PrintIADSObject(IADs * pIADs)
  269. {
  270.     assert(pIADs);
  271.  
  272.     BSTR bsResult;
  273.  
  274.     pIADs->get_Name(&bsResult); 
  275.     wprintf(L" NAME: %s\n",(LPOLESTR) bsResult);
  276.     SysFreeString(bsResult);
  277.     
  278.     pIADs->get_Class(&bsResult); 
  279.     wprintf(L" CLASS: %s\n",(LPOLESTR) bsResult);
  280.     SysFreeString(bsResult);
  281.     
  282.     pIADs->get_GUID(&bsResult); 
  283.     wprintf(L" GUID: %s\n",(LPOLESTR) bsResult);
  284.     SysFreeString(bsResult);
  285.     
  286.     pIADs->get_ADsPath(&bsResult); 
  287.     wprintf(L" ADSPATH: %s\n",(LPOLESTR) bsResult);
  288.     SysFreeString(bsResult);
  289.     
  290.     pIADs->get_Parent(&bsResult); 
  291.     wprintf(L" PARENT: %s\n",(LPOLESTR) bsResult);
  292.     SysFreeString(bsResult);
  293.     
  294.     pIADs->get_Schema(&bsResult); 
  295.     wprintf(L" SCHEMA: %s\n",(LPOLESTR) bsResult);
  296.     SysFreeString(bsResult);
  297.     
  298. }
  299.  
  300. ////////////////////////////////////////////////////////////////////////////////////////////////////
  301. ////////////////////////////////////////////////////////////////////////////////////////////////////
  302. ////////////////////////////////////////////////////////////////////////////////////////////////////
  303. ////////////////////////////////////////////////////////////////////////////////////////////////////
  304. ////////////////////////////////////////////////////////////////////////////////////////////////////
  305. // Error Handling routines
  306.  
  307. // Will display ADSI or COM error messages
  308. // when passed a BAD Hresult
  309. void CheckADHRESULT(HRESULT passedhr,LPOLESTR pwReason)
  310. {
  311.     if (SUCCEEDED(passedhr))
  312.         return;
  313.  
  314.     HRESULT hr;
  315.     DWORD lError;
  316.     WCHAR pwErrBuff[2048];
  317.     WCHAR pwADErrBuff[512];
  318.  
  319.     WCHAR * pADErrCodeStr;
  320.     
  321.     pwErrBuff[0] = NULL;
  322.     pADErrCodeStr = CrackADError( passedhr);
  323.  
  324.     // If an ADSI error code was returned, display it
  325.     if (pADErrCodeStr[0] != NULL)
  326.     {
  327.         wcscat(pwErrBuff,L"<*> ADSI Error HRESULT Returns: <*> \n");
  328.         wcscat(pwErrBuff,pADErrCodeStr);
  329.         wcscat(pwErrBuff,L"\n");
  330.     }           
  331.     
  332.     // Call ADsGetLastError() to retrieve the error text from ADSI
  333.     wcscat(pwErrBuff,L"<*> ADSI Error: <*>\n");
  334.     
  335.     hr = ADsGetLastError(
  336.         &lError,
  337.         pwADErrBuff,
  338.         2047,
  339.         L"",
  340.         0
  341.         );
  342.  
  343.  
  344.     if (FAILED(hr))
  345.         wcscat(pwErrBuff,L"<Unable to retrieve ADs Error>");
  346.     else
  347.         wcscat(pwErrBuff,pwADErrBuff);
  348.  
  349.     wcscat(pwErrBuff,L"\n");
  350.     
  351.     WCHAR sz[1024];
  352.     
  353.     wcscat(pwErrBuff,L"<*> System Error: <*> \n");
  354.  
  355.     // Check the standard system to crack the bad HRESULT into a string
  356.     if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, passedhr, 0, sz, 1024, 0))
  357.         wcscat(sz, L"Unknown HRESULT error");
  358.     else
  359.         wcscat(pwErrBuff, sz);
  360.         
  361.     // Display
  362.     OutputDebugStringW(pwErrBuff);
  363.     OutputDebugStringW(L"\r\n");
  364.     _putws(L"\n**********");
  365.     wprintf(L"\nERROR on %s\n\n",pwReason);
  366.     _putws(pwErrBuff);
  367.     _putws(L"\n**********");
  368.     
  369. }
  370.  
  371. WCHAR * CrackADError(HRESULT hResult)
  372. {
  373.    static WCHAR szwText[ 128 ];
  374.    szwText[0] = 0l;
  375.  
  376.    switch( hResult )
  377.    {
  378.       case  E_ADS_BAD_PATHNAME:
  379.          return L"E_ADS_BAD_PATHNAME";
  380.          break;
  381.  
  382.       case  E_ADS_INVALID_DOMAIN_OBJECT:
  383.          return L"E_ADS_INVALID_DOMAIN_OBJECT";
  384.          break;
  385.  
  386.       case  E_ADS_INVALID_USER_OBJECT:
  387.          return L"E_ADS_INVALID_USER_OBJECT";
  388.          break;
  389.  
  390.       case  E_ADS_INVALID_COMPUTER_OBJECT:
  391.          return L"E_ADS_INVALID_COMPUTER_OBJECT";
  392.          break;
  393.  
  394.       case  E_ADS_UNKNOWN_OBJECT:
  395.          return L"E_ADS_UNKNOWN_OBJECT";
  396.          break;
  397.  
  398.       case  E_ADS_PROPERTY_NOT_SET:
  399.          return L"E_ADS_PROPERTY_NOT_SET";
  400.          break;
  401.  
  402.       case  E_ADS_PROPERTY_NOT_SUPPORTED:
  403.          return L"E_ADS_PROPERTY_NOT_SUPPORTED";
  404.          break;
  405.  
  406.       case  E_ADS_PROPERTY_INVALID:
  407.          return L"E_ADS_PROPERTY_INVALID";
  408.          break;
  409.  
  410.       case  E_ADS_BAD_PARAMETER:
  411.          return L"E_ADS_BAD_PARAMETER";
  412.          break;
  413.  
  414.       case  E_ADS_OBJECT_UNBOUND:
  415.          return L"E_ADS_OBJECT_UNBOUND";
  416.          break;
  417.  
  418.       case  E_ADS_PROPERTY_NOT_MODIFIED:
  419.          return L"E_ADS_PROPERTY_NOT_MODIFIED";
  420.          break;
  421.  
  422.       case  E_ADS_PROPERTY_MODIFIED:
  423.          return L"E_ADS_PROPERTY_MODIFIED";
  424.          break;
  425.  
  426.       case  E_ADS_CANT_CONVERT_DATATYPE:
  427.          return L"E_ADS_CANT_CONVERT_DATATYPE";
  428.          break;
  429.  
  430.       case  E_ADS_PROPERTY_NOT_FOUND:
  431.          return L"E_ADS_PROPERTY_NOTFOUND";
  432.          break;
  433.  
  434.       case  E_ADS_OBJECT_EXISTS:
  435.          return L"E_ADS_OBJECT_EXISTS";
  436.          break;
  437.  
  438.       case  E_ADS_SCHEMA_VIOLATION:
  439.          return L"E_ADS_SCHEMA_VIOLATION";
  440.          break;
  441.  
  442.       case  E_ADS_COLUMN_NOT_SET:
  443.          return L"E_ADS_COLUMN_NOT_SET";
  444.          break;
  445.  
  446.       case  E_ADS_INVALID_FILTER:
  447.          return L"E_ADS_INVALID_FILTER";
  448.          break;
  449.  
  450.       case  HRESULT_FROM_WIN32(ERROR_DS_OPERATIONS_ERROR):
  451.          return L"ERROR_DS_OPERATIONS_ERROR";
  452.          break;
  453.  
  454.       case  HRESULT_FROM_WIN32(ERROR_DS_PROTOCOL_ERROR):
  455.          return L"ERROR_DS_PROTOCOL_ERROR";
  456.          break;
  457.  
  458.       case  HRESULT_FROM_WIN32(ERROR_DS_TIMELIMIT_EXCEEDED):
  459.          return L"ERROR_DS_TIMELIMIT_EXCEEDED";
  460.          break;
  461.  
  462.       case  HRESULT_FROM_WIN32(ERROR_DS_SIZELIMIT_EXCEEDED):
  463.          return L"ERROR_DS_SIZELIMIT_EXCEEDED";
  464.          break;
  465.  
  466.       case  HRESULT_FROM_WIN32(ERROR_DS_COMPARE_FALSE):
  467.          return L"ERROR_DS_COMPARE_FALSE";
  468.          break;
  469.  
  470.  
  471.       case  HRESULT_FROM_WIN32(ERROR_DS_COMPARE_TRUE):
  472.          return L"ERROR_DS_COMPARE_TRUE";
  473.          break;
  474.  
  475.  
  476.       case  HRESULT_FROM_WIN32(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED):
  477.          return L"ERROR_DS_AUTH_METHOD_NOT_SUPPORTED";
  478.          break;
  479.  
  480.  
  481.       case  HRESULT_FROM_WIN32(ERROR_DS_STRONG_AUTH_REQUIRED):
  482.          return L"ERROR_DS_STRONG_AUTH_REQUIRED";
  483.          break;
  484.  
  485.  
  486.       case  HRESULT_FROM_WIN32(ERROR_MORE_DATA):
  487.          return L"ERROR_MORE_DATA";
  488.          break;
  489.  
  490.       case  HRESULT_FROM_WIN32(ERROR_DS_REFERRAL):
  491.          return L"(ERROR_DS_REFERRAL";
  492.          break;
  493.  
  494.       case  HRESULT_FROM_WIN32(ERROR_DS_ADMIN_LIMIT_EXCEEDED):
  495.          return L"ERROR_DS_ADMIN_LIMIT_EXCEEDED";
  496.          break;
  497.  
  498.  
  499.       case  HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION):
  500.          return L"(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION";
  501.          break;
  502.  
  503.       case  HRESULT_FROM_WIN32(ERROR_DS_CONFIDENTIALITY_REQUIRED):
  504.          return L"HRESULT_FROM_WIN32(ERROR_DS_CONFIDENTIALITY_REQUIRED";
  505.          break;
  506.  
  507.       case  HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE):
  508.          return L"ERROR_DS_NO_ATTRIBUTE_OR_VALUE";
  509.          break;
  510.  
  511.       case  HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED):
  512.          return L"(ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED";
  513.          break;
  514.  
  515.       case  HRESULT_FROM_WIN32(ERROR_DS_INAPPROPRIATE_MATCHING):
  516.          return L"(ERROR_DS_INAPPROPRIATE_MATCHING";
  517.          break;
  518.  
  519.       case  HRESULT_FROM_WIN32(ERROR_DS_CONSTRAINT_VIOLATION):
  520.          return L"ERROR_DS_CONSTRAINT_VIOLATION";
  521.          break;
  522.  
  523.       case  HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS):
  524.          return L"ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS";
  525.          break;
  526.  
  527.       case  HRESULT_FROM_WIN32(ERROR_DS_INVALID_ATTRIBUTE_SYNTAX):
  528.          return L"ERROR_DS_INVALID_ATTRIBUTE_SYNTAX";
  529.          break;
  530.  
  531.       case  HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT):
  532.          return L"ERROR_DS_NO_SUCH_OBJECT";
  533.          break;
  534.  
  535.  
  536.       case  HRESULT_FROM_WIN32(ERROR_DS_INVALID_DN_SYNTAX):
  537.          return L"ERROR_DS_INVALID_DN_SYNTAX";
  538.          break;
  539.  
  540.       case  HRESULT_FROM_WIN32(ERROR_DS_IS_LEAF):
  541.          return L"ERROR_DS_IS_LEAF";
  542.          break;
  543.  
  544.       case  HRESULT_FROM_WIN32(ERROR_DS_ALIAS_DEREF_PROBLEM):
  545.          return L"ERROR_DS_ALIAS_DEREF_PROBLEM";
  546.          break;
  547.  
  548.       case  HRESULT_FROM_WIN32(ERROR_DS_INAPPROPRIATE_AUTH):
  549.          return L"ERROR_DS_INAPPROPRIATE_AUTH";
  550.          break;
  551.  
  552.       case  HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD):
  553.          return L"ERROR_INVALID_PASSWORD";
  554.          break;
  555.  
  556.       case  HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
  557.          return L"ERROR_ACCESS_DENIED";
  558.          break;
  559.  
  560.       case  HRESULT_FROM_WIN32(ERROR_DS_BUSY):
  561.          return L"ERROR_DS_BUSY";
  562.          break;
  563.  
  564.       case  HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE):
  565.          return L"ERROR_DS_UNAVAILABLE";
  566.          break;
  567.  
  568.       case  HRESULT_FROM_WIN32(ERROR_DS_UNWILLING_TO_PERFORM):
  569.          return L"ERROR_DS_UNWILLING_TO_PERFORM";
  570.          break;
  571.  
  572.       case  HRESULT_FROM_WIN32(ERROR_DS_LOOP_DETECT):
  573.          return L"ERROR_DS_LOOP_DETECT";
  574.          break;
  575.  
  576.       case  HRESULT_FROM_WIN32(ERROR_DS_NAMING_VIOLATION):
  577.          return L"ERROR_DS_NAMING_VIOLATION";
  578.          break;
  579.  
  580.       case  HRESULT_FROM_WIN32(ERROR_DS_OBJ_CLASS_VIOLATION):
  581.          return L"ERROR_DS_OBJ_CLASS_VIOLATION";
  582.          break;
  583.  
  584.       case  HRESULT_FROM_WIN32(ERROR_DS_CANT_ON_NON_LEAF):
  585.          return L"ERROR_DS_CANT_ON_NONLEAF";
  586.          break;
  587.  
  588.       case  HRESULT_FROM_WIN32(ERROR_DS_CANT_ON_RDN):
  589.          return L"ERROR_DS_CANT_ON_RDN";
  590.          break;
  591.  
  592.       case  HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
  593.          return L"ERROR_ALREADY_EXISTS";
  594.          break;
  595.  
  596.       case  HRESULT_FROM_WIN32(ERROR_DS_CANT_MOD_OBJ_CLASS):
  597.          return L"ERROR_DS_CANT_MOD_OBJ_CLASS";
  598.          break;
  599.  
  600.       case  HRESULT_FROM_WIN32(ERROR_DS_OBJECT_RESULTS_TOO_LARGE):
  601.          return L"ERROR_DS_OBJECT_RESULTS_TOO_LARGE";
  602.          break;
  603.  
  604.       case  HRESULT_FROM_WIN32(ERROR_DS_AFFECTS_MULTIPLE_DSAS):
  605.          return L"ERROR_DS_AFFECTS_MULTIPLE_DSAS";
  606.          break;
  607.  
  608.       case  HRESULT_FROM_WIN32(ERROR_GEN_FAILURE):
  609.          return L"(ERROR_GEN_FAILURE";
  610.          break;
  611.  
  612.       case  HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN):
  613.          return L"ERROR_DS_SERVER_DOWN";
  614.          break;
  615.  
  616.       case  HRESULT_FROM_WIN32(ERROR_DS_LOCAL_ERROR):
  617.          return L"ERROR_DS_LOCAL_ERROR";
  618.          break;
  619.  
  620.       case  HRESULT_FROM_WIN32(ERROR_DS_ENCODING_ERROR):
  621.          return L"ERROR_DS_ENCODING_ERROR";
  622.          break;
  623.  
  624.       case  HRESULT_FROM_WIN32(ERROR_DS_DECODING_ERROR):
  625.          return L"(ERROR_DS_DECODING_ERROR";
  626.          break;
  627.  
  628.       case  HRESULT_FROM_WIN32(ERROR_TIMEOUT):
  629.          return L"(ERROR_TIMEOUT";
  630.          break;
  631.  
  632.       case  HRESULT_FROM_WIN32(ERROR_DS_AUTH_UNKNOWN):
  633.          return L"ERROR_DS_AUTH_UNKNOWN";
  634.          break;
  635.  
  636.       case  HRESULT_FROM_WIN32(ERROR_DS_FILTER_UNKNOWN):
  637.          return L"(ERROR_DS_FILTER_UNKNOWN";
  638.          break;
  639.  
  640.       case  HRESULT_FROM_WIN32(ERROR_CANCELLED):
  641.          return L"(ERROR_CANCELLED";
  642.          break;
  643.  
  644.       case  HRESULT_FROM_WIN32(ERROR_DS_PARAM_ERROR):
  645.          return L"ERROR_DS_PARAM_ERROR";
  646.          break;
  647.  
  648.       case  HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
  649.          return L"ERROR_NOT_ENOUGH_MEMORY";
  650.          break;
  651.  
  652.       case  HRESULT_FROM_WIN32(ERROR_CONNECTION_REFUSED):
  653.          return L"ERROR_CONNECTION_REFUSED";
  654.          break;
  655.  
  656.       case  HRESULT_FROM_WIN32(ERROR_DS_NOT_SUPPORTED):
  657.          return L"ERROR_DS_NOT_SUPPORTED";
  658.          break;
  659.  
  660.       case  HRESULT_FROM_WIN32(ERROR_DS_NO_RESULTS_RETURNED):
  661.          return L"ERROR_DS_NO_RESULTS_RETURNED";
  662.          break;
  663.  
  664.       case  HRESULT_FROM_WIN32(ERROR_DS_CONTROL_NOT_FOUND):
  665.          return L"ERROR_DS_CONTROL_NOT_FOUND";
  666.          break;
  667.  
  668.       case  HRESULT_FROM_WIN32(ERROR_DS_CLIENT_LOOP):
  669.          return L"(ERROR_DS_CLIENT_LOOP";
  670.          break;
  671.  
  672.       case  HRESULT_FROM_WIN32(ERROR_DS_REFERRAL_LIMIT_EXCEEDED):
  673.          return L"ERROR_DS_REFERRAL_LIMIT_EXCEEDED";
  674.          break;
  675.  
  676.       case  E_FAIL:
  677.          return L"E_FAIL";
  678.          break;
  679.  
  680.       case  E_NOTIMPL:
  681.          return L"E_NOIMPL";
  682.          break;
  683.  
  684.       case  S_OK:
  685.          return L"OK";
  686.          break;
  687.  
  688.       case  0x800704b8:
  689.       // we have an extended error
  690.       {
  691.          WCHAR szErrorBuff[ 1024 ];
  692.          WCHAR szNameBuff[ 1024 ];
  693.          DWORD dwError;
  694.  
  695.          ADsGetLastError( &dwError,
  696.                           szErrorBuff,
  697.                           1023,
  698.                           szNameBuff,
  699.                           1023 );
  700.          wcscat( szNameBuff, L" : " );
  701.          wcscat( szNameBuff, szErrorBuff );
  702.          wcscpy( szwText,szNameBuff);
  703.  
  704.          return szwText;
  705.       }
  706.  
  707.    }
  708.  
  709.     return szwText; 
  710. }
  711.  
  712.  
  713.