Windows NT 4.0 source code leak
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.

637 lines
20 KiB

4 years ago
  1. /*++
  2. --*/
  3. #include <ntddk.h>
  4. #include <stdarg.h>
  5. #include <ntverp.h> // Include to determine what version of NT
  6. //
  7. // This is a fix for changes in DDK releases.
  8. //
  9. #ifdef VER_PRODUCTBUILD
  10. #define rmm VER_PRODUCTBUILD
  11. #endif
  12. #include "digifile.h"
  13. #include "memprint.h"
  14. #ifdef ALLOC_PRAGMA
  15. #if rmm > 528
  16. #pragma message( "\n\\\\\n\\\\ Including PAGED CODE\n\\\\ \n" )
  17. #pragma alloc_text( PAGEDIGIFILE, DigiOpenFile )
  18. #pragma alloc_text( PAGEDIGIFILE, DigiCloseFile )
  19. #pragma alloc_text( PAGEDIGIFILE, DigiMapFile )
  20. #pragma alloc_text( PAGEDIGIFILE, DigiUnmapFile )
  21. #endif
  22. #endif
  23. VOID DigiCheckMem( VOID );
  24. #if 0
  25. #define DigiCheckMem() \
  26. { \
  27. PLIST_ENTRY _DigiQueue; \
  28. KIRQL _OldIrql, _CurrentIrql; \
  29. \
  30. _CurrentIrql = KeGetCurrentIrql(); \
  31. \
  32. _DigiQueue = &GlobalNonPagedMemQueue; \
  33. \
  34. KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql ); \
  35. \
  36. while( _DigiQueue->Flink != &GlobalNonPagedMemQueue ) \
  37. { \
  38. PDIGI_MEM_DESCRIPTOR _MemDesc; \
  39. PUCHAR _Buf; \
  40. \
  41. _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \
  42. DIGI_MEM_DESCRIPTOR, \
  43. ListEntry ); \
  44. \
  45. _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \
  46. if( (_MemDesc->BeginTag != (ULONG)'lkir') || \
  47. (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \
  48. { \
  49. DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \
  50. DbgBreakPoint(); \
  51. break; \
  52. } \
  53. \
  54. _DigiQueue = _DigiQueue->Flink; \
  55. } \
  56. \
  57. if( _CurrentIrql < DISPATCH_LEVEL ) \
  58. { \
  59. _DigiQueue = &GlobalPagedMemQueue; \
  60. while( _DigiQueue->Flink != &GlobalPagedMemQueue ) \
  61. { \
  62. PDIGI_MEM_DESCRIPTOR _MemDesc; \
  63. PUCHAR _Buf; \
  64. \
  65. _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \
  66. DIGI_MEM_DESCRIPTOR, \
  67. ListEntry ); \
  68. \
  69. _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \
  70. if( (_MemDesc->BeginTag != (ULONG)'lkir') || \
  71. (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \
  72. { \
  73. DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \
  74. DbgBreakPoint(); \
  75. break; \
  76. } \
  77. \
  78. _DigiQueue = _DigiQueue->Flink; \
  79. } \
  80. } \
  81. \
  82. KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql ); \
  83. }
  84. #endif
  85. //
  86. // Describes an open DIGI file
  87. //
  88. typedef struct _DIGI_FILE_DESCRIPTOR
  89. {
  90. HANDLE NtFileHandle;
  91. PVOID Data;
  92. KSPIN_LOCK Lock;
  93. BOOLEAN Mapped;
  94. } DIGI_FILE_DESCRIPTOR, *PDIGI_FILE_DESCRIPTOR;
  95. typedef struct _DIGI_MEM_DESCRIPTOR_
  96. {
  97. ULONG BeginTag;
  98. ULONG Length;
  99. LIST_ENTRY ListEntry;
  100. } DIGI_MEM_DESCRIPTOR, *PDIGI_MEM_DESCRIPTOR;
  101. //
  102. // Global Data
  103. //
  104. ULONG TotalMemAllocated=0L;
  105. ULONG DefaultPoolTag=(ULONG)('igiD');
  106. LIST_ENTRY GlobalPagedMemQueue={&GlobalPagedMemQueue,&GlobalPagedMemQueue};
  107. LIST_ENTRY GlobalNonPagedMemQueue={&GlobalNonPagedMemQueue,&GlobalNonPagedMemQueue};
  108. KSPIN_LOCK GlobalMemSpinLock;
  109. VOID DigiOpenFile( OUT PNTSTATUS Status,
  110. OUT PHANDLE FileHandle,
  111. OUT PULONG FileLength,
  112. IN PUNICODE_STRING FileName,
  113. IN PHYSICAL_ADDRESS HighestAcceptableAddress )
  114. /*++
  115. Routine Description:
  116. This routine opens a file for future mapping and reads its contents
  117. into allocated memory.
  118. Arguments:
  119. Status - The status of the operation
  120. FileHandle - A handle to be associated with this open
  121. FileLength - Returns the length of the file
  122. FileName - The name of the file
  123. HighestAcceptableAddress - The highest physical address at which
  124. the memory for the file can be allocated.
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. NTSTATUS NtStatus;
  130. IO_STATUS_BLOCK IoStatus;
  131. HANDLE NtFileHandle;
  132. OBJECT_ATTRIBUTES ObjectAttributes;
  133. ULONG LengthOfFile;
  134. WCHAR PathPrefix[] = L"\\SystemRoot\\system32\\drivers\\";
  135. UNICODE_STRING FullFileName;
  136. ULONG FullFileNameLength;
  137. PDIGI_FILE_DESCRIPTOR FileDescriptor;
  138. PVOID FileImage;
  139. //
  140. // This structure represents the data from the
  141. // NtQueryInformationFile API with an information
  142. // class of FileStandardInformation.
  143. //
  144. FILE_STANDARD_INFORMATION StandardInfo;
  145. //
  146. // Insert the correct path prefix.
  147. //
  148. FullFileNameLength = sizeof(PathPrefix) + FileName->MaximumLength;
  149. FullFileName.Buffer = DigiAllocMem( NonPagedPool,
  150. FullFileNameLength );
  151. if (FullFileName.Buffer == NULL) {
  152. *Status = STATUS_INSUFFICIENT_RESOURCES;
  153. return;
  154. }
  155. FullFileName.Length = sizeof (PathPrefix) - sizeof(WCHAR);
  156. FullFileName.MaximumLength = (USHORT)FullFileNameLength;
  157. RtlMoveMemory (FullFileName.Buffer, PathPrefix, sizeof(PathPrefix));
  158. RtlAppendUnicodeStringToString (&FullFileName, FileName);
  159. #if DBG
  160. DbgPrint ("DIGIFILE: Attempting to open %wZ\n", &FullFileName);
  161. #endif
  162. InitializeObjectAttributes ( &ObjectAttributes,
  163. &FullFileName,
  164. OBJ_CASE_INSENSITIVE,
  165. NULL,
  166. NULL );
  167. NtStatus = ZwCreateFile( &NtFileHandle,
  168. SYNCHRONIZE | FILE_READ_DATA,
  169. &ObjectAttributes,
  170. &IoStatus,
  171. NULL, // alloc size = none
  172. FILE_ATTRIBUTE_NORMAL,
  173. FILE_SHARE_READ,
  174. FILE_OPEN,
  175. FILE_SYNCHRONOUS_IO_NONALERT,
  176. NULL, // eabuffer
  177. 0 ); // ealength
  178. if( !NT_SUCCESS(NtStatus) )
  179. {
  180. #if DBG
  181. DbgPrint ("Error opening file %x\n", NtStatus);
  182. #endif
  183. DigiFreeMem( FullFileName.Buffer );
  184. *Status = DIGI_STATUS_FILE_NOT_FOUND;
  185. return;
  186. }
  187. DigiFreeMem( FullFileName.Buffer );
  188. //
  189. // Query the object to determine its length.
  190. //
  191. NtStatus = ZwQueryInformationFile( NtFileHandle,
  192. &IoStatus,
  193. &StandardInfo,
  194. sizeof(FILE_STANDARD_INFORMATION),
  195. FileStandardInformation );
  196. if (!NT_SUCCESS(NtStatus)) {
  197. #if DBG
  198. DbgPrint ("Error querying info on file %x\n", NtStatus);
  199. #endif
  200. ZwClose( NtFileHandle );
  201. *Status = NtStatus;
  202. return;
  203. }
  204. LengthOfFile = StandardInfo.EndOfFile.LowPart;
  205. #if DBG
  206. DbgPrint ("File length is %d\n", LengthOfFile);
  207. #endif
  208. //
  209. // Might be corrupted.
  210. //
  211. if( LengthOfFile < 1 )
  212. {
  213. #if DBG
  214. DbgPrint ("Bad file length %d\n", LengthOfFile);
  215. #endif
  216. ZwClose( NtFileHandle );
  217. *Status = DIGI_STATUS_ERROR_READING_FILE;
  218. return;
  219. }
  220. //
  221. // Allocate buffer for this file
  222. //
  223. FileImage = DigiAllocMem( NonPagedPool,
  224. LengthOfFile );
  225. if( FileImage == NULL )
  226. {
  227. #if DBG
  228. DbgPrint ("Could not allocate buffer\n");
  229. #endif
  230. ZwClose( NtFileHandle );
  231. *Status = DIGI_STATUS_ERROR_READING_FILE;
  232. return;
  233. }
  234. //
  235. // Read the file into our buffer.
  236. //
  237. NtStatus = ZwReadFile( NtFileHandle,
  238. NULL,
  239. NULL,
  240. NULL,
  241. &IoStatus,
  242. FileImage,
  243. LengthOfFile,
  244. NULL,
  245. NULL );
  246. ZwClose( NtFileHandle );
  247. if( (!NT_SUCCESS(NtStatus)) || (IoStatus.Information != LengthOfFile) )
  248. {
  249. #if DBG
  250. DbgPrint ("error reading file %x\n", NtStatus);
  251. #endif
  252. *Status = DIGI_STATUS_ERROR_READING_FILE;
  253. DigiFreeMem( FileImage );
  254. return;
  255. }
  256. //
  257. // Allocate a structure to describe the file.
  258. //
  259. FileDescriptor = DigiAllocMem( NonPagedPool,
  260. sizeof(DIGI_FILE_DESCRIPTOR) );
  261. if( FileDescriptor == NULL )
  262. {
  263. *Status = STATUS_INSUFFICIENT_RESOURCES;
  264. DigiFreeMem( FileImage );
  265. return;
  266. }
  267. FileDescriptor->NtFileHandle = NtFileHandle;
  268. FileDescriptor->Data = FileImage;
  269. KeInitializeSpinLock( &FileDescriptor->Lock );
  270. FileDescriptor->Mapped = FALSE;
  271. *FileHandle = (HANDLE)FileDescriptor;
  272. *FileLength = LengthOfFile;
  273. *Status = STATUS_SUCCESS;
  274. }
  275. VOID DigiCloseFile( IN HANDLE FileHandle )
  276. /*++
  277. Routine Description:
  278. This routine closes a file previously opened with DigiOpenFile.
  279. The file is unmapped if needed and the memory is freed.
  280. Arguments:
  281. FileHandle - The handle returned by DigiOpenFile
  282. Return Value:
  283. None.
  284. --*/
  285. {
  286. PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
  287. DigiFreeMem( FileDescriptor->Data );
  288. DigiFreeMem( FileDescriptor );
  289. }
  290. VOID DigiMapFile( OUT PNTSTATUS Status,
  291. OUT PVOID * MappedBuffer,
  292. IN HANDLE FileHandle )
  293. /*++
  294. Routine Description:
  295. This routine maps an open file, so that the contents can be accessed.
  296. Files can only have one active mapping at any time.
  297. Arguments:
  298. Status - The status of the operation
  299. MappedBuffer - Returns the virtual address of the mapping.
  300. FileHandle - The handle returned by DigiOpenFile.
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
  306. KIRQL oldirql;
  307. KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql);
  308. if (FileDescriptor->Mapped == TRUE) {
  309. *Status = DIGI_STATUS_ALREADY_MAPPED;
  310. KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
  311. return;
  312. }
  313. FileDescriptor->Mapped = TRUE;
  314. KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
  315. *MappedBuffer = FileDescriptor->Data;
  316. *Status = STATUS_SUCCESS;
  317. }
  318. VOID DigiUnmapFile( IN HANDLE FileHandle )
  319. /*++
  320. Routine Description:
  321. This routine unmaps a file previously mapped with DigiOpenFile.
  322. The file is unmapped if needed and the memory is freed.
  323. Arguments:
  324. FileHandle - The handle returned by DigiOpenFile
  325. Return Value:
  326. None.
  327. --*/
  328. {
  329. PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
  330. KIRQL oldirql;
  331. KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql);
  332. FileDescriptor->Mapped = FALSE;
  333. KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
  334. }
  335. PVOID DigiInitMem( IN ULONG PoolTag )
  336. /*++
  337. Routine Description:
  338. Arguments:
  339. PoolTag - Tag to use when allocating memory.
  340. Return Value:
  341. None.
  342. --*/
  343. {
  344. DefaultPoolTag = PoolTag;
  345. InitializeListHead( &GlobalPagedMemQueue );
  346. InitializeListHead( &GlobalNonPagedMemQueue );
  347. KeInitializeSpinLock( &GlobalMemSpinLock );
  348. return( NULL );
  349. } // end DigiInitMem
  350. #if DBG || DIGICHECKMEM
  351. PVOID DigiAllocMem( IN POOL_TYPE PoolType, IN ULONG Length )
  352. /*++
  353. Routine Description:
  354. Arguments:
  355. Return Value:
  356. None.
  357. --*/
  358. {
  359. KIRQL OldIrql;
  360. PDIGI_MEM_DESCRIPTOR buf;
  361. ULONG Len = ((Length + (sizeof(ULONG)-1)) & ~(sizeof(ULONG)-1));
  362. //
  363. // Check memory consistency.
  364. //
  365. DigiCheckMem();
  366. if( (buf = (PDIGI_MEM_DESCRIPTOR)ExAllocatePoolWithTag( PoolType,
  367. Len + sizeof(DIGI_MEM_DESCRIPTOR) + sizeof(ULONG),
  368. DefaultPoolTag)) == NULL )
  369. return(NULL);
  370. TotalMemAllocated += Len;
  371. buf->Length = Len;
  372. buf->BeginTag = (ULONG)'lkir';
  373. *(PULONG)((PUCHAR)buf + Len + sizeof(DIGI_MEM_DESCRIPTOR)) = (ULONG)'igid';
  374. //
  375. // Insert onto tail of global memory queue
  376. //
  377. KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql );
  378. if( PoolType == PagedPool )
  379. {
  380. InsertTailList( &GlobalPagedMemQueue,
  381. &(buf->ListEntry) );
  382. }
  383. else
  384. {
  385. InsertTailList( &GlobalNonPagedMemQueue,
  386. &(buf->ListEntry) );
  387. }
  388. KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql );
  389. return( (PUCHAR)buf + (sizeof(DIGI_MEM_DESCRIPTOR)) );
  390. } // end DigiAllocMem
  391. VOID DigiFreeMem( IN PVOID Buf )
  392. /*++
  393. Routine Description:
  394. Does consistency check on passed in memory block and free's the memory
  395. block.
  396. Arguments:
  397. Buf - pointer to memory block which is to be freed.
  398. Return Value:
  399. None.
  400. --*/
  401. {
  402. PDIGI_MEM_DESCRIPTOR RealBuf;
  403. KIRQL OldIrql;
  404. ULONG Length;
  405. //
  406. // Check memory consistency.
  407. //
  408. DigiCheckMem();
  409. RealBuf = (PDIGI_MEM_DESCRIPTOR)((PUCHAR)Buf - sizeof(DIGI_MEM_DESCRIPTOR));
  410. Length = RealBuf->Length;
  411. if( RealBuf->BeginTag != (ULONG)'lkir' )
  412. {
  413. DbgPrint( "Memory has been corrupted!\n" );
  414. DbgBreakPoint();
  415. }
  416. if( *(PULONG)((PUCHAR)Buf + Length) != (ULONG)'igid' )
  417. {
  418. DbgPrint("Memory Overrun\n");
  419. DbgBreakPoint();
  420. }
  421. TotalMemAllocated -= Length;
  422. KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql );
  423. RemoveEntryList( &(RealBuf->ListEntry) );
  424. KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql );
  425. ExFreePool( RealBuf );
  426. } // end DigiFreeMem
  427. VOID DigiCheckMem( VOID )
  428. {
  429. PLIST_ENTRY _DigiQueue;
  430. KIRQL _OldIrql, _CurrentIrql;
  431. if( DigiPrintFlags & MEM_PRINT_FLAG_NOMEMCHECK )
  432. return;
  433. _DigiQueue = &GlobalNonPagedMemQueue;
  434. KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql );
  435. while( _DigiQueue->Flink != &GlobalNonPagedMemQueue )
  436. {
  437. PDIGI_MEM_DESCRIPTOR _MemDesc;
  438. PUCHAR _Buf;
  439. _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink,
  440. DIGI_MEM_DESCRIPTOR,
  441. ListEntry );
  442. _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR);
  443. if( (_MemDesc->BeginTag != (ULONG)'lkir') ||
  444. (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') )
  445. {
  446. DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc );
  447. DbgBreakPoint();
  448. break;
  449. }
  450. _DigiQueue = _DigiQueue->Flink;
  451. }
  452. _DigiQueue = &GlobalPagedMemQueue;
  453. _CurrentIrql = KeGetCurrentIrql();
  454. while( (_CurrentIrql < DISPATCH_LEVEL) &&
  455. (_DigiQueue->Flink != &GlobalPagedMemQueue) )
  456. {
  457. PDIGI_MEM_DESCRIPTOR _MemDesc;
  458. PUCHAR _Buf;
  459. _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink,
  460. DIGI_MEM_DESCRIPTOR,
  461. ListEntry );
  462. _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR);
  463. if( (_MemDesc->BeginTag != (ULONG)'lkir') ||
  464. (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') )
  465. {
  466. DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc );
  467. DbgBreakPoint();
  468. break;
  469. }
  470. _DigiQueue = _DigiQueue->Flink;
  471. _CurrentIrql = KeGetCurrentIrql();
  472. }
  473. KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql );
  474. }
  475. #endif // end #if DBG || DIGICHECKMEM