home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / ADSDK.ZIP / Samples / ActiveDir / GetSchemaInfo / vc / getschemainfo.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-05  |  15.5 KB  |  499 lines

  1. // attributes.cpp : Defines the entry point for the console application.
  2. //
  3. #include <objbase.h>
  4. #include <wchar.h>
  5. #include <activeds.h>
  6. //Make sure you define UNICODE
  7. //Need to define version 5 for Windows 2000
  8. #define _WIN32_WINNT 0x0500
  9.  
  10.  
  11. ///////////////////////////////////////////////////////////
  12. // PLEASE READ: You must run on Windows 2000 machine to run this sample
  13. ////////////////////////////////////////////////////////////
  14. #include <sddl.h>
  15.  
  16. HRESULT FindAttributesOrClasses(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context.
  17.          LPOLESTR szFilter, //Filter for finding specific attributes.
  18.                             //NULL returns all attributeSchema objects.
  19.          LPOLESTR *pszPropertiesToReturn, //Properties to return for attributeSchema objects found
  20.                                         //NULL returns all set properties.
  21.          BOOL bIsAttributeQuery, //TRUE queries for attributes;FALSE for classes
  22.          BOOL bIsVerbose //TRUE means all properties for the found objects are displayed.
  23.                          //FALSE means only the ldapDisplayName with cn in parentheses:
  24.                          //example: l (Locality-Name)
  25.                             );
  26.  
  27.  
  28.  
  29.  
  30. void wmain( int argc, wchar_t *argv[ ])
  31. {
  32.  
  33. //Handle the command line arguments.
  34. LPOLESTR pszBuffer = new OLECHAR[MAX_PATH*2];
  35. wcscpy(pszBuffer, L"");
  36.  
  37. BOOL bIsAttributeQuery = TRUE;
  38. BOOL bReturnVerbose = FALSE;
  39. LPOLESTR szType = L"attribute";
  40. if (1==argc||(_wcsicmp(argv[1],L"/?") == 0))
  41. {
  42.     wprintf(L"This program queries the schema for the specified classes or attributes.\n");
  43.     wprintf(L"Syntax: getschemainfo [/C|/A][/V][querystring]\n");
  44.     wprintf(L"where /C specifies to query for classes.\n");
  45.     wprintf(L"      /A specifies to query for attributes.\n");
  46.     wprintf(L"      /V specifies that all properties for the found classes or attributes should be returned.\n");
  47.     wprintf(L"      querystring is the query criteria in ldap query format.\n");
  48.     wprintf(L"Defaults: If neither /A or /C is specified, the query is against both.\n");
  49.     wprintf(L"          If no /V is specified, the query returns only the ldapDisplayName and cn of the items found.\n");
  50.     wprintf(L"          If no querystring is specified, the query returns all classes and/or attributes.\n");
  51.     wprintf(L"Example: getschemainfo /A (IsSingleValued=TRUE)\n");
  52.     wprintf(L"Returns all single-valued attributes in the schema.\n");
  53.     wprintf(L"Common querystrings:\n");
  54.     wprintf(L"For attributes:\n");
  55.     wprintf(L"(cn=Street-Address) to find the attribute with CN of Street-Address.\n");
  56.     wprintf(L"(ldapdisplayname=street) to find the attribute with ldapdisplayname of street.\n");
  57.     wprintf(L"(IsSingleValued=TRUE) for single-valued attributes.\n");
  58.     wprintf(L"(IsSingleValued=FALSE) for mulit-valued attributes.\n");
  59.     wprintf(L"(systemFlags:1.2.840.113556.1.4.804:=00000001) for non-replicated attributes\n");
  60.     wprintf(L"(systemFlags:1.2.840.113556.1.4.804:=00000004) for constructed attributes\n");
  61.     wprintf(L"(searchFlags=1) for indexed attributes.\n");
  62.     wprintf(L"(isMemberOfPartialAttributeSet=TRUE) for attributes included in the global catalog\n");
  63.     return;
  64. }
  65. for (int i = 1;i<argc;i++)
  66. {
  67.     if (_wcsicmp(argv[i],L"/C") == 0)
  68.     {
  69.         bIsAttributeQuery = FALSE;
  70.         szType = L"class";
  71.     }
  72.     else if (_wcsicmp(argv[i],L"/A") == 0)
  73.     {
  74.         bIsAttributeQuery = TRUE;
  75.         szType = L"attribute";
  76.     }
  77.     else if (_wcsicmp(argv[i],L"/V") == 0)
  78.     {
  79.         bReturnVerbose = TRUE;
  80.     }
  81.     else
  82.     {
  83.         wcscpy(pszBuffer,argv[i]);
  84.     }
  85. }
  86. if (_wcsicmp(pszBuffer,L"") == 0)
  87.   wprintf(L"\nFinding all %sSchema objects in the schema...\n\n",szType);
  88. else
  89.   wprintf(L"\nFinding %sSchema objects based on query: %s...\n\n",szType, pszBuffer);
  90.     
  91. //Intialize COM
  92. CoInitialize(NULL);
  93. HRESULT hr = S_OK;
  94. //Get rootDSE and the domain container's DN.
  95. IADs *pObject = NULL;
  96. IDirectorySearch *pSchemaNC = NULL;
  97. LPOLESTR szPath = new OLECHAR[MAX_PATH];
  98. VARIANT var;
  99. hr = ADsOpenObject(L"LDAP://rootDSE",
  100.                  NULL,
  101.                  NULL,
  102.                  ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
  103.                  IID_IADs,
  104.                  (void**)&pObject);
  105. if (FAILED(hr))
  106. {
  107.    wprintf(L"Could not execute query. Could not bind to LDAP://rootDSE.\n");
  108.    if (pObject)
  109.      pObject->Release();
  110.    return;
  111. }
  112. if (SUCCEEDED(hr))
  113. {
  114.     hr = pObject->Get(L"schemaNamingContext",&var);
  115.     if (SUCCEEDED(hr))
  116.     {
  117.         wcscpy(szPath,L"LDAP://");
  118.         wcscat(szPath,var.bstrVal);
  119.         hr = ADsOpenObject(szPath,
  120.                          NULL,
  121.                          NULL,
  122.                          ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
  123.                          IID_IDirectorySearch,
  124.                          (void**)&pSchemaNC);
  125.  
  126.         if (SUCCEEDED(hr))
  127.         {
  128.             hr = FindAttributesOrClasses(pSchemaNC, //IDirectorySearch pointer to schema naming context.
  129.                      pszBuffer, 
  130.                      NULL,
  131.                      bIsAttributeQuery,
  132.                      bReturnVerbose
  133.                  );
  134.             if (SUCCEEDED(hr))
  135.             {
  136.                 if (S_FALSE==hr)
  137.                    wprintf(L"No %sSchema object could be found based on the query: %s\n",szType,pszBuffer);
  138.             }
  139.             else if (0x8007203e==hr)
  140.                 wprintf(L"Could not execute query. An invalid filter was specified.\n");
  141.             else
  142.                 wprintf(L"Query failed to run. HRESULT: %x\n",hr);
  143.         }
  144.         else
  145.         {
  146.            wprintf(L"Could not execute query. Could not bind to the schema container.\n");
  147.         }
  148.         if (pSchemaNC)
  149.            pSchemaNC->Release();
  150.     }
  151.     VariantClear(&var);
  152. }
  153. if (pObject)
  154.     pObject->Release();
  155.  
  156.  
  157.  
  158.  
  159.  
  160. // Uninitialize COM
  161. CoUninitialize();
  162. return;
  163. }
  164.  
  165.  
  166.  
  167.  
  168.  
  169. HRESULT FindAttributesOrClasses(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context.
  170.          LPOLESTR szFilter, //Filter for finding specific attributes.
  171.                             //NULL returns all attributeSchema objects.
  172.          LPOLESTR *pszPropertiesToReturn, //Properties to return for attributeSchema objects found
  173.                                         //NULL returns all set properties unless bIsVerbose is FALSE.
  174.          BOOL bIsAttributeQuery, //TRUE queries for attributes;FALSE for classes
  175.          BOOL bIsVerbose //TRUE means all properties for the found objects are displayed.
  176.                          //FALSE means only the ldapDisplayName with cn in parentheses:
  177.                          //example: l (Locality-Name)
  178.                             )
  179. {
  180.     if (!pSchemaNC)
  181.         return E_POINTER;
  182.     //Create search filter
  183.     LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2];
  184.     LPOLESTR szCategory = NULL;
  185.     if (bIsAttributeQuery)
  186.         szCategory = L"attributeSchema";
  187.     else
  188.         szCategory = L"classSchema";
  189.  
  190.  
  191.     if (szFilter)
  192.        wsprintf(pszSearchFilter, L"(&(objectCategory=%s)%s)",szCategory,szFilter);
  193.     else
  194.         wsprintf(pszSearchFilter, L"(objectCategory=%s)",szCategory);
  195.  
  196.     //Attributes are one-level deep in the Schema container so only need to search one level.
  197.     ADS_SEARCHPREF_INFO SearchPrefs;
  198.     SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  199.     SearchPrefs.vValue.dwType = ADSTYPE_INTEGER;
  200.     SearchPrefs.vValue.Integer = ADS_SCOPE_ONELEVEL;
  201.     DWORD dwNumPrefs = 1;
  202.  
  203.     // COL for iterations
  204.     LPOLESTR pszColumn = NULL;    
  205.     ADS_SEARCH_COLUMN col;
  206.     HRESULT hr;
  207.     
  208.     // Interface Pointers
  209.     IADs    *pObj = NULL;
  210.     IADs    * pIADs = NULL;
  211.  
  212.     // Handle used for searching
  213.     ADS_SEARCH_HANDLE hSearch = NULL;
  214.     
  215.     // Set the search preference
  216.     hr = pSchemaNC->SetSearchPreference( &SearchPrefs, dwNumPrefs);
  217.     if (FAILED(hr))
  218.         return hr;
  219.  
  220.     LPOLESTR pszBool = NULL;
  221.     DWORD dwBool;
  222.     PSID pObjectSID = NULL;
  223.     LPOLESTR szSID = NULL;
  224.     LPOLESTR szDSGUID = new WCHAR [39];
  225.     LPGUID pObjectGUID = NULL;
  226.     FILETIME filetime;
  227.     SYSTEMTIME systemtime;
  228.     DATE date;
  229.     VARIANT varDate;
  230.     LARGE_INTEGER liValue;
  231.     LPOLESTR *pszPropertyList = NULL;
  232.     LPOLESTR pszNonVerboseList[] = {L"lDAPDisplayName",L"cn"};
  233.  
  234.     LPOLESTR szCNValue = new OLECHAR[MAX_PATH];
  235.     LPOLESTR szLDAPDispleyNameValue = new OLECHAR[MAX_PATH];
  236.  
  237.     int iCount = 0;
  238.     DWORD x = 0L;
  239.  
  240.  
  241.  
  242.     if (!bIsVerbose)
  243.     {
  244.          //Return non-verbose list properties only
  245.          hr = pSchemaNC->ExecuteSearch(pszSearchFilter,
  246.                                   pszNonVerboseList,
  247.                                   sizeof(pszNonVerboseList)/sizeof(LPOLESTR),
  248.                                   &hSearch
  249.                                   );
  250.     }
  251.     else
  252.     {
  253.         if (!pszPropertiesToReturn)
  254.         {
  255.             //Return all properties.
  256.             hr = pSchemaNC->ExecuteSearch(pszSearchFilter,
  257.                                   NULL,
  258.                                   0L,
  259.                                   &hSearch
  260.                                   );
  261.         }
  262.         else
  263.         {
  264.             //specified subset.
  265.             pszPropertyList = pszPropertiesToReturn;
  266.            //Return specified properties
  267.            hr = pSchemaNC->ExecuteSearch(pszSearchFilter,
  268.                                   pszPropertyList,
  269.                                   sizeof(pszPropertyList)/sizeof(LPOLESTR),
  270.                                   &hSearch
  271.                                   );
  272.         }
  273.     }
  274.      if ( SUCCEEDED(hr) )
  275.     {    
  276.     // Call IDirectorySearch::GetNextRow() to retrieve the next row 
  277.     //of data
  278.       hr = pSchemaNC->GetFirstRow( hSearch);
  279.       if (SUCCEEDED(hr))
  280.       {
  281.         while( hr != S_ADS_NOMORE_ROWS )
  282.         {
  283.             //Keep track of count.
  284.             iCount++;
  285.             if (bIsVerbose)
  286.               wprintf(L"----------------------------------\n");
  287.             // loop through the array of passed column names,
  288.             // print the data for each column
  289.  
  290.             while( pSchemaNC->GetNextColumnName( hSearch, &pszColumn ) != S_ADS_NOMORE_COLUMNS )
  291.             {
  292.                 hr = pSchemaNC->GetColumn( hSearch, pszColumn, &col );
  293.                 if ( SUCCEEDED(hr) )
  294.                 {
  295.                     // Print the data for the column and free the column
  296.                   if(bIsVerbose)
  297.                   {
  298.                     // Get the data for this column
  299.                     wprintf(L"%s\n",col.pszAttrName);
  300.                     switch (col.dwADsType)
  301.                     {
  302.                         case ADSTYPE_DN_STRING:
  303.                           for (x = 0; x< col.dwNumValues; x++)
  304.                           {
  305.                               wprintf(L"  %s\r\n",col.pADsValues[x].DNString);
  306.                           }
  307.                           break;
  308.                         case ADSTYPE_CASE_EXACT_STRING:        
  309.                         case ADSTYPE_CASE_IGNORE_STRING:        
  310.                         case ADSTYPE_PRINTABLE_STRING:        
  311.                         case ADSTYPE_NUMERIC_STRING:            
  312.                         case ADSTYPE_TYPEDNAME:                
  313.                         case ADSTYPE_FAXNUMBER:                
  314.                         case ADSTYPE_PATH:                    
  315.                         case ADSTYPE_OBJECT_CLASS:
  316.                           for (x = 0; x< col.dwNumValues; x++)
  317.                           {
  318.                               wprintf(L"  %s\r\n",col.pADsValues[x].CaseIgnoreString);
  319.                           }
  320.                           break;
  321.                         case ADSTYPE_BOOLEAN:
  322.                           for (x = 0; x< col.dwNumValues; x++)
  323.                           {
  324.                               dwBool = col.pADsValues[x].Boolean;
  325.                               pszBool = dwBool ? L"TRUE" : L"FALSE";
  326.                               wprintf(L"  %s\r\n",pszBool);
  327.                           }
  328.                           break;
  329.                         case ADSTYPE_INTEGER:
  330.                           for (x = 0; x< col.dwNumValues; x++)
  331.                           {
  332.                               wprintf(L"  %d\r\n",col.pADsValues[x].Integer);
  333.                           }
  334.                           break;
  335.                         case ADSTYPE_OCTET_STRING:
  336.                             if ( _wcsicmp(col.pszAttrName,L"objectSID") == 0 )
  337.                             {
  338.                               for (x = 0; x< col.dwNumValues; x++)
  339.                               {
  340.                                   pObjectSID = (PSID)(col.pADsValues[x].OctetString.lpValue);
  341.                                   //Convert SID to string.
  342.                                   ConvertSidToStringSid(pObjectSID, &szSID);
  343.                                   wprintf(L"  %s\r\n",szSID);
  344.                                   LocalFree(szSID);
  345.                               }
  346.                             }
  347.                             else if ( (_wcsicmp(col.pszAttrName,L"objectGUID") == 0)
  348.                                 || (_wcsicmp(col.pszAttrName,L"schemaIDGUID") == 0) 
  349.                                 || (_wcsicmp(col.pszAttrName,L"attributeSecurityGUID") == 0) )
  350.                             {
  351.                               for (x = 0; x< col.dwNumValues; x++)
  352.                               {
  353.                                 //Cast to LPGUID
  354.                                 pObjectGUID = (LPGUID)(col.pADsValues[x].OctetString.lpValue);
  355.                                 //Convert GUID to string.
  356.                                 ::StringFromGUID2(*pObjectGUID, szDSGUID, 39); 
  357.                                 //Print the GUID
  358.                                 wprintf(L"  %s\r\n",szDSGUID);
  359.                               }
  360.                             }
  361.                             else if ( _wcsicmp(col.pszAttrName,L"oMObjectClass") == 0 )
  362.                             {
  363.                               //TODO: 
  364.                               wprintf(L"  TODO:No conversion for this.");
  365.                             }
  366.                             else
  367.                               wprintf(L"  Value of type Octet String. No Conversion.");
  368.                             break;
  369.                         case ADSTYPE_UTC_TIME:
  370.                           for (x = 0; x< col.dwNumValues; x++)
  371.                           {
  372.                             systemtime = col.pADsValues[x].UTCTime;
  373.                             if (SystemTimeToVariantTime(&systemtime,
  374.                                                         &date) != 0) 
  375.                             {
  376.                                 //Pack in variant.vt
  377.                                 varDate.vt = VT_DATE;
  378.                                 varDate.date = date;
  379.                                 VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR);
  380.                                 wprintf(L"  %s\r\n",varDate.bstrVal);
  381.                                 VariantClear(&varDate);
  382.                             }
  383.                             else
  384.                                 wprintf(L"  Could not convert UTC-Time.\n",pszColumn);
  385.                           }
  386.                           break;
  387.                         case ADSTYPE_LARGE_INTEGER:
  388.                           for (x = 0; x< col.dwNumValues; x++)
  389.                           {
  390.                             liValue = col.pADsValues[x].LargeInteger;
  391.                             filetime.dwLowDateTime = liValue.LowPart;
  392.                             filetime.dwHighDateTime = liValue.HighPart;
  393.                             if((filetime.dwHighDateTime==0) && (filetime.dwLowDateTime==0))
  394.                             {
  395.                                 wprintf(L"  No value set.\n");
  396.                             }
  397.                             else
  398.                             {
  399.                                 //Check for properties of type LargeInteger that represent time
  400.                                 //if TRUE, then convert to variant time.
  401.                                 if ((0==wcscmp(L"accountExpires", col.pszAttrName))|
  402.                                     (0==wcscmp(L"badPasswordTime", col.pszAttrName))||
  403.                                     (0==wcscmp(L"lastLogon", col.pszAttrName))||
  404.                                     (0==wcscmp(L"lastLogoff", col.pszAttrName))||
  405.                                     (0==wcscmp(L"lockoutTime", col.pszAttrName))||
  406.                                     (0==wcscmp(L"pwdLastSet", col.pszAttrName))
  407.                                    )
  408.                                 {
  409.                                     //Handle special case for Never Expires where low part is -1
  410.                                     if (filetime.dwLowDateTime==-1)
  411.                                     {
  412.                                         wprintf(L"  Never Expires.\n");
  413.                                     }
  414.                                     else
  415.                                     {
  416.                                         if (FileTimeToLocalFileTime(&filetime, &filetime) != 0) 
  417.                                         {
  418.                                             if (FileTimeToSystemTime(&filetime,
  419.                                                                  &systemtime) != 0)
  420.                                             {
  421.                                                 if (SystemTimeToVariantTime(&systemtime,
  422.                                                                             &date) != 0) 
  423.                                                 {
  424.                                                     //Pack in variant.vt
  425.                                                     varDate.vt = VT_DATE;
  426.                                                     varDate.date = date;
  427.                                                     VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR);
  428.                                                     wprintf(L"  %s\r\n",varDate.bstrVal);
  429.                                                     VariantClear(&varDate);
  430.                                                 }
  431.                                                 else
  432.                                                 {
  433.                                                     wprintf(L"  FileTimeToVariantTime failed\n");
  434.                                                 }
  435.                                             }
  436.                                             else
  437.                                             {
  438.                                                 wprintf(L"  FileTimeToSystemTime failed\n");
  439.                                             }
  440.  
  441.                                         }
  442.                                         else
  443.                                         {
  444.                                             wprintf(L"  FileTimeToLocalFileTime failed\n");
  445.                                         }
  446.                                     }
  447.                                 }
  448.                                 else
  449.                                 {
  450.                                     //Print the LargeInteger.
  451.                                     wprintf(L"  high: %d low: %d\r\n",filetime.dwHighDateTime, filetime.dwLowDateTime);
  452.                                 }
  453.                             }
  454.                           }
  455.                           break;
  456.                         case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  457.                           for (x = 0; x< col.dwNumValues; x++)
  458.                           {
  459.                               wprintf(L"  Security descriptor.\n");
  460.                           }
  461.                           break;
  462.                         default:
  463.                           wprintf(L"Unknown type %d.\n",col.dwADsType);
  464.                     }
  465.                   }
  466.                   else
  467.                   {
  468.                     //Verbose handles only the two single-valued attributes: cn and ldapdisplayname
  469.                     //so this is a special case.
  470.                     if (0==wcscmp(L"cn", pszColumn))
  471.                     {
  472.                       wcscpy(szCNValue,col.pADsValues->CaseIgnoreString);
  473.                     }
  474.                     if (0==wcscmp(L"lDAPDisplayName", pszColumn))
  475.                     {
  476.                       wcscpy(szLDAPDispleyNameValue,col.pADsValues->CaseIgnoreString);
  477.                     }
  478.                   }
  479.                   pSchemaNC->FreeColumn( &col );
  480.                 }
  481.                 FreeADsMem( pszColumn );
  482.             }
  483.            if (!bIsVerbose)
  484.                wprintf(L"%s (%s)\n",szLDAPDispleyNameValue,szCNValue);
  485.             //Get the next row
  486.            hr = pSchemaNC->GetNextRow( hSearch);
  487.         }
  488.  
  489.       }
  490.       // Close the search handle to clean up
  491.       pSchemaNC->CloseSearchHandle(hSearch);
  492.     } 
  493.     if (SUCCEEDED(hr) && 0==iCount)
  494.         hr = S_FALSE;
  495.  
  496.     return hr;
  497. }
  498.  
  499.