// RidSave.cpp : Implementation of CGetRidsApp and DLL registration. #include "stdafx.h" #include "GetRids.h" #include "RidSave.h" #include "ARExt.h" #include "ARExt_i.c" #include #include #include "resstr.h" #include "TxtSid.h" #import "VarSet.tlb" no_namespace rename("property", "aproperty") #ifndef IADsPtr _COM_SMARTPTR_TYPEDEF(IADs, IID_IADs); #endif ///////////////////////////////////////////////////////////////////////////// // RidSave StringLoader gString; DWORD __stdcall GetRidFromVariantSid(const _variant_t& vntSid); //--------------------------------------------------------------------------- // Get and set methods for the properties. //--------------------------------------------------------------------------- STDMETHODIMP RidSave::get_sName(BSTR *pVal) { *pVal = m_sName; return S_OK; } STDMETHODIMP RidSave::put_sName(BSTR newVal) { m_sName = newVal; return S_OK; } STDMETHODIMP RidSave::get_sDesc(BSTR *pVal) { *pVal = m_sDesc; return S_OK; } STDMETHODIMP RidSave::put_sDesc(BSTR newVal) { m_sDesc = newVal; return S_OK; } //--------------------------------------------------------------------------- // PreProcessObject //--------------------------------------------------------------------------- STDMETHODIMP RidSave::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. EAMAccountStats* pStats ) { IVarSetPtr pVs = pMainSettings; VARIANT var; _bstr_t sTemp; IADsPtr pAds; HRESULT hr = S_OK; DWORD rid = 0; // default to 0, if RID not found // We need to process users and groups 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") && _wcsicmp((WCHAR*)sTemp,L"inetOrgPerson") && _wcsicmp((WCHAR*)sTemp,L"group") ) return S_OK; //Get the IADs pointer to manipulate properties pAds = pSource; if ( pAds ) { VariantInit(&var); hr = pAds->Get(_bstr_t(L"objectSID"),&var); if ( SUCCEEDED(hr) ) { // retrieve the RID rid = GetRidFromVariantSid(_variant_t(var, false)); } } // save the RID pVs->put(GET_BSTR(DCTVS_CopiedAccount_SourceRID),(long)rid); return hr; } //--------------------------------------------------------------------------- // ProcessObject //--------------------------------------------------------------------------- STDMETHODIMP RidSave::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. EAMAccountStats* pStats ) { IVarSetPtr pVs = pMainSettings; VARIANT var; _bstr_t sTemp; IADsPtr pAds; HRESULT hr = S_OK; DWORD rid = 0; // default to 0, if RID not found // We need to process users and groups only sTemp = pVs->get(GET_BSTR(DCTVS_CopiedAccount_Type)); if ( _wcsicmp((WCHAR*)sTemp,L"user") && _wcsicmp((WCHAR*)sTemp,L"inetOrgPerson") && _wcsicmp((WCHAR*)sTemp,L"group") ) { return S_OK; } //Get the IADs pointer to manipulate properties pAds = pTarget; if (pAds) { VariantInit(&var); hr = pAds->Get(_bstr_t(L"objectSID"),&var); if ( SUCCEEDED(hr) ) { // retrieve the RID rid = GetRidFromVariantSid(_variant_t(var, false)); } } // save the RID pVs->put(GET_BSTR(DCTVS_CopiedAccount_TargetRID),(long)rid); return hr; } //--------------------------------------------------------------------------- // ProcessUndo //--------------------------------------------------------------------------- STDMETHODIMP RidSave::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. EAMAccountStats* pStats ) { HRESULT hr = S_OK; IVarSetPtr spSettings(pMainSettings); if (spSettings) { // // Update RID for undo of intra-forest moves only as the // target object will receive a new RID in this case. // _bstr_t strIntraForest = spSettings->get(GET_BSTR(DCTVS_Options_IsIntraforest)); if (strIntraForest == GET_BSTR(IDS_YES)) { // // Update RID if target object exists. // IADsPtr spTarget(pTarget); if (spTarget) { // // Update RID only for user and group objects. // _bstr_t strType = spSettings->get(GET_BSTR(DCTVS_CopiedAccount_Type)); PCWSTR pszType = strType; bool bTypeValid = pszType && ((_wcsicmp(pszType, L"user") == 0) || (_wcsicmp(pszType, L"inetOrgPerson") == 0) || (_wcsicmp(pszType, L"group") == 0)); if (bTypeValid) { // // Retrieve RID of object. // VARIANT var; VariantInit(&var); hr = spTarget->Get(_bstr_t(L"objectSID"), &var); if (SUCCEEDED(hr)) { DWORD dwRid = GetRidFromVariantSid(_variant_t(var, false)); spSettings->put(GET_BSTR(DCTVS_CopiedAccount_TargetRID), static_cast(dwRid)); } } } } } else { hr = E_INVALIDARG; } return hr; } //------------------------------------------------------------------------------ // GetRidFromVariantSid Function // // Synopsis // Retrieves the final RID from a SID in variant form. // // Arguments // IN vntSid - SID as an array of bytes (this is the form received from ADSI) // // Return // The RID value if successful or zero if not. //------------------------------------------------------------------------------ DWORD __stdcall GetRidFromVariantSid(const _variant_t& vntSid) { DWORD dwRid = 0; if ((V_VT(&vntSid) == (VT_ARRAY|VT_UI1)) && vntSid.parray) { PSID pSid = (PSID)vntSid.parray->pvData; if (IsValidSid(pSid)) { PUCHAR puch = GetSidSubAuthorityCount(pSid); DWORD dwCount = static_cast(*puch); DWORD dwIndex = dwCount - 1; PDWORD pdw = GetSidSubAuthority(pSid, dwIndex); dwRid = *pdw; } } return dwRid; }