|
|
//---------------------------------------------------------------------------
// UPDTUPN.cpp
//
// Comment: This is a COM object extension for the MCS DCTAccountReplicator.
// This object implements the IExtendAccountMigration interface.
// The process method on this object updates the userPrincipalName
// property on the user object.
//
// (c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved
//
// Proprietary and confidential to Mission Critical Software, Inc.
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "ARExt.h"
#include "ARExt_i.c"
#include "UPNUpdt.h"
#include "ErrDCT.hpp"
#include "Names.hpp"
#include <iads.h>
#include <AdsHlp.h>
#include "resstr.h"
//#import "\bin\NetEnum.tlb" no_namespace
#import "NetEnum.tlb" no_namespace
#include "UpdtUPN.h"
TErrorDct err;
/////////////////////////////////////////////////////////////////////////////
// CUpdtUPN
StringLoader gString;
//---------------------------------------------------------------------------
// Get and set methods for the properties.
//---------------------------------------------------------------------------
STDMETHODIMP CUpdtUPN::get_sName(BSTR *pVal) { *pVal = m_sName; return S_OK; }
STDMETHODIMP CUpdtUPN::put_sName(BSTR newVal) { m_sName = newVal; return S_OK; }
STDMETHODIMP CUpdtUPN::get_sDesc(BSTR *pVal) { *pVal = m_sDesc; return S_OK; }
STDMETHODIMP CUpdtUPN::put_sDesc(BSTR newVal) { m_sDesc = newVal; return S_OK; }
//---------------------------------------------------------------------------
// ProcessObject : This method doesn't do anything.
//---------------------------------------------------------------------------
STDMETHODIMP CUpdtUPN::PreProcessObject( IUnknown *pSource, //in- Pointer to the source AD object
IUnknown *pTarget, //in- Pointer to the target AD object
IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user
IUnknown **ppPropsToSet //in,out - Varset filled with Prop-Value pairs that will be set
// once all extension objects are executed.
) { IVarSetPtr pVs = pMainSettings; _variant_t var; _bstr_t sTemp; _bstr_t sUPN; _bstr_t sPref; _bstr_t sSuff; IADs * pAds = NULL; IADs * pAdsSource = NULL; HRESULT hr; WCHAR sTempUPN[7000]; long ub, lb; _bstr_t sFull; _variant_t HUGEP * pDt; _bstr_t sAdsPath; _variant_t varDN; _bstr_t sIntraforest; _bstr_t sDomainDNS; _bstr_t sTargetOU; WCHAR fileName[MAX_PATH]; bool bReplace = false; tstring sSAMName; tstring sUPNName; _bstr_t sOldUPN; bool bConflicted = false; SUPNStruc UPNStruc;
// We need to process the user accounts only
sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if (!sTemp.length()) return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); if (_wcsicmp((WCHAR*)sTemp,L"user")) return S_OK;
//store the name of this user in the UPN list
sSAMName = _bstr_t(pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)));
//get the target domain DNS name
sDomainDNS = pVs->get(GET_BSTR(DCTVS_Options_TargetDomainDns));
//get the target OU path
sTargetOU = pVs->get(GET_BSTR(DCTVS_Options_OuPath));
//if not retrieved yet, get the default UPN suffix for this domain
if (m_sUPNSuffix.length() == 0) { //if failed, use the domain's DNS name
if (!GetDefaultUPNSuffix(sDomainDNS, sTargetOU)) m_sUPNSuffix = sDomainDNS; }
// Get the Error log filename from the Varset
wcscpy(fileName, (WCHAR*)(pVs->get(GET_BSTR(DCTVS_Options_Logfile)).bstrVal)); // Open the error log
err.LogOpen(fileName, 1);
sPref = pVs->get(GET_BSTR(DCTVS_Options_Prefix)); sSuff = pVs->get(GET_BSTR(DCTVS_Options_Suffix)); sIntraforest = pVs->get(GET_BSTR(DCTVS_Options_IsIntraforest)); sTemp = pVs->get(GET_BSTR(DCTVS_AccountOptions_ReplaceExistingAccounts)); if (!UStrICmp(sTemp,GET_STRING(IDS_YES))) bReplace = true;
sAdsPath = L""; if ( pSource ) { // Get the UPN from the source domain
hr = pSource->QueryInterface(IID_IADs, (void**) &pAdsSource); } if ( pAdsSource ) { if ( SUCCEEDED(hr) ) { hr = pAdsSource->GetEx(L"userPrincipalName", &var); if (SUCCEEDED(hr) ) { SAFEARRAY * pArray = V_ARRAY(&var); hr = SafeArrayGetLBound(pArray, 1, &lb); hr = SafeArrayGetUBound(pArray, 1, &ub);
hr = SafeArrayAccessData(pArray, (void HUGEP **) &pDt); if ( SUCCEEDED(hr) ) { // translate all the UPNs to the target domain.
for ( long x = lb; x <= ub; x++) { wcsncpy(sTempUPN, (WCHAR*) pDt[x].bstrVal, 5000); sTempUPN[4999] = 0;
//Get the stuff before the LAST @ sign.
WCHAR * ndx = NULL; WCHAR * tempNdx = sTempUPN; do { tempNdx = wcschr(tempNdx + 1, L'@'); if ( tempNdx ) ndx = tempNdx; } while (tempNdx);
if (ndx) *ndx = L'\0';
if ( sPref.length() ) sFull = sPref + _bstr_t(sTempUPN); else if ( sSuff.length() ) sFull = _bstr_t(sTempUPN) + sSuff; else sFull = sTempUPN;
sTemp = sFull; sUPN = sTemp + _bstr_t(L"@"); sUPN = sUPN + m_sUPNSuffix; //store UPN name as it enters
sOldUPN = sUPN; sUPNName = sUPN; //get unigue UPN on target
GetUniqueUPN(sUPN, pVs, false, sAdsPath); //see if the two UPN's differ. If they do, then we had a conflict
// if ((_wcsicmp(sOldUPN, sUPN) != 0) && (!bReplace))
if (_wcsicmp((WCHAR*)sOldUPN, sUPN) != 0) { sUPNName = sUPN; hr = ERROR_OBJECT_ALREADY_EXISTS; bConflicted = true; } pDt[x] = _variant_t(sUPN); } SafeArrayUnaccessData(pArray); } } else { sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_TargetSam)); sUPN = sTemp + _bstr_t(L"@"); sUPN = sUPN + m_sUPNSuffix; //store UPN name as it enters
sOldUPN = sUPN; sUPNName = sUPN; //get unigue UPN on target
GetUniqueUPN(sUPN, pVs, true, sAdsPath); //see if the two UPN's differ. If they do, then we had a conflict
// if ((_wcsicmp(sOldUPN, sUPN) != 0) && (!bReplace))
if (_wcsicmp((WCHAR*)sOldUPN, sUPN) != 0) { sUPNName = sUPN; hr = ERROR_OBJECT_ALREADY_EXISTS; bConflicted = true; } } } } else { sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_TargetSam)); sUPN = sTemp + _bstr_t(L"@"); sUPN = sUPN + m_sUPNSuffix; //store UPN name as it enters
sOldUPN = sUPN; sUPNName = sUPN; //get unigue UPN on target
GetUniqueUPN(sUPN, pVs, true, sAdsPath); //see if the two UPN's differ. If they do, then we had a conflict
// if ((_wcsicmp(sOldUPN, sUPN) != 0) && (!bReplace))
if (_wcsicmp((WCHAR*)sOldUPN, sUPN) != 0) { sUPNName = sUPN; hr = ERROR_OBJECT_ALREADY_EXISTS; bConflicted = true; } }
if ( pAds ) pAds->Release(); if (pAdsSource) pAdsSource->Release();
UPNStruc.sName = sUPNName; UPNStruc.sOldName = sOldUPN; UPNStruc.bConflicted = bConflicted; //insert UPN into Map
mUPNMap.insert(CUPNMap::value_type(sSAMName, UPNStruc));
return hr; }
//---------------------------------------------------------------------------
// ProcessObject : This method updates the UPN property of the object. It
// first sees if a E-Mail is specified then it will set UPN
// to that otherwise it builds it from SAMAccountName and the
// Domain name
//---------------------------------------------------------------------------
STDMETHODIMP CUpdtUPN::ProcessObject( IUnknown *pSource, //in- Pointer to the source AD object
IUnknown *pTarget, //in- Pointer to the target AD object
IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user
IUnknown **ppPropsToSet //in,out - Varset filled with Prop-Value pairs that will be set
// once all extension objects are executed.
) { IVarSetPtr pVs = pMainSettings; _bstr_t sTemp; IADs * pAds = NULL; _variant_t var; HRESULT hr; WCHAR fileName[MAX_PATH]; CUPNMap::iterator itUPNMap; tstring sSam; SUPNStruc UPNStruc; bool bReplace = false; _bstr_t sOldUPNSuffix;
// We need to process the user accounts only
sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( _wcsicmp((WCHAR*)sTemp,L"user") ) return S_OK;
sTemp = pVs->get(GET_BSTR(DCTVS_AccountOptions_ReplaceExistingAccounts)); if (!UStrICmp(sTemp,GET_STRING(IDS_YES))) bReplace = true;
//get the target SAM name
sSam = _bstr_t(pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)));
// Get the Error log filename from the Varset
wcscpy(fileName, (WCHAR*)(pVs->get(GET_BSTR(DCTVS_Options_Logfile)).bstrVal)); // Open the error log
err.LogOpen(fileName, 1);
// And only need to process the accounts copied to Win2k domain.
if ( pTarget ) { //Get the IADs pointer to manipulate properties
hr = pTarget->QueryInterface(IID_IADs, (void**) &pAds);
if (SUCCEEDED(hr)) { //get the UPN name for this user from the list
itUPNMap = mUPNMap.find(sSam); if (itUPNMap != mUPNMap.end()) UPNStruc = itUPNMap->second;
if (!UPNStruc.sName.empty()) { bool bSame = false; //if replace mode, don't set UPN if same object we are replacing and
//if not the same object, get it's current UPN Suffix
if (bReplace) { hr = pAds->Get(L"userPrincipalName", &var); if (SUCCEEDED(hr)) { //if replacing the object whose UPN conflicted, don't change it
if (!UPNStruc.sOldName.compare(var.bstrVal)) bSame = true; else //else, get the object's current UPN suffix for re-use
sOldUPNSuffix = GetUPNSuffix(var.bstrVal); } }
if (!bSame) { var = UPNStruc.sName.c_str(); //if replacing an existing object, use it's old UPN suffix
if ((bReplace) && (sOldUPNSuffix.length() != 0)) { //change the suffix on the old name, since it may longer conflict
_bstr_t sUPN = ChangeUPNSuffix(UPNStruc.sOldName.c_str(), sOldUPNSuffix); //if changed, make sure we don't still have a UPN conflict and save the
//new UPN for setting
if (sUPN.length() != 0) { _bstr_t sTempUPN = sUPN; //get unigue UPN on target, now that we could conflict
GetUniqueUPN(sUPN, pVs, true, _bstr_t(L"")); //if changed, set conflicted flag and names for error message
if (sUPN != sTempUPN) { UPNStruc.sName = sUPN; UPNStruc.sOldName = sTempUPN; UPNStruc.bConflicted = true; } else UPNStruc.bConflicted = false;
var = sUPN; } } hr = pAds->Put(L"userPrincipalName", var); if (SUCCEEDED(hr)) { hr = pAds->SetInfo(); if (SUCCEEDED(hr)) { // If we changed the UPN Name due to conflict, we need to log a
//message indicating the fact that we changed it.
if (UPNStruc.bConflicted) err.MsgWrite(1, DCT_MSG_CREATE_FAILED_UPN_CONF_SS, UPNStruc.sOldName.c_str(), UPNStruc.sName.c_str()); } } } } } } if ( pAds ) pAds->Release(); return hr; }
//---------------------------------------------------------------------------
// ProcessUndo : We are not going to undo this.
//---------------------------------------------------------------------------
STDMETHODIMP CUpdtUPN::ProcessUndo( IUnknown *pSource, //in- Pointer to the source AD object
IUnknown *pTarget, //in- Pointer to the target AD object
IUnknown *pMainSettings, //in- Varset filled with the settings supplied by user
IUnknown **ppPropsToSet //in,out - Varset filled with Prop-Value pairs that will be set
// once all extension objects are executed.
) { IVarSetPtr pVs = pMainSettings; _bstr_t sTemp, sSUPN; IADs * pAds = NULL; _variant_t var; HRESULT hr = S_OK; _bstr_t sAdsPath = L""; _bstr_t sTempUPN;
// We need to process the user accounts only
sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( _wcsicmp((WCHAR*)sTemp,L"user") ) return S_OK;
// get the original source account's UPN
sSUPN = pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceUPN)); if (sSUPN.length()) { sTempUPN = sSUPN; GetUniqueUPN(sTempUPN, pVs, true, sAdsPath); int len; WCHAR * ndx, * tempNdx = (WCHAR*)sTempUPN; do { tempNdx = wcschr(tempNdx + 1, L'@'); if ( tempNdx ) ndx = tempNdx; } while (tempNdx);
if (ndx) len = ndx - sTempUPN; if (_wcsnicmp(sTempUPN, sSUPN, len) != 0) return S_OK; // And only need to process the accounts copied to Win2k domain.
if ( pTarget ) { //Get the IADs pointer to manipulate properties
hr = pTarget->QueryInterface(IID_IADs, (void**) &pAds);
if ( SUCCEEDED(hr) ) { var = sSUPN; hr = pAds->Put(L"userPrincipalName", var); hr = pAds->SetInfo(); } } if ( pAds ) pAds->Release(); }
return S_OK; }
//---------------------------------------------------------------------------
// GetUniqueUPN : This function checks if the UPN is unique if not then
// appends a number starting with 0 and retries till a unique
// UPN is found.
//---------------------------------------------------------------------------
void CUpdtUPN::GetUniqueUPN(_bstr_t &sUPN, IVarSetPtr pVs, bool bUsingSamName, _bstr_t sAdsPath) { // Here are the steps that we follow to get the unique UPN name
// 1. Check if the current name is unique. If it is then return that.
// 2. Append collision prefix and suffix if the sam account name has changed due to pref/suffix.
// 3. Add a numeric suffix to the UPN and repeat till a unique UPN is found.
// If the user tells us not to do this then we simply return the current UPN name.
_bstr_t sProcess = pVs->get(GET_BSTR(DCTVS_Options_AllowDuplicateUPNs)); if ( sProcess == GET_BSTR(IDS_YES) ) return;
WCHAR sTempUPN[5000]; // long x = 0;
WCHAR sQuery[5000], sPath[5000]; HRESULT hr = E_FAIL; // LPWSTR pCols[] = { L"distinguishedName" };
LPWSTR pCols[] = { L"sAMAccountName" }; BSTR * pData = NULL; SAFEARRAY * pSaCols = NULL; SAFEARRAYBOUND bd = { 1, 0 }; _bstr_t sTgtDomain = pVs->get(GET_BSTR(DCTVS_Options_TargetDomainDns)); INetObjEnumeratorPtr pQuery(__uuidof(NetObjEnumerator)); IEnumVARIANT * pEnum = NULL; DWORD fetched = 0; _variant_t var; bool bCollPrefSufProcessed = false; _bstr_t sSourceSam = pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam)); _bstr_t sTargetSam = pVs->get(GET_BSTR(DCTVS_CopiedAccount_TargetSam)); _bstr_t sPrefix = pVs->get(GET_BSTR(DCTVS_AccountOptions_Prefix)); _bstr_t sSuffix = pVs->get(GET_BSTR(DCTVS_AccountOptions_Suffix)); _bstr_t sPref = pVs->get(GET_BSTR(DCTVS_Options_Prefix)); _bstr_t sSuff = pVs->get(GET_BSTR(DCTVS_Options_Suffix)); int offset = 0; WCHAR sTemp[5000]; SAFEARRAY * psaPath = NULL; _variant_t varPath; _variant_t * pVar; bool bReplace = false; WCHAR sTempSAM[MAX_PATH]; _bstr_t sNewSAM; _bstr_t sUPNSuffix; _bstr_t sUPNPrefix;
_bstr_t sReplace = pVs->get(GET_BSTR(DCTVS_AccountOptions_ReplaceExistingAccounts)); if (!UStrICmp(sReplace,GET_STRING(IDS_YES))) bReplace = true;
wcscpy(sTempSAM, (WCHAR*)sSourceSam); StripSamName(sTempSAM); if ( sPref.length() ) sNewSAM = sPref + _bstr_t(sTempSAM); else if ( sSuff.length() ) sNewSAM = _bstr_t(sTempSAM) + sSuff; else sNewSAM = sTempSAM; wcscpy(sTempUPN, (WCHAR*) sUPN);
//Get the stuff before the LAST @ sign.
WCHAR * ndx = NULL; WCHAR * tempNdx = sTempUPN; do { tempNdx = wcschr(tempNdx + 1, L'@'); if ( tempNdx ) ndx = tempNdx; } while (tempNdx);
if (ndx) *ndx = L'\0'; sUPNSuffix = ndx+1; sUPNPrefix = sTempUPN;
// Setup the path name to the domain.
wsprintf(sPath, L"LDAP://%s", (WCHAR*)sTgtDomain);
// setup the columns that we want the query to return to us.
pSaCols = SafeArrayCreate(VT_BSTR, 1, &bd); if (pSaCols) { hr = SafeArrayAccessData(pSaCols, (void HUGEP **) &pData); if ( SUCCEEDED(hr) ) { pData[0] = SysAllocString(pCols[0]); } hr = SafeArrayUnaccessData(pSaCols); }
if ( SUCCEEDED(hr) ) { // First we need to set up a query to find the UPN
wcscpy(sTempUPN, (WCHAR*)sUPN); do { wsprintf(sQuery, L"(userPrincipalName=%s)", sTempUPN); hr = pQuery->raw_SetQuery(sPath, sTgtDomain, sQuery, ADS_SCOPE_SUBTREE, FALSE); if ( SUCCEEDED(hr) ) hr = pQuery->raw_SetColumns(pSaCols);
if ( SUCCEEDED(hr) ) hr = pQuery->raw_Execute(&pEnum);
if ( SUCCEEDED(hr) ) { hr = pEnum->Next(1, &var, &fetched); while ( hr == S_OK ) { if ( var.vt & VT_ARRAY ) { psaPath = var.parray; hr = SafeArrayAccessData(psaPath, (void HUGEP**) &pVar); if ( SUCCEEDED(hr) ) { varPath = pVar[0]; } SafeArrayUnaccessData(psaPath); //SafeArrayGetElement(psaPath, &x, (void*)&varPath);
if ( !wcslen((WCHAR*) varPath.bstrVal) ) { hr = S_FALSE; }
if ((!_wcsicmp((WCHAR*)varPath.bstrVal, (WCHAR*)sNewSAM)) && (bReplace)) { // If the account found is the same as the account being processed then we
// need to see if any other accounts have this UPN. if they do then we need
// to change it other wise we do not need to process this any further.
hr = pEnum->Next(1, &var, &fetched); continue; } else break; } } if ( hr == S_OK ) { // If we are here that means we have a collision So we need to update the UPN and try again
// See if we have processed the Prefix/Suffix
if ( !bCollPrefSufProcessed ) { // See if we renamed the samAccountName with the prefix/suffix. If we are already using
// sam name then there is no need to add the prefix/suffix.
if ( !bUsingSamName && RenamedWithPrefixSuffix(sSourceSam, sTargetSam, sPrefix, sSuffix)) { // Since we renamed the sam names we can rename the UPN
if ( sPrefix.length() ) wsprintf(sTempUPN, L"%s%s", (WCHAR*)sPrefix, (WCHAR*)sUPNPrefix);
if ( sSuffix.length() ) wsprintf(sTempUPN, L"%s%s",(WCHAR*)sUPNPrefix, (WCHAR*)sSuffix);
sUPNPrefix = sTempUPN; // we want to apply the prefix/suffix in any case.
} else { // just add a number to the end of the name.
wsprintf(sTempUPN, L"%s%d", (WCHAR*)sUPNPrefix, offset); offset++; } bCollPrefSufProcessed = true; } else { // we went through prefix/suffix and still found a collision so we need to go by the count now.
wsprintf(sTempUPN, L"%s%d", (WCHAR*)sUPNPrefix, offset); offset++; } wcscpy(sTemp, sTempUPN); wsprintf(sTempUPN, L"%s@%s", sTemp, (WCHAR*)sUPNSuffix); } VariantInit(&var); if ( pEnum ) pEnum->Release(); } } while ( hr == S_OK ); SafeArrayDestroy(pSaCols); } sUPN = sTempUPN; }
//---------------------------------------------------------------------------
// RenamedWithPrefixSuffix : Checks to see if the Target sam name
// was renamed with a prefix/suffix.
//---------------------------------------------------------------------------
bool CUpdtUPN::RenamedWithPrefixSuffix(_bstr_t sSourceSam, _bstr_t sTargetSam, _bstr_t sPrefix, _bstr_t sSuffix) { bool retVal = false; if ( sSourceSam != sTargetSam ) { if ( sPrefix.length() ) { if ( !wcsncmp((WCHAR*) sTargetSam, (WCHAR*) sPrefix, sPrefix.length()) ) retVal = true; }
if ( sSuffix.length() ) { if ( !wcscmp((WCHAR*) sTargetSam + (sTargetSam.length() - sSuffix.length()), (WCHAR*) sSuffix ) ) retVal = true; } } return retVal; }
/*********************************************************************
* * * Written by: Paul Thompson * * Date: 24 MAR 2001 * * * * This function is responsible for retrieving the default UPN * * suffix to be used in making UPN names. The suffix will be stored * * in a class member variable. * * First, using the given target OU path, see if the target OU * * has any UPN suffixes defined for it. If so, return store the * * last one enumerated. Otherwise, see if any UPN suffixes have * * been defined on the configuration's partition. If so, store the * * last one enumerated. If no success yet, use the forest root's * * domain DNS name. * * * *********************************************************************/
//BEGIN GetDefaultUPNSuffix
bool CUpdtUPN::GetDefaultUPNSuffix(_bstr_t sDomainDNS, _bstr_t sTargetOU) { /* local variables */ IADs * pDSE = NULL; IADs * pCont = NULL; WCHAR sRoot[1000]; HRESULT hr = S_OK; _variant_t var; _variant_t HUGEP * pVar; int nLast;
/* function body */ //check incoming parameters
if ((sDomainDNS.length() == 0) || (sTargetOU.length() == 0)) return false;
/* first see if the target OU has UPN suffixes defined */ //get a pointer to the target OU
hr = ADsGetObject(sTargetOU,IID_IADs,(void**)&pCont); if ( SUCCEEDED(hr) ) { //get any UPN suffixes defined
hr = pCont->Get( L"uPNSuffixes", &var); if ( SUCCEEDED(hr) ) { //if one, store it and return
if ( var.vt == VT_BSTR ) { m_sUPNSuffix = var.bstrVal; //store the suffix
pCont->Release(); return true; } //else if nore than one, get the first one, store it, and return
else if ( var.vt & VT_ARRAY ) { SAFEARRAY * multiVals = var.parray; SafeArrayAccessData(multiVals, (void HUGEP **) &pVar); nLast = multiVals->rgsabound->cElements - 1; m_sUPNSuffix = _bstr_t(V_BSTR(&pVar[nLast])); SafeArrayUnaccessData(multiVals); pCont->Release(); return true; } }//end if suffixes defined on the partition
pCont->Release(); pCont = NULL; }//if got partition
/* next try the UPN suffixes on the partition container or the root
domain's DNS name */ //get the root DSE container
wcscpy(sRoot,L"LDAP://RootDSE"); hr = ADsGetObject(sRoot,IID_IADs,(void**)&pDSE); if ( SUCCEEDED(hr) ) { //get the suffixes listed on the configuration partition
hr = pDSE->Get(L"configurationNamingContext",&var); if ( SUCCEEDED(hr) ) { swprintf(sRoot,L"LDAP://%ls/CN=Partitions,%ls", (WCHAR*)sDomainDNS, var.bstrVal); hr = ADsGetObject(sRoot,IID_IADs,(void**)&pCont); if ( SUCCEEDED(hr) ) { //get any UPN suffixes defined
hr = pCont->Get( L"uPNSuffixes", &var); if ( SUCCEEDED(hr) ) { //if one, store it and return
if ( var.vt == VT_BSTR ) { m_sUPNSuffix = var.bstrVal; //store the suffix
pDSE->Release(); pCont->Release(); return true; } //else if nore than one, get the first one, store it, and return
else if ( var.vt & VT_ARRAY ) { SAFEARRAY * multiVals = var.parray; SafeArrayAccessData(multiVals, (void HUGEP **) &pVar); nLast = multiVals->rgsabound->cElements - 1; m_sUPNSuffix = _bstr_t(V_BSTR(&pVar[nLast])); SafeArrayUnaccessData(multiVals); pDSE->Release(); pCont->Release(); return true; } }//end if suffixes defined on the partition
pCont->Release(); pCont = NULL; }//if got partition
}//if got config naming context
//since no UPN suffixes defined on the partition, try the root domain's
//DNS name
hr = pDSE->Get(L"RootDomainNamingContext",&var); if ( SUCCEEDED(hr) ) { //convert the DN of the root domain to a DNS name, store it, and return
m_sUPNSuffix = GetDomainDNSFromPath(_bstr_t(var.bstrVal)); pDSE->Release(); return true; } pDSE->Release(); pDSE = NULL; }//if got rootDSE
return false; } //END GetDefaultUPNSuffix
/*********************************************************************
* * * Written by: Paul Thompson * * Date: 26 MAR 2001 * * * * This function is responsible for extracting the UPN Suffix * * from a given UPN name and returning that suffix. * * * *********************************************************************/
//BEGIN GetUPNSuffix
_bstr_t CUpdtUPN::GetUPNSuffix(_bstr_t sUPNName) { /* local variables */ _bstr_t sUPNSuffix = L""; WCHAR * pTemp;
/* function body */ //check incoming parameters
if (sUPNName.length() == 0) return sUPNSuffix;
//find the last '@'
pTemp = wcsrchr((WCHAR*)sUPNName, L'@');
//if found, copy the suffix to the return variable
if (pTemp) sUPNSuffix = pTemp+1;
return sUPNSuffix; } //END GetUPNSuffix
/*********************************************************************
* * * Written by: Paul Thompson * * Date: 26 MAR 2001 * * * * This function is responsible for replacing the UPN Suffix * * on a given UPN name with the given suffix and returning the new * * UPN name. * * * *********************************************************************/
//BEGIN ChangeUPNSuffix
_bstr_t CUpdtUPN::ChangeUPNSuffix(_bstr_t sUPNName, _bstr_t sNewSuffix) { /* local variables */ _bstr_t sNewUPN = L""; WCHAR * pTemp;
/* function body */ //check incoming parameters
if (sUPNName.length() == 0) return sNewUPN;
//create a temporary buffer to hold the UPN Name
WCHAR* sUPN = new WCHAR[sUPNName.length() + 1]; if (!sUPN) return sNewUPN;
//copy the UPN to this buffer
wcscpy(sUPN, sUPNName);
//find the last '@'
pTemp = wcsrchr(sUPN, L'@');
//if found, make the new UPN with the old Prefix and given suffix
if (pTemp) { //end the string after the '@'
*(pTemp+1) = L'\0';
//copy the Prefix plus the new Suffix to the new UPN name
sNewUPN = sUPN + sNewSuffix; } //delete the prefix string
delete [] sUPN;
return sNewUPN; } //END ChangeUPNSuffix
|