home *** CD-ROM | disk | FTP | other *** search
-
- #define INC_OLE2
- #define UNICODE 1
- #define _WIN32_DCOM
-
- #include "stdafx.h"
- #include <afxtempl.h>
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <malloc.h>
- #include <winldap.h>
-
- #include <activeds.h>
- #include <assert.h>
-
- #include "ADSIhelpers.h"
-
-
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- // String for usage information
- WCHAR * pwszUsage = L"Checks to see if a member is in a group\n"
- L"Usage:\n"
- L"IsMember\n"
- L" <*> Checks passed LDAP path for Group Membership<*>\n"
- L" /GROUP \n"
- L" This is the LDAP path for the group to check\n"
- L" /MEMBER \n"
- L" LDAP Path of the object to check membership\n\n"
- L" /RECURSE \n"
- L" Recursively scan for membership\n"
- L" /VERBOSE\n"
- L" Prints out detailed information as \n"
- L" the program is processing\n\n"
- L" <*> OPTIONAL Binding Information <*>\n"
- L" /USER <User name used for binding to the DC>\n"
- L" /PASS <Password used for binding to the DC>\n"
- L" (If these are passed, binding is done with ADsOpenObject())\n"
- L"\n";
-
-
- /* Sample command line:
-
- /LDAP "LDAP://nttest.microsoft.com/CN=UGExercise Sample Container,dc=nttest,dc=microsoft,dc=com" /UNAME BOB /SAMNAME BOB /USER Administrator /PASS "" /RECURSE /VERBOSE
-
- */
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- // Module level global variables
-
- BSTR gbsGroup = NULL; // <Group to check> This is the LDAP path for the group to check
-
- BSTR gbsMember = NULL; // <Member to check>
-
- BSTR gbsUSER = NULL; // <User name used for binding to the DC>
- // If this is NON-NULL, then binding with occurr with AdsOpenObject()
- // Otherwise will use ADsGetObject()
-
- BSTR gbsPASS = NULL; // <Password used for binding to the DC>
-
- BOOL gbRecurse = FALSE; // If TRUE, will recurse any contained groups looking for the member
-
- BOOL gbVerbose = FALSE; // If true- will spit out info as it is finding it
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- // Forward Declarations
- BOOL ParseCommandLine( int argc, wchar_t *argv[ ]);
- void PrintIADSObject (IADs * pIADs);
- void PrintBanner (LPOLESTR pwszBanner);
- void PrintBanner (LPOLESTR pwszBanner);
- HRESULT GetObjectGuid(IDirectoryObject * pDO,BSTR &bsGuid);
- HRESULT CheckGroupObjectMembersForMembership(IADsGroup * pADsGroup,LPWSTR pwszMemberGUID,LPWSTR pwszMemberPath,CStringArray & arMemberOf,
- BOOL bVerbose,LPOLESTR pwszUser = NULL, LPOLESTR pwszPassword = NULL);
-
- #define FETCH_NUM 100 // number of elements to fetch at a time
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* RecursiveRetrieveGroupsMemberBelongsto() - Prints the Recursively scans the members of passed IADsGroup ptr
- and any groups belonging to the passed ptr- for membership
- of Passed group
- Will return a CStringArray of all groups which member belongs to
- Parameters
-
- IADsGroup * pADsGroup - Group from which to list members
- LPWSTR pwszMember - LDAP path for object to check membership
- CStringArray & arMemberOf - Returned array of Groups passed member belongs to
- BOOL bVerbose - IF TRUE- will ouput verbose information on the scanning
-
- OPTIONAL Parameters
-
- LPOLESTR pwszUser - User Name and Password, if the parameters are NOT passed,
- LPOLESTER pwszPassword - Binding will use ADsGetObject, if the parameters
- - Are specified, will use ADsOpenObject, passing user name and password
- */
-
-
- HRESULT RecursiveRetrieveGroupsMemberBelongsto(IADsGroup * pADsGroup,LPWSTR pwszMemberGUID,LPWSTR pwszMemberPath, CStringArray & arMemberOf,
- BOOL bVerbose, LPOLESTR pwszUser = NULL, LPOLESTR pwszPassword = NULL)
- {
- HRESULT hr = S_OK; // COM Result Code
- IADsMembers * pADsMembers = NULL; // Ptr to Members of the IADsGroup
- BOOL fContinue = TRUE; // Looping Variable
- IEnumVARIANT * pEnumVariant = NULL; // Ptr to the Enum variant
- IUnknown * pUnknown = NULL; // IUnknown for getting the ENUM initially
- VARIANT VariantArray[FETCH_NUM]; // Variant array for temp holding retuned data
- ULONG ulElementsFetched = NULL; // Number of elements fetched
- BSTR bsGroupPath = NULL;
-
- // Get the path of the object passed in
- hr = pADsGroup->get_ADsPath(&bsGroupPath);
- CheckADHRESULT(hr);
-
- if (!SUCCEEDED(hr))
- return hr;
-
- if (bVerbose)
- {
- WCHAR pwszOutput[2048];
- wsprintf(pwszOutput,L"Checking the Group:\n\n%s\n\n for the member:\n\n%s\n\n",bsGroupPath,pwszMemberPath);
- PrintBanner(pwszOutput);
- }
-
- // Get a interface pointer to the IADsCollection of members
- hr = pADsGroup->Members(&pADsMembers);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Ask the IADsCollection of members for a new ENUM Interface
- // Note the enum comes back as an IUnknown *
- hr = pADsMembers->get__NewEnum(&pUnknown);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // QI the IUnknown * for a IEnumVARIANT interface
- hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVariant);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // While have not hit errors or end of data....
- while (fContinue)
- {
- ulElementsFetched = 0;
- // Get a "batch" number of group members- number of rows specified by FETCH_NUM
- hr = ADsEnumerateNext(pEnumVariant, FETCH_NUM, VariantArray, &ulElementsFetched);
-
- if (ulElementsFetched )
- {
- // Loop through the current batch- printing the path
- // for each member
- for (ULONG i = 0; i < ulElementsFetched; i++ )
- {
- IDispatch * pDispatch = NULL; // ptr for holding dispath of element
- BSTR bstrCurrentPath = NULL; // Holds path of object
- BSTR bstrGuidCurrent = NULL; // Holds path of object
- IDirectoryObject * pIDOCurrent = NULL;// Holds the current object
-
- // Get the dispatch ptr for the variant
- pDispatch = VariantArray[i].pdispVal;
- assert(HAS_BIT_STYLE(VariantArray[i].vt,VT_DISPATCH));
-
- // Get the IADs interface for the "member" of this group
- hr = pDispatch->QueryInterface(IID_IDirectoryObject,
- (VOID **) &pIDOCurrent ) ;
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Retrieve the GUID for the current object
- hr = GetObjectGuid(pIDOCurrent,bstrGuidCurrent);
- CheckADHRESULT(hr);
-
- if (FAILED(hr))
- return hr;
-
- IADs * pIADsCurrent = NULL;
-
- // Retrieve the IADs Interface for the current object
- hr = pIDOCurrent->QueryInterface(IID_IADs,(void**)&pIADsCurrent);
- CheckADHRESULT(hr);
- if (FAILED(hr))
- return hr;
-
- // Get the ADsPath property for this member
- hr = pIADsCurrent->get_ADsPath(&bstrCurrentPath);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- if (bVerbose)
- wprintf(L"Comparing:\n\n%s\nWITH:\n%s\n\n",bstrGuidCurrent,pwszMemberGUID);
-
- // Is the "member of this group Equal to passed?
- if (_wcsicmp(bstrGuidCurrent,pwszMemberGUID)==0)
- {
- if (bVerbose)
- wprintf(L"!!!!!Object:\n\n%s\n\nIs a member of\n\n%s\n\n",pwszMemberPath,bstrGuidCurrent);
-
- // Add the group to the array
- arMemberOf.Add(bsGroupPath);
- }
- else // Otherwise, we should bind to this and see if it is a group
- { // If is it a group then the QI to IADsGroup will succeed
-
- IADsGroup * pIADsGroupAsMember = NULL;
-
- if (pwszUser)
- hr = ADsOpenObject( bstrCurrentPath,
- pwszUser,
- pwszPassword,
- ADS_SECURE_AUTHENTICATION,
- IID_IADsGroup,
- (void**) &pIADsGroupAsMember);
- else
- hr = ADsGetObject( bstrCurrentPath, IID_IADsGroup,(void **)&pIADsGroupAsMember);
-
- // If we DID bind, then this IS a group
- if (SUCCEEDED(hr))
- {
- // Recursively call ourselves to check THIS group
- hr = RecursiveRetrieveGroupsMemberBelongsto(pIADsGroupAsMember,pwszMemberGUID,pwszMemberPath,arMemberOf,bVerbose,pwszUser ,pwszPassword );
- pIADsGroupAsMember->Release();
- pIADsGroupAsMember = NULL;
- }
- }
- SysFreeString(bstrCurrentPath);
- bstrCurrentPath = NULL;
-
- SysFreeString(bstrGuidCurrent);
- bstrGuidCurrent = NULL;
- if (pIADsCurrent)
- {
- pIADsCurrent->Release();
- pIADsCurrent = NULL;
- }
- }
- // Release
- pIDOCurrent->Release();
- pIDOCurrent = NULL;
- }
- }
- // Clear the variant array
- memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
- }
- else
- fContinue = FALSE;
- }
- pEnumVariant->Release();
- pEnumVariant = NULL;
- }
- pUnknown->Release();
- pUnknown = NULL;
- }
- pADsMembers ->Release();
- pADsMembers = NULL;
- }
-
- // Free the group path if it was retrieved.
- if (bsGroupPath)
- {
- SysFreeString(bsGroupPath);
- bsGroupPath = NULL;
- }
- // If everything WENT ok ->we printed all the
- // data and receieved an S_FALSE (indiciating no more data)
- // if that is the case we REALLY want to return a S_OK
- if (hr == S_FALSE)
- hr = S_OK;
- return hr;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* RecursiveIsMember() - Prints the Recursively scans the members of passed IADsGroup ptr
- and any groups belonging to the passed ptr- for membership
- of Passed group
- Will return a TRUE if the member is found in in the passed group,
- Or if the passed member is a member of any group which is a member
- of the passed group
- Parameters
-
- IADsGroup * pADsGroup - Group from which to check members
- LPWSTR pwszMember - LDAP path for object to check membership
- BOOL bVerbose - IF TRUE- will ouput verbose information on the scanning
-
- OPTIONAL Parameters
-
- LPOLESTR pwszUser - User Name and Password, if the parameters are NOT passed,
- LPOLESTER pwszPassword - Binding will use ADsGetObject, if the parameters
- - Are specified, will use ADsOpenObject, passing user name and password
- */
-
- BOOL RecursiveIsMember(IADsGroup * pADsGroup,LPWSTR pwszMemberGUID,LPWSTR pwszMemberPath,
- BOOL bVerbose, LPOLESTR pwszUser, LPOLESTR pwszPassword)
- {
- HRESULT hr = S_OK; // COM Result Code
- IADsMembers * pADsMembers = NULL; // Ptr to Members of the IADsGroup
- BOOL fContinue = TRUE; // Looping Variable
- IEnumVARIANT * pEnumVariant = NULL; // Ptr to the Enum variant
- IUnknown * pUnknown = NULL; // IUnknown for getting the ENUM initially
- VARIANT VariantArray[FETCH_NUM]; // Variant array for temp holding retuned data
- ULONG ulElementsFetched = NULL; // Number of elements fetched
- BSTR bsGroupPath = NULL;
- BOOL bRet = FALSE;
-
- // Get the path of the object passed in
- hr = pADsGroup->get_ADsPath(&bsGroupPath);
- CheckADHRESULT(hr);
-
- if (!SUCCEEDED(hr))
- return hr;
-
- if (bVerbose)
- {
- WCHAR pwszOutput[2048];
- wsprintf(pwszOutput,L"Checking the Group:\n\n%s\n\n for the member:\n\n%s\n\n",bsGroupPath,pwszMemberPath);
- PrintBanner(pwszOutput);
- }
-
- // Get a interface pointer to the IADsCollection of members
- hr = pADsGroup->Members(&pADsMembers);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Ask the IADsCollection of members for a new ENUM Interface
- // Note the enum comes back as an IUnknown *
- hr = pADsMembers->get__NewEnum(&pUnknown);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // QI the IUnknown * for a IEnumVARIANT interface
- hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVariant);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // While have not hit errors or end of data....
- while (fContinue)
- {
- ulElementsFetched = 0;
- // Get a "batch" number of group members- number of rows specified by FETCH_NUM
- hr = ADsEnumerateNext(pEnumVariant, FETCH_NUM, VariantArray, &ulElementsFetched);
-
- if (ulElementsFetched )
- {
- // Loop through the current batch- printing the path
- // for each member
- for (ULONG i = 0; i < ulElementsFetched; i++ )
- {
- IDispatch * pDispatch = NULL; // ptr for holding dispath of element
- BSTR bstrCurrentPath = NULL; // Holds path of object
- BSTR bstrGuidCurrent = NULL; // Holds path of object
- IDirectoryObject * pIDOCurrent = NULL;// Holds the current object
-
- // Get the dispatch ptr for the variant
- pDispatch = VariantArray[i].pdispVal;
- assert(HAS_BIT_STYLE(VariantArray[i].vt,VT_DISPATCH));
-
- // Get the IADs interface for the "member" of this group
- hr = pDispatch->QueryInterface(IID_IDirectoryObject,
- (VOID **) &pIDOCurrent ) ;
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Retrieve the GUID for the current object
- hr = GetObjectGuid(pIDOCurrent,bstrGuidCurrent);
- CheckADHRESULT(hr);
-
- if (FAILED(hr))
- return hr;
-
- IADs * pIADsCurrent = NULL;
-
- // Retrieve the IADs Interface for the current object
- hr = pIDOCurrent->QueryInterface(IID_IADs,(void**)&pIADsCurrent);
- CheckADHRESULT(hr);
- if (FAILED(hr))
- return hr;
-
- // Get the ADsPath property for this member
- hr = pIADsCurrent->get_ADsPath(&bstrCurrentPath);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- if (bVerbose)
- wprintf(L"Comparing:\n\n%s\nWITH:\n%s\n\n",bstrGuidCurrent,pwszMemberGUID);
-
- // Is the "member of this group Equal to passed?
- if (_wcsicmp(bstrGuidCurrent,pwszMemberGUID)==0)
- {
- if (bVerbose)
- wprintf(L"!!!!!Object:\n\n%s\n\nIs a member of\n\n%s\n\n",pwszMemberPath,bstrGuidCurrent);
-
- bRet = TRUE;
- break;
- }
- else // Otherwise, we should bind to this and see if it is a group
- { // If is it a group then the QI to IADsGroup will succeed
-
- IADsGroup * pIADsGroupAsMember = NULL;
-
- if (pwszUser)
- hr = ADsOpenObject( bstrCurrentPath,
- pwszUser,
- pwszPassword,
- ADS_SECURE_AUTHENTICATION,
- IID_IADsGroup,
- (void**) &pIADsGroupAsMember);
- else
- hr = ADsGetObject( bstrCurrentPath, IID_IADsGroup,(void **)&pIADsGroupAsMember);
-
- // If we DID bind, then this IS a group
- if (SUCCEEDED(hr))
- {
- // Recursively call ourselves to check THIS group
- BOOL bRetRecurse;
- bRetRecurse = RecursiveIsMember(pIADsGroupAsMember,pwszMemberGUID,pwszMemberPath,bVerbose,pwszUser ,pwszPassword );
-
- if (bRetRecurse)
- {
- bRet = TRUE;
- break;
- }
- pIADsGroupAsMember->Release();
- pIADsGroupAsMember = NULL;
- }
- }
- SysFreeString(bstrCurrentPath);
- bstrCurrentPath = NULL;
-
- SysFreeString(bstrGuidCurrent);
- bstrGuidCurrent = NULL;
- }
- // Release
- pIDOCurrent->Release();
- pIDOCurrent = NULL;
- if (pIADsCurrent)
- {
- pIADsCurrent->Release();
- pIADsCurrent = NULL;
- }
- }
- }
- // Clear the variant array
- memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
- }
- else
- fContinue = FALSE;
- }
- pEnumVariant->Release();
- pEnumVariant = NULL;
- }
- pUnknown->Release();
- pUnknown = NULL;
- }
- pADsMembers ->Release();
- pADsMembers = NULL;
- }
-
- // Free the group path if it was retrieved.
- if (bsGroupPath)
- {
- SysFreeString(bsGroupPath);
- bsGroupPath = NULL;
- }
- return bRet;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* RecursiveRetrieveAllMembers() - Recursively scans the members of passed IADsGroup ptr
- Returns all members found
- Parameters
-
- IADsGroup * pADsGroup - Group from which to check members
- BOOL bVerbose - IF TRUE- will ouput verbose information on the scanning
-
- OPTIONAL Parameters
-
- LPOLESTR pwszUser - User Name and Password, if the parameters are NOT passed,
- LPOLESTER pwszPassword - Binding will use ADsGetObject, if the parameters
- - Are specified, will use ADsOpenObject, passing user name and password
- */
- HRESULT RecursiveRetrieveAllMembers(IADsGroup * pADsGroup,CStringArray & arMember,LPOLESTR pwszUser, LPOLESTR pwszPassword)
- {
- HRESULT hr = S_OK; // COM Result Code
- IADsMembers * pADsMembers = NULL; // Ptr to Members of the IADsGroup
- BOOL fContinue = TRUE; // Looping Variable
- IEnumVARIANT * pEnumVariant = NULL; // Ptr to the Enum variant
- IUnknown * pUnknown = NULL; // IUnknown for getting the ENUM initially
- VARIANT VariantArray[FETCH_NUM]; // Variant array for temp holding retuned data
- ULONG ulElementsFetched = NULL; // Number of elements fetched
- BSTR bsGroupPath = NULL; // Path of the passed group *
- BOOL bRet = FALSE;
-
- // Get the path of the object passed in
- hr = pADsGroup->get_ADsPath(&bsGroupPath);
- CheckADHRESULT(hr);
-
- if (!SUCCEEDED(hr))
- return hr;
-
- // Get a interface pointer to the IADsCollection of members
- hr = pADsGroup->Members(&pADsMembers);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Ask the IADsCollection of members for a new ENUM Interface
- // Note the enum comes back as an IUnknown *
- hr = pADsMembers->get__NewEnum(&pUnknown);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // QI the IUnknown * for a IEnumVARIANT interface
- hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVariant);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // While have not hit errors or end of data....
- while (fContinue)
- {
- ulElementsFetched = 0;
- // Get a "batch" number of group members- number of rows specified by FETCH_NUM
- hr = ADsEnumerateNext(pEnumVariant, FETCH_NUM, VariantArray, &ulElementsFetched);
-
- if (ulElementsFetched )
- {
- // Loop through the current batch- Saving the path for each member
- for (ULONG i = 0; i < ulElementsFetched; i++ )
- {
- IDispatch * pDispatch = NULL; // ptr for holding dispath of element
- BSTR bstrCurrentPath = NULL; // Holds path of object
- BSTR bstrGuidCurrent = NULL; // Holds path of object
- IDirectoryObject * pIDOCurrent = NULL;// Holds the current object
-
- // Get the dispatch ptr for the variant
- pDispatch = VariantArray[i].pdispVal;
- assert(HAS_BIT_STYLE(VariantArray[i].vt,VT_DISPATCH));
-
- // Get the IADs interface for the "member" of this group
- hr = pDispatch->QueryInterface(IID_IDirectoryObject,
- (VOID **) &pIDOCurrent ) ;
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- IADs * pIADsCurrent = NULL;
-
- // Retrieve the IADs Interface for the current object
- hr = pIDOCurrent->QueryInterface(IID_IADs,(void**)&pIADsCurrent);
- CheckADHRESULT(hr);
- if (FAILED(hr))
- break;
-
- if (SUCCEEDED(hr))
- {
- // Get the ADsPath property for this member
- hr = pIADsCurrent->get_ADsPath(&bstrCurrentPath);
- CheckADHRESULT(hr);
-
- if (pIADsCurrent)
- {
- pIADsCurrent->Release();
- pIADsCurrent= NULL;
- }
- }
-
- if (SUCCEEDED(hr))
- {
- // Add the group to the array
- arMember.Add(bsGroupPath);
-
- // bind to this and see if it is a group
- // If is it a group then the QI to IADsGroup will succeed
- IADsGroup * pIADsGroupAsMember = NULL;
-
- if (pwszUser)
- hr = ADsOpenObject( bstrCurrentPath,
- pwszUser,
- pwszPassword,
- ADS_SECURE_AUTHENTICATION,
- IID_IADsGroup,
- (void**) &pIADsGroupAsMember);
- else
- hr = ADsGetObject( bstrCurrentPath, IID_IADsGroup,(void **)&pIADsGroupAsMember);
-
- // If we DID bind, then this IS a group
- if (SUCCEEDED(hr))
- {
- // Recursively call ourselves to load the members from THIS group
- hr = RecursiveRetrieveAllMembers(pIADsGroupAsMember,arMember,pwszUser ,pwszPassword );
- if (FAILED(hr))
- break;
-
- pIADsGroupAsMember->Release();
- pIADsGroupAsMember = NULL;
- }
- }
- SysFreeString(bstrCurrentPath);
- bstrCurrentPath = NULL;
-
- SysFreeString(bstrGuidCurrent);
- bstrGuidCurrent = NULL;
- }
- // Release
- pIDOCurrent->Release();
- pIDOCurrent = NULL;
- } // For loop
- }
- else
- fContinue = FALSE;
- // Clear the variant array
- memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
- } // while
- pEnumVariant->Release();
- pEnumVariant = NULL;
- }
- pUnknown->Release();
- pUnknown = NULL;
- }
- pADsMembers ->Release();
- pADsMembers = NULL;
- }
-
- // Free the group path if it was retrieved.
- if (bsGroupPath)
- {
- SysFreeString(bsGroupPath);
- bsGroupPath = NULL;
- }
- return hr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /*
- wmain()- UNICODE version of main()
-
- */
- void wmain( int argc, wchar_t *argv[ ])
- {
- // initialize MFC and print and error on failure
- if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
- return;
- CStringArray arMemberOf;
- HRESULT hr;
- IADsGroup * pIADsG = NULL;
-
- // Initialize COM
- CoInitialize(0);
- if (!ParseCommandLine(argc,argv))
- return;
-
- // Bind to the container passed
- // If USER and PASS passed in, use ADsOpenObject()
- if (gbsUSER)
- hr = ADsOpenObject( gbsGroup,
- gbsUSER,
- gbsPASS,
- ADS_SECURE_AUTHENTICATION,
- IID_IADsGroup,
- (void**) &pIADsG);
- else
- hr = ADsGetObject( gbsGroup, IID_IADsGroup,(void **)&pIADsG);
-
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- VARIANT_BOOL bMember = FALSE;
-
- // Ask the bound to group if it contains the passed member
- hr = pIADsG->IsMember(gbsMember,&bMember);
-
- if (SUCCEEDED(hr))
- {
- /* 0 == FALSE, -1 == TRUE */
- // If it is a member and Recusion is NOT specified
- if (bMember == -1 && !gbRecurse)
- {
- wprintf(L"Object \n\n%s\n\n IS a member of the following Group:\n\n%s\n\n",gbsMember,gbsGroup);
- }
- else if (gbRecurse) // If Recursion is Specified
- {
- BSTR bsMemberGUID = NULL;
- IDirectoryObject * pDOMember = NULL;
-
- // Need to get the member's GUID- so we bind with IDirectoryObject
-
- // Bind to the Member passed
- // If USER and PASS passed in, use ADsOpenObject()
- if (gbsUSER)
- hr = ADsOpenObject( gbsMember,
- gbsUSER,
- gbsPASS,
- ADS_SECURE_AUTHENTICATION,
- IID_IDirectoryObject,
- (void**) &pDOMember);
- else
- hr = ADsGetObject( gbsMember, IID_IDirectoryObject,(void **)&pDOMember );
-
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- hr = GetObjectGuid(pDOMember,bsMemberGUID);
- pDOMember->Release();
- pDOMember = NULL;
- }
- else
- {
- wprintf(L"ERROR!!!!: Cannot bind to member:\n\n%s\n\n",gbsMember);
- return ;
- }
-
- RecursiveRetrieveAllMembers(pIADsG,arMemberOf,gbsUSER ,gbsPASS );
-
- int iSize = arMemberOf.GetSize();
- if (iSize)
- {
- // Display the output:
- wprintf(L"\nObject \n\n%s\n\n Contains the following members:\n",gbsGroup);
- puts("------------------------------------------------");
- for (int x = 0; x <iSize; x++)
- {
- CString s = arMemberOf.GetAt(x);
- _putws(s);
- }
- }
-
- if (bsMemberGUID)
- {
- SysFreeString(bsMemberGUID);
- bsMemberGUID = NULL;
- }
- }
- else // NOT a member and NO recursion specified
- wprintf(L"Object \n\n%s\n\n IS NOT a member of the Group:\n\n%s\n\n",gbsMember,gbsGroup);
- }
- pIADsG->Release();
- pIADsG = NULL;
- }
- else
- CheckADHRESULT(hr);
-
- if (gbsGroup)
- {
- SysFreeString(gbsGroup);
- gbsGroup = NULL;
- }
- if (gbsMember)
- {
- gbsUSER = NULL;
- SysFreeString(gbsUSER);
- }
- if (gbsUSER)
- {
- SysFreeString(gbsPASS);
- gbsPASS = NULL;
- }
-
- CoUninitialize();
- }
-
-
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* CheckGroupObjectMembersForMembership() - Prints the Recirsively scans the members of passed IADsGroup ptr
- and any groups belonging to the passed ptr- for membership
- of Passed group
- Will return a CStringArray of all groups which member belongs to
- Parameters
-
- IADsGroup * pADsGroup - Group from which to list members
- LPWSTR pwszMember - LDAP path for object to check membership
- CStringArray & arMemberOf - Returned array of Groups passed member belongs to
- BOOL bVerbose - IF TRUE- will ouput verbose information on the scanning
-
- OPTIONAL Parameters
-
- LPOLESTR pwszUser - User Name and Password, if the parameters are NOT passed,
- LPOLESTER pwszPassword - Binding will use ADsGetObject, if the parameters
- - Are specified, will use ADsOpenObject, passing user name and password
- */
-
- #define FETCH_NUM 100 // number of elements to fetch at a time for CheckGroupObjectMembersForMembership()
-
- HRESULT CheckGroupObjectMembersForMembership(IADsGroup * pADsGroup,LPWSTR pwszMemberGUID,LPWSTR pwszMemberPath, CStringArray & arMemberOf,
- BOOL bVerbose, LPOLESTR pwszUser, LPOLESTR pwszPassword)
- {
- HRESULT hr = S_OK; // COM Result Code
- IADsMembers * pADsMembers = NULL; // Ptr to Members of the IADsGroup
- BOOL fContinue = TRUE; // Looping Variable
- IEnumVARIANT * pEnumVariant = NULL; // Ptr to the Enum variant
- IUnknown * pUnknown = NULL; // IUnknown for getting the ENUM initially
- VARIANT VariantArray[FETCH_NUM]; // Variant array for temp holding retuned data
- ULONG ulElementsFetched = NULL; // Number of elements fetched
- BSTR bsGroupPath = NULL;
-
- // Get the path of the object passed in
- hr = pADsGroup->get_ADsPath(&bsGroupPath);
- CheckADHRESULT(hr);
-
- if (!SUCCEEDED(hr))
- return hr;
-
- if (bVerbose)
- {
- WCHAR pwszOutput[2048];
- wsprintf(pwszOutput,L"Checking the Group:\n\n%s\n\n for the member:\n\n%s\n\n",bsGroupPath,pwszMemberPath);
- PrintBanner(pwszOutput);
- }
-
- // Get a interface pointer to the IADsCollection of members
- hr = pADsGroup->Members(&pADsMembers);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Ask the IADsCollection of members for a new ENUM Interface
- // Note the enum comes back as an IUnknown *
- hr = pADsMembers->get__NewEnum(&pUnknown);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // QI the IUnknown * for a IEnumVARIANT interface
- hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVariant);
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // While have not hit errors or end of data....
- while (fContinue)
- {
- ulElementsFetched = 0;
- // Get a "batch" number of group members- number of rows specified by FETCH_NUM
- hr = ADsEnumerateNext(pEnumVariant, FETCH_NUM, VariantArray, &ulElementsFetched);
-
- if (ulElementsFetched )
- {
- // Loop through the current batch- printing the path
- // for each member
- for (ULONG i = 0; i < ulElementsFetched; i++ )
- {
- IDispatch * pDispatch = NULL; // ptr for holding dispath of element
- //IADs * pIADsGroupMember = NULL; // IADs ptr to group member
- BSTR bstrCurrentPath = NULL; // Holds path of object
- BSTR bstrGuidCurrent = NULL; // Holds path of object
- IDirectoryObject * pIDOCurrent = NULL;
-
- // Get the dispatch ptr for the variant
- pDispatch = VariantArray[i].pdispVal;
- assert(HAS_BIT_STYLE(VariantArray[i].vt,VT_DISPATCH));
-
- // Get the IADs interface for the "member" of this group
- hr = pDispatch->QueryInterface(IID_IDirectoryObject,
- (VOID **) &pIDOCurrent ) ;
- CheckADHRESULT(hr);
-
- if (SUCCEEDED(hr))
- {
- // Get the ADsPath property for this member
- //hr = pIADsGroupMember->get_ADsPath(&bstrPath) ;
-
- hr = GetObjectGuid(pIDOCurrent,bstrGuidCurrent);
-
- // hr = pIADsGroupMember->get_GUID(&bstrPath);//get_ADsPath() ;
- CheckADHRESULT(hr);
-
- if (FAILED(hr))
- return hr;
-
- IADs * pIADsCurrent = NULL;
-
- hr = pIDOCurrent->QueryInterface(IID_IADs,(void**)&pIADsCurrent);
-
- if (FAILED(hr))
- return hr;
-
-
- hr = pIADsCurrent->get_ADsPath(&bstrCurrentPath);
-
-
- if (SUCCEEDED(hr))
- {
- if (bVerbose)
- wprintf(L"Comparing:\n\n%s\nWITH:\n%s\n\n",bstrGuidCurrent,pwszMemberGUID);
-
- // Is the "member of this group Equal to passed?
- if (_wcsicmp(bstrGuidCurrent,pwszMemberGUID)==0)
- {
- if (bVerbose)
- {
- wprintf(L"!!!!!Object:\n\n%s\n\nIs a member of\n\n%s\n\n",pwszMemberPath,bstrGuidCurrent);
- }
- // Add the group to the array
- arMemberOf.Add(bsGroupPath);
- }
- else // Otherwise, we should bind to this and see if it is a group
- { // If is it a group then the QI to IADsGroup will succeed
-
- IADsGroup * pIADsGroupAsMember = NULL;
-
- if (pwszUser)
- hr = ADsOpenObject( bstrCurrentPath,
- pwszUser,
- pwszPassword,
- ADS_SECURE_AUTHENTICATION,
- IID_IADsGroup,
- (void**) &pIADsGroupAsMember);
- else
- hr = ADsGetObject( bstrCurrentPath, IID_IADsGroup,(void **)&pIADsGroupAsMember);
-
- // If we DID bind, then this IS a group
- if (SUCCEEDED(hr))
- {
- // Recursively call ourselves to check THIS group
- hr = CheckGroupObjectMembersForMembership(pIADsGroupAsMember,pwszMemberGUID,pwszMemberPath,arMemberOf,bVerbose,pwszUser ,pwszPassword );
- pIADsGroupAsMember->Release();
- pIADsGroupAsMember = NULL;
- }
- }
- SysFreeString(bstrCurrentPath);
- bstrCurrentPath = NULL;
-
- SysFreeString(bstrGuidCurrent);
- bstrGuidCurrent = NULL;
- }
- pIDOCurrent->Release();
- pIDOCurrent = NULL;
- }
- }
- // Clear the variant array
- memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
- }
- else
- fContinue = FALSE;
- }
- pEnumVariant->Release();
- pEnumVariant = NULL;
- }
- pUnknown->Release();
- pUnknown = NULL;
- }
- pADsMembers ->Release();
- pADsMembers = NULL;
- }
-
- // Free the group path if it was retrieved.
- if (bsGroupPath)
- {
- SysFreeString(bsGroupPath);
- bsGroupPath = NULL;
- }
- // If everything WENT ok ->we printed all the
- // data and receieved an S_FALSE (indiciating no more data)
- // if that is the case we REALLY want to return a S_OK
- if (hr == S_FALSE)
- hr = S_OK;
- return hr;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* GetObjectGuid() - Retrieves the GUID in String form from the passed Directory Object
- Returns S_OK on success
-
- Parameters
-
- IDirectoryObject * pDO - Directory Object from where GUID will be retrieved.
- BSTR & bsGuid - Returned GUID
- */
-
- HRESULT GetObjectGuid(IDirectoryObject * pDO,BSTR &bsGuid)
- {
-
- GUID *pObjectGUID = NULL;
- PADS_ATTR_INFO pAttributeEntries;
- LPWSTR pAttributeName = L"objectGUID"; //Get the GUID for the object
- DWORD dwAttributesReturned = 0;
- HRESULT hr;
- hr = pDO->GetObjectAttributes( &pAttributeName, //objectGUID
- 1, //Only objectGUID
- &pAttributeEntries, // Returned attributes
- &dwAttributesReturned //Number of attributes returned
- );
-
- if (SUCCEEDED(hr) && dwAttributesReturned>0)
- {
- //Make sure that we got the right type--objectGUID is ADSTYPE_OCTET_STRING
- if (pAttributeEntries->dwADsType == ADSTYPE_OCTET_STRING)
- {
- //Get COM converted string version of the GUID
- //lpvalue should be LPBYTE. Should be able to cast it to ptr to GUID.
- pObjectGUID = (GUID*)(pAttributeEntries->pADsValues[0].OctetString.lpValue);
-
- //OLE str to fit a GUID
-
- LPOLESTR szGUID = new WCHAR [64];
- szGUID[0]=NULL;
- //Convert GUID to string.
- ::StringFromGUID2(*pObjectGUID, szGUID, 39);
- bsGuid = SysAllocString(szGUID);
-
- delete [] szGUID;
- }
- }
-
- return hr;
-
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /*
- PrintIADSObject() - Calls all the methods on a IADs object
- and prints them the console window
- Parameters
-
- IADs * pIADs - IADs Interface from which to retrieve attribute values
- */
- void PrintIADSObject(IADs * pIADs)
- {
- assert(pIADs);
-
- BSTR bsResult;
-
- pIADs->get_Name(&bsResult);
- wprintf(L" NAME: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- pIADs->get_Class(&bsResult);
- wprintf(L" CLASS: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- pIADs->get_GUID(&bsResult);
- wprintf(L" GUID: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- pIADs->get_ADsPath(&bsResult);
- wprintf(L" ADSPATH: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- pIADs->get_Parent(&bsResult);
- wprintf(L" PARENT: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- pIADs->get_Schema(&bsResult);
- wprintf(L" SCHEMA: %s\n",(LPOLESTR) bsResult);
- SysFreeString(bsResult);
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /* PrintBanner() - Prints a banner on the screen
-
- Parameters
-
- LPOLESTR pwszBanner - String to print
- */
- void PrintBanner(LPOLESTR pwszBanner)
- {
- _putws(L"");
- _putws(L"////////////////////////////////////////////////////");
- wprintf(L"\t");
- _putws(pwszBanner);
- _putws(L"////////////////////////////////////////////////////\n");
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /*
- ParseCommandLine()- Parses command line and sets module level globals
-
- Parameters:
-
- int argc - Number of Arguments
- wchar_t *argv[ ] - Array of arguments
-
- Returns:
- TRUE if Command line was successfully parsed
-
- Affectets global variables:
-
- BSTR bsGroup
- BSTR bsMember
- BSTR bsUSER
- BSTR bsPASS
- BOOL gbRecurse
- BOOL gbVerbose
-
- */
- BOOL ParseCommandLine( int argc, wchar_t *argv[ ])
- {
- /*
- ** PARSE the FOLLOWING ARGUMENTS:
-
- BSTR bsGroup = NULL; // <Group to check> This is the LDAP path for the group to check
-
- BSTR bsMember = NULL; // <Member to check> ath in the SCHEMA of the object
-
- BSTR bsUSER = NULL; // <User name used for binding to the DC>
- // If this is NON-NULL, then binding with occurr with AdsOpenObject()
- // Otherwise will use ADsGetObject()
-
- BSTR bsPASS = NULL; // <Password used for binding to the DC>
-
- BOOL gbRecurse = FALSE; // If TRUE, will recurse any contained groups looking for the member
-
- BOOL gbVerbose = FALSE; // If true- will spit out info as it is finding it
-
- */
- if (argc == 1)
- {
- _putws(pwszUsage);
- return FALSE;
- }
- for (int x= 1; x < argc; x++)
- {
- if (_wcsicmp(argv[x],L"/GROUP")==0)
- {
- if (argc == x) // Make sure the parameter was passed
- {
- wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
- _putws(pwszUsage);
- return FALSE;
- }
- // Go to the next argument and save it in module level variable
- x++;
- gbsGroup= SysAllocString(argv[x]);
-
- }
- else if (_wcsicmp(argv[x],L"/MEMBER")==0)
- {
- if (argc == x) // Make sure the parameter was passed
- {
- wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
- _putws(pwszUsage);
- return FALSE;
- }
- // Go to the next argument and save it in module level variable
- x++;
- gbsMember= SysAllocString(argv[x]);
-
- }
- else if (_wcsicmp(argv[x],L"/USER")==0)
- {
- if (argc == x) // Make sure the parameter was passed
- {
- wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
- _putws(pwszUsage);
- return FALSE;
- }
- // Go to the next argument and save it in module level variable
- x++;
- gbsUSER = SysAllocString(argv[x]);
- }
- else if (_wcsicmp(argv[x],L"/PASS")==0)
- {
- if (argc == x) // Make sure the parameter was passed
- {
- wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
- _putws(pwszUsage);
- return FALSE;
- }
- // Go to the next argument and save it in module level variable
- x++;
- gbsPASS = SysAllocString(argv[x]);
- }
- else if (_wcsicmp(argv[x],L"/RECURSE")==0)
- {
- gbRecurse = TRUE;
- }
- else if (_wcsicmp(argv[x],L"/VERBOSE")==0)
- {
- gbVerbose = TRUE;
- }
- else
- {
- wprintf(L"\nERROR: %s UNknown Argument\n\n",argv[x]);
- _putws(pwszUsage);
- return FALSE;
- }
- }
- if (!gbsGroup)
- {
- _putws(L"\nERROR: /GROUP is required!");
- return FALSE;
- }
- if (!gbsMember)
- {
- _putws(L"\nERROR: /MEMBER is required!");
- return FALSE;
- }
- // Check if User is poassed, then password is required:
- if (gbsUSER || gbsPASS)
- if (!gbsUSER || !gbsPASS) // if either one is missing complain
- {
- _putws(L"\nERROR: If /USER is specified /PASS is required!");
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-