Leaked source code of windows server 2003
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.

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