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.

644 lines
17 KiB

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