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.

596 lines
16 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. file.c
  5. Abstract:
  6. This module contains kd host machine file I/O support.
  7. Author:
  8. Drew Bliss (drewb) 21-Feb-2001
  9. Revision History:
  10. --*/
  11. #include "kdp.h"
  12. #pragma hdrstop
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGEKD, KdCreateRemoteFile)
  15. #pragma alloc_text(PAGEKD, KdReadRemoteFile)
  16. #pragma alloc_text(PAGEKD, KdWriteRemoteFile)
  17. #pragma alloc_text(PAGEKD, KdCloseRemoteFile)
  18. #pragma alloc_text(PAGEKD, KdPullRemoteFile)
  19. #pragma alloc_text(PAGEKD, KdPushRemoteFile)
  20. #endif
  21. NTSTATUS
  22. KdCreateRemoteFile(
  23. OUT PHANDLE Handle,
  24. OUT PULONG64 Length, OPTIONAL
  25. IN PUNICODE_STRING FileName,
  26. IN ACCESS_MASK DesiredAccess,
  27. IN ULONG FileAttributes,
  28. IN ULONG ShareAccess,
  29. IN ULONG CreateDisposition,
  30. IN ULONG CreateOptions
  31. )
  32. {
  33. BOOLEAN Enable;
  34. DBGKD_FILE_IO Irp;
  35. ULONG Index;
  36. if (FileName->Length > PACKET_MAX_SIZE - sizeof(Irp)) {
  37. return STATUS_INVALID_PARAMETER;
  38. }
  39. if (KdDebuggerNotPresent != FALSE) {
  40. return STATUS_DEBUGGER_INACTIVE;
  41. }
  42. Enable = KdEnterDebugger(NULL, NULL);
  43. //
  44. // Look for an open slot.
  45. //
  46. for (Index = 0; Index < KD_MAX_REMOTE_FILES; Index++) {
  47. if (KdpRemoteFiles[Index].RemoteHandle == 0) {
  48. break;
  49. }
  50. }
  51. if (Index >= KD_MAX_REMOTE_FILES) {
  52. Irp.Status = STATUS_NO_MEMORY;
  53. goto Exit;
  54. }
  55. Irp.ApiNumber = DbgKdCreateFileApi;
  56. Irp.u.CreateFile.DesiredAccess = DesiredAccess;
  57. Irp.u.CreateFile.FileAttributes = FileAttributes;
  58. Irp.u.CreateFile.ShareAccess = ShareAccess;
  59. Irp.u.CreateFile.CreateDisposition = CreateDisposition;
  60. Irp.u.CreateFile.CreateOptions = CreateOptions;
  61. for (;;) {
  62. STRING MessageData;
  63. STRING MessageHeader;
  64. ULONG ReturnCode;
  65. ULONG Length;
  66. MessageHeader.Length = sizeof(Irp);
  67. MessageHeader.MaximumLength = sizeof(Irp);
  68. MessageHeader.Buffer = (PCHAR)&Irp;
  69. // Copy the filename to the message buffer
  70. // so that a terminator can be added.
  71. KdpCopyFromPtr(KdpMessageBuffer, FileName->Buffer,
  72. FileName->Length, &Length);
  73. MessageData.Length = (USHORT)Length + sizeof(WCHAR);
  74. MessageData.Buffer = (PCHAR) KdpMessageBuffer;
  75. *(PWCHAR)&MessageData.Buffer[MessageData.Length - sizeof(WCHAR)] =
  76. UNICODE_NULL;
  77. //
  78. // Send packet to the kernel debugger on the host machine.
  79. //
  80. KdSendPacket(PACKET_TYPE_KD_FILE_IO,
  81. &MessageHeader,
  82. &MessageData,
  83. &KdpContext);
  84. if (KdDebuggerNotPresent != FALSE) {
  85. Irp.Status = STATUS_DEBUGGER_INACTIVE;
  86. break;
  87. }
  88. //
  89. // Receive packet from the kernel debugger on the host machine.
  90. //
  91. MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
  92. MessageData.Buffer = (PCHAR) KdpMessageBuffer;
  93. do {
  94. ReturnCode = KdReceivePacket(PACKET_TYPE_KD_FILE_IO,
  95. &MessageHeader,
  96. &MessageData,
  97. &Length,
  98. &KdpContext);
  99. } while (ReturnCode == KDP_PACKET_TIMEOUT);
  100. if (ReturnCode == KDP_PACKET_RECEIVED) {
  101. break;
  102. }
  103. }
  104. if (NT_SUCCESS(Irp.Status)) {
  105. KdpRemoteFiles[Index].RemoteHandle = Irp.u.CreateFile.Handle;
  106. // Add one so that zero is reserved for invalid-handle.
  107. *Handle = UlongToHandle(Index + 1);
  108. if (ARGUMENT_PRESENT(Length)) {
  109. *Length = Irp.u.CreateFile.Length;
  110. }
  111. }
  112. Exit:
  113. KdExitDebugger(Enable);
  114. return Irp.Status;
  115. }
  116. NTSTATUS
  117. KdReadRemoteFile(
  118. IN HANDLE Handle,
  119. IN ULONG64 Offset,
  120. OUT PVOID Buffer,
  121. IN ULONG Length,
  122. OUT PULONG Completed
  123. )
  124. {
  125. BOOLEAN Enable;
  126. DBGKD_FILE_IO Irp;
  127. ULONG Index;
  128. ULONG _Completed = 0;
  129. Index = HandleToUlong(Handle) - 1;
  130. if (Index >= KD_MAX_REMOTE_FILES) {
  131. return STATUS_INVALID_PARAMETER;
  132. }
  133. Enable = KdEnterDebugger(NULL, NULL);
  134. if (KdpRemoteFiles[Index].RemoteHandle == 0) {
  135. Irp.Status = STATUS_INVALID_PARAMETER;
  136. goto Exit;
  137. }
  138. Irp.ApiNumber = DbgKdReadFileApi;
  139. Irp.Status = STATUS_SUCCESS;
  140. Irp.u.ReadFile.Handle = KdpRemoteFiles[Index].RemoteHandle;
  141. Irp.u.ReadFile.Offset = Offset;
  142. while (Length > 0) {
  143. STRING MessageData;
  144. STRING MessageHeader;
  145. ULONG ReturnCode;
  146. ULONG RecvLength;
  147. if (Length > PACKET_MAX_SIZE - sizeof(Irp)) {
  148. Irp.u.ReadFile.Length = PACKET_MAX_SIZE - sizeof(Irp);
  149. } else {
  150. Irp.u.ReadFile.Length = Length;
  151. }
  152. MessageHeader.Length = sizeof(Irp);
  153. MessageHeader.MaximumLength = sizeof(Irp);
  154. MessageHeader.Buffer = (PCHAR)&Irp;
  155. //
  156. // Send packet to the kernel debugger on the host machine.
  157. //
  158. KdSendPacket(PACKET_TYPE_KD_FILE_IO,
  159. &MessageHeader,
  160. NULL,
  161. &KdpContext);
  162. //
  163. // Receive packet from the kernel debugger on the host machine.
  164. //
  165. MessageData.MaximumLength = (USHORT)Irp.u.ReadFile.Length;
  166. MessageData.Buffer = Buffer;
  167. do {
  168. ReturnCode = KdReceivePacket(PACKET_TYPE_KD_FILE_IO,
  169. &MessageHeader,
  170. &MessageData,
  171. &RecvLength,
  172. &KdpContext);
  173. } while (ReturnCode == KDP_PACKET_TIMEOUT);
  174. if (ReturnCode == KDP_PACKET_RECEIVED) {
  175. if (!NT_SUCCESS(Irp.Status)) {
  176. break;
  177. }
  178. _Completed += RecvLength;
  179. Buffer = (PVOID)((PUCHAR)Buffer + RecvLength);
  180. Irp.u.ReadFile.Offset += RecvLength;
  181. Length -= RecvLength;
  182. }
  183. }
  184. *Completed = _Completed;
  185. Exit:
  186. KdExitDebugger(Enable);
  187. return Irp.Status;
  188. }
  189. NTSTATUS
  190. KdWriteRemoteFile(
  191. IN HANDLE Handle,
  192. IN ULONG64 Offset,
  193. IN PVOID Buffer,
  194. IN ULONG Length,
  195. OUT PULONG Completed
  196. )
  197. {
  198. BOOLEAN Enable;
  199. DBGKD_FILE_IO Irp;
  200. ULONG Index;
  201. ULONG _Completed = 0;
  202. Index = HandleToUlong(Handle) - 1;
  203. if (Index >= KD_MAX_REMOTE_FILES) {
  204. return STATUS_INVALID_PARAMETER;
  205. }
  206. Enable = KdEnterDebugger(NULL, NULL);
  207. if (KdpRemoteFiles[Index].RemoteHandle == 0) {
  208. Irp.Status = STATUS_INVALID_PARAMETER;
  209. goto Exit;
  210. }
  211. Irp.ApiNumber = DbgKdWriteFileApi;
  212. Irp.Status = STATUS_SUCCESS;
  213. Irp.u.WriteFile.Handle = KdpRemoteFiles[Index].RemoteHandle;
  214. Irp.u.WriteFile.Offset = Offset;
  215. while (Length > 0) {
  216. STRING MessageData;
  217. STRING MessageHeader;
  218. ULONG ReturnCode;
  219. ULONG RecvLength;
  220. if (Length > PACKET_MAX_SIZE - sizeof(Irp)) {
  221. Irp.u.WriteFile.Length = PACKET_MAX_SIZE - sizeof(Irp);
  222. } else {
  223. Irp.u.WriteFile.Length = Length;
  224. }
  225. MessageHeader.Length = sizeof(Irp);
  226. MessageHeader.MaximumLength = sizeof(Irp);
  227. MessageHeader.Buffer = (PCHAR)&Irp;
  228. MessageData.Length = (USHORT)Irp.u.WriteFile.Length;
  229. MessageData.Buffer = Buffer;
  230. //
  231. // Send packet to the kernel debugger on the host machine.
  232. //
  233. KdSendPacket(PACKET_TYPE_KD_FILE_IO,
  234. &MessageHeader,
  235. &MessageData,
  236. &KdpContext);
  237. //
  238. // Receive packet from the kernel debugger on the host machine.
  239. //
  240. MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
  241. MessageData.Buffer = (PCHAR) KdpMessageBuffer;
  242. do {
  243. ReturnCode = KdReceivePacket(PACKET_TYPE_KD_FILE_IO,
  244. &MessageHeader,
  245. &MessageData,
  246. &RecvLength,
  247. &KdpContext);
  248. } while (ReturnCode == KDP_PACKET_TIMEOUT);
  249. if (ReturnCode == KDP_PACKET_RECEIVED) {
  250. if (!NT_SUCCESS(Irp.Status)) {
  251. break;
  252. }
  253. _Completed += Irp.u.WriteFile.Length;
  254. Buffer = (PVOID)((PUCHAR)Buffer + Irp.u.WriteFile.Length);
  255. Irp.u.WriteFile.Offset += Irp.u.WriteFile.Length;
  256. Length -= Irp.u.WriteFile.Length;
  257. }
  258. }
  259. *Completed = _Completed;
  260. Exit:
  261. KdExitDebugger(Enable);
  262. return Irp.Status;
  263. }
  264. NTSTATUS
  265. KdCloseRemoteFile(
  266. IN HANDLE Handle
  267. )
  268. {
  269. BOOLEAN Enable;
  270. DBGKD_FILE_IO Irp;
  271. ULONG Index;
  272. Index = HandleToUlong(Handle) - 1;
  273. if (Index >= KD_MAX_REMOTE_FILES) {
  274. return STATUS_INVALID_PARAMETER;
  275. }
  276. Enable = KdEnterDebugger(NULL, NULL);
  277. if (KdpRemoteFiles[Index].RemoteHandle == 0) {
  278. Irp.Status = STATUS_INVALID_PARAMETER;
  279. goto Exit;
  280. }
  281. Irp.ApiNumber = DbgKdCloseFileApi;
  282. Irp.u.CloseFile.Handle = KdpRemoteFiles[Index].RemoteHandle;
  283. for (;;) {
  284. STRING MessageData;
  285. STRING MessageHeader;
  286. ULONG ReturnCode;
  287. ULONG RecvLength;
  288. MessageHeader.Length = sizeof(Irp);
  289. MessageHeader.MaximumLength = sizeof(Irp);
  290. MessageHeader.Buffer = (PCHAR)&Irp;
  291. //
  292. // Send packet to the kernel debugger on the host machine.
  293. //
  294. KdSendPacket(PACKET_TYPE_KD_FILE_IO,
  295. &MessageHeader,
  296. NULL,
  297. &KdpContext);
  298. //
  299. // Receive packet from the kernel debugger on the host machine.
  300. //
  301. MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
  302. MessageData.Buffer = (PCHAR) KdpMessageBuffer;
  303. do {
  304. ReturnCode = KdReceivePacket(PACKET_TYPE_KD_FILE_IO,
  305. &MessageHeader,
  306. &MessageData,
  307. &RecvLength,
  308. &KdpContext);
  309. } while (ReturnCode == KDP_PACKET_TIMEOUT);
  310. if (ReturnCode == KDP_PACKET_RECEIVED) {
  311. break;
  312. }
  313. }
  314. if (NT_SUCCESS(Irp.Status)) {
  315. KdpRemoteFiles[Index].RemoteHandle = 0;
  316. }
  317. Exit:
  318. KdExitDebugger(Enable);
  319. return Irp.Status;
  320. }
  321. #define TRANSFER_LENGTH 8192
  322. NTSTATUS
  323. KdPullRemoteFile(
  324. IN PUNICODE_STRING FileName,
  325. IN ULONG FileAttributes,
  326. IN ULONG CreateDisposition,
  327. IN ULONG CreateOptions
  328. )
  329. {
  330. NTSTATUS Status;
  331. PVOID Buffer = NULL;
  332. ULONG64 Length;
  333. HANDLE RemoteHandle = NULL;
  334. HANDLE LocalHandle = NULL;
  335. OBJECT_ATTRIBUTES ObjectAttributes;
  336. IO_STATUS_BLOCK IoStatus;
  337. LARGE_INTEGER LargeInt;
  338. ULONG64 Offset;
  339. // Allocate a buffer for data transfers.
  340. Buffer = ExAllocatePoolWithTag(NonPagedPool, TRANSFER_LENGTH, 'oIdK');
  341. if (Buffer == NULL) {
  342. return STATUS_NO_MEMORY;
  343. }
  344. // Open the remote file for reading.
  345. Status = KdCreateRemoteFile(&RemoteHandle, &Length, FileName,
  346. FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL,
  347. FILE_SHARE_READ, FILE_OPEN, 0);
  348. if (!NT_SUCCESS(Status)) {
  349. goto Exit;
  350. }
  351. // Open the local file for writing.
  352. LargeInt.QuadPart = Length;
  353. InitializeObjectAttributes(&ObjectAttributes, FileName,
  354. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  355. NULL, NULL);
  356. Status = ZwCreateFile(&LocalHandle, FILE_GENERIC_WRITE,
  357. &ObjectAttributes, &IoStatus, &LargeInt,
  358. FileAttributes, 0, CreateDisposition,
  359. CreateOptions, NULL, 0);
  360. if (!NT_SUCCESS(Status)) {
  361. goto Exit;
  362. }
  363. // Copy the file contents.
  364. Offset = 0;
  365. while (Length > 0) {
  366. ULONG ReqLength, ReqCompleted;
  367. if (Length > TRANSFER_LENGTH) {
  368. ReqLength = TRANSFER_LENGTH;
  369. } else {
  370. ReqLength = (ULONG)Length;
  371. }
  372. Status = KdReadRemoteFile(RemoteHandle, Offset, Buffer,
  373. ReqLength, &ReqCompleted);
  374. if (!NT_SUCCESS(Status) || ReqCompleted == 0) {
  375. break;
  376. }
  377. LargeInt.QuadPart = Offset;
  378. Status = ZwWriteFile(LocalHandle, NULL, NULL, NULL,
  379. &IoStatus, Buffer, ReqCompleted,
  380. &LargeInt, NULL);
  381. if (!NT_SUCCESS(Status)) {
  382. break;
  383. }
  384. if (IoStatus.Information < ReqCompleted) {
  385. Status = STATUS_UNSUCCESSFUL;
  386. break;
  387. }
  388. Offset += IoStatus.Information;
  389. Length -= IoStatus.Information;
  390. }
  391. Exit:
  392. if (RemoteHandle != NULL) {
  393. KdCloseRemoteFile(RemoteHandle);
  394. }
  395. if (LocalHandle != NULL) {
  396. ZwClose(LocalHandle);
  397. }
  398. if (Buffer != NULL) {
  399. ExFreePool(Buffer);
  400. }
  401. return Status;
  402. }
  403. NTSTATUS
  404. KdPushRemoteFile(
  405. IN PUNICODE_STRING FileName,
  406. IN ULONG FileAttributes,
  407. IN ULONG CreateDisposition,
  408. IN ULONG CreateOptions
  409. )
  410. {
  411. NTSTATUS Status;
  412. PVOID Buffer = NULL;
  413. ULONG64 Length;
  414. HANDLE RemoteHandle = NULL;
  415. HANDLE LocalHandle = NULL;
  416. OBJECT_ATTRIBUTES ObjectAttributes;
  417. IO_STATUS_BLOCK IoStatus;
  418. LARGE_INTEGER LargeInt;
  419. ULONG64 Offset;
  420. FILE_END_OF_FILE_INFORMATION EndOfFile;
  421. // Allocate a buffer for data transfers.
  422. Buffer = ExAllocatePoolWithTag(NonPagedPool, TRANSFER_LENGTH, 'oIdK');
  423. if (Buffer == NULL) {
  424. return STATUS_NO_MEMORY;
  425. }
  426. // Open the remote file for writing.
  427. Status = KdCreateRemoteFile(&RemoteHandle, &Length, FileName,
  428. FILE_GENERIC_WRITE, FileAttributes,
  429. 0, CreateDisposition, CreateOptions);
  430. if (!NT_SUCCESS(Status)) {
  431. goto Exit;
  432. }
  433. // Open the local file for reading.
  434. InitializeObjectAttributes(&ObjectAttributes, FileName,
  435. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  436. NULL, NULL);
  437. Status = ZwOpenFile(&LocalHandle, FILE_GENERIC_READ,
  438. &ObjectAttributes, &IoStatus, FILE_SHARE_READ, 0);
  439. if (!NT_SUCCESS(Status)) {
  440. goto Exit;
  441. }
  442. Status = NtQueryInformationFile(LocalHandle, &IoStatus,
  443. &EndOfFile, sizeof(EndOfFile),
  444. FileEndOfFileInformation);
  445. if (!NT_SUCCESS(Status)) {
  446. goto Exit;
  447. }
  448. // Copy the file contents.
  449. Offset = 0;
  450. Length = EndOfFile.EndOfFile.QuadPart;
  451. while (Length > 0) {
  452. ULONG ReqLength, ReqCompleted;
  453. if (Length > TRANSFER_LENGTH) {
  454. ReqLength = TRANSFER_LENGTH;
  455. } else {
  456. ReqLength = (ULONG)Length;
  457. }
  458. LargeInt.QuadPart = Offset;
  459. Status = ZwReadFile(LocalHandle, NULL, NULL, NULL,
  460. &IoStatus, Buffer, ReqLength,
  461. &LargeInt, NULL);
  462. if (!NT_SUCCESS(Status) || IoStatus.Information == 0) {
  463. break;
  464. }
  465. Status = KdWriteRemoteFile(RemoteHandle, Offset, Buffer,
  466. (ULONG)IoStatus.Information, &ReqCompleted);
  467. if (!NT_SUCCESS(Status)) {
  468. break;
  469. }
  470. if (ReqCompleted < IoStatus.Information) {
  471. Status = STATUS_UNSUCCESSFUL;
  472. break;
  473. }
  474. Offset += ReqCompleted;
  475. Length -= ReqCompleted;
  476. }
  477. Exit:
  478. if (RemoteHandle != NULL) {
  479. KdCloseRemoteFile(RemoteHandle);
  480. }
  481. if (LocalHandle != NULL) {
  482. ZwClose(LocalHandle);
  483. }
  484. if (Buffer != NULL) {
  485. ExFreePool(Buffer);
  486. }
  487. return Status;
  488. }