Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
17 KiB

  1. /*---------------------------------------------------------------------------
  2. File: ProcessExtensions.cpp
  3. Comments: implementation of the CProcessExtensions class.
  4. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  5. Proprietary and confidential to Mission Critical Software, Inc.
  6. REVISION LOG ENTRY
  7. Revision By: Sham Chauthani
  8. Revised on 07/02/99 12:40:00
  9. ---------------------------------------------------------------------------
  10. */
  11. #include "stdafx.h"
  12. #include "Err.hpp"
  13. #include "ErrDct.hpp"
  14. #include "workobj.h"
  15. #include "TReg.hpp"
  16. #include "ProcExts.h"
  17. #include "ResStr.h"
  18. #include "DCTStat.h"
  19. #include "TxtSid.h"
  20. #include "ARExt_i.c"
  21. //#import "\bin\AdsProp.tlb" no_namespace
  22. #import "AdsProp.tlb" no_namespace
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. const _bstr_t sKeyExtension = L"Software\\Mission Critical Software\\DomainAdmin\\Extensions";
  29. #ifdef OFA
  30. const _bstr_t sKeyBase = L"Software\\Mission Critical Software\\OnePointFileAdmin";
  31. #else
  32. const _bstr_t sKeyBase = L"Software\\Mission Critical Software\\DomainAdmin";
  33. #endif
  34. extern TErrorDct err;
  35. // Sort function for the list of interface pointers
  36. int TExtNodeSortBySequence(TNode const * t1, TNode const * t2)
  37. {
  38. TNodeInterface const * p1 = (TNodeInterface const *)t1;
  39. TNodeInterface const * p2 = (TNodeInterface const *)t2;
  40. if ( p1->GetSequence() < p2->GetSequence() )
  41. return -1;
  42. else if ( p1->GetSequence() > p2->GetSequence() )
  43. return 1;
  44. else
  45. return 0;
  46. }
  47. //////////////////////////////////////////////////////////////////////
  48. // Construction/Destruction
  49. //////////////////////////////////////////////////////////////////////
  50. //---------------------------------------------------------------------------
  51. // CONSTRUCTOR : The constructor looks up all the registered COM extensions
  52. // from the registry. For each one it creates a com object and
  53. // puts it into a list as a IExtendAccountMigration *.
  54. //---------------------------------------------------------------------------
  55. CProcessExtensions::CProcessExtensions(
  56. IVarSetPtr pVs //in -Pointer to the Varset with main settings.
  57. )
  58. {
  59. // Store the varset that has the main settings.
  60. m_pVs = pVs;
  61. _variant_t myVal;
  62. myVal = m_pVs->get(GET_BSTR(DCTVS_AREXT_NUMITEM));
  63. if ( myVal.vt != VT_I4 || myVal.lVal < 0 )
  64. {
  65. // GUI told us to run all the Extensions.
  66. // Now look through the registry to get all the registered extension object ClassIDs
  67. // for each one create a object and store the interface pointer in an array.
  68. TRegKey key;
  69. TCHAR sName[300]; // key name
  70. TCHAR sValue[300]; // value name
  71. DWORD valuelen; // value length
  72. DWORD type; // value type
  73. DWORD retval = 0; // Loop sentinel
  74. // DWORD len = 255;
  75. CLSID clsid;
  76. HRESULT hr;
  77. IExtendAccountMigration * pExtTemp;
  78. retval = 0;
  79. // Open the Extensions registry key
  80. DWORD rc = key.Open(sKeyExtension);
  81. // if no extensions then we can leave now.
  82. if ( rc != 0 ) return;
  83. valuelen = sizeof(sValue);
  84. // Go through all Name-Value pairs and try to create those objects
  85. // if successful then put it into the list to be processed.
  86. long ndx = 0;
  87. while (!retval)
  88. {
  89. retval = key.ValueEnum(ndx, sName, sizeof(sName), sValue, &valuelen, &type);
  90. if ( !retval )
  91. {
  92. // each name in here is a Object name for the class ID. we are going to use this to
  93. // Create the object and then put the IExtendAccountRepl * in the list member0
  94. ::CLSIDFromProgID(sName, &clsid);
  95. hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IExtendAccountMigration, (void **) &pExtTemp);
  96. if ( SUCCEEDED(hr) )
  97. {
  98. TNodeInterface * pNode = new TNodeInterface(pExtTemp);
  99. long num;
  100. hr = pExtTemp->get_SequenceNumber(&num);
  101. if ((pNode) && (SUCCEEDED(hr)))
  102. {
  103. pNode->SetSequence(num);
  104. }
  105. if (pNode)
  106. m_listInterface.InsertBottom(pNode);
  107. }
  108. }
  109. if ( retval == ERROR_MORE_DATA )
  110. retval = 0;
  111. ndx++;
  112. }
  113. }
  114. else
  115. {
  116. WCHAR strKey[500];
  117. _variant_t var;
  118. CLSID clsid;
  119. HRESULT hr;
  120. IExtendAccountMigration * pExtTemp;
  121. for ( int i = 0; i < myVal.lVal; i++ )
  122. {
  123. // We need to look at all the extensions that are specified and then build a list of
  124. // interfaces to it.
  125. wsprintf(strKey, GET_STRING(DCTVS_AREXTENSIONS_D), i);
  126. var = pVs->get(strKey);
  127. if ( var.vt == VT_BSTR )
  128. {
  129. // if the key is specified and it is a String then create the object and store its Iface,
  130. ::CLSIDFromProgID((WCHAR*)V_BSTR(&var), &clsid);
  131. hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IExtendAccountMigration, (void **) &pExtTemp);
  132. if ( SUCCEEDED(hr) )
  133. {
  134. TNodeInterface * pNode = new TNodeInterface(pExtTemp);
  135. if (pNode)
  136. m_listInterface.InsertBottom(pNode);
  137. }
  138. }
  139. }
  140. }
  141. m_listInterface.Sort(&TExtNodeSortBySequence);
  142. }
  143. //---------------------------------------------------------------------------
  144. // DESTRUCTOR : Clears the list of interfaces.
  145. //---------------------------------------------------------------------------
  146. CProcessExtensions::~CProcessExtensions()
  147. {
  148. TNodeInterface * pNode;
  149. TNodeInterface * tempNode;
  150. pNode = (TNodeInterface *) m_listInterface.Head();
  151. while ( pNode )
  152. {
  153. tempNode = (TNodeInterface *)pNode->Next();
  154. delete pNode;
  155. pNode = tempNode;
  156. }
  157. }
  158. //---------------------------------------------------------------------------
  159. // Process: This function is called by the account replicator for every
  160. // object that is copied. This function sets up the parameters and
  161. // for every registered extension object it calls the Process method
  162. // on that extension.
  163. //---------------------------------------------------------------------------
  164. HRESULT CProcessExtensions::Process(
  165. TAcctReplNode * pAcctNode, //in- Account replication node
  166. _bstr_t sTargetDomain, //in- Name of the target domain
  167. Options * pOptions, //in- Options as set by the user
  168. BOOL bPreMigration //in- Flag, whether to call pre or post task
  169. )
  170. {
  171. IExtendAccountMigration * pExt;
  172. TNodeInterface * pNode = NULL;
  173. HRESULT hr;
  174. IUnknown * pSUnk = NULL;
  175. IUnknown * pTUnk = NULL;
  176. IUnknown * pMain = NULL;
  177. IUnknown * pProps = NULL;
  178. IVarSetPtr pVar(__uuidof(VarSet));
  179. IObjPropBuilderPtr pProp(__uuidof(ObjPropBuilder));
  180. IADs * pSource = NULL;
  181. IADs * pTarget = NULL;
  182. _variant_t var;
  183. IDispatch * pDisp = NULL;
  184. // Get the IADs to both source and target accounts.
  185. hr = ADsGetObject(const_cast<WCHAR *>(pAcctNode->GetSourcePath()), IID_IADs, (void**) &pSource);
  186. if ( FAILED(hr))
  187. pSource = NULL;
  188. hr = ADsGetObject(const_cast<WCHAR *>(pAcctNode->GetTargetPath()), IID_IADs, (void**) &pTarget);
  189. if ( FAILED(hr))
  190. pTarget = NULL;
  191. // Get IUnknown * s to everything... Need to marshal it that way
  192. if ( pSource != NULL )
  193. pSource->QueryInterface(IID_IUnknown, (void **) &pSUnk);
  194. else
  195. pSUnk = NULL;
  196. if ( pTarget != NULL )
  197. pTarget->QueryInterface(IID_IUnknown, (void **) &pTUnk);
  198. else
  199. pTUnk = NULL;
  200. pVar->QueryInterface(IID_IUnknown, (void **) &pProps);
  201. m_pVs->QueryInterface(IID_IUnknown, (void **) &pMain);
  202. if ( pOptions->bSameForest )
  203. m_pVs->put(GET_BSTR(DCTVS_Options_IsIntraforest),GET_BSTR(IDS_YES));
  204. else
  205. m_pVs->put(GET_BSTR(DCTVS_Options_IsIntraforest),GET_BSTR(IDS_No));
  206. m_pVs->put(L"Options.SourceDomainVersion",(long)pOptions->srcDomainVer);
  207. m_pVs->put(L"Options.TargetDomainVersion",(long)pOptions->tgtDomainVer);
  208. // AccountNode into the Varset.
  209. PutAccountNodeInVarset(pAcctNode, pTarget, m_pVs);
  210. // Put the DB manager into the Varset
  211. pOptions->pDb->QueryInterface(IID_IDispatch, (void**)&pDisp);
  212. var.vt = VT_DISPATCH;
  213. var.pdispVal = pDisp;
  214. m_pVs->putObject(GET_BSTR(DCTVS_DBManager), var);
  215. // Call the Process Object method on all registered objects.that we created
  216. pNode = (TNodeInterface *) m_listInterface.Head();
  217. while ( pNode )
  218. {
  219. try
  220. {
  221. if ( pOptions->pStatus )
  222. {
  223. LONG status = 0;
  224. HRESULT hr = pOptions->pStatus->get_Status(&status);
  225. if ( SUCCEEDED(hr) && status == DCT_STATUS_ABORTING )
  226. break;
  227. }
  228. pExt = pNode->GetInterface();
  229. if ( pOptions->bUndo )
  230. {
  231. hr = pExt->ProcessUndo(pSUnk, pTUnk, pMain, &pProps);
  232. }
  233. else
  234. {
  235. BSTR sName;
  236. pExt->get_sName(&sName);
  237. if ( bPreMigration )
  238. {
  239. hr = pExt->PreProcessObject(pSUnk, pTUnk, pMain, &pProps);
  240. if (hr == ERROR_OBJECT_ALREADY_EXISTS)
  241. pAcctNode->SetHr(hr);
  242. }
  243. else
  244. {
  245. /* we need to run the DisAcct extension last, so don't run it in this loop
  246. run it in the next loop by itself */
  247. //if not DisAcct extension, process this extension
  248. if (wcscmp((WCHAR*)sName, L"Disable Accounts"))
  249. hr = pExt->ProcessObject(pSUnk, pTUnk, pMain, &pProps);
  250. }
  251. }
  252. }
  253. catch (...)
  254. {
  255. BSTR sName;
  256. pExt->get_sName(&sName);
  257. err.LogOpen(pOptions->logFile,1);
  258. err.MsgWrite(ErrE, DCT_MSG_Extension_Exception_SS, (WCHAR*) sName, pAcctNode->GetTargetName());
  259. err.LogClose();
  260. hr = S_OK;
  261. }
  262. pNode = (TNodeInterface *)pNode->Next();
  263. }
  264. /* now run the DisAcct extension here to ensure it is run last, if not undo or premigration */
  265. if ((!pOptions->bUndo) && (!bPreMigration))
  266. {
  267. bool bDone = false;
  268. pNode = (TNodeInterface *) m_listInterface.Head();
  269. while ((pNode) && (!bDone))
  270. {
  271. try
  272. {
  273. if ( pOptions->pStatus )
  274. {
  275. LONG status = 0;
  276. HRESULT hr = pOptions->pStatus->get_Status(&status);
  277. if ( SUCCEEDED(hr) && status == DCT_STATUS_ABORTING )
  278. break;
  279. }
  280. pExt = pNode->GetInterface();
  281. BSTR sName;
  282. pExt->get_sName(&sName);
  283. if (!wcscmp((WCHAR*)sName, L"Disable Accounts"))
  284. {
  285. bDone = true;
  286. hr = pExt->ProcessObject(pSUnk, pTUnk, pMain, &pProps);
  287. }
  288. }
  289. catch (...)
  290. {
  291. BSTR sName;
  292. pExt->get_sName(&sName);
  293. err.LogOpen(pOptions->logFile,1);
  294. err.MsgWrite(ErrE, DCT_MSG_Extension_Exception_SS, (WCHAR*) sName, pAcctNode->GetTargetName());
  295. err.LogClose();
  296. hr = S_OK;
  297. }
  298. pNode = (TNodeInterface *)pNode->Next();
  299. }//end while not done and more
  300. }//end if not undo or premigration
  301. // Now we have the varset with all the settings that the user wants us to set.
  302. // So we can call the SetPropsFromVarset method in out GetProps object to set these
  303. // properties.
  304. hr = pProp->SetPropertiesFromVarset(pAcctNode->GetTargetPath(), /*sTargetDomain,*/ pProps, ADS_ATTR_UPDATE);
  305. // Update the AccountNode with any changes made by the extensions
  306. UpdateAccountNodeFromVarset(pAcctNode, pTarget, m_pVs);
  307. // Cleanup time ...
  308. if ( pSUnk ) pSUnk->Release();
  309. if ( pTUnk ) pTUnk->Release();
  310. if ( pProps ) pProps->Release();
  311. if ( pMain ) pMain->Release();
  312. if ( pSource ) pSource->Release();
  313. if ( pTarget ) pTarget->Release();
  314. return hr;
  315. }
  316. //---------------------------------------------------------------------------
  317. // PutAccountNodeInVarset : Transfers all the account node info into the
  318. // varset.
  319. //---------------------------------------------------------------------------
  320. void CProcessExtensions::PutAccountNodeInVarset(
  321. TAcctReplNode *pNode, //in -Replicated account node to get info
  322. IADs * pTarget, //in -IADs pointer to the target object for the GUID
  323. IVarSet * pVS //out-Varset to put the information in
  324. )
  325. {
  326. _variant_t var = L"";
  327. BSTR sGUID;
  328. DWORD lVal = 0;
  329. HRESULT hr;
  330. WCHAR strSid[MAX_PATH];
  331. DWORD lenStrSid = DIM(strSid);
  332. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceName),pNode->GetName());
  333. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourcePath),pNode->GetSourcePath());
  334. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceProfile),pNode->GetSourceProfile());
  335. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceRID),(long)pNode->GetSourceRid());
  336. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceSam),pNode->GetSourceSam());
  337. pVS->put(GET_WSTR(DCTVS_CopiedAccount_Status),(long)pNode->GetStatus());
  338. pVS->put(GET_WSTR(DCTVS_CopiedAccount_TargetName),pNode->GetTargetName());
  339. pVS->put(GET_WSTR(DCTVS_CopiedAccount_TargetPath),pNode->GetTargetPath());
  340. pVS->put(GET_WSTR(DCTVS_CopiedAccount_TargetProfile),pNode->GetTargetProfile());
  341. pVS->put(GET_WSTR(DCTVS_CopiedAccount_TargetRID),(long)pNode->GetTargetRid());
  342. pVS->put(GET_WSTR(DCTVS_CopiedAccount_TargetSam),pNode->GetTargetSam());
  343. pVS->put(GET_WSTR(DCTVS_CopiedAccount_Type),pNode->GetType());
  344. pVS->put(GET_WSTR(DCTVS_CopiedAccount_Operations),(long)pNode->operations);
  345. pVS->put(GET_WSTR(DCTVS_CopiedAccount_ExpDate),pNode->lExpDate);
  346. pVS->put(GET_WSTR(DCTVS_CopiedAccount_UserFlags), pNode->lFlags);
  347. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceUPN),pNode->GetSourceUPN());
  348. GetTextualSid(pNode->GetSourceSid(),strSid,&lenStrSid);
  349. pVS->put(GET_WSTR(DCTVS_CopiedAccount_SourceDomainSid),strSid);
  350. // Get the GUID
  351. if ( pTarget )
  352. {
  353. hr = pTarget->get_GUID(&sGUID);
  354. if ( SUCCEEDED(hr) )
  355. {
  356. var = sGUID;
  357. SysFreeString(sGUID);
  358. }
  359. }
  360. pVS->put(GET_WSTR(DCTVS_CopiedAccount_GUID), var);
  361. // Get the status
  362. lVal = pNode->GetStatus();
  363. var.Clear();
  364. var.vt = VT_UI4;
  365. var.lVal = lVal;
  366. pVS->put(GET_WSTR(DCTVS_CopiedAccount_Status), var);
  367. }
  368. //---------------------------------------------------------------------------
  369. // UpdateAccountNodeFromVarset : Updates the account node info with the data in the Transfers all the account node info into the
  370. // varset.
  371. //---------------------------------------------------------------------------
  372. void CProcessExtensions::UpdateAccountNodeFromVarset(
  373. TAcctReplNode *pNode, //in -Replicated account node to get info
  374. IADs * pTarget, //in -IADs pointer to the target object for the GUID
  375. IVarSet * pVS //out-Varset to put the information in
  376. )
  377. {
  378. _variant_t var = L"";
  379. DWORD lVal = 0;
  380. _bstr_t text;
  381. long val;
  382. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourceName));
  383. pNode->SetName(text);
  384. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourcePath));
  385. pNode->SetSourcePath(text);
  386. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourceProfile));
  387. pNode->SetSourceProfile(text);
  388. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourceRID));
  389. pNode->SetSourceRid(val);
  390. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourceSam));
  391. pNode->SetSourceSam(text);
  392. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_Status));
  393. pNode->SetStatus(val);
  394. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_TargetName));
  395. pNode->SetTargetName(text);
  396. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_TargetPath));
  397. pNode->SetTargetPath(text);
  398. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_TargetProfile));
  399. pNode->SetTargetProfile(text);
  400. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_TargetRID));
  401. pNode->SetTargetRid(val);
  402. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_TargetSam));
  403. pNode->SetTargetSam(text);
  404. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_Type));
  405. pNode->SetType(text);
  406. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_Operations));
  407. pNode->operations = val;
  408. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_ExpDate));
  409. pNode->lExpDate = val;
  410. val = pVS->get(GET_WSTR(DCTVS_CopiedAccount_UserFlags));
  411. pNode->lFlags = val;
  412. text = pVS->get(GET_WSTR(DCTVS_CopiedAccount_SourceDomainSid));
  413. pNode->SetSourceSid(SidFromString((WCHAR*)text));
  414. }