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

476 lines
10 KiB

  1. #include "headers.hxx"
  2. #include "dspecup.hpp"
  3. #include "Analisys.hpp"
  4. #include "repair.hpp"
  5. #include "AnalisysResults.hpp"
  6. #include "resource.h"
  7. #include "CSVDSReader.hpp"
  8. #include "constants.hpp"
  9. #include "AdsiHelpers.hpp"
  10. // Variables kept from analisys to repair
  11. bool goodAnalisys=false;
  12. AnalisysResults results;
  13. String targetDomainControllerName;
  14. String csvFileName,csv409Name;
  15. CSVDSReader csvReaderIntl;
  16. CSVDSReader csvReader409;
  17. String rootContainerDn,ldapPrefix,domainName;
  18. HRESULT
  19. FindCsvFile(
  20. String& csvFilePath,
  21. String& csv409Path
  22. )
  23. {
  24. LOG_FUNCTION(FindCsvFile);
  25. csvFilePath.erase();
  26. HRESULT hr = S_OK;
  27. do
  28. {
  29. // look for dcpromo.csv and 409.csv file in system
  30. // or current directory
  31. // check the default of
  32. // %windir%\system32\mui\dispspec\dcpromo.csv and
  33. // .\dcpromo.csv
  34. String csvname=L"dcpromo.csv";
  35. String sys32dir = Win::GetSystemDirectory();
  36. String csvPath = sys32dir + L"\\mui\\dispspec\\" + csvname;
  37. if (FS::FileExists(csvPath))
  38. {
  39. csvFilePath = csvPath;
  40. }
  41. else
  42. {
  43. csvPath = L".\\" + csvname;
  44. if (FS::FileExists(FS::NormalizePath(csvPath)))
  45. {
  46. csvFilePath = csvPath;
  47. }
  48. else
  49. {
  50. hr=S_FALSE;
  51. break;
  52. }
  53. }
  54. csvname=L"409.csv";
  55. csvPath = sys32dir + L"\\mui\\dispspec\\" + csvname;
  56. if (FS::FileExists(csvPath))
  57. {
  58. csv409Path = csvPath;
  59. }
  60. else
  61. {
  62. csvPath = L".\\" + csvname;
  63. if (FS::FileExists(FS::NormalizePath(csvPath)))
  64. {
  65. csv409Path = csvPath;
  66. }
  67. else
  68. {
  69. hr=S_FALSE;
  70. break;
  71. }
  72. }
  73. }
  74. while(0);
  75. LOG_HRESULT(hr);
  76. LOG(csvFilePath);
  77. LOG(csv409Path);
  78. return hr;
  79. }
  80. HRESULT
  81. InitializeADSI(
  82. const String &targetDcName,
  83. String &ldapPrefix,
  84. String &rootContainerDn,
  85. String &domainName
  86. )
  87. {
  88. LOG_FUNCTION(InitializeADSI);
  89. HRESULT hr=S_OK;
  90. do
  91. {
  92. Computer targetDc(targetDcName);
  93. hr = targetDc.Refresh();
  94. if (FAILED(hr))
  95. {
  96. error = String::format(
  97. IDS_CANT_TARGET_MACHINE,
  98. targetDcName.c_str());
  99. hr=E_FAIL;
  100. break;
  101. }
  102. if (!targetDc.IsDomainController())
  103. {
  104. error=String::format(
  105. IDS_TARGET_IS_NOT_DC,
  106. targetDcName.c_str());
  107. hr=E_FAIL;
  108. break;
  109. }
  110. String dcName = targetDc.GetActivePhysicalFullDnsName();
  111. ldapPrefix = L"LDAP://" + dcName + L"/";
  112. //
  113. // Find the DN of the configuration container.
  114. //
  115. // Bind to the rootDSE object. We will keep this binding handle
  116. // open for the duration of the analysis and repair phases in order
  117. // to keep a server session open. If we decide to pass creds to the
  118. // AdsiOpenObject call in a later revision, then by keeping the
  119. // session open we will not need to pass the password to subsequent
  120. // AdsiOpenObject calls.
  121. SmartInterface<IADs> rootDse;
  122. hr = AdsiOpenObject<IADs>(ldapPrefix + L"RootDSE", rootDse);
  123. if (FAILED(hr))
  124. {
  125. error=String::format(
  126. IDS_UNABLE_TO_CONNECT_TO_DC,
  127. dcName.c_str());
  128. hr=E_FAIL;
  129. break;
  130. }
  131. // read the configuration naming context.
  132. _variant_t variant;
  133. hr =
  134. rootDse->Get(
  135. AutoBstr(LDAP_OPATT_CONFIG_NAMING_CONTEXT_W),
  136. &variant);
  137. if (FAILED(hr))
  138. {
  139. LOG(L"can't read config NC");
  140. error=String::format(IDS_UNABLE_TO_READ_DIRECTORY_INFO);
  141. hr=E_FAIL;
  142. break;
  143. }
  144. String configNc = V_BSTR(&variant);
  145. ASSERT(!configNc.empty());
  146. LOG(configNc);
  147. wchar_t *domain=wcschr(configNc.c_str(),L',');
  148. ASSERT(domain!=NULL);
  149. domainName=domain+1;
  150. rootContainerDn = L"CN=DisplaySpecifiers," + configNc;
  151. }
  152. while (0);
  153. LOG_HRESULT(hr);
  154. return hr;
  155. }
  156. HRESULT
  157. GetInitialInformation(
  158. String &targetDomainControllerName,
  159. String &csvFilename,
  160. String &csv409Name
  161. )
  162. {
  163. LOG_FUNCTION(GetInitialInformation);
  164. HRESULT hr = S_OK;
  165. do
  166. {
  167. //
  168. // find the dcpromo.csv file to use
  169. //
  170. hr = FindCsvFile(csvFilename, csv409Name);
  171. if (hr == S_FALSE)
  172. {
  173. // no error looking, just not found.
  174. error=String::format(IDS_DCPROMO_CSV_FILE_MISSING);
  175. hr=E_FAIL;
  176. break;
  177. }
  178. BREAK_ON_FAILED_HRESULT(hr);
  179. //
  180. // Determine the target domain controller
  181. //
  182. if (targetDomainControllerName.empty())
  183. {
  184. // no target specified, default to the current machine
  185. targetDomainControllerName =
  186. Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
  187. if (targetDomainControllerName.empty())
  188. {
  189. // no DNS name? that's not right...
  190. LOG(L"no default DNS computer name found. Using netbios name.");
  191. targetDomainControllerName =
  192. Win::GetComputerNameEx(ComputerNameNetBIOS);
  193. ASSERT(!targetDomainControllerName.empty());
  194. }
  195. }
  196. }
  197. while (0);
  198. LOG_HRESULT(hr);
  199. return hr;
  200. }
  201. void AllocError(HRESULT &hr,PWSTR *error,const String& src)
  202. {
  203. if (error==NULL) return;
  204. *error=static_cast<PWSTR>(
  205. CoTaskMemAlloc
  206. (
  207. (src.size()+1)*sizeof(wchar_t)
  208. )
  209. );
  210. if(*error==NULL)
  211. {
  212. hr = Win32ToHresult(ERROR_NOT_ENOUGH_MEMORY);
  213. }
  214. else
  215. {
  216. wcscpy(*error,src.c_str());
  217. }
  218. return;
  219. }
  220. HRESULT
  221. RunAnalisys
  222. (
  223. PWSTR *errorMsg/*=NULL*/,
  224. void *caleeStruct/*=NULL*/,
  225. progressFunction stepIt/*=NULL*/,
  226. progressFunction totalSteps/*=NULL*/
  227. )
  228. {
  229. LOG_FUNCTION(RunAnalisys);
  230. HRESULT hr=S_OK;
  231. goodAnalisys=false;
  232. results.createContainers.clear();
  233. results.conflictingXPObjects.clear();
  234. results.createXPObjects.clear();
  235. results.createW2KObjects.clear();
  236. results.objectActions.clear();
  237. results.customizedValues.clear();
  238. results.extraneousValues.clear();
  239. do
  240. {
  241. hr=GetInitialInformation(
  242. targetDomainControllerName,
  243. csvFileName,
  244. csv409Name
  245. );
  246. BREAK_ON_FAILED_HRESULT(hr);
  247. hr=csvReaderIntl.read(csvFileName.c_str(),LOCALEIDS);
  248. BREAK_ON_FAILED_HRESULT(hr);
  249. hr=csvReader409.read(csv409Name.c_str(),LOCALE409);
  250. BREAK_ON_FAILED_HRESULT(hr);
  251. hr=InitializeADSI(
  252. targetDomainControllerName,
  253. ldapPrefix,
  254. rootContainerDn,
  255. domainName);
  256. BREAK_ON_FAILED_HRESULT(hr);
  257. String reportName;
  258. hr=GetWorkFileName(
  259. String::load(IDS_FILE_NAME_REPORT),
  260. L"txt",
  261. reportName
  262. );
  263. BREAK_ON_FAILED_HRESULT(hr);
  264. Analisys analisys(
  265. csvReader409,
  266. csvReaderIntl,
  267. ldapPrefix,
  268. rootContainerDn,
  269. results,
  270. reportName,
  271. caleeStruct,
  272. stepIt,
  273. totalSteps
  274. );
  275. hr=analisys.run();
  276. BREAK_ON_FAILED_HRESULT(hr);
  277. } while(0);
  278. if(FAILED(hr))
  279. {
  280. AllocError(hr,errorMsg,error);
  281. }
  282. else
  283. {
  284. goodAnalisys=true;
  285. }
  286. LOG_HRESULT(hr);
  287. return hr;
  288. }
  289. HRESULT
  290. RunRepair
  291. (
  292. PWSTR *errorMsg/*=NULL*/,
  293. void *caleeStruct/*=NULL*/,
  294. progressFunction stepIt/*=NULL*/,
  295. progressFunction totalSteps/*=NULL*/
  296. )
  297. {
  298. LOG_FUNCTION(RunRepair);
  299. HRESULT hr=S_OK;
  300. do
  301. {
  302. if (!goodAnalisys)
  303. {
  304. hr=E_FAIL;
  305. AllocError(hr,errorMsg,String::load(IDS_NO_ANALISYS));
  306. break;
  307. }
  308. String ldiffName;
  309. hr=GetWorkFileName(
  310. String::load(IDS_FILE_NAME_LDIF_ACTIONS),
  311. L"ldf",
  312. ldiffName
  313. );
  314. BREAK_ON_FAILED_HRESULT(hr);
  315. String csvName;
  316. hr=GetWorkFileName(
  317. String::load(IDS_FILE_NAME_CSV_ACTIONS),
  318. L"csv",
  319. csvName
  320. );
  321. BREAK_ON_FAILED_HRESULT(hr);
  322. String saveName;
  323. hr=GetWorkFileName(
  324. String::load(IDS_FILE_NAME_UNDO),
  325. L"ldf",
  326. saveName
  327. );
  328. BREAK_ON_FAILED_HRESULT(hr);
  329. String logPath;
  330. hr=GetMyDocuments(logPath);
  331. BREAK_ON_FAILED_HRESULT_ERROR(hr,String::format(IDS_NO_WORK_PATH));
  332. Repair repair
  333. (
  334. csvReader409,
  335. csvReaderIntl,
  336. domainName,
  337. rootContainerDn,
  338. results,
  339. ldiffName,
  340. csvName,
  341. saveName,
  342. logPath,
  343. caleeStruct,
  344. stepIt,
  345. totalSteps
  346. );
  347. hr=repair.run();
  348. BREAK_ON_FAILED_HRESULT(hr);
  349. } while(0);
  350. if(FAILED(hr))
  351. {
  352. AllocError(hr,errorMsg,error);
  353. }
  354. LOG_HRESULT(hr);
  355. return hr;
  356. }
  357. HRESULT
  358. UpgradeDisplaySpecifiers
  359. (
  360. BOOL dryRun,
  361. PWSTR *errorMsg/*=NULL*/,
  362. void *caleeStruct/*=NULL*/,
  363. progressFunction stepIt/*=NULL*/,
  364. progressFunction totalSteps/*=NULL*/
  365. )
  366. {
  367. LOG_FUNCTION(UpgradeDisplaySpecifiers);
  368. HRESULT hr=S_OK;
  369. do
  370. {
  371. hr=RunAnalisys(errorMsg,caleeStruct,stepIt,totalSteps);
  372. BREAK_ON_FAILED_HRESULT(hr);
  373. if(dryRun==false)
  374. {
  375. hr=RunRepair(errorMsg,caleeStruct,stepIt,totalSteps);
  376. BREAK_ON_FAILED_HRESULT(hr);
  377. }
  378. } while(0);
  379. LOG_HRESULT(hr);
  380. return hr;
  381. }