SetupLdrAndSetup.RedirFunc.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. unit SetupLdrAndSetup.RedirFunc;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2025 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Functions for dealing with WOW64 file system redirection.
  8. Used only by the Setup and SetupLdr projects.
  9. The *Redir functions are counterparts to common functions that offer
  10. built-in support for disabling FS redirection.
  11. }
  12. interface
  13. uses
  14. Windows, SysUtils, Shared.FileClass, Shared.VerInfoFunc;
  15. type
  16. TPreviousFsRedirectionState = record
  17. DidDisable: Boolean;
  18. OldValue: Pointer;
  19. end;
  20. function AreFsRedirectionFunctionsAvailable: Boolean;
  21. function DisableFsRedirectionIf(const Disable: Boolean;
  22. var PreviousState: TPreviousFsRedirectionState): Boolean;
  23. procedure RestoreFsRedirection(const PreviousState: TPreviousFsRedirectionState);
  24. function CreateFileRedir(const DisableFsRedir: Boolean; const FileName: String;
  25. const DesiredAccess, ShareMode: DWORD; const SecurityAttributes: PSecurityAttributes;
  26. const CreationDisposition, FlagsAndAttributes: DWORD; TemplateFile: THandle): THandle;
  27. function CreateDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String;
  28. const SecurityAttributes: PSecurityAttributes = nil): BOOL;
  29. function CreateProcessRedir(const DisableFsRedir: Boolean;
  30. const lpApplicationName: PChar; const lpCommandLine: PChar;
  31. const lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  32. const bInheritHandles: BOOL; const dwCreationFlags: DWORD;
  33. const lpEnvironment: Pointer; const lpCurrentDirectory: PChar;
  34. const lpStartupInfo: TStartupInfo;
  35. var lpProcessInformation: TProcessInformation): BOOL;
  36. function CopyFileRedir(const DisableFsRedir: Boolean;
  37. const ExistingFilename, NewFilename: String; const FailIfExists: BOOL): BOOL;
  38. function DeleteFileRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
  39. function DirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  40. function FileOrDirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  41. function FindFirstFileRedir(const DisableFsRedir: Boolean; const Filename: String;
  42. var FindData: TWin32FindData): THandle;
  43. function GetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String): DWORD;
  44. function GetShortNameRedir(const DisableFsRedir: Boolean; const Filename: String): String;
  45. function GetVersionNumbersRedir(const DisableFsRedir: Boolean; const Filename: String;
  46. var VersionNumbers: TFileVersionNumbers): Boolean;
  47. function IsDirectoryAndNotReparsePointRedir(const DisableFsRedir: Boolean;
  48. const Name: String): Boolean;
  49. function MoveFileRedir(const DisableFsRedir: Boolean;
  50. const ExistingFilename, NewFilename: String): BOOL;
  51. function MoveFileExRedir(const DisableFsRedir: Boolean;
  52. const ExistingFilename, NewFilename: String; const Flags: DWORD): BOOL;
  53. function NewFileExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  54. function RemoveDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
  55. function SetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String;
  56. const Attrib: DWORD): BOOL;
  57. function SetNTFSCompressionRedir(const DisableFsRedir: Boolean; const FileOrDir: String; Compress: Boolean): Boolean;
  58. type
  59. TFileRedir = class(TFile)
  60. private
  61. FDisableFsRedir: Boolean;
  62. protected
  63. function CreateHandle(const AFilename: String;
  64. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  65. ASharing: TFileSharing): THandle; override;
  66. public
  67. constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
  68. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  69. ASharing: TFileSharing);
  70. end;
  71. TTextFileReaderRedir = class(TTextFileReader)
  72. private
  73. FDisableFsRedir: Boolean;
  74. protected
  75. function CreateHandle(const AFilename: String;
  76. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  77. ASharing: TFileSharing): THandle; override;
  78. public
  79. constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
  80. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  81. ASharing: TFileSharing);
  82. end;
  83. TTextFileWriterRedir = class(TTextFileWriter)
  84. private
  85. FDisableFsRedir: Boolean;
  86. protected
  87. function CreateHandle(const AFilename: String;
  88. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  89. ASharing: TFileSharing): THandle; override;
  90. public
  91. constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
  92. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  93. ASharing: TFileSharing);
  94. end;
  95. implementation
  96. uses
  97. Shared.CommonFunc, PathFunc;
  98. var
  99. Wow64DisableWow64FsRedirectionFunc: function(var OldValue: Pointer): BOOL; stdcall;
  100. Wow64RevertWow64FsRedirectionFunc: function(OldValue: Pointer): BOOL; stdcall;
  101. FsRedirectionFunctionsAvailable: Boolean;
  102. function AreFsRedirectionFunctionsAvailable: Boolean;
  103. begin
  104. Result := FsRedirectionFunctionsAvailable;
  105. end;
  106. function DisableFsRedirectionIf(const Disable: Boolean;
  107. var PreviousState: TPreviousFsRedirectionState): Boolean;
  108. { If Disable is False, the function does not change the redirection state and
  109. always returns True.
  110. If Disable is True, the function attempts to disable WOW64 file system
  111. redirection, so that c:\windows\system32 goes to the 64-bit System directory
  112. instead of the 32-bit one.
  113. Returns True if successful, False if not. For extended error information when
  114. False is returned, call GetLastError. }
  115. begin
  116. PreviousState.DidDisable := False;
  117. if not Disable then
  118. Result := True
  119. else begin
  120. if FsRedirectionFunctionsAvailable then begin
  121. { Note: Disassembling Wow64DisableWow64FsRedirection and the Rtl function
  122. it calls, it doesn't appear as if it can ever actually fail on 64-bit
  123. Windows. But it always fails on the 32-bit version of Windows Server
  124. 2003 SP1 (with error code 1 - ERROR_INVALID_FUNCTION). }
  125. Result := Wow64DisableWow64FsRedirectionFunc(PreviousState.OldValue);
  126. if Result then
  127. PreviousState.DidDisable := True;
  128. end
  129. else begin
  130. { Should never happen }
  131. SetLastError(ERROR_INVALID_FUNCTION);
  132. Result := False;
  133. end;
  134. end;
  135. end;
  136. procedure RestoreFsRedirection(const PreviousState: TPreviousFsRedirectionState);
  137. { Restores the previous WOW64 file system redirection state after a call to
  138. DisableFsRedirectionIf. There is no indication of failure (which is
  139. extremely unlikely). }
  140. begin
  141. if PreviousState.DidDisable then
  142. Wow64RevertWow64FsRedirectionFunc(PreviousState.OldValue);
  143. end;
  144. { *Redir functions }
  145. function CreateFileRedir(const DisableFsRedir: Boolean; const FileName: String;
  146. const DesiredAccess, ShareMode: DWORD; const SecurityAttributes: PSecurityAttributes;
  147. const CreationDisposition, FlagsAndAttributes: DWORD; TemplateFile: THandle): THandle;
  148. var
  149. PrevState: TPreviousFsRedirectionState;
  150. ErrorCode: DWORD;
  151. begin
  152. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  153. Result := INVALID_HANDLE_VALUE;
  154. Exit;
  155. end;
  156. try
  157. Result := CreateFile(PChar(Filename), DesiredAccess, ShareMode, SecurityAttributes,
  158. CreationDisposition, FlagsAndAttributes, TemplateFile);
  159. ErrorCode := GetLastError;
  160. finally
  161. RestoreFsRedirection(PrevState);
  162. end;
  163. SetLastError(ErrorCode);
  164. end;
  165. function CreateDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String;
  166. const SecurityAttributes: PSecurityAttributes): BOOL;
  167. var
  168. PrevState: TPreviousFsRedirectionState;
  169. ErrorCode: DWORD;
  170. begin
  171. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  172. Result := False;
  173. Exit;
  174. end;
  175. try
  176. Result := CreateDirectory(PChar(Filename), SecurityAttributes);
  177. ErrorCode := GetLastError;
  178. finally
  179. RestoreFsRedirection(PrevState);
  180. end;
  181. SetLastError(ErrorCode);
  182. end;
  183. function CreateProcessRedir(const DisableFsRedir: Boolean;
  184. const lpApplicationName: PChar; const lpCommandLine: PChar;
  185. const lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  186. const bInheritHandles: BOOL; const dwCreationFlags: DWORD;
  187. const lpEnvironment: Pointer; const lpCurrentDirectory: PChar;
  188. const lpStartupInfo: TStartupInfo;
  189. var lpProcessInformation: TProcessInformation): BOOL;
  190. var
  191. PrevState: TPreviousFsRedirectionState;
  192. ErrorCode: DWORD;
  193. begin
  194. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  195. Result := False;
  196. Exit;
  197. end;
  198. try
  199. Result := CreateProcess(lpApplicationName, lpCommandLine,
  200. lpProcessAttributes, lpThreadAttributes,
  201. bInheritHandles, dwCreationFlags, lpEnvironment,
  202. lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  203. ErrorCode := GetLastError;
  204. finally
  205. RestoreFsRedirection(PrevState);
  206. end;
  207. SetLastError(ErrorCode);
  208. end;
  209. function CopyFileRedir(const DisableFsRedir: Boolean;
  210. const ExistingFilename, NewFilename: String; const FailIfExists: BOOL): BOOL;
  211. var
  212. PrevState: TPreviousFsRedirectionState;
  213. ErrorCode: DWORD;
  214. begin
  215. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  216. Result := False;
  217. Exit;
  218. end;
  219. try
  220. Result := CopyFile(PChar(ExistingFilename), PChar(NewFilename), FailIfExists);
  221. ErrorCode := GetLastError;
  222. finally
  223. RestoreFsRedirection(PrevState);
  224. end;
  225. SetLastError(ErrorCode);
  226. end;
  227. function DeleteFileRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
  228. var
  229. PrevState: TPreviousFsRedirectionState;
  230. ErrorCode: DWORD;
  231. begin
  232. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  233. Result := False;
  234. Exit;
  235. end;
  236. try
  237. Result := Windows.DeleteFile(PChar(Filename));
  238. ErrorCode := GetLastError;
  239. finally
  240. RestoreFsRedirection(PrevState);
  241. end;
  242. SetLastError(ErrorCode);
  243. end;
  244. function DirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  245. var
  246. PrevState: TPreviousFsRedirectionState;
  247. ErrorCode: DWORD;
  248. begin
  249. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  250. Result := False;
  251. Exit;
  252. end;
  253. try
  254. Result := DirExists(Filename);
  255. ErrorCode := GetLastError;
  256. finally
  257. RestoreFsRedirection(PrevState);
  258. end;
  259. SetLastError(ErrorCode);
  260. end;
  261. function FileOrDirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  262. var
  263. PrevState: TPreviousFsRedirectionState;
  264. ErrorCode: DWORD;
  265. begin
  266. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  267. Result := False;
  268. Exit;
  269. end;
  270. try
  271. Result := FileOrDirExists(Filename);
  272. ErrorCode := GetLastError;
  273. finally
  274. RestoreFsRedirection(PrevState);
  275. end;
  276. SetLastError(ErrorCode);
  277. end;
  278. function FindFirstFileRedir(const DisableFsRedir: Boolean; const Filename: String;
  279. var FindData: TWin32FindData): THandle;
  280. var
  281. PrevState: TPreviousFsRedirectionState;
  282. ErrorCode: DWORD;
  283. begin
  284. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  285. Result := INVALID_HANDLE_VALUE;
  286. Exit;
  287. end;
  288. try
  289. Result := FindFirstFile(PChar(Filename), FindData);
  290. ErrorCode := GetLastError;
  291. finally
  292. RestoreFsRedirection(PrevState);
  293. end;
  294. SetLastError(ErrorCode);
  295. end;
  296. function GetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String): DWORD;
  297. var
  298. PrevState: TPreviousFsRedirectionState;
  299. ErrorCode: DWORD;
  300. begin
  301. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  302. Result := INVALID_FILE_ATTRIBUTES;
  303. Exit;
  304. end;
  305. try
  306. Result := GetFileAttributes(PChar(Filename));
  307. ErrorCode := GetLastError;
  308. finally
  309. RestoreFsRedirection(PrevState);
  310. end;
  311. SetLastError(ErrorCode);
  312. end;
  313. function GetShortNameRedir(const DisableFsRedir: Boolean; const Filename: String): String;
  314. var
  315. PrevState: TPreviousFsRedirectionState;
  316. begin
  317. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  318. Result := Filename;
  319. Exit;
  320. end;
  321. try
  322. Result := GetShortName(Filename);
  323. finally
  324. RestoreFsRedirection(PrevState);
  325. end;
  326. end;
  327. function GetVersionNumbersRedir(const DisableFsRedir: Boolean; const Filename: String;
  328. var VersionNumbers: TFileVersionNumbers): Boolean;
  329. var
  330. PrevState: TPreviousFsRedirectionState;
  331. begin
  332. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  333. Result := False;
  334. Exit;
  335. end;
  336. try
  337. Result := GetVersionNumbers(Filename, VersionNumbers);
  338. finally
  339. RestoreFsRedirection(PrevState);
  340. end;
  341. end;
  342. function IsDirectoryAndNotReparsePointRedir(const DisableFsRedir: Boolean;
  343. const Name: String): Boolean;
  344. var
  345. PrevState: TPreviousFsRedirectionState;
  346. begin
  347. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  348. Result := False;
  349. Exit;
  350. end;
  351. try
  352. Result := IsDirectoryAndNotReparsePoint(Name);
  353. finally
  354. RestoreFsRedirection(PrevState);
  355. end;
  356. end;
  357. function MoveFileRedir(const DisableFsRedir: Boolean;
  358. const ExistingFilename, NewFilename: String): BOOL;
  359. var
  360. PrevState: TPreviousFsRedirectionState;
  361. ErrorCode: DWORD;
  362. begin
  363. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  364. Result := False;
  365. Exit;
  366. end;
  367. try
  368. Result := MoveFile(PChar(ExistingFilename), PChar(NewFilename));
  369. ErrorCode := GetLastError;
  370. finally
  371. RestoreFsRedirection(PrevState);
  372. end;
  373. SetLastError(ErrorCode);
  374. end;
  375. function MoveFileExRedir(const DisableFsRedir: Boolean;
  376. const ExistingFilename, NewFilename: String; const Flags: DWORD): BOOL;
  377. var
  378. NewFilenameP: PChar;
  379. PrevState: TPreviousFsRedirectionState;
  380. ErrorCode: DWORD;
  381. begin
  382. if (NewFilename = '') and (Flags and MOVEFILE_DELAY_UNTIL_REBOOT <> 0) then
  383. NewFilenameP := nil
  384. else
  385. NewFilenameP := PChar(NewFilename);
  386. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  387. Result := False;
  388. Exit;
  389. end;
  390. try
  391. Result := MoveFileEx(PChar(ExistingFilename), NewFilenameP, Flags);
  392. ErrorCode := GetLastError;
  393. finally
  394. RestoreFsRedirection(PrevState);
  395. end;
  396. SetLastError(ErrorCode);
  397. end;
  398. function NewFileExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
  399. var
  400. PrevState: TPreviousFsRedirectionState;
  401. ErrorCode: DWORD;
  402. begin
  403. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  404. Result := False;
  405. Exit;
  406. end;
  407. try
  408. Result := NewFileExists(Filename);
  409. ErrorCode := GetLastError;
  410. finally
  411. RestoreFsRedirection(PrevState);
  412. end;
  413. SetLastError(ErrorCode);
  414. end;
  415. function RemoveDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
  416. var
  417. PrevState: TPreviousFsRedirectionState;
  418. ErrorCode: DWORD;
  419. begin
  420. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  421. Result := False;
  422. Exit;
  423. end;
  424. try
  425. Result := RemoveDirectory(PChar(Filename));
  426. ErrorCode := GetLastError;
  427. finally
  428. RestoreFsRedirection(PrevState);
  429. end;
  430. SetLastError(ErrorCode);
  431. end;
  432. function SetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String;
  433. const Attrib: DWORD): BOOL;
  434. var
  435. PrevState: TPreviousFsRedirectionState;
  436. ErrorCode: DWORD;
  437. begin
  438. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  439. Result := False;
  440. Exit;
  441. end;
  442. try
  443. Result := SetFileAttributes(PChar(Filename), Attrib);
  444. ErrorCode := GetLastError;
  445. finally
  446. RestoreFsRedirection(PrevState);
  447. end;
  448. SetLastError(ErrorCode);
  449. end;
  450. function SetNTFSCompressionRedir(const DisableFsRedir: Boolean; const FileOrDir: String; Compress: Boolean): Boolean;
  451. var
  452. PrevState: TPreviousFsRedirectionState;
  453. ErrorCode: DWORD;
  454. begin
  455. if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
  456. Result := False;
  457. Exit;
  458. end;
  459. try
  460. Result := SetNTFSCompression(FileOrDir, Compress);
  461. ErrorCode := GetLastError;
  462. finally
  463. RestoreFsRedirection(PrevState);
  464. end;
  465. SetLastError(ErrorCode);
  466. end;
  467. { TFileRedir }
  468. constructor TFileRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
  469. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  470. ASharing: TFileSharing);
  471. begin
  472. FDisableFsRedir := DisableFsRedir;
  473. inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
  474. end;
  475. function TFileRedir.CreateHandle(const AFilename: String;
  476. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  477. ASharing: TFileSharing): THandle;
  478. var
  479. PrevState: TPreviousFsRedirectionState;
  480. ErrorCode: DWORD;
  481. begin
  482. if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
  483. Result := INVALID_HANDLE_VALUE;
  484. Exit;
  485. end;
  486. try
  487. Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
  488. ASharing);
  489. ErrorCode := GetLastError;
  490. finally
  491. RestoreFsRedirection(PrevState);
  492. end;
  493. SetLastError(ErrorCode);
  494. end;
  495. { TTextFileReaderRedir }
  496. constructor TTextFileReaderRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
  497. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  498. ASharing: TFileSharing);
  499. begin
  500. FDisableFsRedir := DisableFsRedir;
  501. inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
  502. end;
  503. function TTextFileReaderRedir.CreateHandle(const AFilename: String;
  504. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  505. ASharing: TFileSharing): THandle;
  506. var
  507. PrevState: TPreviousFsRedirectionState;
  508. ErrorCode: DWORD;
  509. begin
  510. if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
  511. Result := INVALID_HANDLE_VALUE;
  512. Exit;
  513. end;
  514. try
  515. Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
  516. ASharing);
  517. ErrorCode := GetLastError;
  518. finally
  519. RestoreFsRedirection(PrevState);
  520. end;
  521. SetLastError(ErrorCode);
  522. end;
  523. { TTextFileWriterRedir }
  524. constructor TTextFileWriterRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
  525. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  526. ASharing: TFileSharing);
  527. begin
  528. FDisableFsRedir := DisableFsRedir;
  529. inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
  530. end;
  531. function TTextFileWriterRedir.CreateHandle(const AFilename: String;
  532. ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
  533. ASharing: TFileSharing): THandle;
  534. var
  535. PrevState: TPreviousFsRedirectionState;
  536. ErrorCode: DWORD;
  537. begin
  538. if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
  539. Result := INVALID_HANDLE_VALUE;
  540. Exit;
  541. end;
  542. try
  543. Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
  544. ASharing);
  545. ErrorCode := GetLastError;
  546. finally
  547. RestoreFsRedirection(PrevState);
  548. end;
  549. SetLastError(ErrorCode);
  550. end;
  551. initialization
  552. Wow64DisableWow64FsRedirectionFunc := GetProcAddress(GetModuleHandle(kernel32),
  553. 'Wow64DisableWow64FsRedirection');
  554. Wow64RevertWow64FsRedirectionFunc := GetProcAddress(GetModuleHandle(kernel32),
  555. 'Wow64RevertWow64FsRedirection');
  556. FsRedirectionFunctionsAvailable := Assigned(Wow64DisableWow64FsRedirectionFunc) and
  557. Assigned(Wow64RevertWow64FsRedirectionFunc);
  558. { For GetVersionNumbersRedir: Pre-load shell32.dll since GetFileVersionInfo
  559. and GetFileVersionInfoSize will try to load it when reading version info
  560. on 16-bit files. We can't allow the DLL be loaded for the first time while
  561. FS redirection is disabled. }
  562. SafeLoadLibrary(AddBackslash(GetSystemDir) + 'shell32.dll', SEM_NOOPENFILEERRORBOX);
  563. { FormatMessage might be called with FS redirection disabled, so ensure
  564. that all the DLLs FormatMessage searches in for messages (e.g. netmsg.dll,
  565. ws03res.dll) are pre-loaded by calling it now with a randomly-chosen
  566. message ID -- one that won't result in a match and cause the function to
  567. return early.
  568. (Note: Presently, FormatMessage loads the DLLs as "data files" so it
  569. actually may not matter whether it gets 32- or 64-bit versions. But let's
  570. be on the safe side.) }
  571. Win32ErrorString($4C783AFB);
  572. end.