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.

863 lines
23 KiB

  1. #include "headers.hxx"
  2. #include "repair.hpp"
  3. #include "CSVDSReader.hpp"
  4. #include "resourceDspecup.h"
  5. Repair::Repair
  6. (
  7. const CSVDSReader& csvReader409_,
  8. const CSVDSReader& csvReaderIntl_,
  9. const String& domain_,
  10. const String& rootContainerDn_,
  11. AnalysisResults& res,
  12. const String& ldiffName_,
  13. const String& csvName_,
  14. const String& saveName_,
  15. const String& logPath_,
  16. const String& completeDcName_,
  17. void *caleeStruct_/*=NULL*/,
  18. progressFunction stepIt_/*=NULL*/,
  19. progressFunction totalSteps_/*=NULL*/
  20. )
  21. :
  22. results(res),
  23. domain(domain_),
  24. rootContainerDn(rootContainerDn_),
  25. csvReader409(csvReader409_),
  26. csvReaderIntl(csvReaderIntl_),
  27. ldiffName(ldiffName_),
  28. csvName(csvName_),
  29. saveName(saveName_),
  30. logPath(logPath_),
  31. completeDcName(completeDcName_),
  32. caleeStruct(caleeStruct_),
  33. stepIt(stepIt_),
  34. totalSteps(totalSteps_)
  35. {
  36. LOG_CTOR(Repair);
  37. ASSERT(!domain.empty());
  38. ASSERT(!rootContainerDn.empty());
  39. ASSERT(!ldiffName.empty());
  40. ASSERT(!csvName.empty());
  41. ASSERT(!saveName.empty());
  42. ASSERT(!logPath.empty());
  43. };
  44. void Repair::setProgress()
  45. {
  46. // We know the numbers bellow will fit in a long
  47. // and we want IA64 to build
  48. csvActions = static_cast<long>
  49. (
  50. results.createContainers.size() +
  51. results.createW2KObjects.size() +
  52. results.createWhistlerObjects.size()
  53. );
  54. ldiffActions = static_cast<long>
  55. (
  56. results.objectActions.size() +
  57. results.extraneousValues.size()
  58. );
  59. // We have three main tasks:
  60. // 1) building the csv and ldif files to make the changes
  61. // (buildCsv, buildChangeLdif)
  62. // 2) saving the ldif files with objects that will change
  63. // (buildSaveLdif)
  64. // 3) running the csv and ldif files that will actually make
  65. // the changes
  66. // (runCsvOrLdif for the buildCsv and buildChangeLdif files)
  67. // For simplification, The two first tasks will be half of
  68. // the total work and the the last will be the other half.
  69. //
  70. // For task 1, each csv action takes 10 times an ldiff action.
  71. //
  72. // Each task 2 action is an ldif export that will be supposed
  73. // to take 5 times more than an ldif import, since it has to
  74. // call ldiffde to get each object.
  75. //
  76. // The total progress for 1) is
  77. // t1=csvActions*10 + ldiffActions
  78. // The progress for 2) is t2=5*ldiffActions
  79. // The progress for 3) is a proportional division of
  80. // t1+t2 between csvActions and ldiffActions that will add
  81. // up to t1
  82. // t3 = (t1+t2)*csvActions/(csvactions+ldiffActions) +
  83. // (t1+t2)*ldiffActions/(csvactions+ldiffActions)
  84. if(csvActions + ldiffActions == 0)
  85. {
  86. // We don't want to update the page if there are no
  87. // actions
  88. totalSteps=NULL;
  89. stepIt=NULL;
  90. }
  91. else
  92. {
  93. csvBuildStep=10;
  94. ldiffBuildStep=1;
  95. ldiffSaveStep=10;
  96. long totalProgress = csvBuildStep * csvActions +
  97. ldiffBuildStep * ldiffActions +
  98. ldiffSaveStep * ldiffActions;
  99. // totalProgress is accounting for task 1 and 2
  100. csvRunStep = totalProgress * csvActions /
  101. (csvActions+ldiffActions);
  102. ldiffRunStep = totalProgress - csvRunStep;
  103. // now we compute the total time
  104. totalProgress*=2;
  105. if(totalSteps!=NULL)
  106. {
  107. totalSteps(totalProgress,caleeStruct);
  108. }
  109. }
  110. }
  111. HRESULT
  112. Repair::run()
  113. {
  114. LOG_FUNCTION(Repair::run);
  115. setProgress();
  116. HRESULT hr=S_OK;
  117. do
  118. {
  119. // First we build the csv. If we can't build it
  120. // we don't want to run the LDIF and delete
  121. // the recereate objects
  122. if (csvActions != 0)
  123. {
  124. hr=buildCsv();
  125. BREAK_ON_FAILED_HRESULT(hr);
  126. }
  127. // Now we save the current objects and then
  128. // create and run the LDIF
  129. if ( ldiffActions !=0 )
  130. {
  131. // If we can't save we definatelly don't
  132. // want to change anything
  133. hr=buildSaveLdif();
  134. BREAK_ON_FAILED_HRESULT(hr);
  135. // buildChangeLdif will build the Ldif that
  136. // will change the objects saved in
  137. // buildSaveLdif
  138. hr=buildChangeLdif();
  139. BREAK_ON_FAILED_HRESULT(hr);
  140. GetWorkFileName(
  141. logPath,
  142. String::load(IDS_FILE_NAME_LDIF_LOG),
  143. L"txt",
  144. ldifLog
  145. );
  146. // runs the Ldif built in buildChangeLdif
  147. hr=runCsvOrLdif(LDIF,IMPORT,ldiffName,L"",ldifLog);
  148. BREAK_ON_FAILED_HRESULT(hr);
  149. if(stepIt!=NULL)
  150. {
  151. stepIt(ldiffRunStep,caleeStruct);
  152. }
  153. }
  154. // Finally, we run the csv
  155. if (csvActions!=0)
  156. {
  157. String opt=L"-c DOMAINPLACEHOLDER \"" + domain + L"\"";
  158. GetWorkFileName
  159. (
  160. logPath,
  161. String::load(IDS_FILE_NAME_CSV_LOG),
  162. L"txt",
  163. csvLog
  164. );
  165. hr=runCsvOrLdif(CSV,IMPORT,csvName,opt,csvLog);
  166. BREAK_ON_FAILED_HRESULT(hr);
  167. if(stepIt!=NULL)
  168. {
  169. stepIt(csvRunStep,caleeStruct);
  170. }
  171. }
  172. }
  173. while (0);
  174. LOG_HRESULT(hr);
  175. return hr;
  176. }
  177. // Get the export results of a single object
  178. HRESULT
  179. Repair::getLdifExportedObject(
  180. const long locale,
  181. const String &object,
  182. String &objectLines
  183. )
  184. {
  185. LOG_FUNCTION(Repair::getLdifExportedObject);
  186. ASSERT(!object.empty());
  187. ASSERT(locale > 0);
  188. objectLines.erase();
  189. HRESULT hr=S_OK;
  190. do
  191. {
  192. String dn= L"CN=" + object +
  193. String::format(L",CN=%1!3x!,", locale) +
  194. rootContainerDn;
  195. String opt=L"-o ObjectGuid -d \"" + dn + L"\"";
  196. String tempName;
  197. hr=GetWorkTempFileName(L"TMP",tempName);
  198. BREAK_ON_FAILED_HRESULT(hr);
  199. hr=runCsvOrLdif(LDIF,EXPORT,tempName,opt);
  200. BREAK_ON_FAILED_HRESULT(hr);
  201. hr=ReadAllFile(tempName,objectLines);
  202. BREAK_ON_FAILED_HRESULT(hr);
  203. hr=Win::DeleteFile(tempName);
  204. BREAK_ON_FAILED_HRESULT(hr);
  205. } while(0);
  206. LOG_HRESULT(hr);
  207. return hr;
  208. }
  209. // buildSaveLdif will save information on
  210. // all objects that will be changed
  211. // or deleted in runChangeLdif.
  212. // This includes information on:
  213. // results.objectActions
  214. HRESULT
  215. Repair::buildSaveLdif()
  216. {
  217. LOG_FUNCTION(Repair::buildSaveLdif);
  218. HRESULT hr=S_OK;
  219. HANDLE file;
  220. hr=FS::CreateFile(saveName,
  221. file,
  222. GENERIC_WRITE);
  223. if (FAILED(hr))
  224. {
  225. error=String::format(IDS_COULD_NOT_CREATE_FILE,saveName.c_str());
  226. LOG_HRESULT(hr);
  227. return hr;
  228. }
  229. do
  230. {
  231. String objectLines;
  232. ObjectActions::iterator beginObj=results.objectActions.begin();
  233. ObjectActions::iterator endObj=results.objectActions.end();
  234. while(beginObj!=endObj)
  235. {
  236. String dn= L"dn: CN=" + beginObj->first.object +
  237. String::format(L",CN=%1!3x!,", beginObj->first.locale) +
  238. rootContainerDn + L"\r\nchangetype: delete\r\n";
  239. hr=FS::WriteLine(file,dn);
  240. BREAK_ON_FAILED_HRESULT(hr);
  241. hr=getLdifExportedObject(
  242. beginObj->first.locale,
  243. beginObj->first.object,
  244. objectLines
  245. );
  246. BREAK_ON_FAILED_HRESULT(hr);
  247. hr=FS::WriteLine(file,objectLines);
  248. BREAK_ON_FAILED_HRESULT(hr);
  249. if(stepIt!=NULL)
  250. {
  251. stepIt(ldiffSaveStep,caleeStruct);
  252. }
  253. beginObj++;
  254. }
  255. BREAK_ON_FAILED_HRESULT(hr);
  256. beginObj=results.extraneousValues.begin();
  257. endObj=results.extraneousValues.end();
  258. while(beginObj!=endObj)
  259. {
  260. ObjectId tempObj(
  261. beginObj->first.locale,
  262. String(beginObj->first.object)
  263. );
  264. if(
  265. results.objectActions.find(tempObj) ==
  266. results.objectActions.end()
  267. )
  268. {
  269. String dn= L"dn: CN=" + beginObj->first.object +
  270. String::format(L",CN=%1!3x!,", beginObj->first.locale) +
  271. rootContainerDn + L"\r\nchangetype: delete\r\n";
  272. hr=FS::WriteLine(file,dn);
  273. BREAK_ON_FAILED_HRESULT(hr);
  274. hr=getLdifExportedObject(
  275. beginObj->first.locale,
  276. beginObj->first.object,
  277. objectLines
  278. );
  279. BREAK_ON_FAILED_HRESULT(hr);
  280. hr=FS::WriteLine(file,objectLines);
  281. BREAK_ON_FAILED_HRESULT(hr);
  282. }
  283. if(stepIt!=NULL)
  284. {
  285. stepIt(ldiffSaveStep,caleeStruct);
  286. }
  287. beginObj++;
  288. }
  289. BREAK_ON_FAILED_HRESULT(hr);
  290. } while(0);
  291. CloseHandle(file);
  292. LOG_HRESULT(hr);
  293. return hr;
  294. }
  295. HRESULT
  296. Repair::makeObjectsLdif(HANDLE file,ObjectIdList &objects)
  297. {
  298. LOG_FUNCTION(Repair::makeObjectsLdif);
  299. HRESULT hr=S_OK;
  300. do
  301. {
  302. ObjectIdList::iterator begin,end;
  303. String header;
  304. begin=objects.begin();
  305. end=objects.end();
  306. while(begin!=end)
  307. {
  308. header= L"\r\ndn: CN=" + begin->object +
  309. String::format(L",CN=%1!3x!,", begin->locale) +
  310. rootContainerDn;
  311. hr=FS::WriteLine(file,header);
  312. BREAK_ON_FAILED_HRESULT(hr);
  313. hr=FS::WriteLine(file,L"changetype: delete");
  314. BREAK_ON_FAILED_HRESULT(hr);
  315. begin++;
  316. if(stepIt!=NULL)
  317. {
  318. stepIt(ldiffBuildStep,caleeStruct);
  319. }
  320. }
  321. BREAK_ON_FAILED_HRESULT(hr);
  322. } while(0);
  323. LOG_HRESULT(hr);
  324. return hr;
  325. }
  326. // buildChangeLdif wil build the Ldif that
  327. // will change the objects saved im
  328. // buildSaveLdif
  329. HRESULT
  330. Repair::buildChangeLdif()
  331. {
  332. LOG_FUNCTION(Repair::buildChangeLdif);
  333. HRESULT hr=S_OK;
  334. HANDLE file;
  335. hr=FS::CreateFile(ldiffName,
  336. file,
  337. GENERIC_WRITE);
  338. if (FAILED(hr))
  339. {
  340. error=String::format(IDS_COULD_NOT_CREATE_FILE,ldiffName.c_str());
  341. LOG_HRESULT(hr);
  342. return hr;
  343. }
  344. do
  345. {
  346. String header;
  347. String line;
  348. ObjectActions::iterator beginObj=results.objectActions.begin();
  349. ObjectActions::iterator endObj=results.objectActions.end();
  350. while(beginObj!=endObj)
  351. {
  352. header= L"\r\ndn: CN=" + beginObj->first.object +
  353. String::format(L",CN=%1!3x!,", beginObj->first.locale) +
  354. rootContainerDn;
  355. hr=FS::WriteLine(file,header);
  356. BREAK_ON_FAILED_HRESULT(hr);
  357. hr=FS::WriteLine(file,L"changetype: ntdsSchemaModify");
  358. BREAK_ON_FAILED_HRESULT(hr);
  359. PropertyActions::iterator beginAct=beginObj->second.begin();
  360. PropertyActions::iterator endAct=beginObj->second.end();
  361. while(beginAct!=endAct)
  362. {
  363. if(!beginAct->second.delValues.empty())
  364. {
  365. line = L"delete: " + beginAct->first;
  366. hr=FS::WriteLine(file,line);
  367. BREAK_ON_FAILED_HRESULT(hr);
  368. StringList::iterator
  369. beginDel = beginAct->second.delValues.begin();
  370. StringList::iterator
  371. endDel = beginAct->second.delValues.end();
  372. while(beginDel!=endDel)
  373. {
  374. line = beginAct->first + L": " + *beginDel;
  375. hr=FS::WriteLine(file,line);
  376. BREAK_ON_FAILED_HRESULT(hr);
  377. beginDel++;
  378. }
  379. BREAK_ON_FAILED_HRESULT(hr);
  380. hr=FS::WriteLine(file,L"-");
  381. BREAK_ON_FAILED_HRESULT(hr);
  382. }
  383. if(!beginAct->second.addValues.empty())
  384. {
  385. line = L"add: " + beginAct->first;
  386. hr=FS::WriteLine(file,line);
  387. BREAK_ON_FAILED_HRESULT(hr);
  388. StringList::iterator
  389. beginAdd = beginAct->second.addValues.begin();
  390. StringList::iterator
  391. endAdd = beginAct->second.addValues.end();
  392. while(beginAdd!=endAdd)
  393. {
  394. line = beginAct->first + L": " + *beginAdd;
  395. hr=FS::WriteLine(file,line);
  396. BREAK_ON_FAILED_HRESULT(hr);
  397. beginAdd++;
  398. }
  399. BREAK_ON_FAILED_HRESULT(hr);
  400. hr=FS::WriteLine(file,L"-");
  401. BREAK_ON_FAILED_HRESULT(hr);
  402. }
  403. beginAct++;
  404. } // while(beginAct!=endAct)
  405. BREAK_ON_FAILED_HRESULT(hr);
  406. if(stepIt!=NULL)
  407. {
  408. stepIt(ldiffBuildStep,caleeStruct);
  409. }
  410. beginObj++;
  411. } // while(beginObj!=endObj)
  412. BREAK_ON_FAILED_HRESULT(hr);
  413. // Now we will add actions to remove the extraneous objects
  414. beginObj=results.extraneousValues.begin();
  415. endObj=results.extraneousValues.end();
  416. while(beginObj!=endObj)
  417. {
  418. header= L"\r\ndn: CN=" + beginObj->first.object +
  419. String::format(L",CN=%1!3x!,", beginObj->first.locale) +
  420. rootContainerDn;
  421. hr=FS::WriteLine(file,header);
  422. BREAK_ON_FAILED_HRESULT(hr);
  423. hr=FS::WriteLine(file,L"changetype: ntdsSchemaModify");
  424. BREAK_ON_FAILED_HRESULT(hr);
  425. PropertyActions::iterator beginAct=beginObj->second.begin();
  426. PropertyActions::iterator endAct=beginObj->second.end();
  427. while(beginAct!=endAct)
  428. {
  429. if(!beginAct->second.delValues.empty())
  430. {
  431. line = L"delete: " + beginAct->first;
  432. hr=FS::WriteLine(file,line);
  433. BREAK_ON_FAILED_HRESULT(hr);
  434. StringList::iterator
  435. beginDel = beginAct->second.delValues.begin();
  436. StringList::iterator
  437. endDel = beginAct->second.delValues.end();
  438. while(beginDel!=endDel)
  439. {
  440. line = beginAct->first + L": " + *beginDel;
  441. hr=FS::WriteLine(file,line);
  442. BREAK_ON_FAILED_HRESULT(hr);
  443. beginDel++;
  444. }
  445. BREAK_ON_FAILED_HRESULT(hr);
  446. hr=FS::WriteLine(file,L"-");
  447. BREAK_ON_FAILED_HRESULT(hr);
  448. } //if(!beginAct->second.delValues.empty())
  449. beginAct++;
  450. } // while(beginAct!=endAct)
  451. BREAK_ON_FAILED_HRESULT(hr);
  452. if(stepIt!=NULL)
  453. {
  454. stepIt(ldiffBuildStep,caleeStruct);
  455. }
  456. beginObj++;
  457. } // while(beginObj!=endObj)
  458. BREAK_ON_FAILED_HRESULT(hr);
  459. } while(0);
  460. CloseHandle(file);
  461. LOG_HRESULT(hr);
  462. return hr;
  463. }
  464. HRESULT
  465. Repair::makeObjectsCsv(HANDLE file,ObjectIdList &objects)
  466. {
  467. LOG_FUNCTION(Repair::makeObjectsCsv);
  468. HRESULT hr=S_OK;
  469. do
  470. {
  471. ObjectIdList::iterator begin,end;
  472. begin=objects.begin();
  473. end=objects.end();
  474. while(begin!=end)
  475. {
  476. long locale=begin->locale;
  477. const CSVDSReader &csvReader=(locale==0x409)?
  478. csvReader409:
  479. csvReaderIntl;
  480. setOfObjects tempObjs;
  481. pair<String,long> tempObj;
  482. tempObj.first=begin->object;
  483. tempObj.second=begin->locale;
  484. tempObjs.insert(tempObj);
  485. hr=csvReader.makeObjectsCsv(file,tempObjs);
  486. BREAK_ON_FAILED_HRESULT(hr);
  487. begin++;
  488. if(stepIt!=NULL)
  489. {
  490. stepIt(csvBuildStep,caleeStruct);
  491. }
  492. }
  493. BREAK_ON_FAILED_HRESULT(hr);
  494. } while(0);
  495. LOG_HRESULT(hr);
  496. return hr;
  497. }
  498. // buildCsv creates a CSV with:
  499. // results.createContainers,
  500. // results.createW2KObjects
  501. // results.createWhistlerObjects
  502. HRESULT
  503. Repair::buildCsv()
  504. {
  505. LOG_FUNCTION(Repair::buildCsv);
  506. HANDLE file;
  507. HRESULT hr=S_OK;
  508. hr=FS::CreateFile(csvName,
  509. file,
  510. GENERIC_WRITE);
  511. if (FAILED(hr))
  512. {
  513. error=String::format(IDS_COULD_NOT_CREATE_FILE,csvName.c_str());
  514. LOG_HRESULT(hr);
  515. return hr;
  516. }
  517. do
  518. {
  519. LongList::iterator bgCont,endCont;
  520. bgCont=results.createContainers.begin();
  521. endCont=results.createContainers.end();
  522. while(bgCont!=endCont)
  523. {
  524. long locale=*bgCont;
  525. const CSVDSReader &csvReader=(locale==0x409)?
  526. csvReader409:
  527. csvReaderIntl;
  528. long locales[2]={locale,0L};
  529. hr=csvReader.makeLocalesCsv(file,locales);
  530. BREAK_ON_FAILED_HRESULT(hr);
  531. bgCont++;
  532. if(stepIt!=NULL)
  533. {
  534. stepIt(csvBuildStep,caleeStruct);
  535. }
  536. }
  537. BREAK_ON_FAILED_HRESULT(hr);
  538. hr=makeObjectsCsv(file,results.createW2KObjects);
  539. BREAK_ON_FAILED_HRESULT(hr);
  540. hr=makeObjectsCsv(file,results.createWhistlerObjects);
  541. BREAK_ON_FAILED_HRESULT(hr);
  542. } while(0);
  543. CloseHandle(file);
  544. LOG_HRESULT(hr);
  545. return hr;
  546. }
  547. // This finction will run csvde or ldifde(whichExe)
  548. // to import or export (inOut) file. The options specified
  549. // are -u for unicode, -j for the log/err path -f for the file
  550. // -i if import and the extraOptions.
  551. // The log file will be renamed for logFileArg(if !empty)
  552. // If an error file is generated it will be renamed.
  553. HRESULT
  554. Repair::runCsvOrLdif(
  555. csvOrLdif whichExe,
  556. importExport inOut,
  557. const String& file,
  558. const String& extraOptions,//=L""
  559. const String& logFileArg//=L""
  560. )
  561. {
  562. LOG_FUNCTION2(Repair::runCsvOrLdif,file.c_str());
  563. String baseName = (whichExe==LDIF) ? L"LDIF" : L"CSV";
  564. String exeName = baseName + L"de.exe";
  565. String options = (inOut==IMPORT) ? L"-i " + extraOptions : extraOptions;
  566. String operation = (inOut==IMPORT) ? L"importing" : L"exporting";
  567. HRESULT hr=S_OK;
  568. do
  569. {
  570. String sys32dir = Win::GetSystemDirectory();
  571. String wholeName = sys32dir + L"\\" + exeName;
  572. if (!FS::FileExists(wholeName))
  573. {
  574. error=String::format(IDS_EXE_NOT_FOUND,wholeName.c_str());
  575. hr=E_FAIL;
  576. break;
  577. }
  578. if (inOut==IMPORT && !FS::FileExists(file))
  579. {
  580. hr=E_FAIL;
  581. error=String::format(IDS_COULD_NOT_FIND_FILE,file.c_str());
  582. break;
  583. }
  584. String commandLine = L"\"" + wholeName + L"\" " +
  585. options +
  586. L" -u -f \"" +
  587. file +
  588. L"\" -j \"" +
  589. logPath + L"\" " +
  590. L"-s " + completeDcName;
  591. STARTUPINFO si={0};
  592. PROCESS_INFORMATION pi={0};
  593. GetStartupInfo(&si);
  594. String curDir=L"";
  595. String errFile=logPath + L"\\" + baseName + L".err";
  596. String logFile=logPath + L"\\" + baseName + L".log";
  597. if(FS::FileExists(errFile))
  598. {
  599. hr=Win::DeleteFile(errFile);
  600. BREAK_ON_FAILED_HRESULT_ERROR(hr,errFile);
  601. }
  602. if(FS::FileExists(logFile))
  603. {
  604. hr=Win::DeleteFile(logFile);
  605. BREAK_ON_FAILED_HRESULT_ERROR(hr,logFile);
  606. }
  607. hr=Win::CreateProcess
  608. (
  609. commandLine,
  610. NULL, // lpProcessAttributes
  611. NULL, // lpThreadAttributes
  612. false, // dwCreationFlags
  613. NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,// fdwCreate
  614. NULL, // lpEnvironment
  615. curDir, // lpEnvironment
  616. si, // [in] lpStartupInfo
  617. pi // [out] pProcessInformation
  618. );
  619. BREAK_ON_FAILED_HRESULT_ERROR(hr,
  620. String::format(IDS_COULD_NOT_START_EXE,commandLine.c_str()));
  621. do
  622. {
  623. DWORD resWait;
  624. hr=Win::WaitForSingleObject(pi.hProcess,INFINITE,resWait);
  625. // Log operation and break in case FAILED(hr)
  626. if(FAILED(hr))
  627. {
  628. error=String::format(IDS_ERROR_WAITING_EXE,commandLine.c_str());
  629. break;
  630. }
  631. if(!logFileArg.empty())
  632. {
  633. hr=FS::MoveFile(logFile.c_str(), logFileArg.c_str());
  634. if(FAILED(hr))
  635. {
  636. error=String::format(IDS_COULD_NOT_MOVE_FILE,
  637. logFile.c_str(), logFileArg.c_str());
  638. break;
  639. }
  640. }
  641. DWORD resExit;
  642. hr=Win::GetExitCodeProcess(pi.hProcess,resExit);
  643. // Log operation and break in case FAILED(hr)
  644. if(FAILED(hr))
  645. {
  646. error=String::format
  647. (
  648. IDS_ERROR_GETTING_EXE_RETURN,
  649. commandLine.c_str()
  650. );
  651. break;
  652. }
  653. if(resExit!=0)
  654. {
  655. error=String::format
  656. (
  657. IDS_ERROR_EXECUTING_EXE,
  658. resExit,
  659. commandLine.c_str()
  660. );
  661. String betterErrFile;
  662. GetWorkFileName
  663. (
  664. logPath,
  665. String::load(
  666. (whichExe==LDIF) ?
  667. IDS_FILE_NAME_LDIF_ERROR :
  668. IDS_FILE_NAME_CSV_ERROR
  669. ),
  670. L"txt",
  671. betterErrFile
  672. );
  673. hr=FS::MoveFile(errFile.c_str(), betterErrFile.c_str());
  674. if(FAILED(hr))
  675. {
  676. error += String::format(IDS_COULD_NOT_MOVE_FILE,
  677. errFile.c_str(), betterErrFile.c_str());
  678. break;
  679. }
  680. error+=String::format
  681. (
  682. IDS_SEE_ERROR_FILE,
  683. betterErrFile.c_str()
  684. );
  685. hr=E_FAIL;
  686. break;
  687. }
  688. } while(0);
  689. CloseHandle(pi.hProcess);
  690. CloseHandle(pi.hThread);
  691. } while(0);
  692. LOG_HRESULT(hr);
  693. return hr;
  694. }