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.

534 lines
12 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1993 Microsoft Corporation
  5. Module Name:
  6. spfile.c
  7. Abstract:
  8. File operations for text setup.
  9. Author:
  10. Ted Miller (tedm) 2-Aug-1993
  11. Revision History:
  12. --*/
  13. #if 0
  14. //
  15. // Helper macro to make object attribute initialization a little cleaner.
  16. //
  17. #define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
  18. \
  19. RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
  20. \
  21. InitializeObjectAttributes( \
  22. (Obja), \
  23. (UnicodeString), \
  24. OBJ_CASE_INSENSITIVE, \
  25. NULL, \
  26. NULL \
  27. )
  28. #endif
  29. NTSTATUS
  30. SpGetFileSize(
  31. IN HANDLE hFile,
  32. OUT PULONG Size
  33. )
  34. /*++
  35. Routine Description:
  36. Determine the size of a file. Only the low 32 bits of the size
  37. are considered.
  38. Arguments:
  39. hFile - supplies open handle to file whose size is desired.
  40. Size - receives size of file.
  41. Return Value:
  42. --*/
  43. {
  44. NTSTATUS Status;
  45. IO_STATUS_BLOCK IoStatusBlock;
  46. FILE_STANDARD_INFORMATION StandardInfo;
  47. Status = NtQueryInformationFile(
  48. hFile,
  49. &IoStatusBlock,
  50. &StandardInfo,
  51. sizeof(StandardInfo),
  52. FileStandardInformation
  53. );
  54. if(!NT_SUCCESS(Status)) {
  55. KdPrint(("SETUP: SpGetFileSize: status %lx from NtQueryInformationFile\n",Status));
  56. return(Status);
  57. }
  58. *Size = StandardInfo.EndOfFile.LowPart;
  59. return(STATUS_SUCCESS);
  60. }
  61. NTSTATUS
  62. SpMapEntireFile(
  63. IN HANDLE hFile,
  64. OUT PHANDLE Section,
  65. OUT PVOID *ViewBase,
  66. IN BOOLEAN WriteAccess
  67. )
  68. /*++
  69. Routine Description:
  70. Map an entire file for read or write access access.
  71. Arguments:
  72. hFile - supplies handle of open file to be mapped.
  73. Section - receives handle for section object created to map file.
  74. ViewBase - receives address of the view of the file
  75. WriteAccess - if TRUE, map file for read and write access.
  76. If FALSE, map file for read access.
  77. Return Value:
  78. --*/
  79. {
  80. NTSTATUS Status;
  81. LARGE_INTEGER SectionOffset;
  82. SIZE_T ViewSize = 0;
  83. SectionOffset.QuadPart = 0;
  84. Status = NtCreateSection(
  85. Section,
  86. STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ
  87. | (WriteAccess ? SECTION_MAP_WRITE : 0),
  88. NULL,
  89. NULL, // entire file
  90. WriteAccess ? PAGE_READWRITE : PAGE_READONLY,
  91. SEC_COMMIT,
  92. hFile
  93. );
  94. if(!NT_SUCCESS(Status)) {
  95. KdPrint(("SETUP: Status %lx from NtCreateSection\n",Status));
  96. return(Status);
  97. }
  98. *ViewBase = NULL;
  99. Status = NtMapViewOfSection(
  100. *Section,
  101. NtCurrentProcess(),
  102. ViewBase,
  103. 0,
  104. 0,
  105. &SectionOffset,
  106. &ViewSize,
  107. ViewShare,
  108. 0,
  109. WriteAccess ? PAGE_READWRITE : PAGE_READONLY
  110. );
  111. if(!NT_SUCCESS(Status)) {
  112. NTSTATUS s;
  113. KdPrint(("SETUP: SpMapEntireFile: Status %lx from NtMapViewOfSection\n",Status));
  114. s = NtClose(*Section);
  115. if(!NT_SUCCESS(s)) {
  116. KdPrint(("SETUP: SpMapEntireFile: Warning: status %lx from NtClose on section handle\n",s));
  117. }
  118. return(Status);
  119. }
  120. return(STATUS_SUCCESS);
  121. }
  122. #if 0
  123. BOOLEAN
  124. SpUnmapFile(
  125. IN HANDLE Section,
  126. IN PVOID ViewBase
  127. )
  128. {
  129. NTSTATUS Status;
  130. BOOLEAN rc = TRUE;
  131. Status = NtUnmapViewOfSection(NtCurrentProcess(),ViewBase);
  132. if(!NT_SUCCESS(Status)) {
  133. KdPrint(("SETUP: Warning: status %lx from NtUnmapViewOfSection\n",Status));
  134. rc = FALSE;
  135. }
  136. Status = NtClose(Section);
  137. if(!NT_SUCCESS(Status)) {
  138. KdPrint(("SETUP: Warning: status %lx from NtClose on section handle\n",Status));
  139. rc = FALSE;
  140. }
  141. return(rc);
  142. }
  143. #endif
  144. #if 0
  145. NTSTATUS
  146. SpOpenAndMapFile(
  147. IN PWSTR FileName,
  148. OUT PHANDLE FileHandle,
  149. OUT PHANDLE SectionHandle,
  150. OUT PVOID *ViewBase,
  151. OUT PULONG FileSize,
  152. IN BOOLEAN WriteAccess
  153. )
  154. {
  155. IO_STATUS_BLOCK IoStatusBlock;
  156. UNICODE_STRING UnicodeString;
  157. OBJECT_ATTRIBUTES Obja;
  158. NTSTATUS Status;
  159. //
  160. // Open the file.
  161. //
  162. INIT_OBJA(&Obja,&UnicodeString,FileName);
  163. Status = NtCreateFile(
  164. FileHandle,
  165. FILE_GENERIC_READ | (WriteAccess ? FILE_GENERIC_WRITE : 0),
  166. &Obja,
  167. &IoStatusBlock,
  168. NULL,
  169. FILE_ATTRIBUTE_NORMAL,
  170. FILE_SHARE_READ,
  171. FILE_OPEN,
  172. 0,
  173. NULL,
  174. 0
  175. );
  176. if(!NT_SUCCESS(Status)) {
  177. KdPrint(("SETUP: SpOpenAndMapFile: Unable to open %ws (%lx)\n",FileName,Status));
  178. return(Status);
  179. }
  180. //
  181. // Get the size of the file.
  182. //
  183. Status = SpGetFileSize(*FileHandle,FileSize);
  184. if(!NT_SUCCESS(Status)) {
  185. KdPrint(("SETUP: SpOpenAndMapFile: unable to determine size of %ws (%lx)\n",FileName,Status));
  186. NtClose(*FileHandle);
  187. return(Status);
  188. }
  189. //
  190. // Map the file.
  191. //
  192. Status = SpMapEntireFile(*FileHandle,SectionHandle,ViewBase,WriteAccess);
  193. if(!NT_SUCCESS(Status)) {
  194. KdPrint(("SETUP: SpOpenAndMapFile: unable to map %ws (%lx)\n",FileName,Status));
  195. NtClose(*FileHandle);
  196. return(Status);
  197. }
  198. return(STATUS_SUCCESS);
  199. }
  200. #endif
  201. DWORD
  202. DnMapFile(
  203. IN PSTR FileName,
  204. OUT PDWORD FileSize,
  205. OUT PHANDLE FileHandle,
  206. OUT PHANDLE MappingHandle,
  207. OUT PVOID *BaseAddress
  208. )
  209. /*++
  210. Routine Description:
  211. Open and map a file for read access.
  212. Arguments:
  213. FileName - supplies pathname to file to be mapped.
  214. FileSize - receives the size in bytes of the file.
  215. FileHandle - receives the win32 file handle for the open file.
  216. The file will be opened for generic read access.
  217. MappingHandle - receives the win32 handle for the file mapping
  218. object. This object will be for read access.
  219. BaseAddress - receives the address where the file is mapped.
  220. Return Value:
  221. NO_ERROR if the file was opened and mapped successfully.
  222. The caller must unmap the file with DnUnmapFile when
  223. access to the file is no longer desired.
  224. Win32 error code if the file was not successfully mapped.
  225. --*/
  226. {
  227. DWORD rc;
  228. //
  229. // Open the file -- fail if it does not exist.
  230. //
  231. *FileHandle = CreateFile(
  232. FileName,
  233. GENERIC_READ,
  234. FILE_SHARE_READ,
  235. NULL,
  236. OPEN_EXISTING,
  237. 0,
  238. NULL
  239. );
  240. if(*FileHandle == INVALID_HANDLE_VALUE) {
  241. rc = GetLastError();
  242. } else {
  243. //
  244. // Get the size of the file.
  245. //
  246. *FileSize = GetFileSize(*FileHandle,NULL);
  247. if(*FileSize != (DWORD)(-1)) {
  248. if(*FileSize == 0) {
  249. *MappingHandle = 0;
  250. return( NO_ERROR );
  251. }
  252. //
  253. // Create file mapping for the whole file.
  254. //
  255. *MappingHandle = CreateFileMapping(
  256. *FileHandle,
  257. NULL,
  258. PAGE_READONLY,
  259. 0,
  260. *FileSize,
  261. NULL
  262. );
  263. if(*MappingHandle) {
  264. //
  265. // Map the whole file.
  266. //
  267. *BaseAddress = MapViewOfFile(
  268. *MappingHandle,
  269. FILE_MAP_READ,
  270. 0,
  271. 0,
  272. *FileSize
  273. );
  274. if(*BaseAddress) {
  275. return(NO_ERROR);
  276. }
  277. rc = GetLastError();
  278. CloseHandle(*MappingHandle);
  279. }
  280. }
  281. rc = GetLastError();
  282. CloseHandle(*FileHandle);
  283. }
  284. return(rc);
  285. }
  286. DWORD
  287. DnUnmapFile(
  288. IN HANDLE MappingHandle,
  289. IN PVOID BaseAddress
  290. )
  291. /*++
  292. Routine Description:
  293. Unmap a file. Note that the file itself is left open.
  294. Arguments:
  295. MappingHandle - supplies the win32 handle for the open file mapping
  296. object.
  297. BaseAddress - supplies the address where the file is mapped.
  298. Return Value:
  299. NO_ERROR if the file was unmapped successfully.
  300. Win32 error code if the file was not successfully unmapped.
  301. --*/
  302. {
  303. if(!UnmapViewOfFile(BaseAddress)) {
  304. return(GetLastError());
  305. }
  306. if(!CloseHandle(MappingHandle)) {
  307. return(GetLastError());
  308. }
  309. return NO_ERROR;
  310. }
  311. VOID
  312. ValidateAndChecksumFile(
  313. IN PSTR Filename,
  314. OUT PBOOLEAN IsNtImage,
  315. OUT PULONG Checksum,
  316. OUT PBOOLEAN Valid
  317. )
  318. /*++
  319. Routine Description:
  320. Calculate a checksum value for a file using the standard
  321. nt image checksum method. If the file is an nt image, validate
  322. the image using the partial checksum in the image header. If the
  323. file is not an nt image, it is simply defined as valid.
  324. If we encounter an i/o error while checksumming, then the file
  325. is declared invalid.
  326. Arguments:
  327. Filename - supplies full NT path of file to check.
  328. IsNtImage = Receives flag indicating whether the file is an
  329. NT image file.
  330. Checksum - receives 32-bit checksum value.
  331. Valid - receives flag indicating whether the file is a valid
  332. image (for nt images) and that we can read the image.
  333. Return Value:
  334. None.
  335. --*/
  336. {
  337. // NTSTATUS Status;
  338. DWORD Status;
  339. PVOID BaseAddress;
  340. ULONG FileSize;
  341. HANDLE hFile,hSection;
  342. PIMAGE_NT_HEADERS NtHeaders;
  343. ULONG HeaderSum;
  344. //
  345. // Assume not an image and failure.
  346. //
  347. *IsNtImage = FALSE;
  348. *Checksum = 0;
  349. *Valid = FALSE;
  350. //
  351. // Open and map the file for read access.
  352. //
  353. // Status = SpOpenAndMapFile(
  354. // Filename,
  355. // &hFile,
  356. // &hSection,
  357. // &BaseAddress,
  358. // &FileSize,
  359. // FALSE
  360. // );
  361. //
  362. // if(!NT_SUCCESS(Status)) {
  363. // return;
  364. // }
  365. Status = DnMapFile( Filename,
  366. &FileSize,
  367. &hFile,
  368. &hSection,
  369. &BaseAddress );
  370. if( Status != ERROR_SUCCESS ) {
  371. return;
  372. }
  373. if( FileSize == 0 ) {
  374. *IsNtImage = FALSE;
  375. *Checksum = 0;
  376. *Valid = TRUE;
  377. CloseHandle( hFile );
  378. return;
  379. }
  380. try {
  381. NtHeaders = CheckSumMappedFile(BaseAddress,FileSize,&HeaderSum,Checksum);
  382. } except(EXCEPTION_EXECUTE_HANDLER) {
  383. *Checksum = 0;
  384. NtHeaders = NULL;
  385. }
  386. //
  387. // If the file is not an image and we got this far (as opposed to encountering
  388. // an i/o error) then the checksum is declared valid. If the file is an image,
  389. // then its checksum may or may not be valid.
  390. //
  391. if(NtHeaders) {
  392. *IsNtImage = TRUE;
  393. *Valid = HeaderSum ? (*Checksum == HeaderSum) : TRUE;
  394. } else {
  395. *Valid = TRUE;
  396. }
  397. // SpUnmapFile(hSection,BaseAddress);
  398. DnUnmapFile( hSection, BaseAddress );
  399. // NtClose(hFile);
  400. CloseHandle( hFile );
  401. }