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.

618 lines
12 KiB

  1. #include "headers.hxx"
  2. #include "global.hpp"
  3. #include "resource.h"
  4. #include "AdsiHelpers.hpp"
  5. String error;
  6. HRESULT hrError=S_OK;
  7. #define H(X) (\
  8. (X>='a')?\
  9. (\
  10. (X-'a'+10)\
  11. ):\
  12. (\
  13. (X>='A')?(X-'A'+10):(X-'0') \
  14. )\
  15. )\
  16. // Converts && to & and &xxxx to the coresponding digit
  17. // There is no error checking. This function
  18. // suposes the string is correctly escaped
  19. // The escape function is in the folder preBuild as a part
  20. // of the W2KStrs tool.
  21. String unEscape(const String &str)
  22. {
  23. LOG_FUNCTION(unEscape);
  24. String dest;
  25. String::const_iterator c=str.begin();
  26. String::const_iterator end=str.end();
  27. while(c!=end)
  28. {
  29. if(*c=='&')
  30. {
  31. c++;
  32. if(*c=='&')
  33. {
  34. dest+=L'&';
  35. }
  36. else
  37. {
  38. wchar_t sTmp[2];
  39. sTmp[0]= static_cast<wchar_t> (
  40. (H(*c)<<12)+
  41. (H(*(c+1))<<8)+
  42. (H(*(c+2))<<4)+
  43. H(*(c+3))
  44. );
  45. sTmp[1]=0;
  46. dest+=sTmp;
  47. c+=3;
  48. }
  49. }
  50. else
  51. {
  52. dest+=*c;
  53. }
  54. c++;
  55. }
  56. return dest;
  57. }
  58. // Used in WinGetVLFilePointer.
  59. LARGE_INTEGER zero={0};
  60. //////////////// ReadLine
  61. #define CHUNK_SIZE 100
  62. HRESULT
  63. ReadLine(HANDLE handle,
  64. String& text,
  65. bool *endLineFound_/*=NULL*/)
  66. {
  67. LOG_FUNCTION(ReadLine);
  68. ASSERT(handle != INVALID_HANDLE_VALUE);
  69. bool endLineFound=false;
  70. text.erase();
  71. // Acumulating chars read on text would cause the same
  72. // kind of reallocation and copy that text+=chunk will
  73. static wchar_t chunk[CHUNK_SIZE+1];
  74. HRESULT hr=S_OK;
  75. bool flagEof=false;
  76. do
  77. {
  78. LARGE_INTEGER pos;
  79. hr = WinGetVLFilePointer(handle,&pos);
  80. BREAK_ON_FAILED_HRESULT(hr);
  81. long nChunks=0;
  82. wchar_t *csr=NULL;
  83. while(!flagEof && !endLineFound)
  84. {
  85. DWORD bytesRead;
  86. hr = Win::ReadFile(
  87. handle,
  88. chunk,
  89. CHUNK_SIZE*sizeof(wchar_t),
  90. bytesRead,
  91. 0);
  92. if(hr==EOF_HRESULT)
  93. {
  94. flagEof=true;
  95. hr=S_OK;
  96. }
  97. BREAK_ON_FAILED_HRESULT(hr);
  98. if(bytesRead==0)
  99. {
  100. flagEof=true;
  101. }
  102. else
  103. {
  104. *(chunk+bytesRead/sizeof(wchar_t))=0;
  105. csr=wcschr(chunk,L'\n');
  106. if(csr!=NULL)
  107. {
  108. pos.QuadPart+= sizeof(wchar_t)*
  109. ((nChunks * CHUNK_SIZE) + (csr - chunk)+1);
  110. hr=Win::SetFilePointerEx(
  111. handle,
  112. pos,
  113. 0,
  114. FILE_BEGIN);
  115. BREAK_ON_FAILED_HRESULT(hr);
  116. *csr=0;
  117. endLineFound=true;
  118. }
  119. text+=chunk;
  120. nChunks++;
  121. }
  122. }
  123. BREAK_ON_FAILED_HRESULT(hr);
  124. //We know the length will fit in a long
  125. // and we want IA64 to build.
  126. long textLen=static_cast<long>(text.length());
  127. if(textLen!=0 && endLineFound && text[textLen-1]==L'\r')
  128. {
  129. text.erase(textLen-1,1);
  130. }
  131. if(endLineFound_ != NULL)
  132. {
  133. *endLineFound_=endLineFound;
  134. }
  135. if(flagEof)
  136. {
  137. hr=EOF_HRESULT;
  138. }
  139. } while(0);
  140. LOG_HRESULT(hr);
  141. return hr;
  142. }
  143. //////////////// ReadLine
  144. HRESULT
  145. ReadAllFile(const String &fileName,
  146. String &fileStr)
  147. {
  148. LOG_FUNCTION(ReadAllFile);
  149. HRESULT hr=S_OK;
  150. fileStr.erase();
  151. HANDLE file;
  152. hr=FS::CreateFile(fileName,
  153. file,
  154. GENERIC_READ);
  155. if(FAILED(hr))
  156. {
  157. error=fileName;
  158. LOG_HRESULT(hr);
  159. return hr;
  160. }
  161. do
  162. {
  163. bool flagEof=false;
  164. while(!flagEof)
  165. {
  166. String line;
  167. hr=ReadLine(file,line);
  168. if(hr==EOF_HRESULT)
  169. {
  170. hr=S_OK;
  171. flagEof=true;
  172. }
  173. BREAK_ON_FAILED_HRESULT_ERROR(hr,fileName);
  174. fileStr+=line+L"\r\n";
  175. }
  176. BREAK_ON_FAILED_HRESULT_ERROR(hr,fileName);
  177. } while(0);
  178. if ( (fileStr.size() > 0) && (fileStr[0] == 0xfeff) )
  179. {
  180. fileStr.erase(0,1);
  181. }
  182. CloseHandle(file);
  183. LOG_HRESULT(hr);
  184. return hr;
  185. }
  186. HRESULT
  187. GetMyDocuments(String &myDoc)
  188. {
  189. LOG_FUNCTION(GetMyDocuments);
  190. LPMALLOC pMalloc;
  191. HRESULT hr=S_OK;
  192. do //whoever breaks will go to return hr
  193. {
  194. hr=Win::SHGetMalloc(pMalloc);
  195. BREAK_ON_FAILED_HRESULT(hr);
  196. do // whoever breaks will go to pMalloc->Release();
  197. {
  198. LPITEMIDLIST pidl;
  199. hr=Win::SHGetSpecialFolderLocation(
  200. Win::GetDesktopWindow(),
  201. CSIDL_PERSONAL,
  202. pidl
  203. );
  204. BREAK_ON_FAILED_HRESULT(hr);
  205. myDoc=Win::SHGetPathFromIDList(pidl);
  206. if(myDoc.empty() || !FS::PathExists(myDoc))
  207. {
  208. hr=E_FAIL; // don't break to free pidl
  209. }
  210. pMalloc->Free(pidl);
  211. } while(0);
  212. pMalloc->Release();
  213. } while(0);
  214. LOG_HRESULT(hr);
  215. return hr;
  216. }
  217. HRESULT
  218. GetTempFileName
  219. (
  220. const wchar_t *lpPathName, // directory name
  221. const wchar_t *lpPrefixString, // file name prefix
  222. String &name // file name
  223. )
  224. {
  225. LOG_FUNCTION(GetTempFileName);
  226. ASSERT(FS::PathExists(lpPathName));
  227. HRESULT hr=S_OK;
  228. do
  229. {
  230. if (!FS::PathExists(lpPathName))
  231. {
  232. hr=Win32ToHresult(ERROR_FILE_NOT_FOUND);
  233. error=lpPathName;
  234. break;
  235. }
  236. DWORD result;
  237. wchar_t lpName[MAX_PATH]={0};
  238. result=::GetTempFileName(lpPathName,lpPrefixString,0,lpName);
  239. if (result == 0)
  240. {
  241. hr = Win::GetLastErrorAsHresult();
  242. error=lpPathName;
  243. break;
  244. }
  245. name=lpName;
  246. if(FS::FileExists(name))
  247. {
  248. // GetTempFilename actually created the file !
  249. hr=Win::DeleteFile(lpName);
  250. BREAK_ON_FAILED_HRESULT_ERROR(hr,name);
  251. }
  252. } while(0);
  253. LOG_HRESULT(hr);
  254. return hr;
  255. }
  256. // Retrieves a unique temporary file name
  257. HRESULT
  258. GetWorkTempFileName
  259. (
  260. const wchar_t *lpPrefixString,
  261. String &name
  262. )
  263. {
  264. LOG_FUNCTION(GetWorkTempFileName);
  265. HRESULT hr=S_OK;
  266. String path;
  267. do
  268. {
  269. hr=GetMyDocuments(path);
  270. BREAK_ON_FAILED_HRESULT_ERROR(hr,String::format(IDS_NO_WORK_PATH));
  271. hr=GetTempFileName(path.c_str(),lpPrefixString,name);
  272. BREAK_ON_FAILED_HRESULT(hr);
  273. } while(0);
  274. LOG_HRESULT(hr);
  275. return hr;
  276. }
  277. // locate the file with the highest-numbered extension, then add 1 and
  278. // return the result.
  279. int
  280. DetermineNextFileNumber
  281. (
  282. const String& dir,
  283. const String& baseName,
  284. const wchar_t extension[4]
  285. )
  286. {
  287. LOG_FUNCTION(DetermineNextFileNumber);
  288. ASSERT(!dir.empty());
  289. ASSERT(!baseName.empty());
  290. int largest = 0;
  291. String filespec = dir + L"\\" + baseName + L".*."+ extension;
  292. WIN32_FIND_DATA findData;
  293. HANDLE ff = ::FindFirstFile(filespec.c_str(), &findData);
  294. if (ff != INVALID_HANDLE_VALUE)
  295. {
  296. for (;;)
  297. {
  298. String current = findData.cFileName;
  299. // grab the text between the dots: "nnn" in foo.nnn.ext
  300. // first dot
  301. size_t pos = current.find(L".");
  302. if (pos == String::npos)
  303. {
  304. continue;
  305. }
  306. String extension = current.substr(pos + 1);
  307. // second dot
  308. pos = extension.find(L".");
  309. if (pos == String::npos)
  310. {
  311. continue;
  312. }
  313. extension = extension.substr(0, pos);
  314. int i = 0;
  315. extension.convert(i);
  316. largest = max(i, largest);
  317. if (!::FindNextFile(ff, &findData))
  318. {
  319. BOOL success = ::FindClose(ff);
  320. ASSERT(success);
  321. break;
  322. }
  323. }
  324. }
  325. // roll over after 255
  326. return (++largest & 0xFF);
  327. }
  328. // auxiliary in GetWorkFileName
  329. void
  330. GetFileName
  331. (
  332. const String& dir,
  333. const String& baseName,
  334. const wchar_t extension[4],
  335. String &fileName
  336. )
  337. {
  338. LOG_FUNCTION(GetFileName);
  339. int logNumber = DetermineNextFileNumber(dir,baseName,extension);
  340. fileName = dir
  341. + L"\\"
  342. + baseName
  343. + String::format(L".%1!03d!.", logNumber)
  344. + extension;
  345. if (::GetFileAttributes(fileName.c_str()) != 0xFFFFFFFF)
  346. {
  347. // could exist, as the file numbers roll over
  348. BOOL success = ::DeleteFile(fileName.c_str());
  349. ASSERT(success);
  350. }
  351. }
  352. // Retrieves a unique file name
  353. HRESULT
  354. GetWorkFileName
  355. (
  356. const String& baseName,
  357. const wchar_t *extension,
  358. String &name
  359. )
  360. {
  361. LOG_FUNCTION(GetWorkFileName);
  362. HRESULT hr=S_OK;
  363. String path;
  364. do
  365. {
  366. hr=GetMyDocuments(path);
  367. BREAK_ON_FAILED_HRESULT_ERROR(hr,String::format(IDS_NO_WORK_PATH));
  368. GetFileName(path.c_str(),baseName,extension,name);
  369. } while(0);
  370. LOG_HRESULT(hr);
  371. return hr;
  372. }
  373. HRESULT
  374. Notepad(const String& file)
  375. {
  376. LOG_FUNCTION(Notepad);
  377. HRESULT hr=S_OK;
  378. do
  379. {
  380. STARTUPINFO si;
  381. PROCESS_INFORMATION pi;
  382. GetStartupInfo(&si);
  383. String curDir = L"";
  384. String prg = L"notepad " + file;
  385. hr=Win::CreateProcess
  386. (
  387. prg,
  388. NULL, // lpProcessAttributes
  389. NULL, // lpThreadAttributes
  390. false, // dwCreationFlags
  391. NORMAL_PRIORITY_CLASS,// fdwCreate
  392. NULL, // lpEnvironment
  393. curDir, // lpEnvironment
  394. si, // [in] lpStartupInfo
  395. pi // [out] pProcessInformation
  396. );
  397. BREAK_ON_FAILED_HRESULT_ERROR(hr,
  398. String::format(IDS_COULD_NOT_START_EXE,L"notepad"));
  399. CloseHandle(pi.hProcess);
  400. CloseHandle(pi.hThread);
  401. } while(0);
  402. LOG_HRESULT(hr);
  403. return hr;
  404. }
  405. HRESULT
  406. GetPreviousSuccessfullRun(
  407. const String &ldapPrefix,
  408. const String &rootContainerDn,
  409. bool &result
  410. )
  411. {
  412. LOG_FUNCTION(GetPreviousSuccessfullRun);
  413. ASSERT(!ldapPrefix.empty());
  414. ASSERT(!rootContainerDn.empty());
  415. HRESULT hr = S_OK;
  416. result=false;
  417. do
  418. {
  419. String objectPath = ldapPrefix + rootContainerDn;
  420. SmartInterface<IADs> iads(0);
  421. hr = AdsiOpenObject<IADs>(objectPath, iads);
  422. BREAK_ON_FAILED_HRESULT(hr);
  423. _variant_t variant;
  424. hr = iads->Get(AutoBstr(L"objectVersion"), &variant);
  425. if(hr==E_ADS_PROPERTY_NOT_FOUND)
  426. {
  427. result=false;
  428. hr=S_OK;
  429. break;
  430. }
  431. else if (FAILED(hr))
  432. {
  433. hr=E_FAIL;
  434. error=String::format(IDS_CANT_READ_OBJECT_VERSION);
  435. break;
  436. }
  437. result = (variant.lVal==1);
  438. }
  439. while (0);
  440. LOG_HRESULT(hr);
  441. return hr;
  442. }
  443. HRESULT
  444. SetPreviousSuccessfullRun(
  445. const String &ldapPrefix,
  446. const String &rootContainerDn
  447. )
  448. {
  449. LOG_FUNCTION(SetPreviousSuccessfullRun);
  450. ASSERT(!ldapPrefix.empty());
  451. ASSERT(!rootContainerDn.empty());
  452. HRESULT hr = S_OK;
  453. do
  454. {
  455. String objectPath = ldapPrefix + rootContainerDn;
  456. SmartInterface<IADs> iads(0);
  457. hr = AdsiOpenObject<IADs>(objectPath, iads);
  458. BREAK_ON_FAILED_HRESULT(hr);
  459. _variant_t variant(1L);
  460. hr = iads->Put(AutoBstr(L"objectVersion"), variant);
  461. BREAK_ON_FAILED_HRESULT(hr);
  462. hr = iads->SetInfo();
  463. BREAK_ON_FAILED_HRESULT(hr);
  464. }
  465. while (0);
  466. if (FAILED(hr))
  467. {
  468. hr=E_FAIL;
  469. error=String::format(IDS_CANT_WRITE_OBJECT_VERSION);
  470. }
  471. LOG_HRESULT(hr);
  472. return hr;
  473. }
  474. HRESULT
  475. getADLargeInteger(
  476. IDirectoryObject *iDirObj,
  477. wchar_t *name,
  478. ADS_LARGE_INTEGER &value)
  479. {
  480. LOG_FUNCTION(getADLargeInteger);
  481. HRESULT hr=S_OK;
  482. do
  483. {
  484. LPWSTR nameArray[]={name};
  485. DWORD nAttr;
  486. PADS_ATTR_INFO attr;
  487. hr = iDirObj->GetObjectAttributes(nameArray,1,&attr,&nAttr);
  488. BREAK_ON_FAILED_HRESULT(hr);
  489. value=attr->pADsValues->LargeInteger;
  490. } while(0);
  491. LOG_HRESULT(hr);
  492. return hr;
  493. }