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.

622 lines
15 KiB

  1. #include "headers.hxx"
  2. #include "dspecup.hpp"
  3. #include "Analysis.hpp"
  4. #include "repair.hpp"
  5. #include "AnalysisResults.hpp"
  6. #include "resourceDspecup.h"
  7. #include "CSVDSReader.hpp"
  8. #include "constants.hpp"
  9. #include "AdsiHelpers.hpp"
  10. #include "guids.inc"
  11. HRESULT
  12. FindCsvFile(
  13. String& csvFilePath,
  14. String& csv409Path
  15. )
  16. {
  17. LOG_FUNCTION(FindCsvFile);
  18. csvFilePath.erase();
  19. csv409Path.erase();
  20. HRESULT hr = S_OK;
  21. do
  22. {
  23. // look for dcpromo.csv and 409.csv file in system
  24. // or current directory
  25. // check the default of
  26. // %windir%\system32\mui\dispspec\dcpromo.csv and
  27. // .\dcpromo.csv
  28. String csvname=L"dcpromo.csv";
  29. String sys32dir = Win::GetSystemDirectory();
  30. String csvPath = sys32dir + L"\\debug\\adprep\\data\\" + csvname;
  31. if (FS::FileExists(csvPath))
  32. {
  33. csvFilePath = csvPath;
  34. }
  35. else
  36. {
  37. error=String::format(IDS_COULD_NOT_FIND_FILE,csvPath.c_str());
  38. hr=E_FAIL;
  39. break;
  40. }
  41. csvname=L"409.csv";
  42. csvPath = sys32dir + L"\\debug\\adprep\\data\\" + csvname;
  43. if (FS::FileExists(csvPath))
  44. {
  45. csv409Path = csvPath;
  46. }
  47. else
  48. {
  49. error=String::format(IDS_COULD_NOT_FIND_FILE,csvPath.c_str());
  50. hr=E_FAIL;
  51. break;
  52. }
  53. }
  54. while(0);
  55. LOG_HRESULT(hr);
  56. LOG(csvFilePath);
  57. LOG(csv409Path);
  58. return hr;
  59. }
  60. HRESULT
  61. InitializeADSI(
  62. const String &targetDcName,
  63. String &ldapPrefix,
  64. String &rootContainerDn,
  65. String &domainName,
  66. String &completeDcName,
  67. SmartInterface<IADs>& rootDse
  68. )
  69. {
  70. LOG_FUNCTION(InitializeADSI);
  71. HRESULT hr=S_OK;
  72. do
  73. {
  74. Computer targetDc(targetDcName);
  75. hr = targetDc.Refresh();
  76. if (FAILED(hr))
  77. {
  78. error = String::format(
  79. IDS_CANT_TARGET_MACHINE,
  80. targetDcName.c_str());
  81. break;
  82. }
  83. if (!targetDc.IsDomainController())
  84. {
  85. error=String::format(
  86. IDS_TARGET_IS_NOT_DC,
  87. targetDcName.c_str());
  88. hr=E_FAIL;
  89. break;
  90. }
  91. completeDcName = targetDc.GetActivePhysicalFullDnsName();
  92. ldapPrefix = L"LDAP://" + completeDcName + L"/";
  93. //
  94. // Find the DN of the configuration container.
  95. //
  96. // Bind to the rootDSE object. We will keep this binding handle
  97. // open for the duration of the analysis and repair phases in order
  98. // to keep a server session open. If we decide to pass creds to the
  99. // AdsiOpenObject call in a later revision, then by keeping the
  100. // session open we will not need to pass the password to subsequent
  101. // AdsiOpenObject calls.
  102. hr = AdsiOpenObject<IADs>(ldapPrefix + L"RootDSE", rootDse);
  103. if (FAILED(hr))
  104. {
  105. error=String::format(
  106. IDS_UNABLE_TO_CONNECT_TO_DC,
  107. completeDcName.c_str());
  108. hr=E_FAIL;
  109. break;
  110. }
  111. // read the configuration naming context.
  112. _variant_t variant;
  113. hr =
  114. rootDse->Get(
  115. AutoBstr(LDAP_OPATT_CONFIG_NAMING_CONTEXT_W),
  116. &variant);
  117. if (FAILED(hr))
  118. {
  119. LOG(L"can't read config NC");
  120. error=String::format(IDS_UNABLE_TO_READ_DIRECTORY_INFO);
  121. break;
  122. }
  123. String configNc = V_BSTR(&variant);
  124. ASSERT(!configNc.empty());
  125. LOG(configNc);
  126. wchar_t *domain=wcschr(configNc.c_str(),L',');
  127. ASSERT(domain!=NULL);
  128. domainName=domain+1;
  129. rootContainerDn = L"CN=DisplaySpecifiers," + configNc;
  130. }
  131. while (0);
  132. LOG_HRESULT(hr);
  133. return hr;
  134. }
  135. HRESULT
  136. GetInitialInformation(
  137. String &targetDomainControllerName,
  138. String &csvFilename,
  139. String &csv409Name
  140. )
  141. {
  142. LOG_FUNCTION(GetInitialInformation);
  143. HRESULT hr = S_OK;
  144. do
  145. {
  146. //
  147. // find the dcpromo.csv file to use
  148. //
  149. hr = FindCsvFile(csvFilename, csv409Name);
  150. BREAK_ON_FAILED_HRESULT(hr);
  151. //
  152. // Determine the target domain controller
  153. //
  154. if (targetDomainControllerName.empty())
  155. {
  156. // no target specified, default to the current machine
  157. targetDomainControllerName =
  158. Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
  159. if (targetDomainControllerName.empty())
  160. {
  161. // no DNS name? that's not right...
  162. LOG(L"no default DNS computer name found. Using netbios name.");
  163. targetDomainControllerName =
  164. Win::GetComputerNameEx(ComputerNameNetBIOS);
  165. ASSERT(!targetDomainControllerName.empty());
  166. }
  167. }
  168. }
  169. while (0);
  170. LOG_HRESULT(hr);
  171. return hr;
  172. }
  173. ///////////////////////////////////////////////////////////////////
  174. // Function: cchLoadHrMsg
  175. //
  176. // Given an HRESULT error,
  177. // it loads the string for the error. It returns the # of characters returned
  178. int cchLoadHrMsg( HRESULT hr, String &message )
  179. {
  180. if(hr == S_OK) return 0;
  181. wchar_t *msgPtr = NULL;
  182. // Try from the system table
  183. int cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  184. NULL,
  185. hr,
  186. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  187. (LPWSTR)&msgPtr,
  188. 0,
  189. NULL);
  190. if (!cch)
  191. {
  192. //try ads errors
  193. static HMODULE g_adsMod = 0;
  194. if (0 == g_adsMod)
  195. {
  196. g_adsMod = GetModuleHandle (L"activeds.dll");
  197. }
  198. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  199. g_adsMod,
  200. hr,
  201. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  202. (LPWSTR)&msgPtr,
  203. 0,
  204. NULL);
  205. }
  206. if (!cch)
  207. {
  208. // Try NTSTATUS error codes
  209. hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(hr));
  210. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  211. NULL,
  212. hr,
  213. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  214. (LPWSTR)&msgPtr,
  215. 0,
  216. NULL);
  217. }
  218. message.erase();
  219. if(cch!=0)
  220. {
  221. if(msgPtr==NULL)
  222. {
  223. cch=0;
  224. }
  225. else
  226. {
  227. message=msgPtr;
  228. ::LocalFree(msgPtr);
  229. }
  230. }
  231. return cch;
  232. }
  233. // allocates error with src and a message formated from hr
  234. void AllocError(HRESULT &hr,PWSTR *error,const String& src)
  235. {
  236. ASSERT(error!=NULL);
  237. ASSERT(FAILED(hr));
  238. if (error==NULL) return;
  239. // There is no use in formating a message if hr didn't fail
  240. if(!FAILED(hr)) return;
  241. String msg;
  242. if(hr!=E_FAIL)
  243. {
  244. // We ignore the error since it is possible that
  245. // we don't find a message
  246. cchLoadHrMsg(hr,msg);
  247. }
  248. // Under any conditions(no mesage,E_FAIL or good message)
  249. // we print the hr.
  250. msg+=String::format(L" (0x%1!x!).",hr);
  251. // we also add src
  252. msg=src+L" "+msg;
  253. *error=static_cast<PWSTR>(
  254. LocalAlloc
  255. (
  256. LMEM_FIXED,
  257. (msg.size()+1)*sizeof(wchar_t)
  258. )
  259. );
  260. if(*error==NULL)
  261. {
  262. hr = Win32ToHresult(ERROR_NOT_ENOUGH_MEMORY);
  263. }
  264. else
  265. {
  266. wcscpy(*error,msg.c_str());
  267. }
  268. return;
  269. }
  270. HRESULT
  271. RunAnalysis
  272. (
  273. GUID guid,
  274. PWSTR logFilesPath,
  275. void *caleeStruct/*=NULL*/,
  276. progressFunction stepIt/*=NULL*/,
  277. progressFunction totalSteps/*=NULL*/
  278. )
  279. {
  280. LOG_FUNCTION(RunAnalysis);
  281. hResourceModuleHandle=::GetModuleHandle(NULL);
  282. HRESULT hr=S_OK;
  283. try
  284. {
  285. goodAnalysis=false;
  286. results.createContainers.clear();
  287. results.conflictingWhistlerObjects.clear();
  288. results.createWhistlerObjects.clear();
  289. results.createW2KObjects.clear();
  290. results.objectActions.clear();
  291. results.customizedValues.clear();
  292. results.extraneousValues.clear();
  293. hr = ::CoInitialize(0);
  294. ASSERT(SUCCEEDED(hr));
  295. do
  296. {
  297. String normalPath=FS::NormalizePath(logFilesPath);
  298. if (!FS::PathExists(normalPath) || FS::FileExists(normalPath))
  299. {
  300. hr=E_FAIL;
  301. error=String::load(IDS_NO_LOG_FILE_PATH);
  302. break;
  303. }
  304. hr=GetInitialInformation(
  305. targetDomainControllerName,
  306. csvFileName,
  307. csv409Name
  308. );
  309. BREAK_ON_FAILED_HRESULT(hr);
  310. hr=csvReaderIntl.read(csvFileName.c_str(),LOCALEIDS);
  311. BREAK_ON_FAILED_HRESULT(hr);
  312. hr=csvReader409.read(csv409Name.c_str(),LOCALE409);
  313. BREAK_ON_FAILED_HRESULT(hr);
  314. SmartInterface<IADs> rootDse(0);
  315. hr=InitializeADSI
  316. (
  317. targetDomainControllerName,
  318. ldapPrefix,
  319. rootContainerDn,
  320. domainName,
  321. completeDcName,
  322. rootDse
  323. );
  324. BREAK_ON_FAILED_HRESULT(hr);
  325. String reportName;
  326. GetWorkFileName(
  327. normalPath,
  328. String::load(IDS_FILE_NAME_REPORT),
  329. L"txt",
  330. reportName
  331. );
  332. Analysis analysis(
  333. guid,
  334. csvReader409,
  335. csvReaderIntl,
  336. ldapPrefix,
  337. rootContainerDn,
  338. results,
  339. reportName,
  340. caleeStruct,
  341. stepIt,
  342. totalSteps
  343. );
  344. hr=analysis.run();
  345. BREAK_ON_FAILED_HRESULT(hr);
  346. } while(0);
  347. CoUninitialize();
  348. if(SUCCEEDED(hr))
  349. {
  350. goodAnalysis=true;
  351. }
  352. }
  353. catch( const std::bad_alloc& )
  354. {
  355. // Since we are in an out of memory condition.
  356. // we will not show allocate messages.
  357. hr=Win32ToHresult(ERROR_OUTOFMEMORY);
  358. }
  359. LOG_HRESULT(hr);
  360. return hr;
  361. }
  362. HRESULT
  363. RunRepair
  364. (
  365. PWSTR logFilesPath,
  366. void *caleeStruct/*=NULL*/,
  367. progressFunction stepIt/*=NULL*/,
  368. progressFunction totalSteps/*=NULL*/
  369. )
  370. {
  371. hResourceModuleHandle=::GetModuleHandle(NULL);
  372. LOG_FUNCTION(RunRepair);
  373. HRESULT hr=S_OK;
  374. try
  375. {
  376. hr = ::CoInitialize(0);
  377. ASSERT(SUCCEEDED(hr));
  378. do
  379. {
  380. String normalPath=FS::NormalizePath(logFilesPath);
  381. if (!FS::PathExists(normalPath) || FS::FileExists(normalPath))
  382. {
  383. hr=E_FAIL;
  384. error=String::load(IDS_NO_LOG_FILE_PATH);
  385. break;
  386. }
  387. if (!goodAnalysis)
  388. {
  389. hr=E_FAIL;
  390. error=String::load(IDS_NO_ANALYSIS);
  391. break;
  392. }
  393. String ldiffName;
  394. GetWorkFileName(
  395. normalPath,
  396. String::load(IDS_FILE_NAME_LDIF_ACTIONS),
  397. L"ldf",
  398. ldiffName
  399. );
  400. BREAK_ON_FAILED_HRESULT(hr);
  401. String csvName;
  402. GetWorkFileName(
  403. normalPath,
  404. String::load(IDS_FILE_NAME_CSV_ACTIONS),
  405. L"csv",
  406. csvName
  407. );
  408. BREAK_ON_FAILED_HRESULT(hr);
  409. String saveName;
  410. GetWorkFileName(
  411. normalPath,
  412. String::load(IDS_FILE_NAME_UNDO),
  413. L"ldf",
  414. saveName
  415. );
  416. BREAK_ON_FAILED_HRESULT(hr);
  417. String logPath;
  418. Repair repair
  419. (
  420. csvReader409,
  421. csvReaderIntl,
  422. domainName,
  423. rootContainerDn,
  424. results,
  425. ldiffName,
  426. csvName,
  427. saveName,
  428. normalPath,
  429. completeDcName,
  430. caleeStruct,
  431. stepIt,
  432. totalSteps
  433. );
  434. hr=repair.run();
  435. BREAK_ON_FAILED_HRESULT(hr);
  436. } while(0);
  437. CoUninitialize();
  438. }
  439. catch( const std::bad_alloc& )
  440. {
  441. // Since we are in an out of memory condition.
  442. // we will not show allocate messages.
  443. hr=Win32ToHresult(ERROR_OUTOFMEMORY);
  444. }
  445. LOG_HRESULT(hr);
  446. return hr;
  447. }
  448. extern "C"
  449. HRESULT
  450. UpgradeDisplaySpecifiers
  451. (
  452. PWSTR logFilesPath,
  453. GUID *OperationGuid,
  454. BOOL dryRun,
  455. PWSTR *errorMsg,//=NULL
  456. void *caleeStruct,//=NULL
  457. progressFunction stepIt,//=NULL
  458. progressFunction totalSteps//=NULL
  459. )
  460. {
  461. LOG_FUNCTION(UpgradeDisplaySpecifiers);
  462. hResourceModuleHandle=::GetModuleHandle(NULL);
  463. HRESULT hr=S_OK;
  464. do
  465. {
  466. hr = ::CoInitialize(0);
  467. ASSERT(SUCCEEDED(hr));
  468. GUID guid;
  469. if(OperationGuid==NULL)
  470. {
  471. hr = E_INVALIDARG;
  472. error = String::format(IDS_NO_GUID);
  473. break;
  474. }
  475. guid=*OperationGuid;
  476. int sizeGuids=sizeof(guids)/sizeof(*guids);
  477. bool found=false;
  478. for(int t=0;(t<sizeGuids) && (!found);t++)
  479. {
  480. if (guids[t]==guid) found=true;
  481. }
  482. if(!found)
  483. {
  484. hr = E_INVALIDARG;
  485. error = String::format(IDS_NO_OPERATION_GUID);
  486. break;
  487. }
  488. hr=RunAnalysis(guid,logFilesPath,caleeStruct,stepIt,totalSteps);
  489. BREAK_ON_FAILED_HRESULT(hr);
  490. if(dryRun==false)
  491. {
  492. hr=RunRepair(logFilesPath,caleeStruct,stepIt,totalSteps);
  493. BREAK_ON_FAILED_HRESULT(hr);
  494. }
  495. CoUninitialize();
  496. } while(0);
  497. if(FAILED(hr))
  498. {
  499. AllocError(hr,errorMsg,error);
  500. }
  501. LOG_HRESULT(hr);
  502. return hr;
  503. }