Directory Services |
The following code example contains a function that creates a group with only the essential properties explicitly set (cn, sAMAccountType, groupType) and containing no members:
//////////////////////////////////////////////////////////////////////////////////////////////////// /* CreateSimpleGroup() - Function for creating a basic group Parameters IDirectoryObject *pDirObject - Parent Directory Object for the new group LPWSTR pwCommonName - Common Name for the new group IADs ** ppObjRet - Pointer to the Pointer which will receive the new Group int iGroupType - Bitflags for new group: ADS_GROUP_TYPE_GLOBAL_GROUP, ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, ADS_GROUP_TYPE_UNIVERSAL_GROUP, ADS_GROUP_TYPE_SECURITY_ENABLED */ HRESULT CreateSimpleGroup(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IADs *ppObjRet,int iGroupType) { if(!pDirObject) return E_INVALIDARG; // Verify that the group type is Universal Security // if true, ensure that domain is in native mode. if(((iGroupType & ADS_GROUP_TYPE_UNIVERSAL_GROUP)==ADS_GROUP_TYPE_UNIVERSAL_GROUP)&&((iGroupType & ADS_GROUP_TYPE_SECURITY_ENABLED)==ADS_GROUP_TYPE_SECURITY_ENABLED)) { // Verify that the domain that contains the container is in mixed mode. hr = CheckDomainModeOfObject(pDirObject, &bIsMixed); if (SUCCEEDED(hr)) { if (bIsMixed) return E_INVALIDARG; } else { return hr; } } // SamAccountName cannot be larger than 20 characters. if (wcslen(pwSamAcctName) >20) { return E_FAIL; } HRESULT hr; /* ADSVALUE is used to specify attribute data for calling IDirectoryObject::CreateDSObject() When Creating a new group, the required attributes are : objectClass,sAMAccountName and groupType. In this function the "objectClass" is set to "group". The "sAMAccountName" is the Windows NT 4.0 name. In Windows 2000/Windows NT 4 mixed-mode environment, this attribute is exposed to the Windows NT 4 computers. Therefore, this name must be globally unique throughout the network and cannot exceed 20 characters in length. */ ADSVALUE sAMValue; ADSVALUE classValue; ADSVALUE groupType; LPDISPATCH pDisp; WCHAR *pwCommonNameFull; // Build an Array of ADS_ATTR_INFO structures // Be aware that the sAMAccountName and groupType entries contain // a pointer to the respective ADSVALUE structures defined previously. ADS_ATTR_INFO attrInfo[] = { { L"objectClass", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &classValue, 1 }, {L"sAMAccountName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &sAMValue, 1}, {L"groupType", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &groupType, 1} }; // Get the size of the array. DWORD dwAttrs = sizeof(attrInfo)/sizeof(ADS_ATTR_INFO); /* For ADSVALUES, the dwType member and the data value member (in this case "CaseIgnoreString") must be set. */ // To create a group, this parameter must be set to "group". classValue.dwType = ADSTYPE_CASE_IGNORE_STRING; classValue.CaseIgnoreString = L"group"; // Set sAMAccountName to the name passed to this function sAMValue.dwType=ADSTYPE_CASE_IGNORE_STRING; sAMValue.CaseIgnoreString = pwSamAcctName; // Set the groupType to the group type passed to this function groupType.dwType=ADSTYPE_INTEGER; groupType.Integer = iGroupType; // Allocate a buffer to hold the full common name string pwCommonNameFull = new WCHAR[wcslen(pwCommonName)+4]; // Be aware that CN is limited to 64 characters. // Take the passed commonname and prefix a 'CN=' to conform // to the format that IDirectoryObject::CreateDSObject() requires wsprintfW(pwCommonNameFull,L"CN=%s",pwCommonName); // Create the new group. hr = pDirObject->CreateDSObject( pwCommonNameFull, attrInfo, dwAttrs, &pDisp ); if (SUCCEEDED(hr)) { // Query the new group for an IADs to be returned from this function. hr = pDisp->QueryInterface(IID_IADs,(void**) ppObjRet); pDisp->Release(); pDisp = NULL; } return hr; } HRESULT GetDomainMode(IADs *pDomain, BOOL *bIsMixed) { HRESULT hr = E_FAIL; VARIANT var; if (pDomain) { VariantClear(&var); // Get the ntMixedDomain attribute hr = pDomain->Get(CComBSTR("ntMixedDomain"), &var); if (SUCCEEDED(hr)) { // Type should be VT_I4. if (var.vt==VT_I4) { // Zero (0) indicates native mode. if (var.lVal == 0) *bIsMixed = FALSE; // One (1) indicates mixed mode. else if (var.lVal == 1) *bIsMixed = TRUE; else hr=E_FAIL; } } VariantClear(&var); } return hr; } HRESULT CheckDomainModeOfObject(IDirectoryObject *pDirObject, BOOL *bIsMixed) { HRESULT hr = E_FAIL; IADs *pDomain = NULL; VARIANT VarTest; WCHAR *pFound = NULL; int iLen; WCHAR *pDomainPath = new WCHAR[MAX_PATH*2]; // Verify that the domain that contains the container is in mixed mode WCHAR *pVal = NULL; pVal = GetDirectoryObjectAttrib(pDirObject,L"canonicalName"); if (pVal) { // Parse the canonical name for the DNS name of the domain pFound = wcschr(pVal,'/'); // Bind to the domain using the dns name, get defaultnamingcontext, if (pFound) { iLen = pFound - pVal; wcscpy(pDomainPath, L"LDAP://"); wcsncat(pDomainPath, pVal,iLen); wcscat(pDomainPath, L"/rootDSE"); wprintf(L"DNS Name: %s\n", pDomainPath); VariantClear(&VarTest); hr = ADsOpenObject(pDomainPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, // Use Secure Authentication IID_IADs, (void**)&pDomain); if (SUCCEEDED(hr)) { hr = pDomain->Get(CComBSTR("defaultNamingContext"), &VarTest); if (SUCCEEDED(hr)) { wcscpy(pDomainPath, L"LDAP://"); wcsncat(pDomainPath, pVal,iLen); wcscat(pDomainPath, L"/"); wcscat(pDomainPath, VarTest.bstrVal); VariantClear(&VarTest); if (pDomain) pDomain->Release(); if (SUCCEEDED(hr)) { hr = ADsOpenObject(pDomainPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, // Use Secure Authentication. IID_IADs, (void**)&pDomain); if (SUCCEEDED(hr)) { hr = GetDomainMode(pDomain, bIsMixed); } } } } if (pDomain) pDomain->Release(); } } return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// /* GetDirectoryObjectAttrib() - Returns the value of the attribute named in pAttrName from the IDirectoryObject passed. Parameters IDirectoryObject *pDirObject - Object from which to retrieve an attribute value LPWSTR pAttrName - Name of attribute to retrieve */ WCHAR * GetDirectoryObjectAttrib(IDirectoryObject *pDirObject,LPWSTR pAttrName) { HRESULT hr; ADS_ATTR_INFO *pAttrInfo=NULL; DWORD dwReturn; static WCHAR pwReturn[1024]; pwReturn[0] = 0l; hr = pDirObject->GetObjectAttributes( &pAttrName, 1, &pAttrInfo, &dwReturn ); if ( SUCCEEDED(hr) ) { for(DWORD idx=0; idx < dwReturn;idx++, pAttrInfo++ ) { if ( (_wcsicmp(pAttrInfo->pszAttrName,pAttrName) == 0 ) && (pAttrInfo->dwADsType == ADSTYPE_CASE_IGNORE_STRING)) { wcscpy(pwReturn,pAttrInfo->pADsValues->CaseIgnoreString); break; } } FreeADsMem( pAttrInfo ); } return pwReturn; }
The following code example creates a group with only the essential properties explicitly set (cn, sAMAccountType, groupType) and containing no members.
'//////////////////////////////////////////////////////////////////////////////////////////////////// ' CreateSimpleGroup() - Function for creating a basic group ' ' Parameters ' ' oDirObject As IDirectoryObject - Parent Directory Object for the new group ' ByVal sCommonName As String - Common Name for the new group ' ByVal sSAMAcctName As String - Pointer to the Pointer which will receive the new Group ' oDirObject As IDirectoryObject - Parent Directory Object for the new group ' ByVal sCommonName As String - Common Name for the new group ' ByVal sSAMAcctName As String - Sam Account Name for the new group ' oDirObjectRet As IDirectoryObject - New object returned ' ByVal iGroupType As Long - Bitflags for new group: ' ADS_GROUP_TYPE_GLOBAL_GROUP, ' ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, ' ADS_GROUP_TYPE_UNIVERSAL_GROUP, ' ADS_GROUP_TYPE_SECURITY_ENABLED Sub CreateSimpleGroup(oDirObject As IDirectoryObject, ByVal sCommonName As String, ByVal sSAMAcctName As String, oDirObjectRet As IDirectoryObject, ByVal iGroupType As Long) On Error GoTo CleanUp If Len(sSAMAcctName) > 20 Then MsgBox "SamAccountName CANNOT be bigger than 20 characters" Exit Sub End If Dim sGroupType As String Dim oNewObject As IADs Dim oIadsContDirObj As IADsContainer Set oIadsContDirObj = oDirObject ' Get the string value for the group type. sGroupType = Str(iGroupType) ' Get a New group object. Set oNewObject = oIadsContDirObj.Create("group", "CN=" & sCommonName) ' Put the required attributes. oNewObject.Put "sAMAccountName", sSAMAcctName oNewObject.Put "GroupType", iGroupType ' Commit the new group. oNewObject.SetInfo ' Print group vitals. DisplayMessage ">>> Created new GROUP with a groupeType of " & Str(iGroupType) PrintIADSObject oNewObject Set oDirObjectRet = oNewObject Set oNewObject = Nothing Set oIadsContDirObj = Nothing Exit Sub CleanUp: Set oNewObject = Nothing Set oIadsContDirObj = Nothing Set oDirObjectRet = Nothing End Sub