Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Querying Active Directory

Status
Not open for further replies.

jjknack

Programmer
May 17, 2004
9
0
0
US
All,

I am having a problem getting attributes of a user out of active directory. When I execute my query, I get a profile back (mine), and it tells me the attribute that I queried for, but the value is always null. Any ideas as to why this is?

// Open a connection with server.
hr = ADsOpenObject(L"LDAP://myServer",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);

LPWSTR pszAttr[] = { L"distinguishedName" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);

// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(&(objectClass=user)(objectCategory=person)(sAMAccountName=jjknack))",
pszAttr ,dwAttrNameSize,&hSearch );

while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// Get the property.
hr = pDSSearch->GetColumn( hSearch, L"distinguishedName", &col );

// If this object supports this attribute, display it.
if ( SUCCEEDED(hr) )
{ //ADSTYPE_CASE_IGNORE_STRING
WriteMessageCharInt("ADsType: %d", col.dwADsType);
sprintf(tOP, "got attr: %S", col.pszAttrName);
WriteMessageChar(tOP);
WriteMessageCharInt("NUM VALS: %d", col.dwNumValues);
sprintf(tOP, "The distinguishedName property:%s", col.pADsValues->CaseIgnoreString);
WriteMessageChar(tOP);
pDSSearch->FreeColumn( &col );


OUTPUT:
ADsType: 1
got attr: distinguishedName
NUM VALS: 1
The distinguishedName property:(null)

All of the value types under col.pADsValues are (null) as well.
 
Code:
// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(&(objectClass=user)(objectCategory=person)(sAMAccountName=jjknack))",
        pszAttr ,dwAttrNameSize,&hSearch );
I'm guessing that the comment isn't right? That query will return the distinguishedName for all users that are persons and have the samaccountname jjknack. But that should still work.

This is some hacked up code from a program I use:
Code:
ADS_SEARCH_HANDLE hSearch;
ADS_SEARCH_COLUMN col;
strFilter = L"(&(objectclass=user)(objectclass=person)(samaccountname=jjknack))";
LPWSTR strAttrs[] = {L"distinguishedName"};

hr = ADsOpenObject(L"LDAP://myDomain", strUser, strPass, ADS_SECURE_AUTHeNTICATION, IID_IDirectorySearch, (void**) &objSearch);
if(!SUCCEEDED(hr)){return hr;}

hr = objSearch(->ExecuteSearch(strFilter, strAttrs, numAttrs, &hSearch);
if(!SUCCEEDED(hr)){return hr;}

do
{
  hr = objSearch->GetNextRow(hSearch);
  if(!SUCCEEDED(hr)){return hr};
  if(hr == S_ADS_NOMORE_ROWS)break;

  hr = objSearch->GetColumn(hSearch, strAttrs[0], &col);
  if(!SUCCEEDED(hr)){return hr;}

  if(col.dwADsType == ADSTYPE_DN_STRING)
    fprintf(stdout, "%S\n",     col.pADsValues->CaseIgnoreString);
}while(1);
 
Yes, that was an invalid comment...

I still cant get it to work... here is the function in its entirety:

#include "stdafx.h"
#include <stdio.h>
#include <Iads.h>
#include <Adshlp.h>
#include <activeds.h>
#include <comdef.h>
extern "C" {
#include "UtilityFunctions.h"
}

#ifndef __IID_DEFINED__
#define __IID_DEFINED__

typedef struct _IID
{
unsigned long x;
unsigned short s1;
unsigned short s2;
unsigned char c[8];
} IID;

#endif // __IID_DEFINED__

const IID IID_IADs = {0xFD8256D0, 0xFD15, 0x11CE, {0xAB,0xC4,0x02,0x60,0x8C,0x9E,0x75,0x53}};
const IID IID_IADsContainer = {0x001677D0, 0xFD16, 0x11CE, {0xAB,0xC4,0x02,0x60,0x8C,0x9E,0x75,0x53}};
const IID IID_IDirectorySearch = {0x109BA8EC, 0x92F0, 0x11D0, {0xA7,0x90,0x00,0xC0,0x4F,0xD8,0xD5,0xA8}};

extern "C" __declspec(dllexport)
void testAD()
{
HRESULT hr = S_OK; // COM result variable
ADS_SEARCH_COLUMN col; // COL for iterations
LPWSTR szUsername = NULL; // Username
LPWSTR szPassword = NULL; // Password
char tOP[150];

// Interface Pointers.
IDirectorySearch *pDSSearch =NULL;

// Initialize COM.
CoInitialize(0);

// Open a connection with server.
hr = ADsOpenObject(L"LDAP://myServer",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);

LPWSTR strFilter = L"(&(objectclass=user)(objectclass=person)(samaccountname=jjknack))";
LPWSTR pszAttr[] = { L"distinguishedName" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);

hr = pDSSearch->ExecuteSearch(strFilter, pszAttr ,dwAttrNameSize, &hSearch );
if(!SUCCEEDED(hr))
WriteMessageChar ("SEARCH FAILED!") return;;


do
{
hr = pDSSearch->GetNextRow(hSearch);
if(!SUCCEEDED(hr)){WriteMessageChar("GET NEXT ROW FAILED!"); return;}
if(hr == S_ADS_NOMORE_ROWS)break;

hr = pDSSearch->GetColumn(hSearch, pszAttr[0], &col);
if(!SUCCEEDED(hr)){WriteMessageChar("GET COLUMN FAILED!"); return;}

if(col.dwADsType == ADSTYPE_DN_STRING)
{
sprintf(tOP, "%S\n", col.pADsValues->CaseIgnoreString);
WriteMessageChar(tOP);
}
}while(1);


pDSSearch->CloseSearchHandle(hSearch);
pDSSearch->Release();

CoUninitialize();
}

The only thing being printed still is (null)
 
I "got it working"... I am trying to put this code into an interface that I am writing for a 3rd party application. I tested this code in a stand alone EXE and it works. It continues to not work in the 3rd pary app. I will continue with their support. Thanks for your help.
 
Code:
if(col.dwADsType == ADSTYPE_DN_STRING)
{
  sprintf(tOP, "%S\n",     col.pADsValues->CaseIgnoreString);
  WriteMessageChar(tOP);
}

you might want to handle CaseExactString, CaseIgnoreString and DNString seperatly. The code above didn't work for me until I changed the print to use col.pADsValues->DNString. This might be system specific, but I'm not sure.
 
Ok, everything is working just fine now (I had to use IPC [inter-process communication] to get it working, but it does work fine now). My next question now is: the memberof property. It has many entries because a user can be in many groups. Whenever I query for the memberof property, I only get back the first group that I am a member of. Is there a way to get the entire set of groups back?
 
Are you using GetEx() to get the "memberOf" groups? in my code I call:
Code:
hr = objObject->GetEx(L"memberOf", &var);
if(!SUCCEEDED(hr))
{
  hr = objObject->Get(L"memberOf", &var); //GetEx might not work for just one group
}

then I convert var to a SAFEARRAY and print all of the values
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top