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.

5269 lines
186 KiB

  1. /*---------------------------------------------------------------------------
  2. File: MgeDB.cpp
  3. Comments: Implementation of DBManager COM object.
  4. This is interface that the Domain Migrator uses to communicate to the
  5. Database (PROTAR.MDB). This interface allows Domain Migrator to Save and
  6. later retrieve information/Setting to run the Migration process.
  7. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  8. Proprietary and confidential to Mission Critical Software, Inc.
  9. REVISION LOG ENTRY
  10. Revision By: Sham Chauthani
  11. Revised on 07/02/99 12:40:00
  12. ---------------------------------------------------------------------------
  13. */
  14. #include "stdafx.h"
  15. #include "mcs.h"
  16. #include "ErrDct.hpp"
  17. #include "DBMgr.h"
  18. #include "MgeDB.h"
  19. #include <share.h>
  20. #include <comdef.h>
  21. #include <lm.h>
  22. #include "UString.hpp"
  23. #include "TxtSid.h"
  24. #include "LSAUtils.h"
  25. #include "HrMsg.h"
  26. #include "StringConversion.h"
  27. #include <GetDcName.h>
  28. #include <iads.h>
  29. #include <adshlp.h>
  30. #import "msado21.tlb" no_namespace implementation_only rename("EOF", "EndOfFile")
  31. #import "msadox.dll" implementation_only exclude("DataTypeEnum")
  32. //#import <msjro.dll> no_namespace implementation_only
  33. #include <msjro.tlh>
  34. #include <msjro.tli>
  35. #ifdef _DEBUG
  36. #define new DEBUG_NEW
  37. #undef THIS_FILE
  38. static char THIS_FILE[] = __FILE__;
  39. #endif
  40. TErrorDct err;
  41. using namespace _com_util;
  42. #define MAX_BUF_LEN 255
  43. #ifndef JET_DATABASELOCKMODE_PAGE
  44. #define JET_DATABASELOCKMODE_PAGE 0
  45. #endif
  46. #ifndef JET_DATABASELOCKMODE_ROW
  47. #define JET_DATABASELOCKMODE_ROW 1
  48. #endif
  49. #ifndef JETDBENGINETYPE_JET4X
  50. #define JETDBENGINETYPE_JET4X 0x05 // from MSJetOleDb.h
  51. #endif
  52. StringLoader gString;
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CIManageDB
  55. TError dct;
  56. TError& errCommon = dct;
  57. //----------------------------------------------------------------------------
  58. // Constructor / Destructor
  59. //----------------------------------------------------------------------------
  60. CIManageDB::CIManageDB()
  61. {
  62. }
  63. CIManageDB::~CIManageDB()
  64. {
  65. }
  66. //----------------------------------------------------------------------------
  67. // FinalConstruct
  68. //----------------------------------------------------------------------------
  69. HRESULT CIManageDB::FinalConstruct()
  70. {
  71. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  72. HRESULT hr = S_OK;
  73. try
  74. {
  75. _bstr_t sMissing(L"");
  76. _bstr_t sUser(L"Admin");
  77. WCHAR sConnect[LEN_Path];
  78. WCHAR sDir[LEN_Path];
  79. // Get the path to the MDB file from the registry
  80. TRegKey key;
  81. DWORD rc = key.Open(sKeyBase);
  82. if ( !rc )
  83. rc = key.ValueGetStr(L"Directory", sDir, LEN_Path);
  84. if (rc)
  85. {
  86. CString errMsg;
  87. hr = HRESULT_FROM_WIN32(rc);
  88. errMsg.Format(IDS_E_CANNOT_FIND_DATABASE, _com_error(hr).ErrorMessage());
  89. return Error((LPCTSTR)errMsg, GUID_NULL, hr);
  90. }
  91. // Now build the connect string.
  92. //
  93. // Set page level locking to reduce the probability of exceeding
  94. // the maximum locks per file limit. ADMT does not require row
  95. // level locking as there is effectively only one updater.
  96. //
  97. _snwprintf(
  98. sConnect,
  99. sizeof(sConnect) / sizeof(sConnect[0]),
  100. L"Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Database Locking Mode=%d;Data Source=%sprotar.mdb",
  101. JET_DATABASELOCKMODE_PAGE,
  102. sDir
  103. );
  104. sConnect[sizeof(sConnect) / sizeof(sConnect[0]) - 1] = L'\0';
  105. CheckError(m_cn.CreateInstance(__uuidof(Connection)));
  106. m_cn->Open(sConnect, sUser, sMissing, adConnectUnspecified);
  107. m_vtConn = (IDispatch *) m_cn;
  108. // if necessary, upgrade database to 4.x
  109. long lEngineType = m_cn->Properties->Item[_T("Jet OLEDB:Engine Type")]->Value;
  110. if (lEngineType < JETDBENGINETYPE_JET4X)
  111. {
  112. m_cn->Close();
  113. UpgradeDatabase(sDir);
  114. m_cn->Open(sConnect, sUser, sMissing, adConnectUnspecified);
  115. }
  116. //
  117. // If necessary, widen columns containing domain and server names in order to support DNS names.
  118. //
  119. // This change is required in order to be NetBIOS-less compliant.
  120. //
  121. UpdateDomainAndServerColumnWidths(m_cn);
  122. //
  123. // Create the Settings2 table if it does not already exist.
  124. //
  125. CreateSettings2Table(m_cn);
  126. reportStruct * prs = NULL;
  127. _variant_t var;
  128. // Migrated accounts report information
  129. CheckError(m_pQueryMapping.CreateInstance(__uuidof(VarSet)));
  130. m_pQueryMapping->put(L"MigratedAccounts", L"Select SourceDomain, TargetDomain, Type, SourceAdsPath, TargetAdsPath from MigratedObjects where Type <> 'computer' order by time");
  131. prs = new reportStruct();
  132. if (!prs)
  133. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  134. prs->sReportName = GET_BSTR(IDS_REPORT_MigratedAccounts);
  135. prs->arReportFields[0] = GET_BSTR(IDS_TABLE_FIELD_SourceDomain);
  136. prs->arReportSize[0] = 10;
  137. prs->arReportFields[1] = GET_BSTR(IDS_TABLE_FIELD_TargetDomain);
  138. prs->arReportSize[1] = 10;
  139. prs->arReportFields[2] = GET_BSTR(IDS_TABLE_FIELD_Type);
  140. prs->arReportSize[2] = 10;
  141. prs->arReportFields[3] = GET_BSTR(IDS_TABLE_FIELD_SourceAdsPath);
  142. prs->arReportSize[3] = 35;
  143. prs->arReportFields[4] = GET_BSTR(IDS_TABLE_FIELD_TargetAdsPath);
  144. prs->arReportSize[4] = 35;
  145. prs->colsFilled = 5;
  146. var.vt = VT_BYREF | VT_UI1;
  147. var.pbVal = (unsigned char *)prs;
  148. m_pQueryMapping->putObject(L"MigratedAccounts.DispInfo", var);
  149. // Migrated computers report information
  150. m_pQueryMapping->put(L"MigratedComputers", L"Select SourceDomain, TargetDomain, Type, SourceAdsPath, TargetAdsPath from MigratedObjects where Type = 'computer' order by time");
  151. prs = new reportStruct();
  152. if (!prs)
  153. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  154. prs->sReportName = GET_BSTR(IDS_REPORT_MigratedComputers);
  155. prs->arReportFields[0] = GET_BSTR(IDS_TABLE_FIELD_SourceDomain);
  156. prs->arReportSize[0] = 10;
  157. prs->arReportFields[1] = GET_BSTR(IDS_TABLE_FIELD_TargetDomain);
  158. prs->arReportSize[1] = 10;
  159. prs->arReportFields[2] = GET_BSTR(IDS_TABLE_FIELD_Type);
  160. prs->arReportSize[2] = 10;
  161. prs->arReportFields[3] = GET_BSTR(IDS_TABLE_FIELD_SourceAdsPath);
  162. prs->arReportSize[3] = 35;
  163. prs->arReportFields[4] = GET_BSTR(IDS_TABLE_FIELD_TargetAdsPath);
  164. prs->arReportSize[4] = 35;
  165. prs->colsFilled = 5;
  166. var.vt = VT_BYREF | VT_UI1;
  167. var.pbVal = (unsigned char *)prs;
  168. m_pQueryMapping->putObject(L"MigratedComputers.DispInfo", var);
  169. // Expired computers report information
  170. prs = new reportStruct();
  171. if (!prs)
  172. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  173. prs->sReportName = GET_BSTR(IDS_REPORT_ExpiredComputers);
  174. prs->arReportFields[0] = GET_BSTR(IDS_TABLE_FIELD_Time);
  175. prs->arReportSize[0] = 20;
  176. prs->arReportFields[1] = GET_BSTR(IDS_TABLE_FIELD_DomainName);
  177. prs->arReportSize[1] = 15;
  178. prs->arReportFields[2] = GET_BSTR(IDS_TABLE_FIELD_CompName);
  179. prs->arReportSize[2] = 15;
  180. prs->arReportFields[3] = GET_BSTR(IDS_TABLE_FIELD_Description);
  181. prs->arReportSize[3] = 35;
  182. prs->arReportFields[4] = GET_BSTR(IDS_TABLE_FIELD_PwdAge);
  183. prs->arReportSize[4] = 15;
  184. prs->colsFilled = 5;
  185. var.vt = VT_BYREF | VT_UI1;
  186. var.pbVal = (unsigned char *)prs;
  187. m_pQueryMapping->putObject(L"ExpiredComputers.DispInfo", var);
  188. // Account reference report informaiton.
  189. m_pQueryMapping->put(L"AccountReferences", L"Select DomainName, Account, AccountSid, Server, RefCount as '# of Ref', RefType As ReferenceType from AccountRefs where RefCount > 0 order by DomainName, Account, Server");
  190. prs = new reportStruct();
  191. if (!prs)
  192. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  193. prs->sReportName = GET_BSTR(IDS_REPORT_AccountReferences);
  194. prs->arReportFields[0] = GET_BSTR(IDS_TABLE_FIELD_DomainName);
  195. prs->arReportSize[0] = 15;
  196. prs->arReportFields[1] = GET_BSTR(IDS_TABLE_FIELD_Account);
  197. prs->arReportSize[1] = 20;
  198. prs->arReportFields[2] = GET_BSTR(IDS_TABLE_FIELD_AccountSid);
  199. prs->arReportSize[2] = 25;
  200. prs->arReportFields[3] = GET_BSTR(IDS_TABLE_FIELD_Server);
  201. prs->arReportSize[3] = 15;
  202. prs->arReportFields[4] = GET_BSTR(IDS_TABLE_FIELD_RefCount);
  203. prs->arReportSize[4] = 10;
  204. prs->arReportFields[5] = GET_BSTR(IDS_TABLE_FIELD_RefType);
  205. prs->arReportSize[5] = 15;
  206. prs->colsFilled = 6;
  207. var.vt = VT_BYREF | VT_UI1;
  208. var.pbVal = (unsigned char *)prs;
  209. m_pQueryMapping->putObject(L"AccountReferences.DispInfo", var);
  210. // Name conflict report information
  211. m_pQueryMapping->put(L"NameConflicts",
  212. L"SELECT"
  213. L" SourceAccounts.Name,"
  214. L" SourceAccounts.RDN,"
  215. L" SourceAccounts.Type,"
  216. L" TargetAccounts.Type,"
  217. L" IIf(SourceAccounts.Name=TargetAccounts.Name,'" +
  218. GET_BSTR(IDS_TABLE_SAM_CONFLICT_VALUE) +
  219. L"','') +"
  220. L" IIf(SourceAccounts.Name=TargetAccounts.Name And SourceAccounts.RDN=TargetAccounts.RDN,',','') +"
  221. L" IIf(SourceAccounts.RDN=TargetAccounts.RDN,'" +
  222. GET_BSTR(IDS_TABLE_RDN_CONFLICT_VALUE) +
  223. L"',''),"
  224. L" TargetAccounts.[Canonical Name] "
  225. L"FROM SourceAccounts, TargetAccounts "
  226. L"WHERE"
  227. L" SourceAccounts.Name=TargetAccounts.Name OR SourceAccounts.RDN=TargetAccounts.RDN "
  228. L"ORDER BY"
  229. L" SourceAccounts.Name, TargetAccounts.Name");
  230. // m_pQueryMapping->put(L"NameConflicts", L"SELECT SourceAccounts.Name as AccountName, SourceAccounts.Type as SourceType, TargetAccounts.Type as TargetType, SourceAccounts.Description as \
  231. // SourceDescription, TargetAccounts.Description as TargetDescription, SourceAccounts.FullName as SourceFullName, TargetAccounts.FullName as TargetFullName \
  232. // FROM SourceAccounts, TargetAccounts WHERE (((SourceAccounts.Name)=[TargetAccounts].[Name])) ORDER BY SourceAccounts.Name");
  233. prs = new reportStruct();
  234. if (!prs)
  235. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  236. prs->sReportName = GET_BSTR(IDS_REPORT_NameConflicts);
  237. prs->arReportFields[0] = GET_BSTR(IDS_TABLE_FIELD_Account);
  238. prs->arReportSize[0] = 20;
  239. prs->arReportFields[1] = GET_BSTR(IDS_TABLE_FIELD_SourceRDN);
  240. prs->arReportSize[1] = 20;
  241. prs->arReportFields[2] = GET_BSTR(IDS_TABLE_FIELD_SourceType);
  242. prs->arReportSize[2] = 10;
  243. prs->arReportFields[3] = GET_BSTR(IDS_TABLE_FIELD_TargetType);
  244. prs->arReportSize[3] = 10;
  245. prs->arReportFields[4] = GET_BSTR(IDS_TABLE_FIELD_ConflictAtt);
  246. prs->arReportSize[4] = 15;
  247. prs->arReportFields[5] = GET_BSTR(IDS_TABLE_FIELD_TargetCanonicalName);
  248. prs->arReportSize[5] = 25;
  249. prs->colsFilled = 6;
  250. var.vt = VT_BYREF | VT_UI1;
  251. var.pbVal = (unsigned char *)prs;
  252. m_pQueryMapping->putObject(L"NameConflicts.DispInfo", var);
  253. // we will handle the cleanup ourselves.
  254. VariantInit(&var);
  255. CheckError(m_rsAccounts.CreateInstance(__uuidof(Recordset)));
  256. }
  257. catch (_com_error& ce)
  258. {
  259. hr = Error((LPCOLESTR)ce.Description(), ce.GUID(), ce.Error());
  260. }
  261. catch (...)
  262. {
  263. hr = E_FAIL;
  264. }
  265. return hr;
  266. }
  267. //----------------------------------------------------------------------------
  268. // FinalRelease
  269. //----------------------------------------------------------------------------
  270. void CIManageDB::FinalRelease()
  271. {
  272. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  273. try
  274. {
  275. if (m_rsAccounts)
  276. {
  277. m_rsAccounts.Release();
  278. }
  279. if (m_pQueryMapping)
  280. {
  281. // we need to cleanup all the reportStruct objects.
  282. _variant_t var;
  283. reportStruct * pRs;
  284. // Cleanup the MigratedAccounts information
  285. var = m_pQueryMapping->get(L"MigratedAccounts.DispInfo");
  286. if ( var.vt == (VT_BYREF | VT_UI1) )
  287. {
  288. pRs = (reportStruct*) var.pbVal;
  289. delete pRs;
  290. }
  291. // Cleanup the MigratedComputers information
  292. var = m_pQueryMapping->get(L"MigratedComputers.DispInfo");
  293. if ( var.vt == (VT_BYREF | VT_UI1) )
  294. {
  295. pRs = (reportStruct*)var.pbVal;
  296. delete pRs;
  297. }
  298. // Cleanup the ExpiredComputers information
  299. var = m_pQueryMapping->get(L"ExpiredComputers.DispInfo");
  300. if ( var.vt == (VT_BYREF | VT_UI1) )
  301. {
  302. pRs = (reportStruct*)var.pbVal;
  303. delete pRs;
  304. }
  305. // Cleanup the AccountReferences information
  306. var = m_pQueryMapping->get(L"AccountReferences.DispInfo");
  307. if ( var.vt == (VT_BYREF | VT_UI1) )
  308. {
  309. pRs = (reportStruct*)var.pbVal;
  310. delete pRs;
  311. }
  312. // Cleanup the NameConflicts information
  313. var = m_pQueryMapping->get(L"NameConflicts.DispInfo");
  314. if ( var.vt == (VT_BYREF | VT_UI1) )
  315. {
  316. pRs = (reportStruct*)var.pbVal;
  317. delete pRs;
  318. }
  319. m_pQueryMapping.Release();
  320. }
  321. if (m_cn)
  322. {
  323. m_cn.Release();
  324. }
  325. }
  326. catch (...)
  327. {
  328. //eat it
  329. }
  330. }
  331. //---------------------------------------------------------------------------------------------
  332. // SetVarsetToDB : Saves a varset into the table identified as sTableName. ActionID is also
  333. // stored if one is provided.
  334. //---------------------------------------------------------------------------------------------
  335. STDMETHODIMP CIManageDB::SetVarsetToDB(IUnknown *pUnk, BSTR sTableName, VARIANT ActionID)
  336. {
  337. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  338. HRESULT hr = S_OK;
  339. try
  340. {
  341. IVarSetPtr pVSIn = pUnk;
  342. IVarSetPtr pVS(__uuidof(VarSet));
  343. IEnumVARIANTPtr varEnum;
  344. _bstr_t keyName;
  345. _variant_t value;
  346. _variant_t varKey;
  347. _variant_t vTable = sTableName;
  348. _variant_t vtConn;
  349. _variant_t varAction;
  350. DWORD nGot = 0;
  351. long lActionID;
  352. pVS->ImportSubTree(L"", pVSIn);
  353. ClipVarset(pVS);
  354. if (ActionID.vt == VT_I4)
  355. lActionID = ActionID.lVal;
  356. else
  357. lActionID = -1;
  358. // Open the recordset object.
  359. _RecordsetPtr rs(__uuidof(Recordset));
  360. rs->Open(vTable, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  361. // we are now going to enumerate through the varset and put the values into the DB
  362. // Get the IEnumVARIANT pointer to enumerate
  363. varEnum = pVS->_NewEnum;
  364. if (varEnum)
  365. {
  366. value.vt = VT_EMPTY;
  367. // For each value in the varset get the property name and put it into the
  368. // database with the string representation of its value with its type.
  369. while ( (hr = varEnum->Next(1,&varKey,&nGot)) == S_OK )
  370. {
  371. if ( nGot > 0 )
  372. {
  373. keyName = V_BSTR(&varKey);
  374. value = pVS->get(keyName);
  375. rs->AddNew();
  376. if ( lActionID > -1 )
  377. {
  378. // This is going to be actionID information
  379. // So lets put in the actionID in the database.
  380. varAction.vt = VT_I4;
  381. varAction.lVal = lActionID;
  382. rs->Fields->GetItem(L"ActionID")->Value = varAction;
  383. }
  384. rs->Fields->GetItem(L"Property")->Value = keyName;
  385. hr = PutVariantInDB(rs, value);
  386. rs->Update();
  387. if (FAILED(hr))
  388. _com_issue_errorex(hr, pVS, __uuidof(VarSet));
  389. }
  390. }
  391. varEnum.Release();
  392. }
  393. // Cleanup
  394. rs->Close();
  395. }
  396. catch (_com_error& ce)
  397. {
  398. hr = ce.Error();
  399. }
  400. catch (...)
  401. {
  402. hr = E_FAIL;
  403. }
  404. return hr;
  405. }
  406. //---------------------------------------------------------------------------------------------
  407. // PutVariantInDB : Stores a variant into a DB table by decoding it.
  408. //---------------------------------------------------------------------------------------------
  409. HRESULT CIManageDB::PutVariantInDB(_RecordsetPtr pRs, _variant_t val)
  410. {
  411. // This function puts the value passed as a variant into the current record of the recordset
  412. // It updates the VarType and the Value fields of the given property
  413. _variant_t varType; // Numeric value for the type of value
  414. _variant_t varVal; // String representation of the value field
  415. WCHAR strTemp[255];
  416. varType.vt = VT_UI4;
  417. varType.lVal = val.vt;
  418. switch ( val.vt )
  419. {
  420. case VT_BSTR : varVal = val;
  421. break;
  422. case VT_UI4 : wsprintf(strTemp, L"%d", val.lVal);
  423. varVal = strTemp;
  424. break;
  425. case VT_I4 : wsprintf(strTemp, L"%d", val.lVal);
  426. varVal = strTemp;
  427. break;
  428. case VT_EMPTY : break;
  429. case VT_NULL: break;
  430. default : MCSASSERT(FALSE); // What ever this type is we are not supporting it
  431. // so put the support in for this.
  432. return E_INVALIDARG;
  433. }
  434. pRs->Fields->GetItem(L"VarType")->Value = varType;
  435. pRs->Fields->GetItem(L"Value")->Value = varVal;
  436. return S_OK;
  437. }
  438. //---------------------------------------------------------------------------------------------
  439. // ClearTable : Deletes a table indicated by sTableName and applies a filter if provided.
  440. //---------------------------------------------------------------------------------------------
  441. STDMETHODIMP CIManageDB::ClearTable(BSTR sTableName, VARIANT Filter)
  442. {
  443. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  444. HRESULT hr = S_OK;
  445. try
  446. {
  447. // Build a SQL string to Clear the table.
  448. WCHAR sSQL[2000];
  449. WCHAR sFilter[2000];
  450. _variant_t varSQL;
  451. if (Filter.vt == VT_BSTR)
  452. wcscpy(sFilter, (WCHAR*)Filter.bstrVal);
  453. else
  454. wcscpy(sFilter, L"");
  455. wsprintf(sSQL, L"Delete from %s", sTableName);
  456. if ( wcslen(sFilter) > 0 )
  457. {
  458. wcscat(sSQL, L" where ");
  459. wcscat(sSQL, sFilter);
  460. }
  461. varSQL = sSQL;
  462. _RecordsetPtr pRs(__uuidof(Recordset));
  463. pRs->Open(varSQL, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  464. }
  465. catch (_com_error& ce)
  466. {
  467. hr = ce.Error();
  468. }
  469. catch (...)
  470. {
  471. hr = E_FAIL;
  472. }
  473. return hr;
  474. }
  475. //---------------------------------------------------------------------------------------------
  476. // SaveSettings : This method saves the GUI setting varset into the Settings table.
  477. //---------------------------------------------------------------------------------------------
  478. STDMETHODIMP CIManageDB::SaveSettings(IUnknown *pUnk)
  479. {
  480. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  481. HRESULT hr = S_OK;
  482. try
  483. {
  484. //
  485. // Update excluded system properties.
  486. //
  487. IVarSetPtr spVarSet(pUnk);
  488. _variant_t vntSystemExclude = spVarSet->get(_T("AccountOptions.ExcludedSystemProps"));
  489. if (V_VT(&vntSystemExclude) != VT_EMPTY)
  490. {
  491. _CommandPtr spCommand(__uuidof(Command));
  492. spCommand->ActiveConnection = m_cn;
  493. spCommand->CommandType = adCmdText;
  494. spCommand->CommandText =
  495. _T("PARAMETERS A Text; ")
  496. _T("UPDATE Settings2 SET [Value]=[A] WHERE [Property]='AccountOptions.ExcludedSystemProps';");
  497. ParametersPtr spParameters = spCommand->Parameters;
  498. spParameters->Append(spCommand->CreateParameter(L"A", adBSTR, adParamInput, 65535L, vntSystemExclude));
  499. VARIANT varRecordsAffected;
  500. VariantInit(&varRecordsAffected);
  501. spCommand->Execute(&varRecordsAffected, NULL, adExecuteNoRecords);
  502. //
  503. // If the record does not exist then insert a new record.
  504. //
  505. if ((V_VT(&varRecordsAffected) == VT_I4) && (V_I4(&varRecordsAffected) == 0))
  506. {
  507. spCommand->CommandText =
  508. _T("PARAMETERS A Text; ")
  509. _T("INSERT INTO Settings2 (Property, VarType, [Value]) ")
  510. _T("VALUES ('AccountOptions.ExcludedSystemProps', 8, [A]);");
  511. spCommand->Execute(NULL, NULL, adExecuteNoRecords);
  512. }
  513. spVarSet->put(_T("AccountOptions.ExcludedSystemProps"), _variant_t());
  514. //
  515. // Set value of AccountOptions.ExcludedSystemPropsSet to 1 which
  516. // indicates that the excluded system properties has been set.
  517. //
  518. m_cn->Execute(
  519. _T("UPDATE Settings2 SET [Value]='1' ")
  520. _T("WHERE [Property]='AccountOptions.ExcludedSystemPropsSet';"),
  521. &varRecordsAffected,
  522. adCmdText|adExecuteNoRecords
  523. );
  524. if ((V_VT(&varRecordsAffected) == VT_I4) && (V_I4(&varRecordsAffected) == 0))
  525. {
  526. m_cn->Execute(
  527. _T("INSERT INTO Settings2 (Property, VarType, [Value]) ")
  528. _T("VALUES ('AccountOptions.ExcludedSystemPropsSet', 3, '1');"),
  529. NULL,
  530. adCmdText|adExecuteNoRecords
  531. );
  532. }
  533. }
  534. //
  535. // The last generated report times are persisted in the Settings table and therefore
  536. // must be retrieved and re-stored. Note that an old persisted value is only added to the
  537. // current migration task VarSet if the VarSet does not already define the report time.
  538. //
  539. const _TCHAR szReportTimesQuery[] =
  540. _T("SELECT Property, Value FROM Settings WHERE Property LIKE 'Reports.%.TimeGenerated'");
  541. _RecordsetPtr rsReportTimes = m_cn->Execute(szReportTimesQuery, &_variant_t(), adCmdText);
  542. FieldsPtr spFields = rsReportTimes->Fields;
  543. while (rsReportTimes->EndOfFile == VARIANT_FALSE)
  544. {
  545. // Retrieve property name and retrieve corresponding value from VarSet.
  546. _bstr_t strProperty = spFields->Item[0L]->Value;
  547. _variant_t vntValue = spVarSet->get(strProperty);
  548. // If the value returned from the VarSet is empty then the value is not
  549. // defined therefore add value retrieved from settings table to VarSet.
  550. if (V_VT(&vntValue) == VT_EMPTY)
  551. {
  552. vntValue = spFields->Item[1L]->Value;
  553. spVarSet->put(strProperty, vntValue);
  554. }
  555. rsReportTimes->MoveNext();
  556. }
  557. // delete previous settings
  558. CheckError(ClearTable(_T("Settings")));
  559. // insert updated settings
  560. CheckError(SetVarsetToDB(pUnk, _T("Settings")));
  561. }
  562. catch (_com_error& ce)
  563. {
  564. hr = ce.Error();
  565. }
  566. catch (...)
  567. {
  568. hr = E_FAIL;
  569. }
  570. return hr;
  571. }
  572. //---------------------------------------------------------------------------------------------
  573. // GetVarFromDB : Retrieves a variant from the DB table by encoding it.
  574. //---------------------------------------------------------------------------------------------
  575. HRESULT CIManageDB::GetVarFromDB(_RecordsetPtr pRec, _variant_t& val)
  576. {
  577. HRESULT hr = S_OK;
  578. try
  579. {
  580. // retrieve data type
  581. VARTYPE vt = VARTYPE(long(pRec->Fields->GetItem(L"VarType")->Value));
  582. // if data type is empty or null...
  583. if ((vt == VT_EMPTY) || (vt == VT_NULL))
  584. {
  585. // then clear value
  586. val.Clear();
  587. }
  588. else
  589. {
  590. // otherwise retrieve value and convert to given data type
  591. _variant_t vntValue = pRec->Fields->GetItem(L"Value")->Value;
  592. val.ChangeType(vt, &vntValue);
  593. }
  594. }
  595. catch (_com_error& ce)
  596. {
  597. hr = ce.Error();
  598. }
  599. catch (...)
  600. {
  601. hr = E_FAIL;
  602. }
  603. return hr;
  604. }
  605. //---------------------------------------------------------------------------------------------
  606. // GetVarsetFromDB : Retrieves a varset from the specified table. and fills the argument
  607. //---------------------------------------------------------------------------------------------
  608. STDMETHODIMP CIManageDB::GetVarsetFromDB(BSTR sTable, IUnknown **ppVarset, VARIANT ActionID)
  609. {
  610. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  611. HRESULT hr = S_OK;
  612. try
  613. {
  614. IVarSetPtr pVS = *ppVarset;
  615. _bstr_t sKeyName;
  616. _variant_t val;
  617. _variant_t varQuery;
  618. WCHAR sQuery[1000];
  619. long lActionID;
  620. if (ActionID.vt == VT_I4)
  621. lActionID = ActionID.lVal;
  622. else
  623. lActionID = -1;
  624. if ( lActionID == -1 )
  625. wsprintf(sQuery, L"Select * from %s", sTable);
  626. else
  627. wsprintf(sQuery, L"Select * from %s where ActionID = %d", sTable, lActionID);
  628. varQuery = sQuery;
  629. _RecordsetPtr pRs(__uuidof(Recordset));
  630. pRs->Open(varQuery, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  631. if (!pRs->EndOfFile)
  632. {
  633. pRs->MoveFirst();
  634. while ( !pRs->EndOfFile )
  635. {
  636. val = pRs->Fields->GetItem(L"Property")->Value;
  637. sKeyName = val.bstrVal;
  638. hr = GetVarFromDB(pRs, val);
  639. if ( FAILED(hr) )
  640. _com_issue_errorex(hr, pRs, __uuidof(_Recordset));
  641. pVS->put(sKeyName, val);
  642. pRs->MoveNext();
  643. }
  644. RestoreVarset(pVS);
  645. }
  646. }
  647. catch (_com_error& ce)
  648. {
  649. hr = ce.Error();
  650. }
  651. catch (...)
  652. {
  653. hr = E_FAIL;
  654. }
  655. return hr;
  656. }
  657. //---------------------------------------------------------------------------------------------
  658. // GetSettings : Retrieves the settings from the Settings table and fills up the varset
  659. //---------------------------------------------------------------------------------------------
  660. STDMETHODIMP CIManageDB::GetSettings(IUnknown **ppUnk)
  661. {
  662. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  663. HRESULT hr = S_OK;
  664. try
  665. {
  666. // retrieve settings from Settings Table
  667. CheckError(GetVarsetFromDB(L"Settings", ppUnk));
  668. //
  669. // Retrieve value which indicates whether excluded system properties has been set.
  670. //
  671. IVarSetPtr spVarSet(*ppUnk);
  672. _RecordsetPtr spRecordset;
  673. spRecordset = m_cn->Execute(
  674. _T("SELECT Value FROM Settings2 WHERE Property = 'AccountOptions.ExcludedSystemPropsSet'"),
  675. NULL,
  676. adCmdText
  677. );
  678. long lSet = 0;
  679. if (spRecordset->EndOfFile == VARIANT_FALSE)
  680. {
  681. lSet = spRecordset->Fields->GetItem(0L)->Value;
  682. }
  683. spVarSet->put(_T("AccountOptions.ExcludedSystemPropsSet"), lSet);
  684. //
  685. // Retrieve excluded system properties from Settings2 table and add to VarSet.
  686. //
  687. spRecordset = m_cn->Execute(
  688. _T("SELECT Value FROM Settings2 WHERE Property = 'AccountOptions.ExcludedSystemProps'"),
  689. NULL,
  690. adCmdText
  691. );
  692. if (spRecordset->EndOfFile == VARIANT_FALSE)
  693. {
  694. //
  695. // If the returned variant is of type null then must convert
  696. // to type empty as empty may be converted to string whereas
  697. // null cannot.
  698. //
  699. _variant_t vnt = spRecordset->Fields->GetItem(0L)->Value;
  700. if (V_VT(&vnt) == VT_NULL)
  701. {
  702. vnt.Clear();
  703. }
  704. spVarSet->put(_T("AccountOptions.ExcludedSystemProps"), vnt);
  705. }
  706. }
  707. catch (_com_error& ce)
  708. {
  709. hr = ce.Error();
  710. }
  711. catch (...)
  712. {
  713. hr = E_FAIL;
  714. }
  715. return hr;
  716. }
  717. //---------------------------------------------------------------------------------------------
  718. // SetActionHistory : Saves action history information into the Action history table.
  719. //---------------------------------------------------------------------------------------------
  720. STDMETHODIMP CIManageDB::SetActionHistory(long lActionID, IUnknown *pUnk)
  721. {
  722. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  723. HRESULT hr = S_OK;
  724. USES_CONVERSION;
  725. try
  726. {
  727. //
  728. // If the excluded system properties value is defined in the VarSet
  729. // set the value to empty to prevent this value from being saved to
  730. // the action history and settings tables.
  731. //
  732. // Note that this value is no longer required so the value does not
  733. // need to be restored in the VarSet. This value is updated in the
  734. // Settings2 table by explicitly calling the SaveSettings method and
  735. // should never be updated during a normal migration task.
  736. //
  737. static const _TCHAR s_szExcludedSystemProps[] = _T("AccountOptions.ExcludedSystemProps");
  738. IVarSetPtr spVarSet(pUnk);
  739. _variant_t vntSystemExclude = spVarSet->get(s_szExcludedSystemProps);
  740. if (V_VT(&vntSystemExclude) != VT_EMPTY)
  741. {
  742. vntSystemExclude.Clear();
  743. spVarSet->put(s_szExcludedSystemProps, vntSystemExclude);
  744. }
  745. // Call the set varset method to set the values into the database.
  746. SetVarsetToDB(pUnk, L"ActionHistory", _variant_t(lActionID));
  747. //
  748. // remove obsolete records from the distributed action table
  749. // as the action id has now been re-used
  750. //
  751. _TCHAR szSQL[LEN_Path];
  752. _variant_t vntRecordsAffected;
  753. _stprintf(szSQL, L"DELETE FROM DistributedAction WHERE ActionID = %ld", lActionID);
  754. m_cn->Execute(_bstr_t(szSQL), &vntRecordsAffected, adExecuteNoRecords);
  755. }
  756. catch (_com_error& ce)
  757. {
  758. hr = ce.Error();
  759. }
  760. catch (...)
  761. {
  762. hr = E_FAIL;
  763. }
  764. return hr;
  765. }
  766. //---------------------------------------------------------------------------------------------
  767. // GetActionHistory : Retrieves action history information into the varset
  768. //---------------------------------------------------------------------------------------------
  769. STDMETHODIMP CIManageDB::GetActionHistory(long lActionID, IUnknown **ppUnk)
  770. {
  771. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  772. // Get the varset from the database
  773. _variant_t ActionID = lActionID;
  774. // GetVarsetFromDB(L"ActionHistory", ppUnk, ActionID);
  775. // return S_OK;
  776. return GetVarsetFromDB(L"ActionHistory", ppUnk, ActionID);
  777. }
  778. //---------------------------------------------------------------------------------------------
  779. // GetNextActionID : Rotates the Action ID between 1 and MAXID as specified in the system table
  780. //---------------------------------------------------------------------------------------------
  781. STDMETHODIMP CIManageDB::GetNextActionID(long *pActionID)
  782. {
  783. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  784. HRESULT hr = S_OK;
  785. // We open the system table and look at the NextActionID field.
  786. // if the value of the NextActionID is greater than value in MaxID field
  787. // then we return the nextactionid = 1.
  788. try
  789. {
  790. _RecordsetPtr pRs(__uuidof(Recordset));
  791. _variant_t vtSource = L"System";
  792. _variant_t next, max, curr;
  793. WCHAR sActionID[LEN_Path];
  794. next.vt = VT_I4;
  795. max.vt = VT_I4;
  796. curr.vt = VT_I4;
  797. pRs->Filter = L"";
  798. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  799. if (pRs->GetRecordCount() > 0)
  800. {
  801. pRs->MoveFirst();
  802. next.lVal = pRs->Fields->GetItem(L"NextActionID")->Value;
  803. max.lVal = pRs->Fields->GetItem(L"MaxID")->Value;
  804. if ( next.lVal > max.lVal )
  805. next.lVal = 1;
  806. long currentID = next.lVal;
  807. *pActionID = currentID;
  808. curr.lVal = currentID;
  809. next.lVal++;
  810. pRs->Fields->GetItem(L"NextActionID")->Value = next;
  811. pRs->Fields->GetItem(L"CurrentActionID")->Value = curr;
  812. pRs->Update();
  813. // Delete all entries for this pirticular action.
  814. wsprintf(sActionID, L"ActionID=%d", currentID);
  815. _variant_t ActionID = sActionID;
  816. ClearTable(L"ActionHistory", ActionID);
  817. //TODO:: Add code to delete entries from any other tables if needed
  818. // Since we are deleting the actionID in the the ActionHistory table we can
  819. // not undo this stuff. But we still need to keep it around so that the report
  820. // and the GUI can work with it. I am going to set all actionIDs to -1 if actionID is
  821. // cleared
  822. SetActionIDInMigratedObjects(sActionID);
  823. }
  824. else
  825. {
  826. hr = S_FALSE;
  827. }
  828. }
  829. catch (_com_error& ce)
  830. {
  831. hr = ce.Error();
  832. }
  833. catch (...)
  834. {
  835. hr = E_FAIL;
  836. }
  837. return hr;
  838. }
  839. //---------------------------------------------------------------------------------------------
  840. // SaveMigratedObject : Saves information about a object that is migrated.
  841. //---------------------------------------------------------------------------------------------
  842. STDMETHODIMP CIManageDB::SaveMigratedObject(long lActionID, IUnknown *pUnk)
  843. {
  844. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  845. HRESULT hr = S_OK;
  846. // This fucntion updates the migrated objects table in the DB with the
  847. // information in the varset. If the information is not found in the Varset
  848. // then an error may occur.
  849. try
  850. {
  851. _variant_t var;
  852. time_t tm;
  853. COleDateTime dt(time(&tm));
  854. //dt= COleDateTime::GetCurrentTime();
  855. _RecordsetPtr pRs(__uuidof(Recordset));
  856. _variant_t vtSource;
  857. IVarSetPtr pVs = pUnk;
  858. WCHAR sQuery[LEN_Path];
  859. WCHAR sSource[LEN_Path], sTarget[LEN_Path], sDomain[LEN_Path];
  860. HRESULT hr = S_OK;
  861. bool bComp = false;
  862. WCHAR sTemp[LEN_Path];
  863. _bstr_t tempName;
  864. // Delete the record if one already exists in the table. In case it is remigrated/replaced.
  865. var = pVs->get(GET_BSTR(DB_SourceDomain));
  866. wcscpy(sSource, (WCHAR*)V_BSTR(&var));
  867. var = pVs->get(GET_BSTR(DB_TargetDomain));
  868. wcscpy(sTarget, (WCHAR*)V_BSTR(&var));
  869. var = pVs->get(GET_BSTR(DB_SourceSamName));
  870. wcscpy(sDomain, (WCHAR*)V_BSTR(&var));
  871. wsprintf(sQuery, L"delete from MigratedObjects where SourceDomain=\"%s\" and TargetDomain=\"%s\" and SourceSamName=\"%s\"",
  872. sSource, sTarget, sDomain);
  873. vtSource = _bstr_t(sQuery);
  874. hr = pRs->raw_Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  875. vtSource = L"MigratedObjects";
  876. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  877. pRs->AddNew();
  878. var.vt = VT_UI4;
  879. var.lVal = lActionID;
  880. pRs->Fields->GetItem(L"ActionID")->Value = var;
  881. pRs->Fields->GetItem(L"Time")->Value = DATE(dt);
  882. var = pVs->get(GET_BSTR(DB_SourceDomain));
  883. pRs->Fields->GetItem(L"SourceDomain")->Value = var;
  884. var = pVs->get(GET_BSTR(DB_TargetDomain));
  885. pRs->Fields->GetItem(L"TargetDomain")->Value = var;
  886. var = pVs->get(GET_BSTR(DB_SourceAdsPath));
  887. pRs->Fields->GetItem(L"SourceAdsPath")->Value = var;
  888. var = pVs->get(GET_BSTR(DB_TargetAdsPath));
  889. pRs->Fields->GetItem(L"TargetAdsPath")->Value = var;
  890. var = pVs->get(GET_BSTR(DB_status));
  891. pRs->Fields->GetItem(L"status")->Value = var;
  892. var = pVs->get(GET_BSTR(DB_SourceDomainSid));
  893. pRs->Fields->GetItem(L"SourceDomainSid")->Value = var;
  894. var = pVs->get(GET_BSTR(DB_Type));
  895. // make the string into an uppercase string.
  896. if ( var.vt == VT_BSTR )
  897. {
  898. var.bstrVal = UStrLwr((WCHAR*) var.bstrVal);
  899. if ( !_wcsicmp(L"computer", (WCHAR*) var.bstrVal) )
  900. bComp = true;
  901. else
  902. bComp = false;
  903. }
  904. pRs->Fields->GetItem(L"Type")->Value = var;
  905. var = pVs->get(GET_BSTR(DB_SourceSamName));
  906. // for computer accounts make sure the good old $ sign is there.
  907. if (bComp)
  908. {
  909. wcscpy(sTemp, (WCHAR*) var.bstrVal);
  910. if ( sTemp[wcslen(sTemp) - 1] != L'$' )
  911. {
  912. tempName = sTemp;
  913. tempName += L"$";
  914. var = tempName;
  915. }
  916. }
  917. pRs->Fields->GetItem(L"SourceSamName")->Value = var;
  918. var = pVs->get(GET_BSTR(DB_TargetSamName));
  919. // for computer accounts make sure the good old $ sign is there.
  920. if (bComp)
  921. {
  922. wcscpy(sTemp, (WCHAR*) var.bstrVal);
  923. if ( sTemp[wcslen(sTemp) - 1] != L'$' )
  924. {
  925. tempName = sTemp;
  926. tempName += L"$";
  927. var = tempName;
  928. }
  929. }
  930. pRs->Fields->GetItem(L"TargetSamName")->Value = var;
  931. var = pVs->get(GET_BSTR(DB_GUID));
  932. pRs->Fields->GetItem(L"GUID")->Value = var;
  933. var = pVs->get(GET_BSTR(DB_SourceRid));
  934. if ( var.vt == VT_UI4 || var.vt == VT_I4 )
  935. pRs->Fields->GetItem("SourceRid")->Value = var;
  936. else
  937. pRs->Fields->GetItem("SourceRid")->Value = _variant_t((long)0);
  938. var = pVs->get(GET_BSTR(DB_TargetRid));
  939. if ( var.vt == VT_UI4 || var.vt == VT_I4 )
  940. pRs->Fields->GetItem("TargetRid")->Value = var;
  941. else
  942. pRs->Fields->GetItem("TargetRid")->Value = _variant_t((long)0);
  943. pRs->Update();
  944. }
  945. catch (_com_error& ce)
  946. {
  947. hr = ce.Error();
  948. }
  949. catch (...)
  950. {
  951. hr = E_FAIL;
  952. }
  953. return hr;
  954. }
  955. //---------------------------------------------------------------------------------------------
  956. // GetMigratedObjects : Retrieves information about previously migrated objects withis a given
  957. // action or as a whole
  958. //---------------------------------------------------------------------------------------------
  959. STDMETHODIMP CIManageDB::GetMigratedObjects(long lActionID, IUnknown ** ppUnk)
  960. {
  961. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  962. HRESULT hr = S_OK;
  963. // This function returns all migrated objects and their information related
  964. // to a pirticular Action ID. This is going to return nothing if the actionID is
  965. // empty.
  966. try
  967. {
  968. _RecordsetPtr pRs(__uuidof(Recordset));
  969. _variant_t vtSource = L"MigratedObjects";
  970. IVarSetPtr pVs = *ppUnk;
  971. WCHAR sActionInfo[255];
  972. long lCnt = 0;
  973. if ( lActionID != -1 )
  974. {
  975. // If a valid ActionID is specified then we only return the data for that one.
  976. // but if -1 is passed in then we return all migrated objects.
  977. wsprintf(sActionInfo, L"ActionID=%d", lActionID);
  978. pRs->Filter = sActionInfo;
  979. }
  980. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  981. if (pRs->GetRecordCount() > 0)
  982. {
  983. pRs->MoveFirst();
  984. while ( !pRs->EndOfFile )
  985. {
  986. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_ActionID));
  987. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  988. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Time));
  989. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  990. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomain));
  991. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  992. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetDomain));
  993. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  994. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceAdsPath));
  995. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  996. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetAdsPath));
  997. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  998. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_status));
  999. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  1000. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceSamName));
  1001. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  1002. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetSamName));
  1003. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  1004. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Type));
  1005. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  1006. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  1007. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  1008. //delineation
  1009. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  1010. if (wcsstr((WCHAR*)sType, L"group"))
  1011. sType = L"group";
  1012. pVs->put(sActionInfo, sType);
  1013. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_GUID));
  1014. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  1015. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceRid));
  1016. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  1017. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetRid));
  1018. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  1019. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomainSid));
  1020. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  1021. pRs->MoveNext();
  1022. lCnt++;
  1023. }
  1024. pVs->put(L"MigratedObjects", lCnt);
  1025. }
  1026. else
  1027. {
  1028. hr = S_FALSE;
  1029. }
  1030. }
  1031. catch (_com_error& ce)
  1032. {
  1033. hr = ce.Error();
  1034. }
  1035. catch (...)
  1036. {
  1037. hr = E_FAIL;
  1038. }
  1039. return hr;
  1040. }
  1041. //---------------------------------------------------------------------------------------------
  1042. // GetMigratedObjectsWithSSid : Retrieves information about previously migrated objects within
  1043. // a given action or as a whole with a valid Source Domain Sid
  1044. //---------------------------------------------------------------------------------------------
  1045. STDMETHODIMP CIManageDB::GetMigratedObjectsWithSSid(long lActionID, IUnknown ** ppUnk)
  1046. {
  1047. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1048. HRESULT hr = S_OK;
  1049. // This function returns all migrated objects and their information related
  1050. // to a pirticular Action ID. This is going to return nothing if the actionID is
  1051. // empty.
  1052. try
  1053. {
  1054. _RecordsetPtr pRs(__uuidof(Recordset));
  1055. _variant_t vtSource = L"MigratedObjects";
  1056. IVarSetPtr pVs = *ppUnk;
  1057. WCHAR sActionInfo[255];
  1058. long lCnt = 0;
  1059. if ( lActionID != -1 )
  1060. {
  1061. // If a valid ActionID is specified then we only return the data for that one.
  1062. // but if -1 is passed in then we return all migrated objects.
  1063. wsprintf(sActionInfo, L"ActionID=%d", lActionID);
  1064. pRs->Filter = sActionInfo;
  1065. }
  1066. wsprintf(sActionInfo, L"Select * from MigratedObjects where SourceDomainSid IS NOT NULL");
  1067. vtSource = sActionInfo;
  1068. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1069. if (pRs->GetRecordCount() > 0)
  1070. {
  1071. pRs->MoveFirst();
  1072. while ( !pRs->EndOfFile )
  1073. {
  1074. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_ActionID));
  1075. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  1076. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Time));
  1077. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  1078. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomain));
  1079. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  1080. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetDomain));
  1081. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  1082. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceAdsPath));
  1083. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  1084. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetAdsPath));
  1085. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  1086. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_status));
  1087. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  1088. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceSamName));
  1089. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  1090. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetSamName));
  1091. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  1092. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Type));
  1093. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  1094. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  1095. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  1096. //delineation
  1097. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  1098. if (wcsstr((WCHAR*)sType, L"group"))
  1099. sType = L"group";
  1100. pVs->put(sActionInfo, sType);
  1101. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_GUID));
  1102. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  1103. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceRid));
  1104. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  1105. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetRid));
  1106. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  1107. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomainSid));
  1108. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  1109. pRs->MoveNext();
  1110. lCnt++;
  1111. }
  1112. pVs->put(L"MigratedObjects", lCnt);
  1113. }
  1114. else
  1115. {
  1116. hr = S_FALSE;
  1117. }
  1118. }
  1119. catch (_com_error& ce)
  1120. {
  1121. hr = ce.Error();
  1122. }
  1123. catch (...)
  1124. {
  1125. hr = E_FAIL;
  1126. }
  1127. return hr;
  1128. }
  1129. //---------------------------------------------------------------------------------------------
  1130. // SetActionIDInMigratedObjects : For a discarded actionID sets its ActionID to -1 in MO table.
  1131. //---------------------------------------------------------------------------------------------
  1132. void CIManageDB::SetActionIDInMigratedObjects(_bstr_t sFilter)
  1133. {
  1134. _bstr_t sQuery = _bstr_t(L"Update MigratedObjects Set ActionID = -1 where ") + sFilter;
  1135. _variant_t vt = sQuery;
  1136. try
  1137. {
  1138. _RecordsetPtr pRs(__uuidof(Recordset));
  1139. pRs->Open(vt, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1140. }
  1141. catch (...)
  1142. {
  1143. ;
  1144. }
  1145. }
  1146. //---------------------------------------------------------------------------------------------
  1147. // GetRSForReport : Returns a recordset for a given report.
  1148. //---------------------------------------------------------------------------------------------
  1149. STDMETHODIMP CIManageDB::GetRSForReport(BSTR sReport, IUnknown **pprsData)
  1150. {
  1151. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1152. HRESULT hr = S_OK;
  1153. try
  1154. {
  1155. // For a given report we have a mapping in the varset. We can get the query
  1156. // from that varset and execute it and return the varset.
  1157. _variant_t var = m_pQueryMapping->get(sReport);
  1158. if ( var.vt == VT_BSTR )
  1159. {
  1160. _RecordsetPtr pRs(__uuidof(Recordset));
  1161. pRs->Open(var, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1162. // Now that we have the recordset pointer we can get IUnknown pointer to it and return that
  1163. *pprsData = IUnknownPtr(pRs).Detach();
  1164. }
  1165. else
  1166. {
  1167. hr = E_NOTIMPL;
  1168. }
  1169. }
  1170. catch (_com_error& ce)
  1171. {
  1172. hr = ce.Error();
  1173. }
  1174. catch (...)
  1175. {
  1176. hr = E_FAIL;
  1177. }
  1178. return hr;
  1179. }
  1180. //---------------------------------------------------------------------------------------------
  1181. //
  1182. //---------------------------------------------------------------------------------------------
  1183. STDMETHODIMP CIManageDB::SaveSCMPasswords(IUnknown *pUnk)
  1184. {
  1185. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1186. return SetVarsetToDB(pUnk, L"SCMPasswords");
  1187. }
  1188. //---------------------------------------------------------------------------------------------
  1189. //
  1190. //---------------------------------------------------------------------------------------------
  1191. STDMETHODIMP CIManageDB::GetSCMPasswords(IUnknown **ppUnk)
  1192. {
  1193. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1194. return GetVarsetFromDB(L"SCMPasswords", ppUnk);
  1195. }
  1196. //---------------------------------------------------------------------------------------------
  1197. //
  1198. //---------------------------------------------------------------------------------------------
  1199. STDMETHODIMP CIManageDB::ClearSCMPasswords()
  1200. {
  1201. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1202. ClearTable(L"SCMPasswords");
  1203. return S_OK;
  1204. }
  1205. //---------------------------------------------------------------------------------------------
  1206. // GetCurrentActionID : Retrieves the actionID currently in use.
  1207. //---------------------------------------------------------------------------------------------
  1208. STDMETHODIMP CIManageDB::GetCurrentActionID(long *pActionID)
  1209. {
  1210. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1211. HRESULT hr = S_OK;
  1212. try
  1213. {
  1214. _RecordsetPtr pRs(__uuidof(Recordset));
  1215. _variant_t vtSource = L"System";
  1216. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  1217. if (pRs->GetRecordCount() > 0)
  1218. {
  1219. pRs->MoveFirst();
  1220. *pActionID = pRs->Fields->GetItem(L"CurrentActionID")->Value;
  1221. }
  1222. else
  1223. {
  1224. hr = S_FALSE;
  1225. }
  1226. }
  1227. catch (_com_error& ce)
  1228. {
  1229. hr = ce.Error();
  1230. }
  1231. catch (...)
  1232. {
  1233. hr = E_FAIL;
  1234. }
  1235. return hr;
  1236. }
  1237. //---------------------------------------------------------------------------------------------
  1238. // GetAMigratedObject : Given the source name, and the domain information retrieves info about
  1239. // a previous migration.
  1240. //---------------------------------------------------------------------------------------------
  1241. STDMETHODIMP CIManageDB::GetAMigratedObject(BSTR sSrcSamName, BSTR sSrcDomain, BSTR sTgtDomain, IUnknown **ppUnk)
  1242. {
  1243. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1244. HRESULT hr = S_OK;
  1245. try
  1246. {
  1247. _RecordsetPtr pRs(__uuidof(Recordset));
  1248. _variant_t vtSource = L"MigratedObjects";
  1249. IVarSetPtr pVs = *ppUnk;
  1250. WCHAR sActionInfo[LEN_Path];
  1251. long lCnt = 0;
  1252. _bstr_t sName;
  1253. // If the parameters are not correct then we need to return an error
  1254. //if ( (SysStringLen(sSrcSamName) == 0) || (SysStringLen(sSrcDomain) == 0) || (SysStringLen(sTgtDomain) == 0))
  1255. if ( (sSrcSamName == 0) || (sSrcDomain == 0) || (sTgtDomain == 0) || (wcslen(sSrcSamName) == 0) || (wcslen(sSrcDomain) == 0) || (wcslen(sTgtDomain) == 0))
  1256. _com_issue_error(E_INVALIDARG);
  1257. wsprintf(sActionInfo, L"Select * from MigratedObjects where SourceDomain=\"%s\" AND SourceSamName=\"%s\" AND TargetDomain=\"%s\"", sSrcDomain, sSrcSamName, sTgtDomain);
  1258. vtSource = sActionInfo;
  1259. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1260. if (pRs->GetRecordCount() > 0)
  1261. {
  1262. // We want the latest move.
  1263. pRs->MoveLast();
  1264. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_ActionID));
  1265. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  1266. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Time));
  1267. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  1268. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomain));
  1269. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  1270. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetDomain));
  1271. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  1272. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceAdsPath));
  1273. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  1274. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetAdsPath));
  1275. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  1276. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_status));
  1277. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  1278. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceSamName));
  1279. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  1280. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetSamName));
  1281. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  1282. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Type));
  1283. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  1284. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  1285. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  1286. //delineation
  1287. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  1288. if (wcsstr((WCHAR*)sType, L"group"))
  1289. sType = L"group";
  1290. pVs->put(sActionInfo, sType);
  1291. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_GUID));
  1292. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  1293. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceRid));
  1294. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  1295. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetRid));
  1296. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  1297. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomainSid));
  1298. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  1299. }
  1300. else
  1301. {
  1302. hr = S_FALSE;
  1303. }
  1304. }
  1305. catch (_com_error& ce)
  1306. {
  1307. hr = ce.Error();
  1308. }
  1309. catch (...)
  1310. {
  1311. hr = E_FAIL;
  1312. }
  1313. return hr;
  1314. }
  1315. //---------------------------------------------------------------------------------------------
  1316. // GetAMigratedObjectToAnyDomain : Given the source name, and the domain information retrieves info about
  1317. // a previous migration.
  1318. //---------------------------------------------------------------------------------------------
  1319. STDMETHODIMP CIManageDB::GetAMigratedObjectToAnyDomain(BSTR sSrcSamName, BSTR sSrcDomain, IUnknown **ppUnk)
  1320. {
  1321. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1322. HRESULT hr = S_OK;
  1323. try
  1324. {
  1325. _RecordsetPtr pRs(__uuidof(Recordset));
  1326. _variant_t vtSource = L"MigratedObjects";
  1327. IVarSetPtr pVs = *ppUnk;
  1328. WCHAR sActionInfo[LEN_Path];
  1329. long lCnt = 0;
  1330. _bstr_t sName;
  1331. // If the parameters are not correct then we need to return an error
  1332. if ( (wcslen(sSrcSamName) == 0) || (wcslen(sSrcDomain) == 0))
  1333. _com_issue_error(E_INVALIDARG);
  1334. wsprintf(sActionInfo, L"Select * from MigratedObjects where SourceDomain=\"%s\" AND SourceSamName=\"%s\" Order by Time", sSrcDomain, sSrcSamName);
  1335. // pRs->Filter = sActionInfo;
  1336. // wcscpy(sActionInfo, L"Time");
  1337. // pRs->Sort = sActionInfo;
  1338. vtSource = _bstr_t(sActionInfo);
  1339. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1340. if (pRs->GetRecordCount() > 0)
  1341. {
  1342. // We want the latest move.
  1343. pRs->MoveLast();
  1344. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_ActionID));
  1345. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  1346. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Time));
  1347. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  1348. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomain));
  1349. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  1350. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetDomain));
  1351. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  1352. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceAdsPath));
  1353. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  1354. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetAdsPath));
  1355. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  1356. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_status));
  1357. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  1358. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceSamName));
  1359. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  1360. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetSamName));
  1361. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  1362. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Type));
  1363. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  1364. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  1365. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  1366. //delineation
  1367. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  1368. if (wcsstr((WCHAR*)sType, L"group"))
  1369. sType = L"group";
  1370. pVs->put(sActionInfo, sType);
  1371. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_GUID));
  1372. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  1373. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceRid));
  1374. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  1375. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetRid));
  1376. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  1377. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomainSid));
  1378. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  1379. }
  1380. else
  1381. {
  1382. hr = S_FALSE;
  1383. }
  1384. }
  1385. catch (_com_error& ce)
  1386. {
  1387. hr = ce.Error();
  1388. }
  1389. catch (...)
  1390. {
  1391. hr = E_FAIL;
  1392. }
  1393. return hr;
  1394. }
  1395. //---------------------------------------------------------------------------------------------
  1396. // GenerateReport Generates an HTML report for the given Query and saves it in the File.
  1397. //---------------------------------------------------------------------------------------------
  1398. STDMETHODIMP CIManageDB::GenerateReport(BSTR sReportName, BSTR sFileName, BSTR sSrcDomain, BSTR sTgtDomain, LONG bSourceNT4)
  1399. {
  1400. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1401. HRESULT hr = S_OK;
  1402. FILE* logFile = NULL;
  1403. try
  1404. {
  1405. _RecordsetPtr pRs;
  1406. IUnknownPtr pUnk;
  1407. _variant_t var;
  1408. WCHAR sKey[LEN_Path];
  1409. CString reportingTitle;
  1410. CString srcDm = (WCHAR*) sSrcDomain;
  1411. CString tgtDm = (WCHAR*) sTgtDomain;
  1412. //convert source and target domain names, only used in the name conflict report,
  1413. //to uppercase
  1414. srcDm.MakeUpper();
  1415. tgtDm.MakeUpper();
  1416. // construct the statement if the report is "ExpiredComputers"
  1417. if (wcscmp((WCHAR*) sReportName, L"ExpiredComputers") == 0)
  1418. {
  1419. WCHAR newCmdText[256];
  1420. IADsDomain *pDomain;
  1421. _bstr_t sSrcDom(L"WinNT://");
  1422. sSrcDom += sSrcDomain;
  1423. hr = ADsGetObject(sSrcDom, IID_IADsDomain, (void **) &pDomain);
  1424. if (FAILED(hr))
  1425. _com_issue_error(hr);
  1426. long lMaxPassAge;
  1427. hr = pDomain->get_MaxPasswordAge(&lMaxPassAge);
  1428. pDomain->Release();
  1429. if (FAILED(hr))
  1430. _com_issue_error(hr);
  1431. _snwprintf(newCmdText,sizeof(newCmdText)/sizeof(newCmdText[0]),
  1432. L"Select Time, DomainName, CompName, Description, int(pwdage/86400) & ' days' as 'Password Age' from PasswordAge where pwdage > %ld order by DomainName, CompName",
  1433. lMaxPassAge);
  1434. newCmdText[sizeof(newCmdText)/sizeof(newCmdText[0]) - 1] = 0;
  1435. m_pQueryMapping->put(sReportName,newCmdText);
  1436. }
  1437. CheckError(GetRSForReport(sReportName, &pUnk));
  1438. pRs = pUnk;
  1439. // Now that we have the recordset we need to get the number of columns
  1440. int numFields = pRs->Fields->Count;
  1441. int size = 100 / numFields;
  1442. reportingTitle.LoadString(IDS_ReportingTitle);
  1443. // Open the html file to write to
  1444. logFile = fopen(_bstr_t(sFileName), "wb");
  1445. if ( !logFile )
  1446. _com_issue_error(HRESULT_FROM_WIN32(GetLastError())); //TODO: stream i/o doesn't set last error
  1447. //Put the header information into the File.
  1448. fputs("<HTML>\r\n", logFile);
  1449. fputs("<HEAD>\r\n", logFile);
  1450. fputs("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; CHARSET=utf-8\">\r\n", logFile);
  1451. fprintf(logFile, "<TITLE>%s</TITLE>\r\n", WTUTF8(reportingTitle.GetBuffer(0)));
  1452. fputs("</HEAD>\r\n", logFile);
  1453. fputs("<BODY TEXT=\"#000000\" BGCOLOR=\"#ffffff\">\r\n", logFile);
  1454. fprintf(logFile, "<B><FONT SIZE=5><P ALIGN=\"CENTER\">%s</P>\r\n", WTUTF8(reportingTitle.GetBuffer(0)));
  1455. // Get the display information for the report
  1456. // I know I did not need to do all this elaborate setup to get the fieldnames and the report names
  1457. // I could have gotten this information dynamically but had to change it because we need to get the
  1458. // info from the Res dll for internationalization.
  1459. wsprintf(sKey, L"%s.DispInfo", (WCHAR*) sReportName);
  1460. _variant_t v1;
  1461. reportStruct * prs;
  1462. v1 = m_pQueryMapping->get(sKey);
  1463. prs = (reportStruct *) v1.pbVal;
  1464. VariantInit(&v1);
  1465. fprintf(logFile, "</FONT><FONT SIZE=4><P ALIGN=\"CENTER\">%s</P>\r\n", WTUTF8(prs->sReportName));
  1466. fputs("<P ALIGN=\"CENTER\"><CENTER><TABLE WIDTH=90%%>\r\n", logFile);
  1467. fputs("<TR>\r\n", logFile);
  1468. for (int i = 0; i < numFields; i++)
  1469. {
  1470. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" BGCOLOR=\"#000080\">\r\n", prs->arReportSize[i]);
  1471. //if Canonical Name column, left align text since the name can be really long
  1472. if (i==5)
  1473. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#00ff00\"><P ALIGN=\"LEFT\">%s</B></FONT></TD>\r\n", WTUTF8(prs->arReportFields[i]));
  1474. else
  1475. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#00ff00\"><P ALIGN=\"CENTER\">%s</B></FONT></TD>\r\n", WTUTF8(prs->arReportFields[i]));
  1476. }
  1477. fputs("</TR>\r\n", logFile);
  1478. //if name conflict report, add domains to the top of the report
  1479. if (wcscmp((WCHAR*) sReportName, L"NameConflicts") == 0)
  1480. {
  1481. fputs("</TR>\r\n", logFile);
  1482. //add "Source Domain ="
  1483. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[0]);
  1484. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</B></FONT></TD>\r\n", WTUTF8(GET_STRING(IDS_TABLE_NC_SDOMAIN)));
  1485. //add %SourceDomainName%
  1486. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[1]);
  1487. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\"> = %s</B></FONT></TD>\r\n", WTUTF8(LPCTSTR(srcDm)));
  1488. fputs("<TD>\r\n", logFile);
  1489. fputs("<TD>\r\n", logFile);
  1490. //add "Target Domain ="
  1491. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[4]);
  1492. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</B></FONT></TD>\r\n", WTUTF8(GET_STRING(IDS_TABLE_NC_TDOMAIN)));
  1493. //add %TargetDomainName%
  1494. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[5]);
  1495. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\"> = %s</B></FONT></TD>\r\n", WTUTF8(LPCTSTR(tgtDm)));
  1496. fputs("</TR>\r\n", logFile);
  1497. }
  1498. //write Account Reference report here since we need to build lists and
  1499. //categorize
  1500. if (wcscmp((WCHAR*) sReportName, L"AccountReferences") == 0)
  1501. {
  1502. CStringList inMotList;
  1503. CString accountName;
  1504. CString domainName;
  1505. CString listName;
  1506. POSITION currentPos;
  1507. //add "Migrated by ADMT" as section header for Account Reference report
  1508. fputs("</TR>\r\n", logFile);
  1509. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[0]);
  1510. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</B></FONT></TD>\r\n", WTUTF8(GET_STRING(IDS_TABLE_AR_MOT_HDR)));
  1511. fputs("</TR>\r\n", logFile);
  1512. //look at each entry in the recordset and add the the migrated list if it was
  1513. //migrated and in the MOT
  1514. while ( !pRs->EndOfFile )
  1515. {
  1516. //retrieve the domain and account name for this entry
  1517. var = pRs->Fields->Item[(long)0]->GetValue();
  1518. domainName = (WCHAR*)V_BSTR(&var);
  1519. var = pRs->Fields->Item[(long)1]->GetValue();
  1520. accountName = (WCHAR*)V_BSTR(&var);
  1521. //see if this account is in the Migrated Objects table
  1522. IVarSetPtr pVsMot(__uuidof(VarSet));
  1523. IUnknown * pMotUnk;
  1524. pVsMot->QueryInterface(IID_IUnknown, (void**) &pMotUnk);
  1525. HRESULT hrFind = GetAMigratedObjectToAnyDomain(accountName.AllocSysString(),
  1526. domainName.AllocSysString(), &pMotUnk);
  1527. pMotUnk->Release();
  1528. //if this entry was in the MOT, save in the list
  1529. if ( hrFind == S_OK )
  1530. {
  1531. //list stores the account in the form domain\account
  1532. listName = domainName;
  1533. listName += L"\\";
  1534. listName += accountName;
  1535. //add the name to the list, if not already in it
  1536. currentPos = inMotList.Find(listName);
  1537. if (currentPos == NULL)
  1538. inMotList.AddTail(listName);
  1539. }
  1540. pRs->MoveNext();
  1541. }//end while build MOT list
  1542. //go back to the top of the recordset and print each entry that is in the
  1543. //list created above
  1544. pRs->MoveFirst();
  1545. while ( !pRs->EndOfFile )
  1546. {
  1547. BOOL bInList = FALSE;
  1548. //retrieve the domain and account name for this entry
  1549. var = pRs->Fields->Item[(long)0]->GetValue();
  1550. domainName = (WCHAR*)V_BSTR(&var);
  1551. var = pRs->Fields->Item[(long)1]->GetValue();
  1552. accountName = (WCHAR*)V_BSTR(&var);
  1553. //list stored the accounts in the form domain\account
  1554. listName = domainName;
  1555. listName += L"\\";
  1556. listName += accountName;
  1557. //see if this entry name is in the list, if so, print it
  1558. if (inMotList.Find(listName) != NULL)
  1559. {
  1560. fputs("<TR>\r\n", logFile);
  1561. for (int i = 0; i < numFields; i++)
  1562. {
  1563. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[i]);
  1564. var = pRs->Fields->Item[(long) i]->GetValue();
  1565. if ( var.vt == VT_BSTR )
  1566. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(EscapeSpecialChars(V_BSTR(&var))));
  1567. else
  1568. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"CENTER\">%d</FONT></TD>\r\n", var.lVal);
  1569. }
  1570. fputs("</TR>\r\n", logFile);
  1571. }//end if in list and need to print
  1572. pRs->MoveNext();
  1573. }//end while print those in MOT
  1574. //add "Not Migrated by ADMT" as section header for Account Reference report
  1575. fputs("</TR>\r\n", logFile);
  1576. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[0]);
  1577. fprintf(logFile, "<B><FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</B></FONT></TD>\r\n", WTUTF8(GET_STRING(IDS_TABLE_AR_NOTMOT_HDR)));
  1578. fputs("</TR>\r\n", logFile);
  1579. //go back to the top of the recordset and print each entry that is NOT
  1580. //in the list created above
  1581. pRs->MoveFirst();
  1582. while ( !pRs->EndOfFile )
  1583. {
  1584. BOOL bInList = FALSE;
  1585. //retrieve the domain and account name for this entry
  1586. var = pRs->Fields->Item[(long)0]->GetValue();
  1587. domainName = (WCHAR*)V_BSTR(&var);
  1588. var = pRs->Fields->Item[(long)1]->GetValue();
  1589. accountName = (WCHAR*)V_BSTR(&var);
  1590. //list stored the accounts in the form domain\account
  1591. listName = domainName;
  1592. listName += L"\\";
  1593. listName += accountName;
  1594. //see if this entry name is in the list, if not, print it
  1595. if (inMotList.Find(listName) == NULL)
  1596. {
  1597. fputs("<TR>\r\n", logFile);
  1598. for (int i = 0; i < numFields; i++)
  1599. {
  1600. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[i]);
  1601. var = pRs->Fields->Item[(long) i]->GetValue();
  1602. if ( var.vt == VT_BSTR )
  1603. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(EscapeSpecialChars(V_BSTR(&var))));
  1604. else
  1605. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"CENTER\">%d</FONT></TD>\r\n", var.lVal);
  1606. }
  1607. fputs("</TR>\r\n", logFile);
  1608. }//end if NOT in list and need to print
  1609. pRs->MoveNext();
  1610. }//end while print those NOT in Mot
  1611. inMotList.RemoveAll(); //free the list
  1612. }//end if Account Ref report
  1613. while ((!pRs->EndOfFile) && (wcscmp((WCHAR*) sReportName, L"AccountReferences")))
  1614. {
  1615. fputs("<TR>\r\n", logFile);
  1616. for (int i = 0; i < numFields; i++)
  1617. {
  1618. bool bTranslateType = false;
  1619. bool bHideRDN = false;
  1620. fprintf(logFile, "<TD WIDTH=\"%d%%\" VALIGN=\"TOP\" >\r\n", prs->arReportSize[i]);
  1621. var = pRs->Fields->Item[(long) i]->GetValue();
  1622. if ( var.vt == VT_BSTR )
  1623. {
  1624. //set flag for translating type fields to localizable strings
  1625. if ((!wcscmp((WCHAR*) sReportName, L"NameConflicts")) && ((i==2) || (i==3)))
  1626. bTranslateType = true;
  1627. if ((!wcscmp((WCHAR*) sReportName, L"MigratedComputers")) && (i==2))
  1628. bTranslateType = true;
  1629. if ((!wcscmp((WCHAR*) sReportName, L"MigratedAccounts")) && (i==2))
  1630. bTranslateType = true;
  1631. //clear flag for not displaying RDN for NT 4.0 Source domains
  1632. if ((!wcscmp((WCHAR*) sReportName, L"NameConflicts")) && (i==1) && bSourceNT4)
  1633. bHideRDN = true;
  1634. if (bTranslateType)
  1635. {
  1636. //convert type from English only to a localizable string
  1637. CString atype;
  1638. if (!_wcsicmp((WCHAR*)V_BSTR(&var), L"user") || !_wcsicmp((WCHAR*)V_BSTR(&var), L"inetOrgPerson"))
  1639. atype = GET_STRING(IDS_TypeUser);
  1640. else if (wcsstr((WCHAR*)V_BSTR(&var), L"group"))
  1641. atype = GET_STRING(IDS_TypeGroup);
  1642. else if (!_wcsicmp((WCHAR*)V_BSTR(&var), L"computer"))
  1643. atype = GET_STRING(IDS_TypeComputer);
  1644. else
  1645. atype = GET_STRING(IDS_TypeUnknown);
  1646. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(LPCTSTR(atype)));
  1647. }
  1648. //replace hard-coded "days" with a localizable string
  1649. else if((!wcscmp((WCHAR*) sReportName, L"ExpiredComputers")) && (i==4))
  1650. {
  1651. CString apwdage;
  1652. WCHAR * ndx;
  1653. if ((ndx = wcsstr((WCHAR*)V_BSTR(&var), L"days")) != NULL)
  1654. {
  1655. *ndx = L'\0';
  1656. apwdage = (WCHAR*)V_BSTR(&var);
  1657. apwdage += GET_STRING(IDS_PwdAgeDays);
  1658. }
  1659. else
  1660. apwdage = (WCHAR*)V_BSTR(&var);
  1661. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(EscapeSpecialChars(LPCTSTR(apwdage))));
  1662. }
  1663. //else if NT 4.0 Source do not show our fabricated RDN
  1664. else if (bHideRDN)
  1665. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(L""));
  1666. else
  1667. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"LEFT\">%s</FONT></TD>\r\n", WTUTF8(EscapeSpecialChars(V_BSTR(&var))));
  1668. }
  1669. else
  1670. if ( var.vt == VT_DATE )
  1671. {
  1672. _variant_t v1;
  1673. VariantChangeType(&v1, &var, VARIANT_NOVALUEPROP, VT_BSTR);
  1674. WCHAR sMsg[LEN_Path];
  1675. wcscpy(sMsg, (WCHAR*) V_BSTR(&v1));
  1676. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"CENTER\">%s</FONT></TD>\r\n", WTUTF8(EscapeSpecialChars(LPCTSTR(sMsg))));
  1677. }
  1678. else
  1679. {
  1680. //TODO :: The types need more work
  1681. fprintf(logFile, "<FONT SIZE=3 COLOR=\"#000000\"><P ALIGN=\"CENTER\">%d</FONT></TD>\r\n", var.lVal);
  1682. }
  1683. }
  1684. fputs("</TR>\r\n", logFile);
  1685. pRs->MoveNext();
  1686. }
  1687. fputs("</TABLE>\r\n", logFile);
  1688. fputs("</CENTER></P>\r\n", logFile);
  1689. fputs("<B><FONT SIZE=5><P ALIGN=\"CENTER\"></P></B></FONT></BODY>\r\n", logFile);
  1690. fputs("</HTML>\r\n", logFile);
  1691. }
  1692. catch (_com_error& ce)
  1693. {
  1694. hr = ce.Error();
  1695. }
  1696. catch (...)
  1697. {
  1698. hr = E_FAIL;
  1699. }
  1700. if (logFile)
  1701. {
  1702. fclose(logFile);
  1703. }
  1704. return hr;
  1705. }
  1706. //---------------------------------------------------------------------------------------------
  1707. // AddDistributedAction : Adds a distributed action record to the DistributedAction table.
  1708. //---------------------------------------------------------------------------------------------
  1709. STDMETHODIMP CIManageDB::AddDistributedAction(BSTR sServerName, BSTR sResultFile, long lStatus, BSTR sText)
  1710. {
  1711. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1712. HRESULT hr = S_OK;
  1713. USES_CONVERSION;
  1714. try
  1715. {
  1716. // Get the current action ID.
  1717. long lActionID;
  1718. CheckError(GetCurrentActionID(&lActionID));
  1719. _TCHAR szSQL[1024];
  1720. //
  1721. // try to insert a new failed distributed action record for this action id and server
  1722. //
  1723. _stprintf(
  1724. szSQL,
  1725. _T("INSERT INTO DistributedAction")
  1726. _T(" (ActionID, ServerName, ResultFile, Status, StatusText) ")
  1727. _T("VALUES")
  1728. _T(" (%ld, '%s', '%s', %ld, '%s')"),
  1729. lActionID,
  1730. OLE2CT(sServerName),
  1731. OLE2CT(sResultFile),
  1732. lStatus,
  1733. OLE2CT(sText)
  1734. );
  1735. _variant_t vntRecordsAffected;
  1736. _RecordsetPtr spRecordset;
  1737. hr = m_cn->raw_Execute(_bstr_t(szSQL), &vntRecordsAffected, adExecuteNoRecords, &spRecordset);
  1738. //
  1739. // if insert failed then try to update existing record for this action id and server
  1740. //
  1741. // The action identifier used by ADMT to identify a migration task has a maximum value
  1742. // of 50. After a task has been executed with an id of 50 the id for the next task is
  1743. // reset back to 1. The tuple of the action id and the server name uniquely identifies a
  1744. // failed distributed task. The insert will fail if a record with the same action id
  1745. // and server name already exist. The only way out of this situation is to replace
  1746. // the existing record with the updated result file and status information. This means
  1747. // that the user will not be able to retry the old failed distributed task but at least
  1748. // they will be able to retry the later failed distributed task.
  1749. //
  1750. if (FAILED(hr))
  1751. {
  1752. _stprintf(
  1753. szSQL,
  1754. _T("UPDATE DistributedAction")
  1755. _T(" SET ResultFile = '%s', Status = %ld, StatusText = '%s' ")
  1756. _T("WHERE ActionID = %ld AND ServerName = '%s'"),
  1757. OLE2CT(sResultFile),
  1758. lStatus,
  1759. OLE2CT(sText),
  1760. lActionID,
  1761. OLE2CT(sServerName)
  1762. );
  1763. m_cn->Execute(_bstr_t(szSQL), &vntRecordsAffected, adExecuteNoRecords);
  1764. }
  1765. }
  1766. catch (_com_error& ce)
  1767. {
  1768. hr = ce.Error();
  1769. }
  1770. catch (...)
  1771. {
  1772. hr = E_FAIL;
  1773. }
  1774. return hr;
  1775. }
  1776. //---------------------------------------------------------------------------------------------
  1777. // GetFailedDistributedActions : Returns all the failed distributed action
  1778. //---------------------------------------------------------------------------------------------
  1779. STDMETHODIMP CIManageDB::GetFailedDistributedActions(long lActionID, IUnknown ** pUnk)
  1780. {
  1781. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1782. HRESULT hr = S_OK;
  1783. try
  1784. {
  1785. IVarSetPtr pVs = * pUnk;
  1786. WCHAR sQuery[LEN_Path];
  1787. int nCnt = 0, nCntActionID = 1;
  1788. WCHAR sKey[LEN_Path];
  1789. _variant_t var;
  1790. // The failed action has the 0x80000000 bit set so we check for that (2147483648)
  1791. if ( lActionID == -1 )
  1792. wcscpy(sQuery, L"Select * from DistributedAction where status < 0");
  1793. else
  1794. wsprintf(sQuery, L"Select * from DistributedAction where ActionID=%d and status < 0", lActionID);
  1795. _variant_t vtSource = _bstr_t(sQuery);
  1796. _RecordsetPtr pRs(__uuidof(Recordset));
  1797. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1798. while (!pRs->EndOfFile)
  1799. {
  1800. wsprintf(sKey, L"DA.%d.ActionID", nCnt);
  1801. pVs->put(sKey, pRs->Fields->GetItem(L"ActionID")->Value);
  1802. wsprintf(sKey, L"DA.%d.Server", nCnt);
  1803. pVs->put(sKey, pRs->Fields->GetItem(L"ServerName")->Value);
  1804. wsprintf(sKey, L"DA.%d.Status", nCnt);
  1805. pVs->put(sKey, pRs->Fields->GetItem(L"Status")->Value);
  1806. wsprintf(sKey, L"DA.%d.JobFile", nCnt);
  1807. pVs->put(sKey, pRs->Fields->GetItem(L"ResultFile")->Value);
  1808. wsprintf(sKey, L"DA.%d.StatusText", nCnt);
  1809. pVs->put(sKey, pRs->Fields->GetItem(L"StatusText")->Value);
  1810. nCnt++;
  1811. pRs->MoveNext();
  1812. }
  1813. pVs->put(L"DA", (long) nCnt);
  1814. }
  1815. catch (_com_error& ce)
  1816. {
  1817. hr = ce.Error();
  1818. }
  1819. catch (...)
  1820. {
  1821. hr = E_FAIL;
  1822. }
  1823. return hr;
  1824. }
  1825. //---------------------------------------------------------------------------------------------
  1826. // SetServiceAccount : This method is saves the account info for the Service on a pirticular
  1827. // machine.
  1828. //---------------------------------------------------------------------------------------------
  1829. STDMETHODIMP CIManageDB::SetServiceAccount(
  1830. BSTR System, //in- System name
  1831. BSTR Service, //in- Service name
  1832. BSTR ServiceDisplayName, // in - Display name for service
  1833. BSTR Account //in- Account used by this service
  1834. )
  1835. {
  1836. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1837. HRESULT hr = S_OK;
  1838. try
  1839. {
  1840. // Create a new record and save the information
  1841. _variant_t var;
  1842. WCHAR sFilter[LEN_Path];
  1843. wsprintf(sFilter, L"System = \"%s\" and Service = \"%s\"", System, Service);
  1844. var = sFilter;
  1845. ClearTable(L"ServiceAccounts", var);
  1846. _RecordsetPtr pRs(__uuidof(Recordset));
  1847. _variant_t vtSource = L"ServiceAccounts";
  1848. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  1849. pRs->AddNew();
  1850. var = _bstr_t(System);
  1851. pRs->Fields->GetItem(L"System")->Value = var;
  1852. var = _bstr_t(Service);
  1853. pRs->Fields->GetItem(L"Service")->Value = var;
  1854. var = _bstr_t(ServiceDisplayName);
  1855. pRs->Fields->GetItem(L"ServiceDisplayName")->Value = var;
  1856. var = _bstr_t(Account);
  1857. pRs->Fields->GetItem(L"Account")->Value = var;
  1858. pRs->Update();
  1859. }
  1860. catch (_com_error& ce)
  1861. {
  1862. hr = ce.Error();
  1863. }
  1864. catch (...)
  1865. {
  1866. hr = E_FAIL;
  1867. }
  1868. return hr;
  1869. }
  1870. //---------------------------------------------------------------------------------------------
  1871. // GetServiceAccount : This method gets all the Services referencing the Account specified. The
  1872. // values are returned in System.Service format in the VarSet.
  1873. //---------------------------------------------------------------------------------------------
  1874. STDMETHODIMP CIManageDB::GetServiceAccount(
  1875. BSTR Account, //in- The account to lookup
  1876. IUnknown ** pUnk //out-Varset containing Services
  1877. )
  1878. {
  1879. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1880. HRESULT hr = S_OK;
  1881. try
  1882. {
  1883. IVarSetPtr pVs = * pUnk;
  1884. _bstr_t sQuery;
  1885. _bstr_t sKey;
  1886. WCHAR key[500];
  1887. _variant_t var;
  1888. long ndx = 0;
  1889. _RecordsetPtr pRs(__uuidof(Recordset));
  1890. // Set up the query to lookup a pirticular account or all accounts
  1891. if ( wcslen((WCHAR*)Account) == 0 )
  1892. sQuery = _bstr_t(L"Select * from ServiceAccounts order by System, Service");
  1893. else
  1894. sQuery = _bstr_t(L"Select * from ServiceAccounts where Account = \"") + _bstr_t(Account) + _bstr_t(L"\" order by System, Service");
  1895. var = sQuery;
  1896. // Get the data, Setup the varset and then return the info
  1897. pRs->Open(var, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1898. while (!pRs->EndOfFile)
  1899. {
  1900. // computer name
  1901. swprintf(key,L"Computer.%ld",ndx);
  1902. var = pRs->Fields->GetItem("System")->Value;
  1903. pVs->put(key,var);
  1904. // service name
  1905. swprintf(key,L"Service.%ld",ndx);
  1906. var = pRs->Fields->GetItem("Service")->Value;
  1907. pVs->put(key,var);
  1908. swprintf(key,L"ServiceDisplayName.%ld",ndx);
  1909. var = pRs->Fields->GetItem("ServiceDisplayName")->Value;
  1910. pVs->put(key,var);
  1911. // account name
  1912. swprintf(key,L"ServiceAccount.%ld",ndx);
  1913. var = pRs->Fields->GetItem("Account")->Value;
  1914. pVs->put(key, var);
  1915. swprintf(key,L"ServiceAccountStatus.%ld",ndx);
  1916. var = pRs->Fields->GetItem("Status")->Value;
  1917. pVs->put(key,var);
  1918. pRs->MoveNext();
  1919. ndx++;
  1920. pVs->put(L"ServiceAccountEntries",ndx);
  1921. }
  1922. }
  1923. catch (_com_error& ce)
  1924. {
  1925. hr = ce.Error();
  1926. }
  1927. catch (...)
  1928. {
  1929. hr = E_FAIL;
  1930. }
  1931. return hr;
  1932. }
  1933. //---------------------------------------------------------------------------------------------
  1934. // SavePasswordAge : Saves the password age of the computer account at a given time.
  1935. // It also stores the computer description.
  1936. //---------------------------------------------------------------------------------------------
  1937. STDMETHODIMP CIManageDB::SavePasswordAge(BSTR sDomain, BSTR sComp, BSTR sDesc, long lAge)
  1938. {
  1939. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1940. HRESULT hr = S_OK;
  1941. try
  1942. {
  1943. _bstr_t sQuery;
  1944. WCHAR sTemp[LEN_Path];
  1945. _variant_t var;
  1946. time_t tm;
  1947. COleDateTime dt(time(&tm));
  1948. // Delete the entry if one exists.
  1949. wsprintf(sTemp, L"DomainName=\"%s\" and compname=\"%s\"", (WCHAR*) sDomain, (WCHAR*) sComp);
  1950. var = sTemp;
  1951. ClearTable(L"PasswordAge", var);
  1952. var = L"PasswordAge";
  1953. _RecordsetPtr pRs(__uuidof(Recordset));
  1954. pRs->Open(var, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  1955. pRs->AddNew();
  1956. pRs->Fields->GetItem(L"Time")->Value = DATE(dt);
  1957. pRs->Fields->GetItem(L"DomainName")->Value = sDomain;
  1958. pRs->Fields->GetItem(L"CompName")->Value = sComp;
  1959. pRs->Fields->GetItem(L"Description")->Value = sDesc;
  1960. pRs->Fields->GetItem(L"PwdAge")->Value = lAge;
  1961. pRs->Update();
  1962. }
  1963. catch (_com_error& ce)
  1964. {
  1965. hr = ce.Error();
  1966. }
  1967. catch (...)
  1968. {
  1969. hr = E_FAIL;
  1970. }
  1971. return hr;
  1972. }
  1973. //---------------------------------------------------------------------------------------------
  1974. // GetPasswordAge : Gets the password age and description of a given computer
  1975. //---------------------------------------------------------------------------------------------
  1976. STDMETHODIMP CIManageDB::GetPasswordAge(BSTR sDomain, BSTR sComp, BSTR *sDesc, long *lAge, long *lTime)
  1977. {
  1978. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  1979. HRESULT hr = S_OK;
  1980. try
  1981. {
  1982. _bstr_t sQuery;
  1983. WCHAR sTemp[LEN_Path];
  1984. _variant_t var;
  1985. time_t tm;
  1986. COleDateTime dt(time(&tm));
  1987. DATE val;
  1988. wsprintf(sTemp, L"DomainName =\"%s\" AND CompName = \"%s\"", (WCHAR*) sDomain, (WCHAR*) sComp);
  1989. sQuery = _bstr_t(L"Select * from PasswordAge where ") + _bstr_t(sTemp);
  1990. var = sQuery;
  1991. _RecordsetPtr pRs(__uuidof(Recordset));
  1992. pRs->Open(var, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  1993. if ( ! pRs->EndOfFile )
  1994. {
  1995. val = pRs->Fields->GetItem(L"Time")->Value;
  1996. *sDesc = pRs->Fields->GetItem(L"Description")->Value.bstrVal;
  1997. *lAge = pRs->Fields->GetItem(L"PwdAge")->Value;
  1998. }
  1999. else
  2000. {
  2001. hr = S_FALSE;
  2002. }
  2003. pRs->Close();
  2004. }
  2005. catch (_com_error& ce)
  2006. {
  2007. hr = ce.Error();
  2008. }
  2009. catch (...)
  2010. {
  2011. hr = E_FAIL;
  2012. }
  2013. return hr;
  2014. }
  2015. //---------------------------------------------------------------------------------------------
  2016. // SetServiceAcctEntryStatus : Sets the Account and the status for a given service on a given
  2017. // computer.
  2018. //---------------------------------------------------------------------------------------------
  2019. STDMETHODIMP CIManageDB::SetServiceAcctEntryStatus(BSTR sComp, BSTR sSvc, BSTR sAcct, long Status)
  2020. {
  2021. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2022. HRESULT hr = S_OK;
  2023. try
  2024. {
  2025. _variant_t var;
  2026. _bstr_t sQuery;
  2027. WCHAR sTemp[LEN_Path];
  2028. wsprintf(sTemp, L"Select * from ServiceAccounts where System = \"%s\" and Service = \"%s\"", (WCHAR*) sComp, (WCHAR*) sSvc);
  2029. sQuery = sTemp;
  2030. _variant_t vtSource = sQuery;
  2031. _RecordsetPtr pRs(__uuidof(Recordset));
  2032. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2033. if ( !pRs->EndOfFile )
  2034. {
  2035. if ( sAcct )
  2036. {
  2037. var = _bstr_t(sAcct);
  2038. pRs->Fields->GetItem(L"Account")->Value = var;
  2039. }
  2040. var = Status;
  2041. pRs->Fields->GetItem(L"Status")->Value = var;
  2042. pRs->Update();
  2043. }
  2044. else
  2045. {
  2046. hr = E_INVALIDARG;
  2047. }
  2048. }
  2049. catch (_com_error& ce)
  2050. {
  2051. hr = ce.Error();
  2052. }
  2053. catch (...)
  2054. {
  2055. hr = E_FAIL;
  2056. }
  2057. return hr;
  2058. }
  2059. //---------------------------------------------------------------------------------------------
  2060. // SetDistActionStatus : Sets the Distributed action's status and its message.
  2061. //---------------------------------------------------------------------------------------------
  2062. STDMETHODIMP CIManageDB::SetDistActionStatus(long lActionID, BSTR sComp, long lStatus, BSTR sText)
  2063. {
  2064. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2065. HRESULT hr = S_OK;
  2066. try
  2067. {
  2068. _variant_t var;
  2069. _bstr_t sQuery;
  2070. WCHAR sTemp[LEN_Path];
  2071. if ( lActionID == -1 )
  2072. {
  2073. // lookup by the job filename
  2074. wsprintf(sTemp,L"Select * from DistributedAction where ResultFile = \"%s\"",(WCHAR*) sComp);
  2075. }
  2076. else
  2077. {
  2078. // lookup by action ID and computer name
  2079. wsprintf(sTemp, L"Select * from DistributedAction where ServerName = \"%s\" and ActionID = %d", (WCHAR*) sComp, lActionID);
  2080. }
  2081. sQuery = sTemp;
  2082. _variant_t vtSource = sQuery;
  2083. _RecordsetPtr pRs(__uuidof(Recordset));
  2084. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2085. if ( !pRs->EndOfFile )
  2086. {
  2087. var = _bstr_t(sText);
  2088. pRs->Fields->GetItem(L"StatusText")->Value = var;
  2089. var = lStatus;
  2090. pRs->Fields->GetItem(L"Status")->Value = var;
  2091. pRs->Update();
  2092. }
  2093. else
  2094. {
  2095. hr = E_INVALIDARG;
  2096. }
  2097. }
  2098. catch (_com_error& ce)
  2099. {
  2100. hr = ce.Error();
  2101. }
  2102. catch (...)
  2103. {
  2104. hr = E_FAIL;
  2105. }
  2106. return hr;
  2107. }
  2108. //---------------------------------------------------------------------------------------------
  2109. // CancelDistributedAction : Deletes a pirticular distributed action
  2110. //---------------------------------------------------------------------------------------------
  2111. STDMETHODIMP CIManageDB::CancelDistributedAction(long lActionID, BSTR sComp)
  2112. {
  2113. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2114. WCHAR sFilter[LEN_Path];
  2115. wsprintf(sFilter, L"ActionID = %d and ServerName = \"%s\"", lActionID, (WCHAR*) sComp);
  2116. _variant_t Filter = sFilter;
  2117. return ClearTable(L"DistributedAction", Filter);
  2118. }
  2119. //---------------------------------------------------------------------------------------------
  2120. // AddAcctRef : Adds an account reference record.
  2121. //---------------------------------------------------------------------------------------------
  2122. STDMETHODIMP CIManageDB::AddAcctRef(BSTR sDomain, BSTR sAcct, BSTR sAcctSid, BSTR sComp, long lCount, BSTR sType)
  2123. {
  2124. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2125. HRESULT hr = S_OK;
  2126. try
  2127. {
  2128. time_t tm;
  2129. COleDateTime dt(time(&tm));
  2130. _variant_t var;
  2131. WCHAR sFilter[LEN_Path];
  2132. VARIANT_BOOL bSidColumn = VARIANT_FALSE;
  2133. //find out if the new sid column is there, if not, don't try
  2134. //writing to it
  2135. SidColumnInARTable(&bSidColumn);
  2136. wsprintf(sFilter, L"DomainName = \"%s\" and Server = \"%s\" and Account = \"%s\" and RefType = \"%s\"", sDomain, sComp, sAcct, sType);
  2137. var = sFilter;
  2138. ClearTable(L"AccountRefs", var);
  2139. _RecordsetPtr pRs(__uuidof(Recordset));
  2140. _variant_t vtSource = L"AccountRefs";
  2141. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2142. pRs->AddNew();
  2143. pRs->Fields->GetItem(L"Time")->Value = DATE(dt);
  2144. pRs->Fields->GetItem(L"DomainName")->Value = sDomain;
  2145. pRs->Fields->GetItem(L"Server")->Value = sComp;
  2146. pRs->Fields->GetItem(L"Account")->Value = sAcct;
  2147. pRs->Fields->GetItem(L"RefCount")->Value = lCount;
  2148. pRs->Fields->GetItem(L"RefType")->Value = sType;
  2149. if (bSidColumn)
  2150. {
  2151. wcscpy((WCHAR*) sAcctSid, UStrUpr((WCHAR*)sAcctSid));
  2152. pRs->Fields->GetItem(L"AccountSid")->Value = sAcctSid;
  2153. }
  2154. pRs->Update();
  2155. }
  2156. catch (_com_error& ce)
  2157. {
  2158. hr = ce.Error();
  2159. }
  2160. catch (...)
  2161. {
  2162. hr = E_FAIL;
  2163. }
  2164. return hr;
  2165. }
  2166. void CIManageDB::ClipVarset(IVarSetPtr pVS)
  2167. {
  2168. HRESULT hr = S_OK;
  2169. _bstr_t sTemp, keyName, sTempKey;
  2170. long offset = 0;
  2171. bool cont = true;
  2172. WCHAR sKeyName[MAX_BUF_LEN];
  2173. _variant_t varKey, value;
  2174. IEnumVARIANT * varEnum;
  2175. DWORD nGot = 0;
  2176. IUnknown * pEnum = NULL;
  2177. CString strTemp;
  2178. int len;
  2179. // we are now going to enumerate through the varset and clip the strings if larger then MAX_BUFFER
  2180. hr = pVS->get__NewEnum(&pEnum);
  2181. if ( SUCCEEDED(hr) )
  2182. {
  2183. // Get the IEnumVARIANT pointer to enumerate
  2184. hr = pEnum->QueryInterface(IID_IEnumVARIANT,(void**)&varEnum);
  2185. pEnum->Release();
  2186. pEnum = NULL;
  2187. }
  2188. if ( SUCCEEDED(hr))
  2189. {
  2190. while ( (hr = varEnum->Next(1,&varKey,&nGot)) == S_OK )
  2191. {
  2192. if ( nGot > 0 )
  2193. {
  2194. keyName = V_BSTR(&varKey);
  2195. value = pVS->get(keyName);
  2196. if ( value.vt == VT_BSTR )
  2197. {
  2198. sTemp = value;
  2199. if ( sTemp.length() > MAX_BUF_LEN )
  2200. {
  2201. CString str((WCHAR*) sTemp);
  2202. // This won't fit in the buffer. We need to break it up and save
  2203. while (cont)
  2204. {
  2205. cont = false;
  2206. strTemp = str.Mid((offset*255), 255);
  2207. len = strTemp.GetLength();
  2208. if ( len )
  2209. {
  2210. offset++;
  2211. wsprintf(sKeyName, L"BROKEN.%s.%d", (WCHAR*) keyName, offset);
  2212. sTempKey = sKeyName;
  2213. sTemp = strTemp;
  2214. pVS->put(sTempKey, sTemp);
  2215. cont = (len == 255);
  2216. }
  2217. }
  2218. pVS->put(keyName, L"DIVIDED_KEY");
  2219. wsprintf(sKeyName, L"BROKEN.%s", (WCHAR*) keyName);
  2220. sTempKey = sKeyName;
  2221. pVS->put(sTempKey, offset);
  2222. cont = true;
  2223. offset = 0;
  2224. }
  2225. }
  2226. }
  2227. }
  2228. varEnum->Release();
  2229. }
  2230. }
  2231. void CIManageDB::RestoreVarset(IVarSetPtr pVS)
  2232. {
  2233. HRESULT hr = S_OK;
  2234. _bstr_t sTemp, keyName, sTempKey;
  2235. long offset = 0;
  2236. bool cont = true;
  2237. WCHAR sKeyName[MAX_BUF_LEN];
  2238. _variant_t varKey, value;
  2239. IEnumVARIANT * varEnum;
  2240. DWORD nGot = 0;
  2241. IUnknown * pEnum = NULL;
  2242. _bstr_t strTemp;
  2243. // we are now going to enumerate through the varset and clip the strings if larger then MAX_BUFFER
  2244. hr = pVS->get__NewEnum(&pEnum);
  2245. if ( SUCCEEDED(hr) )
  2246. {
  2247. // Get the IEnumVARIANT pointer to enumerate
  2248. hr = pEnum->QueryInterface(IID_IEnumVARIANT,(void**)&varEnum);
  2249. pEnum->Release();
  2250. pEnum = NULL;
  2251. }
  2252. if ( SUCCEEDED(hr))
  2253. {
  2254. while ( (hr = varEnum->Next(1,&varKey,&nGot)) == S_OK )
  2255. {
  2256. if ( nGot > 0 )
  2257. {
  2258. keyName = V_BSTR(&varKey);
  2259. value = pVS->get(keyName);
  2260. if ( value.vt == VT_BSTR )
  2261. {
  2262. sTemp = value;
  2263. if (!_wcsicmp((WCHAR*)sTemp, L"DIVIDED_KEY"))
  2264. {
  2265. wsprintf(sKeyName, L"BROKEN.%s", (WCHAR*) keyName);
  2266. sTempKey = sKeyName;
  2267. value = pVS->get(sTempKey);
  2268. if ( value.vt == VT_I4 )
  2269. {
  2270. offset = value.lVal;
  2271. for ( long x = 1; x <= offset; x++ )
  2272. {
  2273. wsprintf(sKeyName, L"BROKEN.%s.%d", (WCHAR*) keyName, x);
  2274. sTempKey = sKeyName;
  2275. value = pVS->get(sTempKey);
  2276. if ( value.vt == VT_BSTR )
  2277. {
  2278. sTemp = value;
  2279. strTemp += V_BSTR(&value);
  2280. }
  2281. }
  2282. pVS->put(keyName, strTemp);
  2283. strTemp = L"";
  2284. }
  2285. }
  2286. }
  2287. }
  2288. }
  2289. varEnum->Release();
  2290. }
  2291. }
  2292. STDMETHODIMP CIManageDB::AddSourceObject(BSTR sDomain, BSTR sSAMName, BSTR sType, BSTR sRDN, BSTR sCanonicalName, LONG bSource)
  2293. {
  2294. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2295. HRESULT hr = S_OK;
  2296. try
  2297. {
  2298. m_rsAccounts->AddNew();
  2299. m_rsAccounts->Fields->GetItem(L"Domain")->Value = sDomain;
  2300. m_rsAccounts->Fields->GetItem(L"Name")->Value = sSAMName;
  2301. wcscpy((WCHAR*) sType, UStrLwr((WCHAR*)sType));
  2302. m_rsAccounts->Fields->GetItem(L"Type")->Value = sType;
  2303. m_rsAccounts->Fields->GetItem(L"RDN")->Value = sRDN;
  2304. m_rsAccounts->Fields->GetItem(L"Canonical Name")->Value = sCanonicalName;
  2305. m_rsAccounts->Update();
  2306. }
  2307. catch (_com_error& ce)
  2308. {
  2309. hr = ce.Error();
  2310. }
  2311. catch (...)
  2312. {
  2313. hr = E_FAIL;
  2314. }
  2315. return hr;
  2316. }
  2317. STDMETHODIMP CIManageDB::OpenAccountsTable(LONG bSource)
  2318. {
  2319. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2320. HRESULT hr = S_OK;
  2321. try
  2322. {
  2323. if (m_rsAccounts->State == adStateClosed)
  2324. {
  2325. _variant_t vtSource;
  2326. if ( bSource )
  2327. vtSource = L"SourceAccounts";
  2328. else
  2329. vtSource = L"TargetAccounts";
  2330. //if not modified already, modify the table
  2331. if (!NCTablesColumnsChanged(bSource))
  2332. hr = ChangeNCTableColumns(bSource);
  2333. if (SUCCEEDED(hr))
  2334. m_rsAccounts->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2335. }
  2336. else
  2337. hr = S_FALSE;
  2338. }
  2339. catch (_com_error& ce)
  2340. {
  2341. hr = ce.Error();
  2342. }
  2343. catch (...)
  2344. {
  2345. hr = E_FAIL;
  2346. }
  2347. return hr;
  2348. }
  2349. STDMETHODIMP CIManageDB::CloseAccountsTable()
  2350. {
  2351. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2352. HRESULT hr = S_OK;
  2353. try
  2354. {
  2355. if (m_rsAccounts->State == adStateOpen)
  2356. {
  2357. m_rsAccounts->Close();
  2358. }
  2359. }
  2360. catch (_com_error& ce)
  2361. {
  2362. hr = ce.Error();
  2363. }
  2364. catch (...)
  2365. {
  2366. hr = E_FAIL;
  2367. }
  2368. return hr;
  2369. }
  2370. // Returns the number of entries in the migratedobjects table.
  2371. STDMETHODIMP CIManageDB::AreThereAnyMigratedObjects(long *count)
  2372. {
  2373. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2374. HRESULT hr = S_OK;
  2375. try
  2376. {
  2377. _RecordsetPtr pRs(__uuidof(Recordset));
  2378. _variant_t vtSource = L"MigratedObjects";
  2379. WCHAR sActionInfo[LEN_Path];
  2380. _variant_t var;
  2381. wcscpy(sActionInfo, L"Select count(*) as NUM from MigratedObjects");
  2382. vtSource = _bstr_t(sActionInfo);
  2383. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2384. var = pRs->Fields->GetItem((long)0)->Value;
  2385. * count = var.lVal;
  2386. }
  2387. catch (_com_error& ce)
  2388. {
  2389. hr = ce.Error();
  2390. }
  2391. catch (...)
  2392. {
  2393. hr = E_FAIL;
  2394. }
  2395. return hr;
  2396. }
  2397. STDMETHODIMP CIManageDB::GetActionHistoryKey(long lActionID, BSTR sKeyName, VARIANT *pVar)
  2398. {
  2399. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2400. HRESULT hr = S_OK;
  2401. try
  2402. {
  2403. _RecordsetPtr pRs(__uuidof(Recordset));
  2404. _variant_t vtSource;
  2405. WCHAR sActionInfo[LEN_Path];
  2406. _variant_t var;
  2407. wsprintf(sActionInfo, L"Select * from ActionHistory where Property = \"%s\" and ActionID = %d", (WCHAR*) sKeyName, lActionID);
  2408. vtSource = _bstr_t(sActionInfo);
  2409. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2410. if ((pRs->BOF == VARIANT_FALSE) && (pRs->EndOfFile == VARIANT_FALSE))
  2411. {
  2412. GetVarFromDB(pRs, var);
  2413. }
  2414. *pVar = var.Detach();
  2415. }
  2416. catch (_com_error& ce)
  2417. {
  2418. hr = ce.Error();
  2419. }
  2420. catch (...)
  2421. {
  2422. hr = E_FAIL;
  2423. }
  2424. return hr;
  2425. }
  2426. STDMETHODIMP CIManageDB::GetMigratedObjectBySourceDN(BSTR sSourceDN, IUnknown **ppUnk)
  2427. {
  2428. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2429. HRESULT hr = S_OK;
  2430. try
  2431. {
  2432. _RecordsetPtr pRs(__uuidof(Recordset));
  2433. _variant_t vtSource = L"MigratedObjects";
  2434. IVarSetPtr pVs = *ppUnk;
  2435. WCHAR sActionInfo[LEN_Path];
  2436. long lCnt = 0;
  2437. _bstr_t sName;
  2438. // If the parameters are not correct then we need to return an error
  2439. if ( (wcslen(sSourceDN) == 0) )
  2440. _com_issue_error(E_INVALIDARG);
  2441. wsprintf(sActionInfo, L"SELECT * FROM MigratedObjects WHERE SourceAdsPath Like '%%%s'", (WCHAR*) sSourceDN);
  2442. vtSource = sActionInfo;
  2443. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2444. if (pRs->GetRecordCount() > 0)
  2445. {
  2446. // We want the latest move.
  2447. pRs->MoveLast();
  2448. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_ActionID));
  2449. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  2450. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Time));
  2451. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  2452. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomain));
  2453. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  2454. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetDomain));
  2455. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  2456. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceAdsPath));
  2457. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  2458. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetAdsPath));
  2459. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  2460. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_status));
  2461. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  2462. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceSamName));
  2463. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  2464. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetSamName));
  2465. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  2466. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Type));
  2467. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  2468. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  2469. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  2470. //delineation
  2471. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  2472. if (wcsstr((WCHAR*)sType, L"group"))
  2473. sType = L"group";
  2474. pVs->put(sActionInfo, sType);
  2475. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_GUID));
  2476. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  2477. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceRid));
  2478. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  2479. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetRid));
  2480. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  2481. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomainSid));
  2482. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  2483. }
  2484. else
  2485. {
  2486. hr = S_FALSE;
  2487. }
  2488. }
  2489. catch (_com_error& ce)
  2490. {
  2491. hr = ce.Error();
  2492. }
  2493. catch (...)
  2494. {
  2495. hr = E_FAIL;
  2496. }
  2497. return hr;
  2498. }
  2499. STDMETHODIMP CIManageDB::SaveUserProps(IUnknown * pUnk)
  2500. {
  2501. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2502. HRESULT hr = S_OK;
  2503. try
  2504. {
  2505. _RecordsetPtr pRs(__uuidof(Recordset));
  2506. _variant_t vtSource;
  2507. IVarSetPtr pVs = pUnk;
  2508. WCHAR sQuery[LEN_Path];
  2509. WCHAR sSource[LEN_Path], sDomain[LEN_Path];
  2510. HRESULT hr = S_OK;
  2511. bool bComp = false;
  2512. _variant_t var;
  2513. var = pVs->get(GET_BSTR(DCTVS_Options_SourceDomain));
  2514. wcscpy(sDomain, (WCHAR*)V_BSTR(&var));
  2515. var = pVs->get(GET_BSTR(DCTVS_CopiedAccount_SourceSam));
  2516. wcscpy(sSource, (WCHAR*)V_BSTR(&var));
  2517. wsprintf(sQuery, L"delete from UserProps where SourceDomain=\"%s\" and SourceSam=\"%s\"",
  2518. sDomain, sSource);
  2519. vtSource = _bstr_t(sQuery);
  2520. hr = pRs->raw_Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  2521. vtSource = L"UserProps";
  2522. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2523. pRs->AddNew();
  2524. pRs->Fields->GetItem(L"ActionID")->Value = pVs->get(GET_BSTR(DB_ActionID));
  2525. pRs->Fields->GetItem(L"SourceDomain")->Value = sDomain;
  2526. pRs->Fields->GetItem(L"SourceSam")->Value = sSource;
  2527. pRs->Fields->GetItem(L"Flags")->Value = pVs->get(GET_BSTR(DCTVS_CopiedAccount_UserFlags));
  2528. pRs->Fields->GetItem(L"Expires")->Value = pVs->get(GET_BSTR(DCTVS_CopiedAccount_ExpDate));
  2529. pRs->Update();
  2530. }
  2531. catch (_com_error& ce)
  2532. {
  2533. hr = ce.Error();
  2534. }
  2535. catch (...)
  2536. {
  2537. hr = E_FAIL;
  2538. }
  2539. return hr;
  2540. }
  2541. STDMETHODIMP CIManageDB::GetUserProps(BSTR sDom, BSTR sSam, IUnknown **ppUnk)
  2542. {
  2543. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2544. HRESULT hr = S_OK;
  2545. try
  2546. {
  2547. _RecordsetPtr pRs(__uuidof(Recordset));
  2548. IVarSetPtr pVs = *ppUnk;
  2549. // If the parameters are not correct then we need to return an error
  2550. if ( !wcslen((WCHAR*)sDom) && !wcslen((WCHAR*)sSam) )
  2551. _com_issue_error(E_INVALIDARG);
  2552. _CommandPtr spCommand (__uuidof(Command));
  2553. spCommand->ActiveConnection = m_cn;
  2554. spCommand->CommandText =
  2555. L"PARAMETERS SD Text ( 255 ), SS Text ( 50 ); "
  2556. L"SELECT UserProps.* "
  2557. L"FROM UserProps "
  2558. L"WHERE (((UserProps.SourceDomain)=[SD]) AND ((UserProps.SourceSam)=[SS])) ";
  2559. spCommand->CommandType = adCmdText;
  2560. spCommand->Parameters->Append(spCommand->CreateParameter(L"SD", adBSTR, adParamInput, 255, sDom));
  2561. spCommand->Parameters->Append(spCommand->CreateParameter(L"SS", adBSTR, adParamInput, 50, sSam));
  2562. _variant_t vntSource(IDispatchPtr(spCommand).GetInterfacePtr());
  2563. pRs->Open(vntSource, vtMissing, adOpenStatic, adLockReadOnly, adCmdUnspecified);
  2564. if (pRs->GetRecordCount() > 0)
  2565. {
  2566. // We want the latest move.
  2567. pRs->MoveLast();
  2568. pVs->put(L"ActionID",pRs->Fields->GetItem(L"ActionID")->Value);
  2569. pVs->put(L"SourceDomain",pRs->Fields->GetItem(L"SourceDomain")->Value);
  2570. pVs->put(L"SourceSam",pRs->Fields->GetItem(L"SourceSam")->Value);
  2571. pVs->put(GET_BSTR(DCTVS_CopiedAccount_UserFlags),pRs->Fields->GetItem(L"Flags")->Value);
  2572. pVs->put(GET_BSTR(DCTVS_CopiedAccount_ExpDate),pRs->Fields->GetItem(L"Expires")->Value);
  2573. }
  2574. else
  2575. {
  2576. hr = S_FALSE;
  2577. }
  2578. }
  2579. catch (_com_error& ce)
  2580. {
  2581. hr = ce.Error();
  2582. }
  2583. catch (...)
  2584. {
  2585. hr = E_FAIL;
  2586. }
  2587. return hr;
  2588. }
  2589. /*********************************************************************
  2590. * *
  2591. * Written by: Paul Thompson *
  2592. * Date: 18 AUG 2000 *
  2593. * *
  2594. * This protected member function of the CIManageDB checks to see*
  2595. * if the new Source domain SID column is in the MigratedObjects *
  2596. * table. *
  2597. * *
  2598. *********************************************************************/
  2599. //BEGIN SrcSidColumnInMigratedObjectsTable
  2600. STDMETHODIMP CIManageDB::SrcSidColumnInMigratedObjectsTable(VARIANT_BOOL *pbFound)
  2601. {
  2602. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2603. HRESULT hr = S_OK;
  2604. *pbFound = VARIANT_FALSE;
  2605. try
  2606. {
  2607. _RecordsetPtr pRs(__uuidof(Recordset));
  2608. _variant_t vtSource = L"MigratedObjects";
  2609. long numColumns;
  2610. long ndx = 0;
  2611. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2612. //get the number of columns
  2613. numColumns = pRs->Fields->GetCount();
  2614. //look for new column's name in each column header
  2615. while ((ndx < numColumns) && (*pbFound == VARIANT_FALSE))
  2616. {
  2617. //get the column name
  2618. _variant_t var(ndx);
  2619. _bstr_t columnName = pRs->Fields->GetItem(var)->Name;
  2620. //if this is the Src Sid column then set return value flag to true
  2621. if (!_wcsicmp((WCHAR*)columnName, GET_BSTR(DB_SourceDomainSid)))
  2622. *pbFound = VARIANT_TRUE;
  2623. ndx++;
  2624. }
  2625. }
  2626. catch (_com_error& ce)
  2627. {
  2628. hr = ce.Error();
  2629. }
  2630. catch (...)
  2631. {
  2632. hr = E_FAIL;
  2633. }
  2634. return hr;
  2635. }
  2636. //END SrcSidColumnInMigratedObjectsTable
  2637. /*********************************************************************
  2638. * *
  2639. * Written by: Paul Thompson *
  2640. * Date: 18 AUG 2000 *
  2641. * *
  2642. * This protected member function of the CIManageDB retrieves *
  2643. * information about previously migrated objects, from a MOT missing *
  2644. * the source sid column, within a given action or as a whole. *
  2645. * *
  2646. *********************************************************************/
  2647. //BEGIN GetMigratedObjectsFromOldMOT
  2648. STDMETHODIMP CIManageDB::GetMigratedObjectsFromOldMOT(long lActionID, IUnknown ** ppUnk)
  2649. {
  2650. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2651. HRESULT hr = S_OK;
  2652. // This function returns all migrated objects and their information related
  2653. // to a pirticular Action ID. This is going to return nothing if the actionID is
  2654. // empty.
  2655. try
  2656. {
  2657. _RecordsetPtr pRs(__uuidof(Recordset));
  2658. _variant_t vtSource = L"MigratedObjects";
  2659. IVarSetPtr pVs = *ppUnk;
  2660. WCHAR sActionInfo[255];
  2661. long lCnt = 0;
  2662. if ( lActionID != -1 )
  2663. {
  2664. // If a valid ActionID is specified then we only return the data for that one.
  2665. // but if -1 is passed in then we return all migrated objects.
  2666. wsprintf(sActionInfo, L"ActionID=%d", lActionID);
  2667. pRs->Filter = sActionInfo;
  2668. }
  2669. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2670. if (pRs->GetRecordCount() > 0)
  2671. {
  2672. pRs->MoveFirst();
  2673. while ( !pRs->EndOfFile )
  2674. {
  2675. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_ActionID));
  2676. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  2677. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Time));
  2678. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  2679. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomain));
  2680. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  2681. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetDomain));
  2682. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  2683. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceAdsPath));
  2684. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  2685. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetAdsPath));
  2686. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  2687. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_status));
  2688. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  2689. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceSamName));
  2690. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  2691. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetSamName));
  2692. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  2693. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Type));
  2694. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Type")->Value);
  2695. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_GUID));
  2696. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  2697. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceRid));
  2698. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  2699. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetRid));
  2700. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  2701. pRs->MoveNext();
  2702. lCnt++;
  2703. }
  2704. pVs->put(L"MigratedObjects", lCnt);
  2705. }
  2706. else
  2707. {
  2708. hr = S_FALSE;
  2709. }
  2710. }
  2711. catch (_com_error& ce)
  2712. {
  2713. hr = ce.Error();
  2714. }
  2715. catch (...)
  2716. {
  2717. hr = E_FAIL;
  2718. }
  2719. return hr;
  2720. }
  2721. //END GetMigratedObjectsFromOldMOT
  2722. /*********************************************************************
  2723. * *
  2724. * Written by: Paul Thompson *
  2725. * Date: 18 AUG 2000 *
  2726. * *
  2727. * This protected member function of the CIManageDB adds the *
  2728. * source domain SID column to the MigratedObjects table. *
  2729. * *
  2730. *********************************************************************/
  2731. //BEGIN CreateSrcSidColumnInMOT
  2732. STDMETHODIMP CIManageDB::CreateSrcSidColumnInMOT(VARIANT_BOOL *pbCreated)
  2733. {
  2734. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2735. /* local constants */
  2736. const long COLUMN_MAX_CHARS = 255;
  2737. /* local variables */
  2738. HRESULT hr = S_OK;
  2739. /* function body */
  2740. *pbCreated = VARIANT_FALSE;
  2741. try
  2742. {
  2743. ADOX::_CatalogPtr m_pCatalog(__uuidof(ADOX::Catalog));
  2744. ADOX::_TablePtr m_pTable = NULL;
  2745. WCHAR sConnect[MAX_PATH];
  2746. WCHAR sDir[MAX_PATH];
  2747. // Get the path to the MDB file from the registry
  2748. TRegKey key;
  2749. DWORD rc = key.Open(sKeyBase);
  2750. if ( !rc )
  2751. rc = key.ValueGetStr(L"Directory", sDir, MAX_PATH);
  2752. if ( rc != 0 )
  2753. wcscpy(sDir, L"");
  2754. // Now build the connect string.
  2755. wsprintf(sConnect, L"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sprotar.mdb;", sDir);
  2756. //Open the catalog
  2757. m_pCatalog->PutActiveConnection(sConnect);
  2758. //get a pointer to the database's MigratedObjects Table
  2759. m_pTable = m_pCatalog->Tables->Item[L"MigratedObjects"];
  2760. //append a new column to the end of the MOT
  2761. m_pTable->Columns->Append(L"SourceDomainSid", adVarWChar, COLUMN_MAX_CHARS);
  2762. //set the column to be nullable
  2763. // ADOX::_ColumnPtr pColumn = m_pTable->Columns->Item[L"SourceDomainSid"];
  2764. // pColumn->Attributes = ADOX::adColNullable;
  2765. *pbCreated = VARIANT_TRUE;
  2766. }
  2767. catch (_com_error& ce)
  2768. {
  2769. hr = ce.Error();
  2770. }
  2771. catch (...)
  2772. {
  2773. hr = E_FAIL;
  2774. }
  2775. return hr;
  2776. }
  2777. //END CreateSrcSidColumnInMOT
  2778. /*********************************************************************
  2779. * *
  2780. * Written by: Paul Thompson *
  2781. * Date: 22 AUG 2000 *
  2782. * *
  2783. * This protected member function of the CIManageDB deletes the *
  2784. * source domain SID column from the MigratedObjects table. *
  2785. * *
  2786. *********************************************************************/
  2787. //BEGIN DeleteSrcSidColumnInMOT
  2788. STDMETHODIMP CIManageDB::DeleteSrcSidColumnInMOT(VARIANT_BOOL *pbDeleted)
  2789. {
  2790. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2791. /* local constants */
  2792. /* local variables */
  2793. HRESULT hr = S_OK;
  2794. /* function body */
  2795. *pbDeleted = VARIANT_FALSE;
  2796. try
  2797. {
  2798. ADOX::_CatalogPtr m_pCatalog(__uuidof(ADOX::Catalog));
  2799. ADOX::_TablePtr m_pTable = NULL;
  2800. WCHAR sConnect[MAX_PATH];
  2801. WCHAR sDir[MAX_PATH];
  2802. // Get the path to the MDB file from the registry
  2803. TRegKey key;
  2804. DWORD rc = key.Open(sKeyBase);
  2805. if ( !rc )
  2806. rc = key.ValueGetStr(L"Directory", sDir, MAX_PATH);
  2807. if ( rc != 0 )
  2808. wcscpy(sDir, L"");
  2809. // Now build the connect string.
  2810. wsprintf(sConnect, L"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sprotar.mdb;", sDir);
  2811. //Open the catalog
  2812. m_pCatalog->PutActiveConnection(sConnect);
  2813. //get a pointer to the database's MigratedObjects Table
  2814. m_pTable = m_pCatalog->Tables->Item[L"MigratedObjects"];
  2815. //delete the column from the MOT
  2816. m_pTable->Columns->Delete(L"SourceDomainSid");
  2817. *pbDeleted = VARIANT_TRUE;
  2818. }
  2819. catch (_com_error& ce)
  2820. {
  2821. hr = ce.Error();
  2822. }
  2823. catch (...)
  2824. {
  2825. hr = E_FAIL;
  2826. }
  2827. return hr;
  2828. }
  2829. //END DeleteSrcSidColumnInMOT
  2830. /*********************************************************************
  2831. * *
  2832. * Written by: Paul Thompson *
  2833. * Date: 21 AUG 2000 *
  2834. * *
  2835. * This protected member function of the CIManageDB populates the*
  2836. * new Source domain SID column in the MigratedObjects table for all *
  2837. * entries from the given domain. If the domain cannot be reached no*
  2838. * entry is added. *
  2839. * *
  2840. *********************************************************************/
  2841. //BEGIN PopulateSrcSidColumnByDomain
  2842. STDMETHODIMP CIManageDB::PopulateSrcSidColumnByDomain(BSTR sDomainName,
  2843. BSTR sSid,
  2844. VARIANT_BOOL * pbPopulated)
  2845. {
  2846. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2847. /* local variables */
  2848. HRESULT hr = S_OK;
  2849. PSID pSid = NULL;
  2850. DWORD rc = 0;
  2851. _bstr_t domctrl;
  2852. WCHAR txtSid[MAX_PATH];
  2853. DWORD dwArraySizeOfTxtSid = sizeof(txtSid)/sizeof(txtSid[0]);
  2854. DWORD lenTxt = DIM(txtSid);
  2855. /* function body */
  2856. *pbPopulated = VARIANT_FALSE; //init flag to false
  2857. try
  2858. {
  2859. _RecordsetPtr pRs(__uuidof(Recordset));
  2860. WCHAR sActionInfo[MAX_PATH];
  2861. //if we don't already know the source sid then find it
  2862. if (sSid == NULL)
  2863. _com_issue_error(E_INVALIDARG);
  2864. if (wcslen(sSid) >= dwArraySizeOfTxtSid)
  2865. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  2866. wcscpy(txtSid, (WCHAR*)sSid);
  2867. if (!wcscmp(txtSid, L""))
  2868. {
  2869. //get the sid for this domain
  2870. if ( sDomainName[0] != L'\\' )
  2871. {
  2872. rc = GetAnyDcName5(sDomainName, domctrl);
  2873. }
  2874. if ( rc )
  2875. return hr;
  2876. rc = GetDomainSid(domctrl,&pSid);
  2877. if ( !GetTextualSid(pSid,txtSid,&lenTxt) )
  2878. {
  2879. if (pSid)
  2880. FreeSid(pSid);
  2881. return hr;
  2882. }
  2883. if (pSid)
  2884. FreeSid(pSid);
  2885. }
  2886. //
  2887. // Update source domain SID for all objects from specified source domain.
  2888. //
  2889. // Note that 'hand-constructed' SQL statement is okay here as the inputs
  2890. // are internally generated by ADMT.
  2891. //
  2892. _snwprintf(
  2893. sActionInfo,
  2894. sizeof(sActionInfo) / sizeof(sActionInfo[0]),
  2895. L"UPDATE MigratedObjects SET SourceDomainSid='%s' WHERE SourceDomain='%s'",
  2896. txtSid,
  2897. sDomainName
  2898. );
  2899. sActionInfo[sizeof(sActionInfo) / sizeof(sActionInfo[0]) - 1] = L'\0';
  2900. m_cn->Execute(_bstr_t(sActionInfo), &_variant_t(), adExecuteNoRecords);
  2901. *pbPopulated = VARIANT_TRUE; //set flag since populated
  2902. }
  2903. catch (_com_error& ce)
  2904. {
  2905. hr = ce.Error();
  2906. }
  2907. catch (...)
  2908. {
  2909. hr = E_FAIL;
  2910. }
  2911. return hr;
  2912. }
  2913. //END PopulateSrcSidColumnByDomain
  2914. /*********************************************************************
  2915. * *
  2916. * Written by: Paul Thompson *
  2917. * Date: 26 SEPT 2000 *
  2918. * *
  2919. * This protected member function of the CIManageDB checks to see*
  2920. * if the new Account SID column is in the Account References table. *
  2921. * *
  2922. *********************************************************************/
  2923. //BEGIN SidColumnInARTable
  2924. STDMETHODIMP CIManageDB::SidColumnInARTable(VARIANT_BOOL *pbFound)
  2925. {
  2926. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2927. HRESULT hr = S_OK;
  2928. *pbFound = VARIANT_FALSE;
  2929. try
  2930. {
  2931. _RecordsetPtr pRs(__uuidof(Recordset));
  2932. _variant_t vtSource = L"AccountRefs";
  2933. long numColumns;
  2934. long ndx = 0;
  2935. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  2936. //get the number of columns
  2937. numColumns = pRs->Fields->GetCount();
  2938. //look for new column's name in each column header
  2939. while ((ndx < numColumns) && (*pbFound == VARIANT_FALSE))
  2940. {
  2941. //get the column name
  2942. _variant_t var(ndx);
  2943. _bstr_t columnName = pRs->Fields->GetItem(var)->Name;
  2944. //if this is the Src Sid column then set return value flag to true
  2945. if (!_wcsicmp((WCHAR*)columnName, L"AccountSid"))
  2946. *pbFound = VARIANT_TRUE;
  2947. ndx++;
  2948. }
  2949. }
  2950. catch (_com_error& ce)
  2951. {
  2952. hr = ce.Error();
  2953. }
  2954. catch (...)
  2955. {
  2956. hr = E_FAIL;
  2957. }
  2958. return hr;
  2959. }
  2960. //END SidColumnInARTable
  2961. /*********************************************************************
  2962. * *
  2963. * Written by: Paul Thompson *
  2964. * Date: 26 SEPT 2000 *
  2965. * *
  2966. * This protected member function of the CIManageDB adds the *
  2967. * SID column to the Account Reference table, if it is not already *
  2968. * there. *
  2969. * *
  2970. *********************************************************************/
  2971. //BEGIN CreateSidColumnInAR
  2972. STDMETHODIMP CIManageDB::CreateSidColumnInAR()
  2973. {
  2974. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2975. /* local constants */
  2976. const long COLUMN_MAX_CHARS = 255;
  2977. /* local variables */
  2978. HRESULT hr = S_OK;
  2979. /* function body */
  2980. try
  2981. {
  2982. ADOX::_CatalogPtr m_pCatalog(__uuidof(ADOX::Catalog));
  2983. ADOX::_TablePtr m_pTable = NULL;
  2984. WCHAR sConnect[MAX_PATH];
  2985. WCHAR sDir[MAX_PATH];
  2986. // Get the path to the MDB file from the registry
  2987. TRegKey key;
  2988. DWORD rc = key.Open(sKeyBase);
  2989. if ( !rc )
  2990. rc = key.ValueGetStr(L"Directory", sDir, MAX_PATH);
  2991. if ( rc != 0 )
  2992. wcscpy(sDir, L"");
  2993. // Now build the connect string.
  2994. wsprintf(sConnect, L"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sprotar.mdb;", sDir);
  2995. //Open the catalog
  2996. m_pCatalog->PutActiveConnection(sConnect);
  2997. //get a pointer to the database's MigratedObjects Table
  2998. m_pTable = m_pCatalog->Tables->Item[L"AccountRefs"];
  2999. //append a new column to the end of the MOT
  3000. m_pTable->Columns->Append(L"AccountSid", adVarWChar, COLUMN_MAX_CHARS);
  3001. }
  3002. catch (_com_error& ce)
  3003. {
  3004. hr = ce.Error();
  3005. }
  3006. catch (...)
  3007. {
  3008. hr = E_FAIL;
  3009. }
  3010. return hr;
  3011. }
  3012. //END CreateSidColumnInAR
  3013. //---------------------------------------------------------------------------
  3014. // UpgradeDatabase
  3015. //
  3016. // Upgrades Protar.mdb database from version 3.x to 4.x. Version 4.x adds
  3017. // UNICODE support.
  3018. //
  3019. // 2001-02-13 Mark Oluper - initial
  3020. //---------------------------------------------------------------------------
  3021. void CIManageDB::UpgradeDatabase(LPCTSTR pszFolder)
  3022. {
  3023. try
  3024. {
  3025. _bstr_t strFolder = pszFolder;
  3026. _bstr_t strDatabase = strFolder + _T("Protar.mdb");
  3027. _bstr_t strDatabase3x = strFolder + _T("Protar3x.mdb");
  3028. _bstr_t strDatabase4x = strFolder + _T("Protar4x.mdb");
  3029. _bstr_t strConnectionPrefix = _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=");
  3030. _bstr_t strSourceConnection = strConnectionPrefix + strDatabase;
  3031. _bstr_t strTargetConnection = strConnectionPrefix + strDatabase4x + _T(";Jet OLEDB:Engine Type=5");
  3032. IJetEnginePtr spJetEngine(__uuidof(JetEngine));
  3033. HRESULT hr = spJetEngine->raw_CompactDatabase(strSourceConnection, strTargetConnection);
  3034. if (FAILED(hr))
  3035. {
  3036. AdmtThrowError(
  3037. hr,
  3038. _Module.GetResourceInstance(),
  3039. IDS_E_UPGRADE_TO_TEMPORARY,
  3040. (LPCTSTR)strDatabase,
  3041. (LPCTSTR)strDatabase4x
  3042. );
  3043. }
  3044. if (!MoveFileEx(strDatabase, strDatabase3x, MOVEFILE_WRITE_THROUGH))
  3045. {
  3046. DWORD dwError = GetLastError();
  3047. DeleteFile(strDatabase4x);
  3048. AdmtThrowError(
  3049. HRESULT_FROM_WIN32(dwError),
  3050. _Module.GetResourceInstance(),
  3051. IDS_E_UPGRADE_RENAME_ORIGINAL,
  3052. (LPCTSTR)strDatabase,
  3053. (LPCTSTR)strDatabase3x
  3054. );
  3055. }
  3056. if (!MoveFileEx(strDatabase4x, strDatabase, MOVEFILE_WRITE_THROUGH))
  3057. {
  3058. DWORD dwError = GetLastError();
  3059. MoveFileEx(strDatabase3x, strDatabase, MOVEFILE_WRITE_THROUGH);
  3060. DeleteFile(strDatabase4x);
  3061. AdmtThrowError(
  3062. HRESULT_FROM_WIN32(dwError),
  3063. _Module.GetResourceInstance(),
  3064. IDS_E_UPGRADE_RENAME_UPGRADED,
  3065. (LPCTSTR)strDatabase4x,
  3066. (LPCTSTR)strDatabase
  3067. );
  3068. }
  3069. }
  3070. catch (_com_error& ce)
  3071. {
  3072. AdmtThrowError(ce, _Module.GetResourceInstance(), IDS_E_UPGRADE_TO_4X);
  3073. }
  3074. catch (...)
  3075. {
  3076. AdmtThrowError(E_FAIL, _Module.GetResourceInstance(), IDS_E_UPGRADE_TO_4X);
  3077. }
  3078. }
  3079. //---------------------------------------------------------------------------
  3080. // UpdateDomainAndServerColumnWidths
  3081. //
  3082. // Synopsis
  3083. // Updates column widths that hold domain or server names to the maximum
  3084. // supported column width of 255 characters which is also the maximum length
  3085. // of a DNS name.
  3086. //
  3087. // Arguments
  3088. // IN spConnection - a pointer to a connection interface for the
  3089. // Protar database
  3090. //
  3091. // Return Value
  3092. // None - if an error occurs an exception is thrown.
  3093. //
  3094. // 2002-06-22 Mark Oluper - initial
  3095. //---------------------------------------------------------------------------
  3096. void CIManageDB::UpdateDomainAndServerColumnWidths(_ConnectionPtr spConnection)
  3097. {
  3098. static struct SColumnData
  3099. {
  3100. PCTSTR pszTableName;
  3101. PCTSTR pszColumnName;
  3102. PCTSTR pszIndexName;
  3103. }
  3104. s_ColumnData[] =
  3105. {
  3106. { _T("DistributedAction"), _T("ServerName"), _T("PrimaryKey") },
  3107. { _T("PasswordAge"), _T("DomainName"), _T("Domain") },
  3108. { _T("SourceAccounts"), _T("Domain"), _T("PrimaryKey") },
  3109. { _T("TargetAccounts"), _T("Domain"), _T("PrimaryKey") },
  3110. { _T("UserProps"), _T("SourceDomain"), _T("PrimaryKey") },
  3111. };
  3112. const int cColumnData = sizeof(s_ColumnData) / sizeof(s_ColumnData[0]);
  3113. const _TCHAR TEMPORARY_COLUMN_NAME[] = _T("TemporaryColumn");
  3114. const long MAX_COLUMN_SIZE = 255l;
  3115. try
  3116. {
  3117. //
  3118. // For each specified column verify column size and increase size
  3119. // if size is less than the maximum.
  3120. //
  3121. ADOX::_CatalogPtr spCatalog(__uuidof(ADOX::Catalog));
  3122. spCatalog->PutRefActiveConnection(IDispatchPtr(spConnection));
  3123. ADOX::TablesPtr spTables = spCatalog->Tables;
  3124. bool bColumnsUpdated = false;
  3125. for (int iColumnData = 0; iColumnData < cColumnData; iColumnData++)
  3126. {
  3127. //
  3128. // If the current column's defined size is less than the
  3129. // maximum column size then the column width must be increased.
  3130. //
  3131. SColumnData& data = s_ColumnData[iColumnData];
  3132. PCTSTR pszTableName = data.pszTableName;
  3133. PCTSTR pszColumnName = data.pszColumnName;
  3134. PCTSTR pszIndexName = data.pszIndexName;
  3135. ADOX::_TablePtr spTable = spTables->Item[pszTableName];
  3136. ADOX::ColumnsPtr spColumns = spTable->Columns;
  3137. ADOX::_ColumnPtr spOldColumn = spColumns->Item[pszColumnName];
  3138. if (spOldColumn->DefinedSize < MAX_COLUMN_SIZE)
  3139. {
  3140. //
  3141. // Create a new column with a temporary name. Assign the old column's type and attributes
  3142. // values to the new column. Set the new column's defined size equal to the maximum. Add
  3143. // the new column to the table.
  3144. //
  3145. // Note that a new column must be created in order to increase the column width.
  3146. //
  3147. ADOX::_ColumnPtr spNewColumn(__uuidof(ADOX::Column));
  3148. spNewColumn->Name = TEMPORARY_COLUMN_NAME;
  3149. spNewColumn->Type = spOldColumn->Type;
  3150. spNewColumn->Attributes = spOldColumn->Attributes;
  3151. spNewColumn->DefinedSize = MAX_COLUMN_SIZE;
  3152. spColumns->Append(_variant_t(IDispatchPtr(spNewColumn).GetInterfacePtr()), adVarWChar, 0);
  3153. //
  3154. // Set the new column's values equal to the old column's values.
  3155. //
  3156. _TCHAR szCommandText[256];
  3157. const size_t cchCommandText = sizeof(szCommandText) / sizeof(szCommandText[0]);
  3158. szCommandText[cchCommandText - 1] = _T('\0');
  3159. int cchStored = _sntprintf(
  3160. szCommandText,
  3161. cchCommandText,
  3162. _T("UPDATE [%s] SET [%s] = [%s]"),
  3163. pszTableName,
  3164. TEMPORARY_COLUMN_NAME,
  3165. pszColumnName
  3166. );
  3167. if ((cchStored < 0) || (szCommandText[cchCommandText - 1] != _T('\0')))
  3168. {
  3169. _ASSERT(FALSE);
  3170. _com_issue_error(E_FAIL);
  3171. }
  3172. szCommandText[cchCommandText - 1] = _T('\0');
  3173. m_cn->Execute(szCommandText, &_variant_t(), adExecuteNoRecords);
  3174. //
  3175. // Create new index. Assign old index's property values
  3176. // to new index including column names. Delete old index.
  3177. //
  3178. // Note that the old index must be deleted before deleting the old column.
  3179. //
  3180. ADOX::IndexesPtr spIndexes = spTable->Indexes;
  3181. ADOX::_IndexPtr spOldIndex = spIndexes->Item[pszIndexName];
  3182. ADOX::_IndexPtr spNewIndex(__uuidof(ADOX::Index));
  3183. spNewIndex->Name = spOldIndex->Name;
  3184. spNewIndex->Unique = spOldIndex->Unique;
  3185. spNewIndex->PrimaryKey = spOldIndex->PrimaryKey;
  3186. spNewIndex->IndexNulls = spOldIndex->IndexNulls;
  3187. spNewIndex->Clustered = spOldIndex->Clustered;
  3188. ADOX::ColumnsPtr spOldIndexColumns = spOldIndex->Columns;
  3189. ADOX::ColumnsPtr spNewIndexColumns = spNewIndex->Columns;
  3190. long cColumn = spOldIndexColumns->Count;
  3191. for (long iColumn = 0; iColumn < cColumn; iColumn++)
  3192. {
  3193. ADOX::_ColumnPtr spOldColumn = spOldIndexColumns->Item[iColumn];
  3194. spNewIndexColumns->Append(spOldColumn->Name, adVarWChar, 0);
  3195. }
  3196. spIndexes->Delete(pszIndexName);
  3197. //
  3198. // Delete old column and rename new column.
  3199. //
  3200. spOldColumn.Release();
  3201. spColumns->Delete(_variant_t(pszColumnName));
  3202. spNewColumn->Name = pszColumnName;
  3203. //
  3204. // Add the new index to the table.
  3205. //
  3206. // Note that the index must be added after renaming new column.
  3207. //
  3208. spIndexes->Append(_variant_t(IDispatchPtr(spNewIndex).GetInterfacePtr()));
  3209. //
  3210. // Set columns updated to true so that domain names will also be updated.
  3211. //
  3212. bColumnsUpdated = true;
  3213. }
  3214. }
  3215. spTables.Release();
  3216. spCatalog.Release();
  3217. //
  3218. // If columns have been updated then update domain names.
  3219. //
  3220. if (bColumnsUpdated)
  3221. {
  3222. UpdateDomainNames();
  3223. }
  3224. }
  3225. catch (_com_error& ce)
  3226. {
  3227. AdmtThrowError(ce, _Module.GetResourceInstance(), IDS_E_UNABLE_TO_UPDATE_COLUMNS);
  3228. }
  3229. catch (...)
  3230. {
  3231. AdmtThrowError(E_FAIL, _Module.GetResourceInstance(), IDS_E_UNABLE_TO_UPDATE_COLUMNS);
  3232. }
  3233. }
  3234. //---------------------------------------------------------------------------
  3235. // UpdateDomainNames
  3236. //
  3237. // Synopsis
  3238. // Updates domain names from NetBIOS name to DNS name.
  3239. //
  3240. // Arguments
  3241. // None
  3242. //
  3243. // Return Value
  3244. // None - if an error occurs an exception is thrown.
  3245. //
  3246. // 2002-09-15 Mark Oluper - initial
  3247. //---------------------------------------------------------------------------
  3248. void CIManageDB::UpdateDomainNames()
  3249. {
  3250. //
  3251. // AccountRefs - account references report is sorted on domain name
  3252. // therefore must update to keep old and new records
  3253. // together
  3254. // Conflict - table not used
  3255. // MigratedObjects - domain name is used to query for previously migrated
  3256. // objects therefore must update
  3257. // PasswordAge - domain name is used to update records therefore must
  3258. // update
  3259. // SourceAccounts - generation of name conflicts report clears table
  3260. // therefore not necessary to update
  3261. // TargetAccounts - generation of name conflicts report clears table
  3262. // therefore not necessary to update
  3263. // UserProps - domain name used to delete records therefore must
  3264. // update
  3265. //
  3266. static struct STableColumnData
  3267. {
  3268. PCTSTR pszTableName;
  3269. PCTSTR pszColumnName;
  3270. }
  3271. s_TableColumnData[] =
  3272. {
  3273. { _T("AccountRefs"), _T("DomainName") },
  3274. // { _T("Conflict"), _T("Domain") },
  3275. { _T("MigratedObjects"), _T("SourceDomain") },
  3276. { _T("MigratedObjects"), _T("TargetDomain") },
  3277. { _T("PasswordAge"), _T("DomainName") },
  3278. // { _T("SourceAccounts"), _T("Domain") },
  3279. // { _T("TargetAccounts"), _T("Domain") },
  3280. { _T("UserProps"), _T("SourceDomain") },
  3281. };
  3282. const int cTableColumnData = sizeof(s_TableColumnData) / sizeof(s_TableColumnData[0]);
  3283. //
  3284. // For each domain name column...
  3285. //
  3286. for (int iTableColumnData = 0; iTableColumnData < cTableColumnData; iTableColumnData++)
  3287. {
  3288. STableColumnData& data = s_TableColumnData[iTableColumnData];
  3289. PCTSTR pszTableName = data.pszTableName;
  3290. PCTSTR pszColumnName = data.pszColumnName;
  3291. //
  3292. // Retrieve unique domain names from column.
  3293. //
  3294. _RecordsetPtr spRecords = QueryUniqueColumnValues(pszTableName, pszColumnName);
  3295. FieldPtr spField = spRecords->Fields->Item[0L];
  3296. while (spRecords->EndOfFile == VARIANT_FALSE)
  3297. {
  3298. _bstr_t strDomain = spField->Value;
  3299. //
  3300. // If domain name is not a DNS name...
  3301. //
  3302. if ((PCTSTR)strDomain && (_tcschr(strDomain, _T('.')) == NULL))
  3303. {
  3304. //
  3305. // Attempt to retrieve DNS name of domain. First attempt to retrieve domain
  3306. // names using DC locator APIs. If this fails then attempt to retrieve
  3307. // domain names from ActionHistory table.
  3308. //
  3309. _bstr_t strDnsName;
  3310. _bstr_t strFlatName;
  3311. DWORD dwError = GetDomainNames5(strDomain, strFlatName, strDnsName);
  3312. if (dwError != ERROR_SUCCESS)
  3313. {
  3314. IUnknownPtr spunk;
  3315. HRESULT hr = GetSourceDomainInfo(strDomain, &spunk);
  3316. if (SUCCEEDED(hr))
  3317. {
  3318. IVarSetPtr spVarSet = spunk;
  3319. if (spVarSet)
  3320. {
  3321. strDnsName = spVarSet->get(_T("Options.SourceDomainDns"));
  3322. }
  3323. }
  3324. }
  3325. //
  3326. // If a DNS name has been retrieved...
  3327. //
  3328. if ((PCTSTR)strDnsName)
  3329. {
  3330. //
  3331. // Replace NetBIOS name with DNS name for all records in table.
  3332. //
  3333. UpdateColumnValues(pszTableName, pszColumnName, 255, strDomain, strDnsName);
  3334. }
  3335. }
  3336. spRecords->MoveNext();
  3337. }
  3338. }
  3339. }
  3340. //---------------------------------------------------------------------------
  3341. // QueryUniqueColumnValues
  3342. //
  3343. // Synopsis
  3344. // Retrieves a set of values which are unique in the specified column in the
  3345. // specified table.
  3346. //
  3347. // Note that a forward only, read only recordset is returned.
  3348. //
  3349. // Arguments
  3350. // IN pszTable - table name
  3351. // IN pszColumn - column name
  3352. //
  3353. // Return Value
  3354. // _RecordsetPtr - a forward only, read only recordset
  3355. //
  3356. // 2002-09-15 Mark Oluper - initial
  3357. //---------------------------------------------------------------------------
  3358. _RecordsetPtr CIManageDB::QueryUniqueColumnValues(PCTSTR pszTable, PCTSTR pszColumn)
  3359. {
  3360. //
  3361. // Generate select query.
  3362. //
  3363. // Note that the GROUP BY clause generates a result set containing only unique values.
  3364. //
  3365. _TCHAR szCommandText[256];
  3366. szCommandText[DIM(szCommandText) - 1] = _T('\0');
  3367. int cchStored = _sntprintf(
  3368. szCommandText, DIM(szCommandText),
  3369. _T("SELECT [%s] FROM [%s] GROUP BY [%s];"),
  3370. pszColumn, pszTable, pszColumn
  3371. );
  3372. if ((cchStored < 0) || (szCommandText[DIM(szCommandText) - 1] != _T('\0')))
  3373. {
  3374. _ASSERT(FALSE);
  3375. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  3376. }
  3377. szCommandText[DIM(szCommandText) - 1] = _T('\0');
  3378. //
  3379. // Retrieve unique values from column.
  3380. //
  3381. _RecordsetPtr spRecords(__uuidof(Recordset));
  3382. spRecords->Open(_variant_t(szCommandText), m_vtConn, adOpenForwardOnly, adLockReadOnly, adCmdText);
  3383. return spRecords;
  3384. }
  3385. //---------------------------------------------------------------------------
  3386. // UpdateColumnValues
  3387. //
  3388. // Synopsis
  3389. // Updates values in specified column in specified table. Sets the value to
  3390. // specified value B where value equals specified value A. Note that the only
  3391. // data type supported are strings.
  3392. //
  3393. // Arguments
  3394. // IN pszTable - table name
  3395. // IN pszColumn - column name
  3396. // IN nWidth - column width
  3397. // IN pszValueA - string value A
  3398. // IN pszValueB - string value B
  3399. //
  3400. // Return Value
  3401. // None - if an error occurs an exception is thrown.
  3402. //
  3403. // 2002-09-15 Mark Oluper - initial
  3404. //---------------------------------------------------------------------------
  3405. void CIManageDB::UpdateColumnValues
  3406. (
  3407. PCTSTR pszTable, PCTSTR pszColumn, int nWidth, PCTSTR pszValueA, PCTSTR pszValueB
  3408. )
  3409. {
  3410. //
  3411. // Generate parameterized update query.
  3412. //
  3413. _TCHAR szCommandText[256];
  3414. szCommandText[DIM(szCommandText) - 1] = _T('\0');
  3415. int cchStored = _sntprintf(
  3416. szCommandText, DIM(szCommandText),
  3417. _T("PARAMETERS A Text ( %d ), B Text ( %d ); ")
  3418. _T("UPDATE [%s] SET [%s]=[B] WHERE [%s]=[A];"),
  3419. nWidth, nWidth,
  3420. pszTable, pszColumn, pszColumn
  3421. );
  3422. if ((cchStored < 0) || (szCommandText[DIM(szCommandText) - 1] != _T('\0')))
  3423. {
  3424. _ASSERT(FALSE);
  3425. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  3426. }
  3427. szCommandText[DIM(szCommandText) - 1] = _T('\0');
  3428. //
  3429. // Update values.
  3430. //
  3431. _CommandPtr spCommand(__uuidof(Command));
  3432. spCommand->ActiveConnection = m_cn;
  3433. spCommand->CommandType = adCmdText;
  3434. spCommand->CommandText = szCommandText;
  3435. ParametersPtr spParameters = spCommand->Parameters;
  3436. spParameters->Append(spCommand->CreateParameter(L"A", adBSTR, adParamInput, nWidth, _variant_t(pszValueA)));
  3437. spParameters->Append(spCommand->CreateParameter(L"B", adBSTR, adParamInput, nWidth, _variant_t(pszValueB)));
  3438. spCommand->Execute(NULL, NULL, adExecuteNoRecords);
  3439. }
  3440. //---------------------------------------------------------------------------------------------
  3441. // GetMigratedObjectByType : Given the type of object this function retrieves info about
  3442. // all previously migrated objects of this type. The scope of the
  3443. // search can be limited by optional ActionID (not -1) or optional
  3444. // source domain (not empty).
  3445. //---------------------------------------------------------------------------------------------
  3446. STDMETHODIMP CIManageDB::GetMigratedObjectByType(long lActionID, BSTR sSrcDomain, BSTR sType, IUnknown **ppUnk)
  3447. {
  3448. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3449. HRESULT hr = S_OK;
  3450. try
  3451. {
  3452. _RecordsetPtr pRs(__uuidof(Recordset));
  3453. _variant_t vtSource = L"MigratedObjects";
  3454. IVarSetPtr pVs = *ppUnk;
  3455. WCHAR sActionInfo[LEN_Path];
  3456. long lCnt = 0;
  3457. _bstr_t sName;
  3458. _bstr_t sTypeQuery;
  3459. // If the type parameter is not correct then we need to return an error
  3460. if (wcslen((WCHAR*)sType) == 0)
  3461. _com_issue_error(E_INVALIDARG);
  3462. //we now store the group type as "ggroup", "lgroup", "ugroup" and we need to allow
  3463. //for lookup based on any of these three and also "group", which will be any of them
  3464. if (_wcsicmp((WCHAR*)sType, L"group") == 0)
  3465. sTypeQuery = L"Type = 'group' OR Type = 'ggroup' OR Type = 'lgroup' OR Type = 'ugroup'";
  3466. else if (_wcsicmp((WCHAR*)sType, L"ggroup") == 0)
  3467. sTypeQuery = L"Type = 'ggroup'";
  3468. else if (_wcsicmp((WCHAR*)sType, L"lgroup") == 0)
  3469. sTypeQuery = L"Type = 'lgroup'";
  3470. else if (_wcsicmp((WCHAR*)sType, L"ugroup") == 0)
  3471. sTypeQuery = L"Type = 'ugroup'";
  3472. else
  3473. {
  3474. sTypeQuery = L"Type = '";
  3475. sTypeQuery += sType;
  3476. sTypeQuery += L"'";
  3477. }
  3478. // If a valid ActionID is specified then we only return the data for that one.
  3479. // but if -1 is passed in then we return all migrated objects of the specified type.
  3480. if ( lActionID != -1 )
  3481. {
  3482. wsprintf(sActionInfo, L"Select * from MigratedObjects where ActionID = %d AND (%s) Order by Time", lActionID, (WCHAR*)sTypeQuery);
  3483. }
  3484. //else if source domain specified, get objects of the specified type from that domain
  3485. else if (wcslen((WCHAR*)sSrcDomain) != 0)
  3486. {
  3487. wsprintf(sActionInfo, L"Select * from MigratedObjects where SourceDomain=\"%s\" AND (%s) Order by Time", sSrcDomain, (WCHAR*)sTypeQuery);
  3488. }
  3489. else //else get all objects of the specified type
  3490. {
  3491. wsprintf(sActionInfo, L"Select * from MigratedObjects where %s Order by Time", (WCHAR*)sTypeQuery);
  3492. }
  3493. vtSource = _bstr_t(sActionInfo);
  3494. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  3495. if (pRs->GetRecordCount() > 0)
  3496. {
  3497. pRs->MoveFirst();
  3498. while ( !pRs->EndOfFile )
  3499. {
  3500. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_ActionID));
  3501. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  3502. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Time));
  3503. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  3504. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomain));
  3505. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  3506. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetDomain));
  3507. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  3508. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceAdsPath));
  3509. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  3510. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetAdsPath));
  3511. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  3512. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_status));
  3513. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  3514. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceSamName));
  3515. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  3516. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetSamName));
  3517. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  3518. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Type));
  3519. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Type")->Value);
  3520. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_GUID));
  3521. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  3522. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceRid));
  3523. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  3524. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetRid));
  3525. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  3526. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomainSid));
  3527. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  3528. pRs->MoveNext();
  3529. lCnt++;
  3530. }
  3531. pVs->put(L"MigratedObjects", lCnt);
  3532. }
  3533. else
  3534. {
  3535. hr = S_FALSE;
  3536. }
  3537. }
  3538. catch (_com_error& ce)
  3539. {
  3540. hr = ce.Error();
  3541. }
  3542. catch (...)
  3543. {
  3544. hr = E_FAIL;
  3545. }
  3546. return hr;
  3547. }
  3548. //---------------------------------------------------------------------------------------------
  3549. // GetAMigratedObjectBySidAndRid : Given a source domain Sid and account Rid this function
  3550. // retrieves info about that migrated object, if any.
  3551. //---------------------------------------------------------------------------------------------
  3552. STDMETHODIMP CIManageDB::GetAMigratedObjectBySidAndRid(BSTR sSrcDomainSid, BSTR sRid, IUnknown **ppUnk)
  3553. {
  3554. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3555. HRESULT hr = S_OK;
  3556. try
  3557. {
  3558. _RecordsetPtr pRs(__uuidof(Recordset));
  3559. _variant_t vtSource = L"MigratedObjects";
  3560. IVarSetPtr pVs = *ppUnk;
  3561. WCHAR sActionInfo[LEN_Path];
  3562. // If the type parameter is not correct then we need to return an error
  3563. if ((wcslen((WCHAR*)sSrcDomainSid) == 0) || (wcslen((WCHAR*)sRid) == 0))
  3564. _com_issue_error(E_INVALIDARG);
  3565. int nRid = _wtoi(sRid);
  3566. wsprintf(sActionInfo, L"Select * from MigratedObjects where SourceDomainSid=\"%s\" AND SourceRid=%d Order by Time", sSrcDomainSid, nRid);
  3567. vtSource = _bstr_t(sActionInfo);
  3568. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  3569. if (pRs->GetRecordCount() > 0)
  3570. {
  3571. // We want the latest move.
  3572. pRs->MoveLast();
  3573. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_ActionID));
  3574. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  3575. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Time));
  3576. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  3577. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomain));
  3578. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  3579. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetDomain));
  3580. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  3581. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceAdsPath));
  3582. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  3583. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetAdsPath));
  3584. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  3585. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_status));
  3586. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  3587. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceSamName));
  3588. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  3589. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetSamName));
  3590. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  3591. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_Type));
  3592. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  3593. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  3594. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  3595. //delineation
  3596. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  3597. if (wcsstr((WCHAR*)sType, L"group"))
  3598. sType = L"group";
  3599. pVs->put(sActionInfo, sType);
  3600. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_GUID));
  3601. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  3602. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceRid));
  3603. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  3604. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_TargetRid));
  3605. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  3606. wsprintf(sActionInfo, L"MigratedObjects.%s", GET_STRING(DB_SourceDomainSid));
  3607. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  3608. }
  3609. else
  3610. {
  3611. hr = S_FALSE;
  3612. }
  3613. }
  3614. catch (_com_error& ce)
  3615. {
  3616. hr = ce.Error();
  3617. }
  3618. catch (...)
  3619. {
  3620. hr = E_FAIL;
  3621. }
  3622. return hr;
  3623. }
  3624. /*********************************************************************
  3625. * *
  3626. * Written by: Paul Thompson *
  3627. * Date: 22 MAR 2001 *
  3628. * *
  3629. * This private member function of the CIManageDB checks to see *
  3630. * if the "Description" column in the Source Accounts table has been *
  3631. * changed to "RDN". If so, then we have modified both the Source *
  3632. * and Target Accounts tables for the new form of the "Name Conflict"*
  3633. * report. *
  3634. * *
  3635. *********************************************************************/
  3636. //BEGIN NCTablesColumnsChanged
  3637. BOOL CIManageDB::NCTablesColumnsChanged(BOOL bSource)
  3638. {
  3639. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3640. HRESULT hr = S_OK;
  3641. BOOL bFound = FALSE;
  3642. try
  3643. {
  3644. _RecordsetPtr pRs(__uuidof(Recordset));
  3645. _variant_t vtSource;
  3646. long numColumns;
  3647. long ndx = 0;
  3648. if (bSource)
  3649. vtSource = L"SourceAccounts";
  3650. else
  3651. vtSource = L"TargetAccounts";
  3652. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdTable);
  3653. //get the number of columns
  3654. numColumns = pRs->Fields->GetCount();
  3655. //look for new column's name in each column header
  3656. while ((ndx < numColumns) && (bFound == FALSE))
  3657. {
  3658. //get the column name
  3659. _variant_t var(ndx);
  3660. _bstr_t columnName = pRs->Fields->GetItem(var)->Name;
  3661. //if this is the Src Sid column then set return value flag to true
  3662. if (!_wcsicmp((WCHAR*)columnName, L"RDN"))
  3663. bFound = TRUE;
  3664. ndx++;
  3665. }
  3666. }
  3667. catch (_com_error& ce)
  3668. {
  3669. hr = ce.Error();
  3670. }
  3671. catch (...)
  3672. {
  3673. hr = E_FAIL;
  3674. }
  3675. return bFound;
  3676. }
  3677. //END NCTablesColumnsChanged
  3678. /*********************************************************************
  3679. * *
  3680. * Written by: Paul Thompson *
  3681. * Date: 22 MAR 2001 *
  3682. * *
  3683. * This private member function of the CIManageDB modifies *
  3684. * several of the columns in the Source and Target Accounts tables. *
  3685. * It changes several column names and one column type to support new*
  3686. * changes to the "Name Conflict" report. *
  3687. * *
  3688. *********************************************************************/
  3689. //BEGIN ChangeNCTableColumns
  3690. HRESULT CIManageDB::ChangeNCTableColumns(BOOL bSource)
  3691. {
  3692. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3693. /* local constants */
  3694. const long COLUMN_MAX_CHARS = 255;
  3695. /* local variables */
  3696. HRESULT hr = S_OK;
  3697. /* function body */
  3698. try
  3699. {
  3700. ADOX::_CatalogPtr m_pCatalog(__uuidof(ADOX::Catalog));
  3701. ADOX::_TablePtr m_pTable = NULL;
  3702. WCHAR sConnect[MAX_PATH];
  3703. WCHAR sDir[MAX_PATH];
  3704. // Get the path to the MDB file from the registry
  3705. TRegKey key;
  3706. DWORD rc = key.Open(sKeyBase);
  3707. if ( !rc )
  3708. rc = key.ValueGetStr(L"Directory", sDir, MAX_PATH);
  3709. if ( rc != 0 )
  3710. wcscpy(sDir, L"");
  3711. // Now build the connect string.
  3712. wsprintf(sConnect, L"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sprotar.mdb;", sDir);
  3713. //Open the catalog
  3714. m_pCatalog->PutActiveConnection(sConnect);
  3715. //get a pointer to the database's Source or Target Accounts Table
  3716. if (bSource)
  3717. m_pTable = m_pCatalog->Tables->Item[L"SourceAccounts"];
  3718. else
  3719. m_pTable = m_pCatalog->Tables->Item[L"TargetAccounts"];
  3720. if (m_pTable)
  3721. {
  3722. //remove the old Description column
  3723. m_pTable->Columns->Delete(L"Description");
  3724. //remove the old FullName column
  3725. m_pTable->Columns->Delete(L"FullName");
  3726. //append the RDN column to the end of the Table
  3727. m_pTable->Columns->Append(L"RDN", adVarWChar, COLUMN_MAX_CHARS);
  3728. //append the Canonical Name column to the end of the Table
  3729. m_pTable->Columns->Append(L"Canonical Name", adLongVarWChar, COLUMN_MAX_CHARS);
  3730. }
  3731. }
  3732. catch (_com_error& ce)
  3733. {
  3734. hr = ce.Error();
  3735. }
  3736. catch (...)
  3737. {
  3738. hr = E_FAIL;
  3739. }
  3740. return hr;
  3741. }
  3742. //END ChangeNCTableColumns
  3743. //---------------------------------------------------------------------------------------------
  3744. // GetMigratedObjectsByTarget : Retrieves information about previously migrated objects with
  3745. // a given target domain and SAM name.
  3746. //---------------------------------------------------------------------------------------------
  3747. STDMETHODIMP CIManageDB::GetMigratedObjectsByTarget(BSTR sTargetDomain, BSTR sTargetSAM, IUnknown ** ppUnk)
  3748. {
  3749. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3750. HRESULT hr = S_OK;
  3751. // This function returns all migrated objects and their information related
  3752. // to a particular target domain and SAM name . This is going to return nothing if the actionID is
  3753. // empty.
  3754. try
  3755. {
  3756. _RecordsetPtr pRs(__uuidof(Recordset));
  3757. _variant_t vtSource = L"MigratedObjects";
  3758. IVarSetPtr pVs = *ppUnk;
  3759. WCHAR sActionInfo[255];
  3760. long lCnt = 0;
  3761. wsprintf(sActionInfo, L"Select * from MigratedObjects where TargetDomain=\"%s\" AND TargetSamName=\"%s\"", sTargetDomain, sTargetSAM);
  3762. vtSource = sActionInfo;
  3763. pRs->Open(vtSource, m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  3764. if (pRs->GetRecordCount() > 0)
  3765. {
  3766. pRs->MoveFirst();
  3767. while ( !pRs->EndOfFile )
  3768. {
  3769. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_ActionID));
  3770. pVs->put(sActionInfo, pRs->Fields->GetItem(L"ActionID")->Value);
  3771. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Time));
  3772. pVs->put(sActionInfo, pRs->Fields->GetItem(L"Time")->Value);
  3773. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomain));
  3774. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomain")->Value);
  3775. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetDomain));
  3776. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetDomain")->Value);
  3777. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceAdsPath));
  3778. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceAdsPath")->Value);
  3779. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetAdsPath));
  3780. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetAdsPath")->Value);
  3781. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_status));
  3782. pVs->put(sActionInfo, pRs->Fields->GetItem(L"status")->Value);
  3783. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceSamName));
  3784. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceSamName")->Value);
  3785. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetSamName));
  3786. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetSamName")->Value);
  3787. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_Type));
  3788. //ADMT V2.0 now stores a group's type, in the migrated objects table, not all as
  3789. //"group", as in ADMT V1.0, but now as "ggroup", "lgroup", or ""ugroup". But most the
  3790. //code still expects "group" returned (only GetMigratedObjectByType will return this new
  3791. //delineation
  3792. _bstr_t sType = pRs->Fields->GetItem(L"Type")->Value;
  3793. if (wcsstr((WCHAR*)sType, L"group"))
  3794. sType = L"group";
  3795. pVs->put(sActionInfo, sType);
  3796. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_GUID));
  3797. pVs->put(sActionInfo, pRs->Fields->GetItem(L"GUID")->Value);
  3798. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceRid));
  3799. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceRid")->Value);
  3800. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_TargetRid));
  3801. pVs->put(sActionInfo, pRs->Fields->GetItem(L"TargetRid")->Value);
  3802. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", lCnt, GET_STRING(DB_SourceDomainSid));
  3803. pVs->put(sActionInfo, pRs->Fields->GetItem(L"SourceDomainSid")->Value);
  3804. pRs->MoveNext();
  3805. lCnt++;
  3806. }
  3807. pVs->put(L"MigratedObjects", lCnt);
  3808. }
  3809. else
  3810. {
  3811. hr = S_FALSE;
  3812. }
  3813. }
  3814. catch (_com_error& ce)
  3815. {
  3816. hr = ce.Error();
  3817. }
  3818. catch (...)
  3819. {
  3820. hr = E_FAIL;
  3821. }
  3822. return hr;
  3823. }
  3824. //---------------------------------------------------------------------------
  3825. // GetSourceDomainInfo Method
  3826. //
  3827. // Method attempts to retrieve source domain information from the action
  3828. // history table. The action history table contains values for the source
  3829. // domain's flat (NetBIOS) name, DNS name and SID.
  3830. //---------------------------------------------------------------------------
  3831. STDMETHODIMP CIManageDB::GetSourceDomainInfo(BSTR sSourceDomainName, IUnknown** ppunkVarSet)
  3832. {
  3833. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  3834. HRESULT hr = S_OK;
  3835. try
  3836. {
  3837. *ppunkVarSet = NULL;
  3838. _bstr_t strName(sSourceDomainName);
  3839. if (strName.length())
  3840. {
  3841. bool bFound = false;
  3842. //
  3843. // retrieve current action ID from the System table because records
  3844. // in the ActionHistory table having this value represent the latest
  3845. // information in the action history table
  3846. //
  3847. _RecordsetPtr spSystem(__uuidof(Recordset));
  3848. spSystem->Open(_variant_t(_T("System")), m_vtConn, adOpenStatic, adLockReadOnly, adCmdTable);
  3849. long lCurrentActionId = spSystem->Fields->GetItem(_T("CurrentActionID"))->Value;
  3850. spSystem->Close();
  3851. //
  3852. // retrieve source domain information from action history table
  3853. //
  3854. // the following query statement joins the ActionHistory table with
  3855. // itself in order to create a set of records of the following form
  3856. //
  3857. // ActionID, DnsName, FlatName, Sid
  3858. //
  3859. // this makes it easier and more efficient to find a record
  3860. // containing the source domain information of interest
  3861. static _TCHAR c_szSource[] =
  3862. _T("SELECT A.ActionID AS ActionID, A.Value AS DnsName, B.Value AS FlatName, C.Value AS Sid ")
  3863. _T("FROM (ActionHistory AS A ")
  3864. _T("INNER JOIN ActionHistory AS B ON A.ActionID = B.ActionID) ")
  3865. _T("INNER JOIN ActionHistory AS C ON B.ActionID = C.ActionID ")
  3866. _T("WHERE A.Property='Options.SourceDomainDns' ")
  3867. _T("AND B.Property='Options.SourceDomain' ")
  3868. _T("AND C.Property='Options.SourceDomainSid' ")
  3869. _T("ORDER BY A.ActionID");
  3870. // open read only snapshot of records
  3871. _RecordsetPtr spActionId(__uuidof(Recordset));
  3872. spActionId->Open(_variant_t(c_szSource), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  3873. // if records found...
  3874. if ((spActionId->BOF == VARIANT_FALSE) && (spActionId->EndOfFile == VARIANT_FALSE))
  3875. {
  3876. IVarSetPtr spVarSet(__uuidof(VarSet));
  3877. FieldsPtr spFields = spActionId->Fields;
  3878. FieldPtr spActionIdField = spFields->Item[_T("ActionID")];
  3879. FieldPtr spDnsNameField = spFields->Item[_T("DnsName")];
  3880. FieldPtr spFlatNameField = spFields->Item[_T("FlatName")];
  3881. FieldPtr spSidField = spFields->Item[_T("Sid")];
  3882. // find record with current action ID
  3883. // this will contain the latest information
  3884. spActionId->MoveLast();
  3885. while ((spActionId->BOF == VARIANT_FALSE) && (long(spActionIdField->Value) != lCurrentActionId))
  3886. {
  3887. spActionId->MovePrevious();
  3888. }
  3889. // if action ID found...
  3890. if (spActionId->BOF == VARIANT_FALSE)
  3891. {
  3892. bool bCheckingLessOrEqual = true;
  3893. _bstr_t str;
  3894. // starting with record with current action ID
  3895. // first check records with action IDs less than or equal to the current action ID
  3896. // then check records with action IDs greater than the current action ID
  3897. // this logic checks records in order from the newest to the oldest
  3898. // and accounts for the fact that action IDs will wrap back to 1 after
  3899. // the maximum action ID has been used
  3900. for (;;)
  3901. {
  3902. // if given name matches DNS name then found
  3903. str = spDnsNameField->Value;
  3904. if (str.length())
  3905. {
  3906. if (_tcsicmp(str, strName) == 0)
  3907. {
  3908. bFound = true;
  3909. break;
  3910. }
  3911. }
  3912. // if given name matches flat name then found
  3913. str = spFlatNameField->Value;
  3914. if (str.length())
  3915. {
  3916. if (_tcsicmp(str, strName) == 0)
  3917. {
  3918. bFound = true;
  3919. break;
  3920. }
  3921. }
  3922. // move to previous record
  3923. spActionId->MovePrevious();
  3924. // if beginning of records is reached...
  3925. if (spActionId->BOF == VARIANT_TRUE)
  3926. {
  3927. // if checking action IDs less than current action ID...
  3928. if (bCheckingLessOrEqual)
  3929. {
  3930. // move to last record and begin checking
  3931. // records with action IDs greater than current
  3932. spActionId->MoveLast();
  3933. bCheckingLessOrEqual = false;
  3934. }
  3935. else
  3936. {
  3937. // otherwise break out of loop as the action ID
  3938. // comparison has failed to stop the loop before
  3939. // reaching the beginning again
  3940. break;
  3941. }
  3942. }
  3943. // check action ID
  3944. long lActionId = spActionIdField->Value;
  3945. // if checking action IDs less than or equal to current
  3946. if (bCheckingLessOrEqual)
  3947. {
  3948. // if action ID is less than or equal to zero
  3949. if (lActionId <= 0)
  3950. {
  3951. // do not process records with action IDs less than or equal
  3952. // to zero as these records are now obsolete and will be deleted
  3953. // move to last record and begin checking records with
  3954. // action IDs greater than current action ID
  3955. spActionId->MoveLast();
  3956. bCheckingLessOrEqual = false;
  3957. }
  3958. }
  3959. else
  3960. {
  3961. // stop checking once current action ID is reached
  3962. if (lActionId <= lCurrentActionId)
  3963. {
  3964. break;
  3965. }
  3966. }
  3967. }
  3968. // if matching record found...
  3969. if (bFound)
  3970. {
  3971. // put information into varset and set output data
  3972. spVarSet->put(_T("Options.SourceDomain"), spFlatNameField->Value);
  3973. spVarSet->put(_T("Options.SourceDomainDns"), spDnsNameField->Value);
  3974. spVarSet->put(_T("Options.SourceDomainSid"), spSidField->Value);
  3975. *ppunkVarSet = IUnknownPtr(spVarSet).Detach();
  3976. }
  3977. }
  3978. }
  3979. //
  3980. // if source domain was not found in the action history table it is very likely
  3981. // that the information has been replaced with subsequent migration task information
  3982. // therefore will try to obtain this information from the migrated objects table
  3983. //
  3984. if (bFound == false)
  3985. {
  3986. //
  3987. // query for migrated objects from specified source domain and sort by time
  3988. //
  3989. _RecordsetPtr spObjects(__uuidof(Recordset));
  3990. _bstr_t strSource = _T("SELECT SourceDomain, SourceDomainSid FROM MigratedObjects WHERE SourceDomain='");
  3991. strSource += strName;
  3992. strSource += _T("' ORDER BY Time");
  3993. spObjects->Open(_variant_t(strSource), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  3994. //
  3995. // if migrated objects found...
  3996. //
  3997. if ((spObjects->BOF == VARIANT_FALSE) && (spObjects->EndOfFile == VARIANT_FALSE))
  3998. {
  3999. //
  4000. // the last record contains the most recent information
  4001. //
  4002. spObjects->MoveLast();
  4003. //
  4004. // set source domain information
  4005. //
  4006. // note that the migrated objects table does not have the DNS name
  4007. // and so the DNS field is set to the flat or NetBIOS name
  4008. //
  4009. FieldsPtr spFields = spObjects->Fields;
  4010. FieldPtr spDomainField = spFields->Item[_T("SourceDomain")];
  4011. FieldPtr spSidField = spFields->Item[_T("SourceDomainSid")];
  4012. IVarSetPtr spVarSet(__uuidof(VarSet));
  4013. spVarSet->put(_T("Options.SourceDomain"), spDomainField->Value);
  4014. spVarSet->put(_T("Options.SourceDomainDns"), spDomainField->Value);
  4015. spVarSet->put(_T("Options.SourceDomainSid"), spSidField->Value);
  4016. *ppunkVarSet = IUnknownPtr(spVarSet).Detach();
  4017. }
  4018. }
  4019. }
  4020. else
  4021. {
  4022. hr = E_INVALIDARG;
  4023. }
  4024. }
  4025. catch (_com_error& ce)
  4026. {
  4027. hr = ce.Error();
  4028. }
  4029. catch (...)
  4030. {
  4031. hr = E_FAIL;
  4032. }
  4033. return hr;
  4034. }
  4035. //---------------------------------------------------------------------------
  4036. // UpdateMigratedTargetObject Method
  4037. //
  4038. // Method updates target name information based on GUID of target object.
  4039. //---------------------------------------------------------------------------
  4040. STDMETHODIMP CIManageDB::UpdateMigratedTargetObject(IUnknown* punkVarSet)
  4041. {
  4042. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  4043. HRESULT hr = S_OK;
  4044. try
  4045. {
  4046. IVarSetPtr spVarSet(punkVarSet);
  4047. _bstr_t strADsPath = spVarSet->get(_T("MigratedObjects.TargetAdsPath"));
  4048. _bstr_t strSamName = spVarSet->get(_T("MigratedObjects.TargetSamName"));
  4049. _bstr_t strGuid = spVarSet->get(_T("MigratedObjects.GUID"));
  4050. _bstr_t strCommandText =
  4051. _T("SELECT TargetAdsPath, TargetSamName FROM MigratedObjects WHERE GUID = '") + strGuid + _T("'");
  4052. _RecordsetPtr spRecordset(__uuidof(Recordset));
  4053. spRecordset->Open(_variant_t(strCommandText), m_vtConn, adOpenStatic, adLockOptimistic, adCmdText);
  4054. FieldsPtr spFields = spRecordset->Fields;
  4055. while (spRecordset->EndOfFile == VARIANT_FALSE)
  4056. {
  4057. spFields->Item[_T("TargetAdsPath")]->Value = strADsPath;
  4058. spFields->Item[_T("TargetSamName")]->Value = strSamName;
  4059. spRecordset->Update();
  4060. spRecordset->MoveNext();
  4061. }
  4062. }
  4063. catch (_com_error& ce)
  4064. {
  4065. hr = ce.Error();
  4066. }
  4067. catch (...)
  4068. {
  4069. hr = E_FAIL;
  4070. }
  4071. return hr;
  4072. }
  4073. //---------------------------------------------------------------------------
  4074. // UpdateMigratedObjectStatus Method
  4075. //
  4076. // Method updates status of migrated object.
  4077. //---------------------------------------------------------------------------
  4078. STDMETHODIMP CIManageDB::UpdateMigratedObjectStatus(BSTR bstrGuid, long lStatus)
  4079. {
  4080. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  4081. USES_CONVERSION;
  4082. HRESULT hr = S_OK;
  4083. try
  4084. {
  4085. _TCHAR szSQL[256];
  4086. _stprintf(
  4087. szSQL,
  4088. _T("UPDATE MigratedObjects SET status = %ld WHERE GUID = '%s'"),
  4089. lStatus,
  4090. OLE2CT(bstrGuid)
  4091. );
  4092. m_cn->Execute(_bstr_t(szSQL), &_variant_t(), adExecuteNoRecords);
  4093. }
  4094. catch (_com_error& ce)
  4095. {
  4096. hr = ce.Error();
  4097. }
  4098. catch (...)
  4099. {
  4100. hr = E_FAIL;
  4101. }
  4102. return hr;
  4103. }
  4104. //------------------------------------------------------------------------------
  4105. // GetMigratedObjectsForSecurityTranslation Method
  4106. //
  4107. // Synopsis
  4108. // Given the source and target domain's NetBIOS names retrieve the users and
  4109. // groups that have been migrated between the given domains. Only data required
  4110. // for security translation is retrieved.
  4111. //
  4112. // Arguments
  4113. // IN bstrSourceDomain - source domain's NetBIOS name
  4114. // IN bstrTargetDomain - target domain's NetBIOS name
  4115. // IN punkVarSet - the VarSet data structure to be filled in with the
  4116. // migrated objects data
  4117. //
  4118. // Return
  4119. // HRESULT - S_OK if successful otherwise an error result
  4120. //------------------------------------------------------------------------------
  4121. STDMETHODIMP CIManageDB::GetMigratedObjectsForSecurityTranslation(BSTR bstrSourceDomain, BSTR bstrTargetDomain, IUnknown* punkVarSet)
  4122. {
  4123. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  4124. HRESULT hr = S_OK;
  4125. try
  4126. {
  4127. //
  4128. // Validate arguments. A source and target domain must be specified.
  4129. //
  4130. if ((SysStringLen(bstrSourceDomain) == 0) || (SysStringLen(bstrTargetDomain) == 0) || (punkVarSet == NULL))
  4131. {
  4132. _com_issue_error(E_INVALIDARG);
  4133. }
  4134. //
  4135. // Generate SQL query string. Query for user or group objects that
  4136. // have been migrated from the source domain to the target domain.
  4137. //
  4138. _bstr_t strQuery =
  4139. L"SELECT SourceSamName, TargetSamName, Type, SourceRid, TargetRid FROM MigratedObjects "
  4140. L"WHERE SourceDomain = '" + _bstr_t(bstrSourceDomain) +
  4141. L"' AND TargetDomain = '" + _bstr_t(bstrTargetDomain) +
  4142. L"' AND (Type = 'user' OR Type = 'group' OR Type = 'ggroup' OR Type = 'lgroup' OR Type = 'ugroup')";
  4143. //
  4144. // Retrieve data from database and fill in VarSet data structure.
  4145. //
  4146. _RecordsetPtr rs(__uuidof(Recordset));
  4147. rs->Open(_variant_t(strQuery), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  4148. int nIndex;
  4149. WCHAR szKey[256];
  4150. IVarSetPtr spVarSet(punkVarSet);
  4151. FieldsPtr spFields = rs->Fields;
  4152. FieldPtr spSourceSamField = spFields->Item[L"SourceSamName"];
  4153. FieldPtr spTargetSamField = spFields->Item[L"TargetSamName"];
  4154. FieldPtr spTypeField = spFields->Item[L"Type"];
  4155. FieldPtr spSourceRidField = spFields->Item[L"SourceRid"];
  4156. FieldPtr spTargetRidField = spFields->Item[L"TargetRid"];
  4157. for (nIndex = 0; rs->EndOfFile == VARIANT_FALSE; nIndex++)
  4158. {
  4159. // source object's SAM account name
  4160. wsprintf(szKey, L"MigratedObjects.%d.SourceSamName", nIndex);
  4161. spVarSet->put(szKey, spSourceSamField->Value);
  4162. // target object's SAM account name
  4163. wsprintf(szKey, L"MigratedObjects.%d.TargetSamName", nIndex);
  4164. spVarSet->put(szKey, spTargetSamField->Value);
  4165. // object type - note that specific group type is translated to generic group type
  4166. wsprintf(szKey, L"MigratedObjects.%d.Type", nIndex);
  4167. _bstr_t strType = spTypeField->Value;
  4168. spVarSet->put(szKey, ((LPCTSTR)strType && wcsstr(strType, L"group")) ? L"group" : strType);
  4169. // source object's RID
  4170. wsprintf(szKey, L"MigratedObjects.%d.SourceRid", nIndex);
  4171. spVarSet->put(szKey, spSourceRidField->Value);
  4172. // target object's RID
  4173. wsprintf(szKey, L"MigratedObjects.%d.TargetRid", nIndex);
  4174. spVarSet->put(szKey, spTargetRidField->Value);
  4175. rs->MoveNext();
  4176. }
  4177. // count of objects returned
  4178. spVarSet->put(L"MigratedObjects", static_cast<long>(nIndex));
  4179. }
  4180. catch (_com_error& ce)
  4181. {
  4182. hr = ce.Error();
  4183. }
  4184. catch (...)
  4185. {
  4186. hr = E_FAIL;
  4187. }
  4188. return hr;
  4189. }
  4190. //---------------------------------------------------------------------------------------------
  4191. // GetDistributedActionStatus Method
  4192. //
  4193. // Synopsis
  4194. // Given the migration task action identifier and the server name return the status of the
  4195. // agent dispatch to this server during the specified migration task.
  4196. //
  4197. // Arguments
  4198. // IN lActionId - action identifier of the migration task
  4199. // IN bstrServerName - server's NetBIOS name
  4200. // OUT plStatus - the agent status from the migration
  4201. //
  4202. // Return
  4203. // HRESULT - S_OK if successful otherwise an error result
  4204. //---------------------------------------------------------------------------------------------
  4205. STDMETHODIMP CIManageDB::GetDistributedActionStatus(long lActionId, BSTR bstrServerName, long* plStatus)
  4206. {
  4207. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  4208. HRESULT hr = S_OK;
  4209. USES_CONVERSION;
  4210. try
  4211. {
  4212. //
  4213. // Validate arguments. A valid action identifier and a server name must be specified.
  4214. //
  4215. if ((lActionId <= 0) || (SysStringLen(bstrServerName) == 0) || (plStatus == NULL))
  4216. {
  4217. _com_issue_error(E_INVALIDARG);
  4218. }
  4219. //
  4220. // Retrieve status for specified action identifier and server.
  4221. //
  4222. _TCHAR szSQL[256];
  4223. int cch = _sntprintf(
  4224. szSQL,
  4225. sizeof(szSQL) / sizeof(szSQL[0]),
  4226. _T("SELECT Status FROM DistributedAction WHERE ActionID=%ld AND ServerName='%s'"),
  4227. lActionId,
  4228. OLE2CT(bstrServerName)
  4229. );
  4230. szSQL[DIM(szSQL) - 1] = L'\0';
  4231. if (cch < 0)
  4232. {
  4233. _com_issue_error(E_FAIL);
  4234. }
  4235. _RecordsetPtr rs(__uuidof(Recordset));
  4236. rs->Open(_variant_t(szSQL), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  4237. if (rs->EndOfFile == VARIANT_FALSE)
  4238. {
  4239. *plStatus = rs->Fields->Item[0L]->Value;
  4240. }
  4241. else
  4242. {
  4243. *plStatus = 0;
  4244. }
  4245. }
  4246. catch (_com_error& ce)
  4247. {
  4248. hr = ce.Error();
  4249. }
  4250. catch (...)
  4251. {
  4252. hr = E_FAIL;
  4253. }
  4254. return hr;
  4255. }
  4256. //---------------------------------------------------------------------------------------------
  4257. // GetServerNamesFromActionHistory Method
  4258. //
  4259. // Synopsis
  4260. // Given a server name retrieve the flat and DNS names from the Action History table.
  4261. //
  4262. // Arguments
  4263. // IN lActionId - action identifier of the migration task
  4264. // IN bstrServerName - server name (either NetBIOS or DNS)
  4265. // OUT pbstrFlatName - the flat (NetBIOS) name of server
  4266. // OUT pbstrDnsName - the DNS name of server
  4267. //
  4268. // Return
  4269. // HRESULT - S_OK if successful otherwise an error result
  4270. //---------------------------------------------------------------------------------------------
  4271. STDMETHODIMP CIManageDB::GetServerNamesFromActionHistory(long lActionId, BSTR bstrServerName, BSTR* pbstrFlatName, BSTR* pbstrDnsName)
  4272. {
  4273. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  4274. HRESULT hr = S_OK;
  4275. USES_CONVERSION;
  4276. try
  4277. {
  4278. //
  4279. // Validate arguments. A valid action identifier and a server name must be specified.
  4280. //
  4281. if ((lActionId <= 0) || (SysStringLen(bstrServerName) == 0) || (pbstrFlatName == NULL) || (pbstrDnsName == NULL))
  4282. {
  4283. _com_issue_error(E_INVALIDARG);
  4284. }
  4285. //
  4286. // Retrieve record from action history table having ActionID field equal to specified
  4287. // action identifier, Property field equal to Servers.# or Servers.#.DnsName where #
  4288. // is an index number and Value field equal to specified server name.
  4289. //
  4290. _TCHAR szCommandText[512];
  4291. int cch = _sntprintf(
  4292. szCommandText,
  4293. DIM(szCommandText),
  4294. _T("SELECT Property, Value FROM ActionHistory ")
  4295. _T("WHERE ActionID = %ld AND Property LIKE 'Servers.%%' AND Value = '%s'"),
  4296. lActionId,
  4297. OLE2CT(bstrServerName)
  4298. );
  4299. szCommandText[DIM(szCommandText) - 1] = L'\0';
  4300. if (cch < 0)
  4301. {
  4302. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  4303. }
  4304. _RecordsetPtr rs(__uuidof(Recordset));
  4305. rs->Open(_variant_t(szCommandText), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  4306. if (rs->EndOfFile == VARIANT_FALSE)
  4307. {
  4308. _bstr_t strPropertyA = rs->Fields->Item[0L]->Value;
  4309. _bstr_t strValueA = rs->Fields->Item[1L]->Value;
  4310. rs->Close();
  4311. PCWSTR pszPropertyA = strPropertyA;
  4312. if (pszPropertyA)
  4313. {
  4314. //
  4315. // If retrieved Property equals Servers.#.DnsName then query for record
  4316. // having Property equal to Servers.# and retrieve value of Value field
  4317. // which will contain the flat (NetBIOS) name.
  4318. //
  4319. // If retrieved Property equals Servers.# then query for record having
  4320. // Property equal to Servers.#.DnsName and retrieve value of Value field
  4321. // which will contain the DNS name. Note that a record with Property
  4322. // equal to Servers.#.DnsName will not exist for NT4 servers.
  4323. //
  4324. PCWSTR pszDnsName = wcsstr(pszPropertyA, L".DnsName");
  4325. WCHAR szPropertyB[64];
  4326. if (pszDnsName)
  4327. {
  4328. size_t cch = pszDnsName - pszPropertyA;
  4329. if (cch >= DIM(szPropertyB))
  4330. {
  4331. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  4332. }
  4333. wcsncpy(szPropertyB, pszPropertyA, cch);
  4334. szPropertyB[cch] = L'\0';
  4335. }
  4336. else
  4337. {
  4338. wcscpy(szPropertyB, pszPropertyA);
  4339. wcscat(szPropertyB, L".DnsName");
  4340. }
  4341. cch = _sntprintf(
  4342. szCommandText,
  4343. DIM(szCommandText),
  4344. _T("SELECT Value FROM ActionHistory ")
  4345. _T("WHERE ActionID = %ld AND Property = '%s'"),
  4346. lActionId,
  4347. szPropertyB
  4348. );
  4349. szCommandText[DIM(szCommandText) - 1] = L'\0';
  4350. if (cch < 0)
  4351. {
  4352. _com_issue_error(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
  4353. }
  4354. rs->Open(_variant_t(szCommandText), m_vtConn, adOpenStatic, adLockReadOnly, adCmdText);
  4355. if (rs->EndOfFile == VARIANT_FALSE)
  4356. {
  4357. _bstr_t strValueB = rs->Fields->Item[0L]->Value;
  4358. if (pszDnsName)
  4359. {
  4360. *pbstrFlatName = strValueB.copy();
  4361. *pbstrDnsName = strValueA.copy();
  4362. }
  4363. else
  4364. {
  4365. *pbstrFlatName = strValueA.copy();
  4366. *pbstrDnsName = strValueB.copy();
  4367. }
  4368. }
  4369. else
  4370. {
  4371. if (pszDnsName == NULL)
  4372. {
  4373. *pbstrFlatName = strValueA.copy();
  4374. *pbstrDnsName = NULL;
  4375. }
  4376. else
  4377. {
  4378. _com_issue_error(E_FAIL);
  4379. }
  4380. }
  4381. }
  4382. else
  4383. {
  4384. _com_issue_error(E_FAIL);
  4385. }
  4386. }
  4387. else
  4388. {
  4389. hr = S_FALSE;
  4390. }
  4391. }
  4392. catch (_com_error& ce)
  4393. {
  4394. hr = ce.Error();
  4395. }
  4396. catch (...)
  4397. {
  4398. hr = E_FAIL;
  4399. }
  4400. return hr;
  4401. }
  4402. //---------------------------------------------------------------------------
  4403. // CreateSettings2Table
  4404. //
  4405. // Synopsis
  4406. // Creates Settings2 table if it doesn't already exist.
  4407. //
  4408. // The Settings2 table has an identical structure to the Settings table
  4409. // except that the Value column is a Memo data type which may hold up to
  4410. // 65535 characters instead of the maximum of 255 characters that a Text
  4411. // column may hold. Note as well that the data in this table will not be
  4412. // deleted and refreshed each migration task unlike the Settings table.
  4413. //
  4414. // Arguments
  4415. // IN spConnection - connection interface to Protar.mdb database
  4416. //
  4417. // Return Value
  4418. // None - generates an exception if a failure occurs.
  4419. //
  4420. // 2002-10-17 Mark Oluper - initial
  4421. //---------------------------------------------------------------------------
  4422. void CIManageDB::CreateSettings2Table(_ConnectionPtr spConnection)
  4423. {
  4424. static const _TCHAR s_szTableName[] = _T("Settings2");
  4425. static struct SColumnData
  4426. {
  4427. PCTSTR pszName;
  4428. enum DataTypeEnum dteType;
  4429. enum ADOX::ColumnAttributesEnum caeAttributes;
  4430. long lDefinedSize;
  4431. }
  4432. s_ColumnData[] =
  4433. {
  4434. { _T("Property"), adVarWChar, ADOX::adColNullable, 255L },
  4435. { _T("VarType"), adInteger, ADOX::adColNullable, 0L },
  4436. { _T("Value"), adLongVarWChar, ADOX::adColNullable, 65535L },
  4437. };
  4438. const size_t cColumnData = sizeof(s_ColumnData) / sizeof(s_ColumnData[0]);
  4439. //
  4440. // Connect to database catalog and verify whether Settings2 table exists.
  4441. //
  4442. ADOX::_CatalogPtr spCatalog(__uuidof(ADOX::Catalog));
  4443. spCatalog->PutRefActiveConnection(IDispatchPtr(spConnection));
  4444. ADOX::TablesPtr spTables = spCatalog->Tables;
  4445. ADOX::_TablePtr spTable;
  4446. HRESULT hr = spTables->get_Item(_variant_t(s_szTableName), &spTable);
  4447. //
  4448. // If table not found then create table.
  4449. //
  4450. if (FAILED(hr))
  4451. {
  4452. if (hr == 0x800A0CC1) // adErrItemNotFound
  4453. {
  4454. //
  4455. // Create table object, set name and associate with catalog.
  4456. //
  4457. CheckError(spTable.CreateInstance(__uuidof(ADOX::Table)));
  4458. spTable->Name = s_szTableName;
  4459. spTable->ParentCatalog = spCatalog;
  4460. //
  4461. // Create and add columns to table.
  4462. //
  4463. ADOX::ColumnsPtr spColumns = spTable->Columns;
  4464. for (size_t iColumnData = 0; iColumnData < cColumnData; iColumnData++)
  4465. {
  4466. ADOX::_ColumnPtr spColumn(__uuidof(ADOX::Column));
  4467. spColumn->Name = s_ColumnData[iColumnData].pszName;
  4468. spColumn->Type = s_ColumnData[iColumnData].dteType;
  4469. spColumn->Attributes = s_ColumnData[iColumnData].caeAttributes;
  4470. spColumn->DefinedSize = s_ColumnData[iColumnData].lDefinedSize;
  4471. spColumn->ParentCatalog = spCatalog;
  4472. spColumns->Append(_variant_t(IDispatchPtr(spColumn).GetInterfacePtr()), adEmpty, 0);
  4473. }
  4474. //
  4475. // Add table to database.
  4476. //
  4477. spTables->Append(_variant_t(IDispatchPtr(spTable).GetInterfacePtr()));
  4478. //
  4479. // Create primary key index. Note that the table must be added to database
  4480. // before the columns in the table may be added to the index.
  4481. //
  4482. ADOX::_IndexPtr spIndex(__uuidof(ADOX::Index));
  4483. spIndex->Name = _T("PrimaryKey");
  4484. spIndex->Unique = VARIANT_TRUE;
  4485. spIndex->PrimaryKey = VARIANT_TRUE;
  4486. spIndex->IndexNulls = ADOX::adIndexNullsAllow;
  4487. ADOX::ColumnsPtr spIndexColumns = spIndex->Columns;
  4488. spIndexColumns->Append(_variant_t(s_ColumnData[0].pszName), adVarWChar, 0);
  4489. ADOX::IndexesPtr spIndexes = spTable->Indexes;
  4490. spIndexes->Append(_variant_t(IDispatchPtr(spIndex).GetInterfacePtr()));
  4491. //
  4492. // Add excluded system properties set and excluded system properties records.
  4493. //
  4494. // The excluded system properties set value is initialized to false so that
  4495. // list of excluded system properties will be generated.
  4496. //
  4497. spConnection->Execute(
  4498. _T("INSERT INTO Settings2 (Property, VarType, [Value]) ")
  4499. _T("VALUES ('AccountOptions.ExcludedSystemPropsSet', 3, '0');"),
  4500. NULL,
  4501. adCmdText|adExecuteNoRecords
  4502. );
  4503. _CommandPtr spCommand(__uuidof(Command));
  4504. spCommand->ActiveConnection = spConnection;
  4505. spCommand->CommandType = adCmdText;
  4506. spCommand->CommandText =
  4507. _T("INSERT INTO Settings2 (Property, VarType, [Value]) ")
  4508. _T("VALUES ('AccountOptions.ExcludedSystemProps', 8, '');");
  4509. spCommand->Execute(NULL, NULL, adExecuteNoRecords);
  4510. }
  4511. else
  4512. {
  4513. AdmtThrowError(hr);
  4514. }
  4515. }
  4516. }