ADSI 使用 C++ 过滤 OU 中的所有计算机
ADSI Filter All computers from an OU using c++
我是 C++ 新手。在 MSDN article 的帮助下,我尝试使用 ADSI 获取域中 OU 下的所有计算机。但是我收到 8254L (FILTER_UNKNOWN) 错误。我不确定我在这里做错了什么。我尝试更新过滤器但错误没有改变。请在这里指出我做错了什么。
下面是我用来获取列表的代码。
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <objbase.h>
#include <wchar.h>
#include <activeds.h>
#include <sddl.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
HRESULT FindComputers(IDirectorySearch *pContainerToSearch, // IDirectorySearch pointer to the container to search.
LPOLESTR szFilter, // Filter to find specific users.
// NULL returns all user objects.
LPOLESTR *pszPropertiesToReturn, // Properties to return for user objects found.
// NULL returns all set properties.
BOOL bIsVerbose // TRUE indicates that display all properties for the found objects.
// FALSE indicates that only the RDN.
);
// Entry point for the application.
void wmain(int argc, wchar_t *argv[])
{
// Initialize COM.
CoInitialize(NULL);
HRESULT hr = S_OK;
// Get rootDSE and the current user domain container distinguished name.
IADs *pObject = NULL;
IDirectorySearch *pContainerToSearch = NULL;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
BOOL bReturnVerbose = FALSE;
DWORD dwLength = MAX_PATH * 2;
LPOLESTR pszBuffer = new OLECHAR[dwLength];
VARIANT var;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (FAILED(hr))
{
wprintf(L"Cannot execute query. Cannot bind to LDAP://rootDSE.\n");
if (pObject)
pObject->Release();
return;
}
if (SUCCEEDED(hr))
{
hr = pObject->Get(_bstr_t("defaultNamingContext"), &var);
if (SUCCEEDED(hr))
{
wprintf(L"bstrVal: %s\n", var.bstrVal);
// Build path to the domain container.
// wcsncpy_s(szPath, L"LDAP://", MAX_PATH);
// wcsncat_s(szPath, var.bstrVal, MAX_PATH - wcslen(szPath));
//hr = ADsOpenObject(szPath,
hr = ADsOpenObject(L"LDAP://OU=IA Computers,OU=Infosys,DC=iaseries,Dc=local",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IDirectorySearch,
(void**)&pContainerToSearch);
if (SUCCEEDED(hr))
{
hr = FindComputers(pContainerToSearch, // IDirectorySearch pointer to domainDNS container.
pszBuffer,
NULL, // Return all properties.
bReturnVerbose
);
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
wprintf(L"Computer object cannot be found.\n");
}
else if (E_ADS_INVALID_FILTER == hr)
wprintf(L"Cannot execute query. Invalid filter was specified.\n");
else
wprintf(L"Query failed to run. HRESULT: %x\n", hr);
}
else
{
wprintf(L"Cannot execute query. Cannot bind to the container.\n");
}
if (pContainerToSearch)
pContainerToSearch->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
// Uninitialize COM.
CoUninitialize();
delete[] szPath;
delete[] pszBuffer;
getchar();
}
HRESULT FindComputers(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 indicates that all properties for the found objects are displayed.
// FALSE indicates only the RDN.
)
{
if (!pContainerToSearch)
return E_POINTER;
DWORD dwLength = (MAX_PATH * 2)+100;
// Create search filter.
LPOLESTR pszSearchFilter = new OLECHAR[dwLength];
// Add the filter.
//swprintf_s(pszSearchFilter, dwLength, L"((objectClass=Computer)%s)", szFilter);
swprintf_s(pszSearchFilter, dwLength, L"(&(objectClass=*)(objectCategory=Computer)%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 = S_OK;
// Interface Pointers
IADs *pObj = NULL;
IADs * pIADs = NULL;
// Search handle.
ADS_SEARCH_HANDLE hSearch = NULL;
// Set search preference.
hr = pContainerToSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
return hr;
LPOLESTR pszBool = NULL;
DWORD dwBool = 0;
PSID pObjectSID = NULL;
LPOLESTR szSID = NULL;
LPOLESTR szDSGUID = new WCHAR[39];
LPGUID pObjectGUID = NULL;
SYSTEMTIME systemtime;
DATE date;
VARIANT varDate;
LPOLESTR *pszPropertyList = NULL;
LPOLESTR pszNonVerboseList[] = { L"name", L"distinguishedName" };
LPOLESTR szName = new OLECHAR[MAX_PATH];
LPOLESTR szDN = new OLECHAR[MAX_PATH];
VariantInit(&varDate);
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,
(DWORD)-1,
&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 data row.
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:
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_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
{
#ifdef _MBCS
// Verbose handles only the two single-valued attributes: cn and ldapdisplayname,
// so this is a special case.
if (0 == wcscmp(L"name", pszColumn))
{
//wcscpy_s(szName, col.pADsValues->CaseIgnoreString);
szName = col.pADsValues->CaseIgnoreString;
}
if (0 == wcscmp(L"distinguishedName", pszColumn))
{
//wcscpy_s(szDN, col.pADsValues->CaseIgnoreString);
szDN = col.pADsValues->CaseIgnoreString;
}
#endif _MBCS
}
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 cleanup.
pContainerToSearch->CloseSearchHandle(hSearch);
}
if (SUCCEEDED(hr) && 0 == iCount)
hr = S_FALSE;
delete[] szName;
delete[] szDN;
delete[] szDSGUID;
delete[] pszSearchFilter;
return hr;
}
我能弄清楚这个问题。以下是工作示例的代码。
我没有清理代码太多。如果您打算使用,请更新。
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <objbase.h>
#include <wchar.h>
#include <activeds.h>
#include <sddl.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
HRESULT FindComputers(IDirectorySearch *pContainerToSearch); // IDirectorySearch pointer to the container to search.
// Entry point for the application.
void wmain(int argc, wchar_t *argv[])
{
// Initialize COM.
CoInitialize(NULL);
HRESULT hr = S_OK;
// Get rootDSE and the current user domain container distinguished name.
IADs *pObject = NULL;
IDirectorySearch *pContainerToSearch = NULL;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
BOOL bReturnVerbose = FALSE;
DWORD dwLength = MAX_PATH * 2;
VARIANT var;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (FAILED(hr))
{
wprintf(L"Cannot execute query. Cannot bind to LDAP://rootDSE.\n");
if (pObject)
pObject->Release();
return;
}
if (SUCCEEDED(hr))
{
hr = pObject->Get(_bstr_t("defaultNamingContext"), &var);
if (SUCCEEDED(hr))
{
//wprintf(L"bstrVal: %s\n", var.bstrVal);
// Build path to the domain container.
// wcsncpy_s(szPath, L"LDAP://", MAX_PATH);
// wcsncat_s(szPath, var.bstrVal, MAX_PATH - wcslen(szPath));
//hr = ADsOpenObject(szPath,
hr = ADsOpenObject(L"LDAP://OU=IA Computers,OU=MyDept,DC=Test,Dc=com",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IDirectorySearch,
(void**)&pContainerToSearch);
if (SUCCEEDED(hr))
{
hr = FindComputers(pContainerToSearch); // IDirectorySearch pointer to domainDNS container.
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
wprintf(L"Computer object cannot be found.\n");
}
else if (E_ADS_INVALID_FILTER == hr)
wprintf(L"Cannot execute query. Invalid filter was specified.\n");
else
wprintf(L"Query failed to run. HRESULT: %x\n", hr);
}
else
{
wprintf(L"Cannot execute query. Cannot bind to the container.\n");
}
if (pContainerToSearch)
pContainerToSearch->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
// Uninitialize COM.
CoUninitialize();
delete[] szPath;
getchar();
}
HRESULT FindComputers(IDirectorySearch *pContainerToSearch) // IDirectorySearch pointer to the container to search.
{
if (!pContainerToSearch)
return E_POINTER;
DWORD dwLength = (MAX_PATH * 2);
// Create search filter.
LPOLESTR pszSearchFilter = new OLECHAR[dwLength];
// Add the filter.
pszSearchFilter = L"((objectCategory=computer))";
// 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 = S_OK;
// Interface Pointers
IADs *pObj = NULL;
IADs * pIADs = NULL;
// Search handle.
ADS_SEARCH_HANDLE hSearch = NULL;
// Set search preference.
hr = pContainerToSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
return hr;
LPOLESTR pszNonVerboseList[] = { L"name", L"distinguishedName" };
LPOLESTR szName = new OLECHAR[MAX_PATH];
LPOLESTR szDN = new OLECHAR[MAX_PATH];
int iCount = 0;
DWORD x = 0L;
// Return non-verbose list properties only.
hr = pContainerToSearch->ExecuteSearch(pszSearchFilter,
pszNonVerboseList,
sizeof(pszNonVerboseList) / sizeof(LPOLESTR),
&hSearch
);
if (SUCCEEDED(hr))
{
// Call IDirectorySearch::GetNextRow() to retrieve the next data row.
hr = pContainerToSearch->GetFirstRow(hSearch);
if (SUCCEEDED(hr))
{
while (hr != S_ADS_NOMORE_ROWS)
{
// Keep track of count.
iCount++;
// 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))
{
// Verbose handles only the two single-valued attributes: cn and ldapdisplayname,
// so this is a special case.
if (0 == wcscmp(L"name", pszColumn))
{
//wcscpy_s(szName, col.pADsValues->CaseIgnoreString);
szName = col.pADsValues->CaseIgnoreString;
}
if (0 == wcscmp(L"distinguishedName", pszColumn))
{
//wcscpy_s(szDN, col.pADsValues->CaseIgnoreString);
szDN = col.pADsValues->CaseIgnoreString;
}
pContainerToSearch->FreeColumn(&col);
}
FreeADsMem(pszColumn);
}
wprintf(L"%s\n DN: %s\n\n", szName, szDN);
// Get the next row.
hr = pContainerToSearch->GetNextRow(hSearch);
}
}
// Close the search handle to cleanup.
pContainerToSearch->CloseSearchHandle(hSearch);
}
if (SUCCEEDED(hr) && 0 == iCount)
hr = S_FALSE;
delete[] szName;
delete[] szDN;
delete[] pszSearchFilter;
return hr;
}
谢谢,
维杰
我是 C++ 新手。在 MSDN article 的帮助下,我尝试使用 ADSI 获取域中 OU 下的所有计算机。但是我收到 8254L (FILTER_UNKNOWN) 错误。我不确定我在这里做错了什么。我尝试更新过滤器但错误没有改变。请在这里指出我做错了什么。
下面是我用来获取列表的代码。
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <objbase.h>
#include <wchar.h>
#include <activeds.h>
#include <sddl.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
HRESULT FindComputers(IDirectorySearch *pContainerToSearch, // IDirectorySearch pointer to the container to search.
LPOLESTR szFilter, // Filter to find specific users.
// NULL returns all user objects.
LPOLESTR *pszPropertiesToReturn, // Properties to return for user objects found.
// NULL returns all set properties.
BOOL bIsVerbose // TRUE indicates that display all properties for the found objects.
// FALSE indicates that only the RDN.
);
// Entry point for the application.
void wmain(int argc, wchar_t *argv[])
{
// Initialize COM.
CoInitialize(NULL);
HRESULT hr = S_OK;
// Get rootDSE and the current user domain container distinguished name.
IADs *pObject = NULL;
IDirectorySearch *pContainerToSearch = NULL;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
BOOL bReturnVerbose = FALSE;
DWORD dwLength = MAX_PATH * 2;
LPOLESTR pszBuffer = new OLECHAR[dwLength];
VARIANT var;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (FAILED(hr))
{
wprintf(L"Cannot execute query. Cannot bind to LDAP://rootDSE.\n");
if (pObject)
pObject->Release();
return;
}
if (SUCCEEDED(hr))
{
hr = pObject->Get(_bstr_t("defaultNamingContext"), &var);
if (SUCCEEDED(hr))
{
wprintf(L"bstrVal: %s\n", var.bstrVal);
// Build path to the domain container.
// wcsncpy_s(szPath, L"LDAP://", MAX_PATH);
// wcsncat_s(szPath, var.bstrVal, MAX_PATH - wcslen(szPath));
//hr = ADsOpenObject(szPath,
hr = ADsOpenObject(L"LDAP://OU=IA Computers,OU=Infosys,DC=iaseries,Dc=local",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IDirectorySearch,
(void**)&pContainerToSearch);
if (SUCCEEDED(hr))
{
hr = FindComputers(pContainerToSearch, // IDirectorySearch pointer to domainDNS container.
pszBuffer,
NULL, // Return all properties.
bReturnVerbose
);
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
wprintf(L"Computer object cannot be found.\n");
}
else if (E_ADS_INVALID_FILTER == hr)
wprintf(L"Cannot execute query. Invalid filter was specified.\n");
else
wprintf(L"Query failed to run. HRESULT: %x\n", hr);
}
else
{
wprintf(L"Cannot execute query. Cannot bind to the container.\n");
}
if (pContainerToSearch)
pContainerToSearch->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
// Uninitialize COM.
CoUninitialize();
delete[] szPath;
delete[] pszBuffer;
getchar();
}
HRESULT FindComputers(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 indicates that all properties for the found objects are displayed.
// FALSE indicates only the RDN.
)
{
if (!pContainerToSearch)
return E_POINTER;
DWORD dwLength = (MAX_PATH * 2)+100;
// Create search filter.
LPOLESTR pszSearchFilter = new OLECHAR[dwLength];
// Add the filter.
//swprintf_s(pszSearchFilter, dwLength, L"((objectClass=Computer)%s)", szFilter);
swprintf_s(pszSearchFilter, dwLength, L"(&(objectClass=*)(objectCategory=Computer)%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 = S_OK;
// Interface Pointers
IADs *pObj = NULL;
IADs * pIADs = NULL;
// Search handle.
ADS_SEARCH_HANDLE hSearch = NULL;
// Set search preference.
hr = pContainerToSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
return hr;
LPOLESTR pszBool = NULL;
DWORD dwBool = 0;
PSID pObjectSID = NULL;
LPOLESTR szSID = NULL;
LPOLESTR szDSGUID = new WCHAR[39];
LPGUID pObjectGUID = NULL;
SYSTEMTIME systemtime;
DATE date;
VARIANT varDate;
LPOLESTR *pszPropertyList = NULL;
LPOLESTR pszNonVerboseList[] = { L"name", L"distinguishedName" };
LPOLESTR szName = new OLECHAR[MAX_PATH];
LPOLESTR szDN = new OLECHAR[MAX_PATH];
VariantInit(&varDate);
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,
(DWORD)-1,
&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 data row.
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:
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_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
{
#ifdef _MBCS
// Verbose handles only the two single-valued attributes: cn and ldapdisplayname,
// so this is a special case.
if (0 == wcscmp(L"name", pszColumn))
{
//wcscpy_s(szName, col.pADsValues->CaseIgnoreString);
szName = col.pADsValues->CaseIgnoreString;
}
if (0 == wcscmp(L"distinguishedName", pszColumn))
{
//wcscpy_s(szDN, col.pADsValues->CaseIgnoreString);
szDN = col.pADsValues->CaseIgnoreString;
}
#endif _MBCS
}
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 cleanup.
pContainerToSearch->CloseSearchHandle(hSearch);
}
if (SUCCEEDED(hr) && 0 == iCount)
hr = S_FALSE;
delete[] szName;
delete[] szDN;
delete[] szDSGUID;
delete[] pszSearchFilter;
return hr;
}
我能弄清楚这个问题。以下是工作示例的代码。 我没有清理代码太多。如果您打算使用,请更新。
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <objbase.h>
#include <wchar.h>
#include <activeds.h>
#include <sddl.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
HRESULT FindComputers(IDirectorySearch *pContainerToSearch); // IDirectorySearch pointer to the container to search.
// Entry point for the application.
void wmain(int argc, wchar_t *argv[])
{
// Initialize COM.
CoInitialize(NULL);
HRESULT hr = S_OK;
// Get rootDSE and the current user domain container distinguished name.
IADs *pObject = NULL;
IDirectorySearch *pContainerToSearch = NULL;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
BOOL bReturnVerbose = FALSE;
DWORD dwLength = MAX_PATH * 2;
VARIANT var;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (FAILED(hr))
{
wprintf(L"Cannot execute query. Cannot bind to LDAP://rootDSE.\n");
if (pObject)
pObject->Release();
return;
}
if (SUCCEEDED(hr))
{
hr = pObject->Get(_bstr_t("defaultNamingContext"), &var);
if (SUCCEEDED(hr))
{
//wprintf(L"bstrVal: %s\n", var.bstrVal);
// Build path to the domain container.
// wcsncpy_s(szPath, L"LDAP://", MAX_PATH);
// wcsncat_s(szPath, var.bstrVal, MAX_PATH - wcslen(szPath));
//hr = ADsOpenObject(szPath,
hr = ADsOpenObject(L"LDAP://OU=IA Computers,OU=MyDept,DC=Test,Dc=com",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IDirectorySearch,
(void**)&pContainerToSearch);
if (SUCCEEDED(hr))
{
hr = FindComputers(pContainerToSearch); // IDirectorySearch pointer to domainDNS container.
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
wprintf(L"Computer object cannot be found.\n");
}
else if (E_ADS_INVALID_FILTER == hr)
wprintf(L"Cannot execute query. Invalid filter was specified.\n");
else
wprintf(L"Query failed to run. HRESULT: %x\n", hr);
}
else
{
wprintf(L"Cannot execute query. Cannot bind to the container.\n");
}
if (pContainerToSearch)
pContainerToSearch->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
// Uninitialize COM.
CoUninitialize();
delete[] szPath;
getchar();
}
HRESULT FindComputers(IDirectorySearch *pContainerToSearch) // IDirectorySearch pointer to the container to search.
{
if (!pContainerToSearch)
return E_POINTER;
DWORD dwLength = (MAX_PATH * 2);
// Create search filter.
LPOLESTR pszSearchFilter = new OLECHAR[dwLength];
// Add the filter.
pszSearchFilter = L"((objectCategory=computer))";
// 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 = S_OK;
// Interface Pointers
IADs *pObj = NULL;
IADs * pIADs = NULL;
// Search handle.
ADS_SEARCH_HANDLE hSearch = NULL;
// Set search preference.
hr = pContainerToSearch->SetSearchPreference(&SearchPrefs, dwNumPrefs);
if (FAILED(hr))
return hr;
LPOLESTR pszNonVerboseList[] = { L"name", L"distinguishedName" };
LPOLESTR szName = new OLECHAR[MAX_PATH];
LPOLESTR szDN = new OLECHAR[MAX_PATH];
int iCount = 0;
DWORD x = 0L;
// Return non-verbose list properties only.
hr = pContainerToSearch->ExecuteSearch(pszSearchFilter,
pszNonVerboseList,
sizeof(pszNonVerboseList) / sizeof(LPOLESTR),
&hSearch
);
if (SUCCEEDED(hr))
{
// Call IDirectorySearch::GetNextRow() to retrieve the next data row.
hr = pContainerToSearch->GetFirstRow(hSearch);
if (SUCCEEDED(hr))
{
while (hr != S_ADS_NOMORE_ROWS)
{
// Keep track of count.
iCount++;
// 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))
{
// Verbose handles only the two single-valued attributes: cn and ldapdisplayname,
// so this is a special case.
if (0 == wcscmp(L"name", pszColumn))
{
//wcscpy_s(szName, col.pADsValues->CaseIgnoreString);
szName = col.pADsValues->CaseIgnoreString;
}
if (0 == wcscmp(L"distinguishedName", pszColumn))
{
//wcscpy_s(szDN, col.pADsValues->CaseIgnoreString);
szDN = col.pADsValues->CaseIgnoreString;
}
pContainerToSearch->FreeColumn(&col);
}
FreeADsMem(pszColumn);
}
wprintf(L"%s\n DN: %s\n\n", szName, szDN);
// Get the next row.
hr = pContainerToSearch->GetNextRow(hSearch);
}
}
// Close the search handle to cleanup.
pContainerToSearch->CloseSearchHandle(hSearch);
}
if (SUCCEEDED(hr) && 0 == iCount)
hr = S_FALSE;
delete[] szName;
delete[] szDN;
delete[] pszSearchFilter;
return hr;
}
谢谢, 维杰