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.

654 lines
18 KiB

  1. #ifndef UTIL_H
  2. #define UTIL_H
  3. #pragma once
  4. #include "fusionheap.h"
  5. #include "wincrypt.h"
  6. #include "fusionhandle.h"
  7. #include "numberof.h"
  8. #pragma warning(push)
  9. #pragma warning(disable: 4201)
  10. inline
  11. USHORT FusionGetMajorFromVersionHighHalf(DWORD dwVerHigh)
  12. {
  13. return HIWORD(dwVerHigh);
  14. }
  15. inline
  16. USHORT FusionGetMinorFromVersionHighHalf(DWORD dwVerHigh)
  17. {
  18. return LOWORD(dwVerHigh);
  19. }
  20. inline
  21. USHORT FusionGetRevisionFromVersionLowHalf(DWORD dwVerLow)
  22. {
  23. return HIWORD(dwVerLow);
  24. }
  25. inline
  26. USHORT FusionGetBuildFromVersionLowHalf(DWORD dwVerLow)
  27. {
  28. return LOWORD(dwVerLow);
  29. }
  30. #include "debmacro.h"
  31. #include "FusionArray.h"
  32. #include "fusionbuffer.h"
  33. #include "EnumBitOperations.h"
  34. //
  35. // FusionCopyString() has a non-obvious interface due to the overloading of
  36. // pcchBuffer to both describe the size of the buffer on entry and the number of
  37. // characters required on exit.
  38. //
  39. // prgchBuffer is the buffer to write to. If *pcchBuffer is zero when FusionCopyString()
  40. // is called, it may be NULL.
  41. //
  42. // pcchBuffer is a required parameter, which on entry must contain the number of unicode
  43. // characters in the buffer pointed to by prgchBuffer. On exit, if the buffer was
  44. // not large enough to hold the character string, including a trailing null,
  45. // it is set to the number of WCHARs required to hold the string, including the
  46. // trailing null, and HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) is returned.
  47. //
  48. // If the buffer is large enough, *pcchBuffer is set to the number of characters
  49. // written into the buffer, including the trailing null character.
  50. //
  51. // This is contrary to most functions which return the number of characters written
  52. // not including the trailing null, but since both on input and in the error case,
  53. // it deals with the size of the buffer required rather than the number of non-
  54. // null characters written, it seems inconsistent to only in the success case
  55. // omit the null from the count.
  56. //
  57. // szIn is a pointer to sequence of unicode characters to be copied.
  58. //
  59. // cchIn is the number of Unicode characters in the character string to copy. If a
  60. // value less than zero is passed in, szIn must point to a null-terminated string,
  61. // and the current length of the string is used. If a value zero or greater is
  62. // passed, exactly that many characters are assumed to be in the character string.
  63. //
  64. HRESULT FusionCopyString(
  65. WCHAR *prgchBuffer,
  66. SIZE_T *pcchBuffer,
  67. LPCWSTR szIn,
  68. SIZE_T cchIn
  69. );
  70. BOOL
  71. FusionDupString(
  72. PWSTR *ppszOut,
  73. PCWSTR szIn,
  74. SIZE_T cchIn
  75. );
  76. BOOL
  77. SxspMapLANGIDToCultures(
  78. LANGID langid,
  79. CBaseStringBuffer &rbuffGeneric,
  80. CBaseStringBuffer &rbuffSpecific
  81. );
  82. BOOL
  83. SxspMapCultureToLANGID(
  84. PCWSTR pcwszCultureString,
  85. LANGID &lid,
  86. PBOOL pfFound
  87. );
  88. typedef struct _SXSP_LANGUAGE_BUFFER_PAIR
  89. {
  90. CBaseStringBuffer * m_Generic;
  91. CBaseStringBuffer * m_Specific;
  92. } SXSP_LANGUAGE_BUFFER_PAIR, *PSXSP_LANGUAGE_BUFFER_PAIR;
  93. typedef const SXSP_LANGUAGE_BUFFER_PAIR * PCSXSP_LANGUAGE_BUFFER_PAIR;
  94. BOOL
  95. SxspCultureStringToCultureStrings(
  96. PCWSTR pcwszCultureString,
  97. bool & rfFoundOut,
  98. SXSP_LANGUAGE_BUFFER_PAIR & LanguagePair
  99. );
  100. BOOL
  101. FusionpParseProcessorArchitecture(
  102. IN PCWSTR String,
  103. IN SIZE_T Cch,
  104. OUT USHORT *ProcessorArchitecture OPTIONAL,
  105. bool &rfValid
  106. );
  107. BOOL
  108. FusionpFormatProcessorArchitecture(
  109. IN USHORT ProcessorArchitecture,
  110. CBaseStringBuffer &rBuffer
  111. );
  112. BOOL
  113. FusionpFormatEnglishLanguageName(
  114. IN LANGID LangID,
  115. CBaseStringBuffer &rBuffer
  116. );
  117. /*-----------------------------------------------------------------------------
  118. like ::CreateDirectoryW, but will create the parent directories as needed
  119. -----------------------------------------------------------------------------*/
  120. BOOL
  121. FusionpCreateDirectories(
  122. PCWSTR pszDirectory,
  123. SIZE_T cchDirectory
  124. );
  125. /*-----------------------------------------------------------------------------
  126. '\\' or '/'
  127. -----------------------------------------------------------------------------*/
  128. BOOL
  129. FusionpIsPathSeparator(
  130. WCHAR ch
  131. );
  132. /*-----------------------------------------------------------------------------
  133. just the 52 chars a-zA-Z, need to check with fs
  134. -----------------------------------------------------------------------------*/
  135. BOOL
  136. FusionpIsDriveLetter(
  137. WCHAR ch
  138. );
  139. /*-----------------------------------------------------------------------------
  140. -----------------------------------------------------------------------------*/
  141. VOID
  142. FusionpSetLastErrorFromHRESULT(
  143. HRESULT hr
  144. );
  145. DWORD
  146. FusionpHRESULTToWin32(
  147. HRESULT hr
  148. );
  149. /*-----------------------------------------------------------------------------
  150. -----------------------------------------------------------------------------*/
  151. class CFusionDirectoryDifference;
  152. BOOL
  153. FusionpCompareDirectoriesSizewiseRecursively(
  154. CFusionDirectoryDifference* pResult,
  155. const CBaseStringBuffer &rdir1,
  156. const CBaseStringBuffer &rdir2
  157. );
  158. class CFusionDirectoryDifference
  159. {
  160. private: // deliberately unimplemented
  161. CFusionDirectoryDifference(const CFusionDirectoryDifference&);
  162. VOID operator=(const CFusionDirectoryDifference&);
  163. public:
  164. CFusionDirectoryDifference()
  165. :
  166. m_e(eEqual),
  167. m_pstr1(&m_str1),
  168. m_pstr2(&m_str2)
  169. {
  170. }
  171. VOID
  172. DbgPrint(
  173. PCWSTR dir1,
  174. PCWSTR dir2
  175. );
  176. public:
  177. enum E
  178. {
  179. eEqual,
  180. eExtraOrMissingFile,
  181. eMismatchedFileSize,
  182. eMismatchedFileCount,
  183. eFileDirectoryMismatch
  184. };
  185. E m_e;
  186. union
  187. {
  188. struct
  189. {
  190. CBaseStringBuffer * m_pstr1;
  191. CBaseStringBuffer * m_pstr2;
  192. };
  193. struct // eExtraOrMissingFile
  194. {
  195. CBaseStringBuffer * m_pstrExtraOrMissingFile;
  196. };
  197. struct // eMismatchFileSize
  198. {
  199. CBaseStringBuffer * m_pstrMismatchedSizeFile1;
  200. CBaseStringBuffer * m_pstrMismatchedSizeFile2;
  201. ULONGLONG m_nMismatchedFileSize1;
  202. ULONGLONG m_nMismatchedFileSize2;
  203. };
  204. struct // eMismatchFileCount
  205. {
  206. CBaseStringBuffer * m_pstrMismatchedCountDir1;
  207. CBaseStringBuffer * m_pstrMismatchedCountDir2;
  208. ULONGLONG m_nMismatchedFileCount1;
  209. ULONGLONG m_nMismatchedFileCount2;
  210. };
  211. struct // eFileDirectoryMismatch
  212. {
  213. CBaseStringBuffer * m_pstrFile;
  214. CBaseStringBuffer * m_pstrDirectory;
  215. };
  216. };
  217. // private:
  218. CStringBuffer m_str1;
  219. CStringBuffer m_str2;
  220. };
  221. /*-----------------------------------------------------------------------------
  222. -----------------------------------------------------------------------------*/
  223. class CFusionFilePathAndSize
  224. {
  225. public:
  226. CFusionFilePathAndSize() : m_size(0), m_bHasHashInfo(false), m_HashAlgorithm(0) { }
  227. // bsearch and qsort accept optionally subtley different functions
  228. // bsearch looks for a key in an array, the key and the array elements
  229. // can be of different types, qsort compares only elements in the array
  230. static int __cdecl QsortComparePath(const void*, const void*);
  231. // for qsort/bsearch an array of pointers to CFusionFilePathAndSize
  232. static int __cdecl QsortIndirectComparePath(const void*, const void*);
  233. CStringBuffer m_path;
  234. __int64 m_size;
  235. // Do we actually have valid hashing data?
  236. bool m_bHasHashInfo;
  237. CStringBuffer m_HashString;
  238. ALG_ID m_HashAlgorithm;
  239. private:
  240. CFusionFilePathAndSize(const CFusionFilePathAndSize &); // intentionally not implemented
  241. void operator =(const CFusionFilePathAndSize &); // intentionally not implemented
  242. };
  243. /*-----------------------------------------------------------------------------
  244. two DWORDs to an __int64
  245. -----------------------------------------------------------------------------*/
  246. ULONGLONG
  247. FusionpFileSizeFromFindData(
  248. const WIN32_FIND_DATAW& wfd
  249. );
  250. /*-----------------------------------------------------------------------------
  251. HRESULT_FROM_WIN32(GetLastError()) or E_FAIL if GetLastError() == NO_ERROR
  252. -----------------------------------------------------------------------------*/
  253. HRESULT
  254. FusionpHresultFromLastError();
  255. /*-----------------------------------------------------------------------------
  256. FindFirstFile results you always ignore "." and ".."
  257. -----------------------------------------------------------------------------*/
  258. BOOL FusionpIsDotOrDotDot(PCWSTR str);
  259. /*-----------------------------------------------------------------------------
  260. simple code for walking directories, with a per file callback
  261. could be fleshed out more, but good enough for present purposes
  262. -----------------------------------------------------------------------------*/
  263. #define SXSP_DIR_WALK_FLAGS_FIND_AT_LEAST_ONE_FILEUNDER_CURRENTDIR (1)
  264. #define SXSP_DIR_WALK_FLAGS_INSTALL_ASSEMBLY_UNDER_CURRECTDIR_SUCCEED (2)
  265. class CDirWalk
  266. {
  267. public:
  268. enum ECallbackReason
  269. {
  270. eBeginDirectory = 1,
  271. eFile,
  272. eEndDirectory
  273. };
  274. CDirWalk();
  275. //
  276. // the callback cannot reenable what is has disabled
  277. // perhaps move these to be member data bools
  278. //
  279. enum ECallbackResult
  280. {
  281. eKeepWalking = 0x00000000,
  282. eError = 0x00000001,
  283. eSuccess = 0x00000002,
  284. eStopWalkingFiles = 0x00000004,
  285. eStopWalkingDirectories = 0x00000008,
  286. eStopWalkingDeep = 0x00000010
  287. };
  288. //
  289. // Just filter on like *.dll, in the future you can imagine
  290. // filtering on attributes like read onlyness, or running
  291. // SQL queries over the "File System Oledb Provider"...
  292. //
  293. // Also, note that we currently do a FindFirstFile/FindNextFile
  294. // loop for each filter, plus sometimes one more with *
  295. // to pick up directories. It is probably more efficient to
  296. // use * and then filter individually but I don't feel like
  297. // porting over \Vsee\Lib\Io\Wildcard.cpp right now (which
  298. // was itself ported from FsRtl, and should be in Win32!)
  299. //
  300. const PCWSTR* m_fileFiltersBegin;
  301. const PCWSTR* m_fileFiltersEnd;
  302. CStringBuffer m_strParent; // set this to the initial directory to walk
  303. SIZE_T m_cchOriginalPath;
  304. WIN32_FIND_DATAW m_fileData; // not valid for directory callbacks, but could be with a little work
  305. PVOID m_context;
  306. CStringBuffer m_strLastObjectFound;
  307. ECallbackResult
  308. (*m_callback)(
  309. ECallbackReason reason,
  310. CDirWalk* dirWalk,
  311. DWORD dwWalkDirFlags
  312. );
  313. BOOL
  314. Walk();
  315. protected:
  316. ECallbackResult
  317. WalkHelper();
  318. private:
  319. CDirWalk(const CDirWalk &); // intentionally not implemented
  320. void operator =(const CDirWalk &); // intentionally not implemented
  321. };
  322. ENUM_BIT_OPERATIONS(CDirWalk::ECallbackResult)
  323. /*-----------------------------------------------------------------------------*/
  324. typedef struct _FUSION_FLAG_FORMAT_MAP_ENTRY
  325. {
  326. DWORD m_dwFlagMask;
  327. PCWSTR m_pszString;
  328. SIZE_T m_cchString;
  329. PCWSTR m_pszShortString;
  330. SIZE_T m_cchShortString;
  331. DWORD m_dwFlagsToTurnOff; // enables more generic flags first in map hiding more specific combinations later
  332. } FUSION_FLAG_FORMAT_MAP_ENTRY, *PFUSION_FLAG_FORMAT_MAP_ENTRY;
  333. #define DEFINE_FUSION_FLAG_FORMAT_MAP_ENTRY(_x, _ss) { _x, L ## #_x, NUMBER_OF(L ## #_x) - 1, L ## _ss, NUMBER_OF(_ss) - 1, _x },
  334. typedef const FUSION_FLAG_FORMAT_MAP_ENTRY *PCFUSION_FLAG_FORMAT_MAP_ENTRY;
  335. BOOL
  336. FusionpFormatFlags(
  337. IN DWORD dwFlagsToFormat,
  338. IN bool fUseLongNames,
  339. IN SIZE_T cMapEntries,
  340. IN PCFUSION_FLAG_FORMAT_MAP_ENTRY prgMapEntries,
  341. IN OUT CBaseStringBuffer &rbuff
  342. );
  343. /*-----------------------------------------------------------------------------
  344. inline implementations
  345. -----------------------------------------------------------------------------*/
  346. inline BOOL
  347. FusionpIsPathSeparator(
  348. WCHAR ch
  349. )
  350. /*
  351. NTRAID#NTBUG9-591195-2002/03/31-JayKrell
  352. path issues, case mapping.. (but this is probably ok)
  353. */
  354. {
  355. return ((ch == L'\\') || (ch == L'/'));
  356. }
  357. inline BOOL
  358. FusionpIsDotOrDotDot(
  359. PCWSTR str
  360. )
  361. /*
  362. NTRAID#NTBUG9-591195-2002/03/31-JayKrell
  363. path issues, case mapping..
  364. */
  365. {
  366. return ((str[0] == L'.') && ((str[1] == L'\0') || ((str[1] == L'.') && (str[2] == L'\0'))));
  367. }
  368. inline BOOL
  369. FusionpIsDriveLetter(
  370. WCHAR ch
  371. )
  372. /*
  373. NTRAID#NTBUG9-591195-2002/03/31-JayKrell
  374. path issues, case mapping..
  375. */
  376. {
  377. if (ch >= L'a' && ch <= L'z')
  378. return TRUE;
  379. if (ch >= L'A' && ch <= L'Z')
  380. return TRUE;
  381. return FALSE;
  382. }
  383. inline ULONGLONG
  384. FusionpFileSizeFromFindData(
  385. const WIN32_FIND_DATAW& wfd
  386. )
  387. {
  388. ULARGE_INTEGER uli;
  389. uli.LowPart = wfd.nFileSizeLow;
  390. uli.HighPart = wfd.nFileSizeHigh;
  391. return uli.QuadPart;
  392. }
  393. inline HRESULT
  394. FusionpHresultFromLastError()
  395. {
  396. HRESULT hr = E_FAIL;
  397. DWORD dwLastError = ::FusionpGetLastWin32Error();
  398. if (dwLastError != NO_ERROR)
  399. {
  400. hr = HRESULT_FROM_WIN32(dwLastError);
  401. }
  402. return hr;
  403. }
  404. template <> inline BOOL
  405. FusionWin32CopyContents<CFusionFilePathAndSize>(
  406. CFusionFilePathAndSize& rtDestination,
  407. const CFusionFilePathAndSize& rtSource
  408. )
  409. {
  410. BOOL fSuccess = FALSE;
  411. FN_TRACE_WIN32(fSuccess);
  412. IFW32FALSE_EXIT(rtDestination.m_path.Win32Assign(rtSource.m_path, rtSource.m_path.Cch()));
  413. IFW32FALSE_EXIT(rtDestination.m_HashString.Win32Assign(rtSource.m_HashString, rtSource.m_HashString.Cch()));
  414. rtDestination.m_size = rtSource.m_size;
  415. rtDestination.m_HashAlgorithm = rtSource.m_HashAlgorithm;
  416. rtDestination.m_bHasHashInfo = rtSource.m_bHasHashInfo;
  417. fSuccess = TRUE;
  418. Exit:
  419. return fSuccess;
  420. }
  421. #define FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING (0x00000001)
  422. #define FUSIONP_REG_QUERY_DWORD_MISSING_VALUE_IS_FAILURE (0x00000001)
  423. #define FUSIONP_REG_QUERY_BINARY_NO_FAIL_IF_NON_BINARY (0x00000001)
  424. BOOL
  425. FusionpRegQuerySzValueEx(
  426. DWORD dwFlags,
  427. HKEY hKey,
  428. PCWSTR lpValueName,
  429. CBaseStringBuffer &Buffer,
  430. DWORD &rdwWin32Error,
  431. SIZE_T cExceptionalLastErrorValues,
  432. ...
  433. );
  434. BOOL
  435. FusionpRegQuerySzValueEx(
  436. DWORD dwFlags,
  437. HKEY hKey,
  438. PCWSTR lpValueName,
  439. CBaseStringBuffer &Buffer
  440. );
  441. BOOL
  442. FusionpRegQueryDwordValueEx(
  443. DWORD dwFlags,
  444. HKEY hKey,
  445. PCWSTR wszValueName,
  446. PDWORD pdwValue,
  447. DWORD dwDefaultValue = 0
  448. );
  449. BOOL
  450. FusionpRegQueryBinaryValueEx(
  451. DWORD dwFlags,
  452. HKEY hKey,
  453. PCWSTR lpValueName,
  454. CFusionArray<BYTE> &rbBuffer
  455. );
  456. BOOL
  457. FusionpRegQueryBinaryValueEx(
  458. DWORD dwFlags,
  459. HKEY hKey,
  460. PCWSTR lpValueName,
  461. CFusionArray<BYTE> &rbBuffer,
  462. DWORD &rdwLastError,
  463. SIZE_T cExceptionalLastErrors,
  464. ...
  465. );
  466. BOOL
  467. FusionpRegQueryBinaryValueEx(
  468. DWORD dwFlags,
  469. HKEY hKey,
  470. PCWSTR lpValueName,
  471. CFusionArray<BYTE> &rbBuffer,
  472. DWORD &rdwLastError,
  473. SIZE_T cExceptionalLastErrors,
  474. va_list ap
  475. );
  476. BOOL
  477. FusionpAreWeInOSSetupMode(
  478. BOOL*
  479. );
  480. BOOL
  481. FusionpAreWeInMiniSetupMode(
  482. BOOL*
  483. );
  484. BOOL
  485. FusionpMapLangIdToString(
  486. DWORD dwFlags,
  487. LANGID LangID,
  488. PCWSTR *StringOut
  489. );
  490. BOOL
  491. SxspDequoteString(
  492. IN DWORD dwFlags,
  493. IN PCWSTR pcwszStringIn,
  494. IN SIZE_T cchStringIn,
  495. OUT PWSTR pwszStringOut,
  496. OUT SIZE_T *pcchStringOut
  497. );
  498. BOOL
  499. FusionpGetActivationContextFromFindResult(
  500. IN PCACTCTX_SECTION_KEYED_DATA askd,
  501. OUT HANDLE *
  502. );
  503. #define FUSIONP_SEARCH_PATH_ACTCTX (0x00000001)
  504. BOOL
  505. FusionpSearchPath(
  506. ULONG ulFusionFlags,
  507. LPCWSTR lpPath,
  508. LPCWSTR lpFileName, // file name
  509. LPCWSTR lpExtension, // file extension
  510. CBaseStringBuffer & StringBuffer,
  511. SIZE_T * lpFilePartOffset, // file component
  512. HANDLE hActCtx
  513. );
  514. BOOL
  515. FusionpGetModuleFileName(
  516. ULONG ulFusionFlags,
  517. HMODULE hmodDll,
  518. CBaseStringBuffer & StringBuffer
  519. );
  520. #define SXSP_DOES_FILE_EXIST_FLAG_COMPRESSION_AWARE (0x00000001)
  521. #define SXSP_DOES_FILE_EXIST_FLAG_INCLUDE_NETWORK_ERRORS (0x00000002)
  522. #define SXSP_DOES_FILE_EXIST_FLAG_CHECK_FILE_ONLY (0x00000004)
  523. #define SXSP_DOES_FILE_EXIST_FLAG_CHECK_DIRECTORY_ONLY (0x00000008)
  524. BOOL
  525. SxspDoesFileExist(
  526. DWORD dwFlags,
  527. PCWSTR pszFileName,
  528. bool &rfExists
  529. );
  530. #define SXSP_DOES_FILE_OR_DIRECTORY_EXIST_FLAG_COMPRESSION_AWARE (0x00000001)
  531. #define SXSP_DOES_FILE_OR_DIRECTORY_EXIST_FLAG_INCLUDE_NETWORK_ERRORS (0x00000002)
  532. #define SXSP_DOES_FILE_OR_DIRECTORY_EXIST_DISPOSITION_FILE_EXISTS (1)
  533. #define SXSP_DOES_FILE_OR_DIRECTORY_EXIST_DISPOSITION_DIRECTORY_EXISTS (2)
  534. #define SXSP_DOES_FILE_OR_DIRECTORY_EXIST_DISPOSITION_NEITHER_EXISTS (3)
  535. BOOL
  536. SxspDoesFileOrDirectoryExist(
  537. DWORD dwFlags,
  538. PCWSTR pszFileName,
  539. OUT DWORD &rdwDisposition
  540. );
  541. BOOL
  542. SxspGetFileAttributesW(
  543. PCWSTR lpFileName,
  544. DWORD &rdwFileAttributes
  545. );
  546. BOOL
  547. SxspGetFileAttributesW(
  548. PCWSTR lpFileName,
  549. DWORD &rdwFileAttributes,
  550. DWORD &rdwWin32Error,
  551. SIZE_T cExceptionalWin32Errors,
  552. ...
  553. );
  554. BOOL
  555. SxspFormatULONG(
  556. ULONG ul,
  557. SIZE_T CchBuffer,
  558. WCHAR Buffer[],
  559. SIZE_T *CchWrittenOrRequired
  560. );
  561. #pragma warning(pop)
  562. #endif