Pesquisando com a interface IDirectorySearch
A interface IDirectorySearch fornece uma interface de alto nível e baixa sobrecarga para consultar dados de um diretório ou catálogo global. A interface COM IDirectorySearch pode ser usada apenas com um vtable e, portanto, não está disponível para ambientes de desenvolvimento baseados em automação.
Para realizar uma pesquisa
- Vincular a um objeto no diretório.
- Chame QueryInterface para obter o ponteiro IDirectorySearch.
- Execute a pesquisa usando o ponteiro IDirectorySearch. Chame o método IDirectorySearch::ExecuteSearch e passe um filtro de pesquisa, os nomes de atributos solicitados e outros parâmetros.
Para obter mais informações sobre a sintaxe do filtro de pesquisa, consulte Sintaxe do filtro de pesquisa.
A execução da consulta é específica do provedor. Com alguns provedores, a execução de consulta real não ocorre até IDirectorySearch::GetFirstRow ou IDirectorySearch::GetNextRow é chamado. A interface IDirectorySearch funciona diretamente com filtros de pesquisa. Nem o dialeto SQL nem o dialeto LDAP são necessários.
A interface IDirectorySearch fornece métodos para enumerar o conjunto de resultados, linha por linha. O método IDirectorySearch::GetFirstRow recupera a primeira linha e IDirectorySearch::GetNextRow move você para a próxima linha da linha atual. Quando você tiver atingido a última linha, chamar esses métodos retorna o código de erro S_ADS_NOMORE_ROWS. Por outro lado, IDirectorySearch::GetPreviousRow move você para trás uma linha de cada vez. Um valor de retorno S_ADS_NOMORE_ROWS indica que você atingiu a primeira linha do conjunto de resultados. Esses métodos operam no conjunto de resultados, residente na memória, no cliente. Assim, quando pesquisas paginadas e assíncronas são realizadas e a opção _CACHE_RESULTS é desativada, a rolagem para trás pode ter consequências inesperadas.
Quando você tiver localizado a linha apropriada, chame IDirectorySearch::GetColumn para obter itens de dados, coluna por coluna. Para cada chamada, você passa o nome da coluna de interesse. O item de dados retornado é um ponteiro para uma estrutura ADS_SEARCH_COLUMN. GetColumn aloca essa estrutura para você, mas você deve liberá-la usando FreeColumn. Chame CloseSearchHandle para concluir a operação de pesquisa.
Para executar uma pesquisa de diretório
Vincular a um provedor LDAP. Pode ser um controlador de domínio ou um provedor de catálogo global.
Recupere a interface COM IDirectorySearch com uma chamada para QueryInterface, essa operação pode ter sido feita na Etapa 1 durante a associação inicial.
Opcionalmente, chame SetSearchPreference para selecionar opções para manipular os resultados da sua pesquisa.
Chame ExecuteSearch. Dependendo das opções definidas em SetSearchPreference , isso pode, ou não, iniciar a execução da consulta.
Chame GetNextRow para mover o índice de linha (interno para IDirectorySearch) para a primeira linha.
Leia os dados da linha usando GetColumn e chame FreeColumn para liberar a memória alocada por GetColumn.
Repita a Etapa 5 até que todos os dados sejam recuperados do resultado da pesquisa ou até que GetNextRow retorne S_ADS_NOMORE_ROWS.
Chame AbandonSearch e CloseSearchHandle quando concluir.
O exemplo de código a seguir mostra esse cenário. Para iniciar a vinculação ao ADSI, chame a função ADsOpenObject.
HRESULT hr = S_OK; // COM result variable
ADS_SEARCH_COLUMN col; // COL for iterations
LPWSTR szUsername = NULL; // user name
LPWSTR szPassword = NULL; // password
// Interface Pointers.
IDirectorySearch *pDSSearch =NULL;
// Initialize COM.
CoInitialize(0);
// Add code to securely retrieve the user name and password or
// leave both as NULL to use the default security context.
// Open a connection with server.
hr = ADsOpenObject(L"LDAP://coho.salmon.Fabrikam.com",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);
Isso fornece um ponteiro para a interface IDirectorySearch.
Agora que há uma interface COM para uma instância IDirectoryInterface, chame IDirectorySearch::SetSearchPreference.
Crie uma matriz de nomes de atributos para se preparar para chamar a função IDirectorySearch::ExecuteSearch . Os nomes de atributo são definidos dentro do esquema do Active Directory. Para obter mais informações sobre a definição de esquema, consulte Modelo de esquema ADSI. Os nomes de atributos listados são retornados, se suportados pelo objeto, como o conjunto de resultados da pesquisa.
LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
Agora, chame a função ExecuteSearch . A pesquisa não é executada até que você chame o método GetNextRow.
// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(cn=c*)",pszAttr ,dwAttrNameSize,&hSearch );
Chame GetNextRow para iterar linhas no resultado. Cada linha é então consultada para o atributo "description". Se o atributo for encontrado, ele será exibido.
LPWSTR pszColumn;
while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// Get the property.
hr = pDSSearch->GetColumn( hSearch, L"description", &col );
// If this object supports this attribute, display it.
if ( SUCCEEDED(hr) )
{
if (col.dwADsType == ADSTYPE_CASE_IGNORE_STRING)
wprintf(L"The description property:%s\r\n", col.pADsValues->CaseIgnoreString);
pDSSearch->FreeColumn( &col );
}
else
puts("description property NOT available");
puts("------------------------------------------------");
dwCount++;
}
pDSSearch->CloseSearchHandle(hSearch);
pDSSearch->Release();
Para encerrar a pesquisa, chame o método AbandonSearch .
Lembre-se de que, se um tamanho de página não estiver definido, GetNextRow bloqueará até que todo o conjunto de resultados seja retornado ao cliente. Se o tamanho da página estiver definido, GetNextRow bloqueará até que a primeira página (tamanho da página = número de linhas em uma página) seja retornada. Se o tamanho da página estiver definido e a consulta for classificada e você não estiver pesquisando em pelo menos um atributo indexado, o valor do tamanho da página será ignorado e o servidor calculará todo o conjunto de resultados antes de retornar os dados. Isso tem o efeito de bloqueio GetNextRow até que a consulta seja concluída.
Observação
Para alterar essa consulta de uma pesquisa de diretório para uma pesquisa de catálogo global, a chamada ADsOpenObject é alterada.
// Open a connection with the server.
hr = ADsOpenObject(L"GC://coho.salmon.Fabrikam.com",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);