#include #include #include //Make sure you define UNICODE //Need to define version 5 for Windows 2000 #define _WIN32_WINNT 0x0500 #include HRESULT FindUsers(IDirectorySearch *pContainerToSearch, //IDirectorySearch pointer to the container to search. LPOLESTR szFilter, //Filter for finding specific users. //NULL returns all user objects. LPOLESTR *pszPropertiesToReturn, //Properties to return for user objects found //NULL returns all set properties. BOOL bIsVerbose //TRUE means display all properties for the found objects. //FALSE means only the RDN ); void wmain( int argc, wchar_t *argv[ ]) { //Handle the command line arguments. LPOLESTR pszBuffer = new OLECHAR[MAX_PATH*2]; wcscpy(pszBuffer, L""); BOOL bReturnVerbose = FALSE; for (int i = 1;i<argc;i++) { if (_wcsicmp(argv,L"/V") == 0) { bReturnVerbose = TRUE; } else if ((_wcsicmp(argv,L"/?") == 0)|| (_wcsicmp(argv,L"-?") == 0)) { wprintf(L"This program queries for users in the current user's domain./n"); wprintf(L"Syntax: queryusers [/V][querystring]/n"); wprintf(L"where /V specifies that all properties for the found users should be returned./n"); wprintf(L"querystring is the query criteria in ldap query format./n"); wprintf(L"Defaults: If no /V is specified, the query returns only the RDN and DN of the items found./n"); wprintf(L"If no querystring is specified, the query returns all users./n"); wprintf(L"Example: queryusers (sn=Smith)/n"); wprintf(L"Returns all users with surname Smith./n"); return; } else { wcscpy(pszBuffer,argv); } } if (_wcsicmp(pszBuffer,L"") == 0) wprintf(L"/nFinding all user objects.../n/n"); else wprintf(L"/nFinding user objects based on query: %s.../n/n", pszBuffer); //Initialize COM CoInitialize(NULL); HRESULT hr = S_OK; //Get rootDSE and the current user's domain container distinguished name. IADs *pObject = NULL; IDirectorySearch *pContainerToSearch = NULL; LPOLESTR szPath = new OLECHAR[MAX_PATH]; VARIANT var; hr = ADsOpenObject(L"LDAP://rootDSE", NULL, NULL, ADS_SECURE_AUTHENTICATION, //Use Secure Authentication IID_IADs, (void**)&pObject); if (FAILED(hr)) { wprintf(L"Could not execute query. Could not bind to LDAP://rootDSE./n"); if (pObject) pObject->Release(); return; } if (SUCCEEDED(hr)) { hr = pObject->Get(L"defaultNamingContext",&var); if (SUCCEEDED(hr)) { //Build path to the domain container. wcscpy(szPath,L"LDAP://"); wcscat(szPath,var.bstrVal); hr = ADsOpenObject(szPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, //Use Secure Authentication IID_IDirectorySearch, (void**)&pContainerToSearch); if (SUCCEEDED(hr)) { hr = FindUsers(pContainerToSearch, //IDirectorySearch pointer to domainDNS container. pszBuffer, NULL, //Return all properties bReturnVerbose ); if (SUCCEEDED(hr)) { if (S_FALSE==hr) wprintf(L"No user object could be found./n"); } else if (0x8007203e==hr) wprintf(L"Could not execute query. An invalid filter was specified./n"); else wprintf(L"Query failed to run. HRESULT: %x/n",hr); } else { wprintf(L"Could not execute query. Could not bind to the container./n"); } if (pContainerToSearch) pContainerToSearch->Release(); } VariantClear(&var); } if (pObject) pObject->Release(); // Uninitialize COM CoUninitialize(); return; } HRESULT FindUsers(IDirectorySearch *pContainerToSearch, //IDirectorySearch pointer to the container to search. LPOLESTR szFilter, //Filter for finding specific users. //NULL returns all user objects. LPOLESTR *pszPropertiesToReturn, //Properties to return for user objects found //NULL returns all set properties. BOOL bIsVerbose //TRUE means all properties for the found objects are displayed. //FALSE means only the RDN ) { if (!pContainerToSearch) return E_POINTER; //Create search filter LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2]; //Add the filter. wsprintf(pszSearchFilter, L"(&(objectClass=user)(objectCategory=person)%s)",szFilter); //Specify subtree search ADS_SEARCHPREF_INFO SearchPrefs; SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs.vValue.dwType = ADSTYPE_INTEGER; SearchPrefs.vValue.Integer = ADS_SCOPE_SUBTREE; DWORD dwNumPrefs = 1; // COL for iterations LPOLESTR pszColumn = NULL; ADS_SEARCH_COLUMN col; HRESULT hr; // Interface Pointers IADs *pObj = NULL; IADs * pIADs = NULL; // Handle used for searching. ADS_SEARCH_HANDLE hSearch = NULL; // Set the search preference. hr = pContainerToSearch->SetSearchPreference( &SearchPrefs, dwNumPrefs); if (FAILED(hr)) return hr; LPOLESTR pszBool = NULL; DWORD dwBool; PSID pObjectSID = NULL; LPOLESTR szSID = NULL; LPOLESTR szDSGUID = new WCHAR [39]; LPGUID pObjectGUID = NULL; FILETIME filetime; SYSTEMTIME systemtime; DATE date; VARIANT varDate; LARGE_INTEGER liValue; LPOLESTR *pszPropertyList = NULL; LPOLESTR pszNonVerboseList[] = {L"name",L"distinguishedName"}; LPOLESTR szName = new OLECHAR[MAX_PATH]; LPOLESTR szDN = new OLECHAR[MAX_PATH]; int iCount = 0; DWORD x = 0L; if (!bIsVerbose) { //Return non-verbose list properties only. hr = pContainerToSearch->ExecuteSearch(pszSearchFilter, pszNonVerboseList, sizeof(pszNonVerboseList)/sizeof(LPOLESTR), &hSearch ); } else { if (!pszPropertiesToReturn) { //Return all properties. hr = pContainerToSearch->ExecuteSearch(pszSearchFilter, NULL, 0L, &hSearch ); } else { //Specified subset. pszPropertyList = pszPropertiesToReturn; //Return specified properties. hr = pContainerToSearch->ExecuteSearch(pszSearchFilter, pszPropertyList, sizeof(pszPropertyList)/sizeof(LPOLESTR), &hSearch ); } } if ( SUCCEEDED(hr) ) { // Call IDirectorySearch::GetNextRow() to retrieve the next row //of data. hr = pContainerToSearch->GetFirstRow( hSearch); if (SUCCEEDED(hr)) { while( hr != S_ADS_NOMORE_ROWS ) { //Keep track of count. iCount++; if (bIsVerbose) wprintf(L"----------------------------------/n"); // Loop through the array of passed column names, // print the data for each column. while( pContainerToSearch->GetNextColumnName( hSearch, &pszColumn ) != S_ADS_NOMORE_COLUMNS ) { hr = pContainerToSearch->GetColumn( hSearch, pszColumn, &col ); if ( SUCCEEDED(hr) ) { // Print the data for the column and free the column. if(bIsVerbose) { // Get the data for this column. wprintf(L"%s/n",col.pszAttrName); switch (col.dwADsType) { case ADSTYPE_DN_STRING: for (x = 0; x< col.dwNumValues; x++) { wprintf(L" %s/r/n",col.pADsValues[x].DNString); } break; case ADSTYPE_CASE_EXACT_STRING: case ADSTYPE_CASE_IGNORE_STRING: case ADSTYPE_PRINTABLE_STRING: case ADSTYPE_NUMERIC_STRING: case ADSTYPE_TYPEDNAME: case ADSTYPE_FAXNUMBER: case ADSTYPE_PATH: case ADSTYPE_OBJECT_CLASS: for (x = 0; x< col.dwNumValues; x++) { wprintf(L" %s/r/n",col.pADsValues[x].CaseIgnoreString); } break; case ADSTYPE_BOOLEAN: for (x = 0; x< col.dwNumValues; x++) { dwBool = col.pADsValues[x].Boolean; pszBool = dwBool ? L"TRUE" : L"FALSE"; wprintf(L" %s/r/n",pszBool); } break; case ADSTYPE_INTEGER: for (x = 0; x< col.dwNumValues; x++) { wprintf(L" %d/r/n",col.pADsValues[x].Integer); } break; case ADSTYPE_OCTET_STRING: if ( _wcsicmp(col.pszAttrName,L"objectSID") == 0 ) { for (x = 0; x< col.dwNumValues; x++) { pObjectSID = (PSID)(col.pADsValues[x].OctetString.lpValue); //Convert SID to string. ConvertSidToStringSid(pObjectSID, &szSID); wprintf(L" %s/r/n",szSID); LocalFree(szSID); } } else if ( (_wcsicmp(col.pszAttrName,L"objectGUID") == 0) ) { for (x = 0; x< col.dwNumValues; x++) { //Cast to LPGUID pObjectGUID = (LPGUID)(col.pADsValues[x].OctetString.lpValue); //Convert GUID to string. ::StringFromGUID2(*pObjectGUID, szDSGUID, 39); //Print the GUID wprintf(L" %s/r/n",szDSGUID); } } else wprintf(L" Value of type Octet String. No Conversion."); break; case ADSTYPE_UTC_TIME: for (x = 0; x< col.dwNumValues; x++) { systemtime = col.pADsValues[x].UTCTime; if (SystemTimeToVariantTime(&systemtime, &date) != 0) { //Pack in variant.vt. varDate.vt = VT_DATE; varDate.date = date; VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR); wprintf(L" %s/r/n",varDate.bstrVal); VariantClear(&varDate); } else wprintf(L" Could not convert UTC-Time./n",pszColumn); } break; case ADSTYPE_LARGE_INTEGER: for (x = 0; x< col.dwNumValues; x++) { liValue = col.pADsValues[x].LargeInteger; filetime.dwLowDateTime = liValue.LowPart; filetime.dwHighDateTime = liValue.HighPart; if((filetime.dwHighDateTime==0) && (filetime.dwLowDateTime==0)) { wprintf(L" No value set./n"); } else { //Check for properties of type LargeInteger that represent time. //If TRUE, then convert to variant time. if ((0==wcscmp(L"accountExpires", col.pszAttrName))| (0==wcscmp(L"badPasswordTime", col.pszAttrName))|| (0==wcscmp(L"lastLogon", col.pszAttrName))|| (0==wcscmp(L"lastLogoff", col.pszAttrName))|| (0==wcscmp(L"lockoutTime", col.pszAttrName))|| (0==wcscmp(L"pwdLastSet", col.pszAttrName)) ) { //Handle special case for Never Expires where low part is -1 if (filetime.dwLowDateTime==-1) { wprintf(L" Never Expires./n"); } else { if (FileTimeToLocalFileTime(&filetime, &filetime) != 0) { if (FileTimeToSystemTime(&filetime, &systemtime) != 0) { if (SystemTimeToVariantTime(&systemtime, &date) != 0) { //Pack in variant.vt. varDate.vt = VT_DATE; varDate.date = date; VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR); wprintf(L" %s/r/n",varDate.bstrVal); VariantClear(&varDate); } else { wprintf(L" FileTimeToVariantTime failed/n"); } } else { wprintf(L" FileTimeToSystemTime failed/n"); } } else { wprintf(L" FileTimeToLocalFileTime failed/n"); } } } else { //Print the LargeInteger. wprintf(L" high: %d low: %d/r/n",filetime.dwHighDateTime, filetime.dwLowDateTime); } } } break; case ADSTYPE_NT_SECURITY_DESCRIPTOR: for (x = 0; x< col.dwNumValues; x++) { wprintf(L" Security descriptor./n"); } break; default: wprintf(L"Unknown type %d./n",col.dwADsType); } } else { //Verbose handles only the two single-valued attributes: cn and ldapdisplayname //so this is a special case. if (0==wcscmp(L"name", pszColumn)) { wcscpy(szName,col.pADsValues->CaseIgnoreString); } if (0==wcscmp(L"distinguishedName", pszColumn)) { wcscpy(szDN,col.pADsValues->CaseIgnoreString); } } pContainerToSearch->FreeColumn( &col ); } FreeADsMem( pszColumn ); } if (!bIsVerbose) wprintf(L"%s/n DN: %s/n/n",szName,szDN); //Get the next row hr = pContainerToSearch->GetNextRow( hSearch); } } // Close the search handle to clean up pContainerToSearch->CloseSearchHandle(hSearch); } if (SUCCEEDED(hr) && 0==iCount) hr = S_FALSE; return hr; }