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.

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