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.

611 lines
17 KiB

  1. #include "brian.h"
  2. typedef struct _ASYNC_READ {
  3. USHORT FileIndex;
  4. BOOLEAN UseEvent;
  5. PIO_APC_ROUTINE ApcRoutine;
  6. PVOID ApcContext;
  7. PUSHORT BufferIndexPtr;
  8. USHORT BufferIndex;
  9. ULONG Length;
  10. PLARGE_INTEGER ByteOffsetPtr;
  11. LARGE_INTEGER ByteOffset;
  12. PULONG KeyPtr;
  13. ULONG Key;
  14. BOOLEAN DisplayParms;
  15. BOOLEAN VerboseResults;
  16. USHORT AsyncIndex;
  17. } ASYNC_READ, *PASYNC_READ;
  18. #define USE_EVENT_DEFAULT TRUE
  19. #define APC_ROUTINE_DEFAULT NULL
  20. #define APC_CONTEXT_DEFAULT NULL
  21. #define READ_LENGTH_DEFAULT 100L
  22. #define DISPLAY_PARMS_DEFAULT FALSE
  23. #define VERBOSE_RESULTS_DEFAULT FALSE
  24. VOID
  25. FullRead(
  26. IN OUT PASYNC_READ AsyncRead
  27. );
  28. VOID
  29. InputRead(
  30. IN PCHAR ParamBuffer
  31. )
  32. {
  33. ULONG FileIndex;
  34. BOOLEAN UseEvent;
  35. PIO_APC_ROUTINE ApcRoutine;
  36. PVOID ApcContext;
  37. PUSHORT BufferIndexPtr;
  38. USHORT BufferIndex;
  39. ULONG Length;
  40. PLARGE_INTEGER ByteOffsetPtr;
  41. LARGE_INTEGER ByteOffset;
  42. PULONG KeyPtr;
  43. ULONG Key;
  44. BOOLEAN DisplayParms;
  45. BOOLEAN VerboseResults;
  46. USHORT AsyncIndex;
  47. BOOLEAN ParamReceived;
  48. BOOLEAN LastInput;
  49. //
  50. // Set the defaults.
  51. //
  52. UseEvent = USE_EVENT_DEFAULT;
  53. ApcRoutine = APC_ROUTINE_DEFAULT;
  54. ApcContext = APC_CONTEXT_DEFAULT;
  55. BufferIndexPtr = NULL;
  56. BufferIndex = 0;
  57. Length = READ_LENGTH_DEFAULT;
  58. ByteOffsetPtr = NULL;
  59. ByteOffset = RtlConvertUlongToLargeInteger( 0L );
  60. KeyPtr = NULL;
  61. Key = 0;
  62. DisplayParms = DISPLAY_PARMS_DEFAULT;
  63. VerboseResults = VERBOSE_RESULTS_DEFAULT;
  64. AsyncIndex = 0;
  65. ParamReceived = FALSE;
  66. LastInput = TRUE;
  67. //
  68. // While there is more input, analyze the parameter and update the
  69. // query flags.
  70. //
  71. while (TRUE) {
  72. ULONG DummyCount;
  73. ULONG TempIndex;
  74. //
  75. // Swallow leading white spaces.
  76. //
  77. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  78. if (*ParamBuffer) {
  79. //
  80. // If the next parameter is legal then check the paramter value.
  81. // Update the parameter value.
  82. //
  83. if ((*ParamBuffer == '-'
  84. || *ParamBuffer == '/')
  85. && (ParamBuffer++, *ParamBuffer != '\0')) {
  86. //
  87. // Switch on the next character.
  88. //
  89. switch (*ParamBuffer) {
  90. //
  91. // Update the buffer index.
  92. //
  93. case 'b' :
  94. case 'B' :
  95. //
  96. // Move to the next character, as long as there
  97. // are no white spaces continue analyzing letters.
  98. // On the first bad letter, skip to the next
  99. // parameter.
  100. //
  101. ParamBuffer++;
  102. TempIndex = AsciiToInteger( ParamBuffer );
  103. BufferIndex = (USHORT) TempIndex;
  104. BufferIndexPtr = &BufferIndex;
  105. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  106. break;
  107. //
  108. // Update the byte count.
  109. //
  110. case 'l' :
  111. case 'L' :
  112. //
  113. // Move to the next character, as long as there
  114. // are no white spaces continue analyzing letters.
  115. // On the first bad letter, skip to the next
  116. // parameter.
  117. //
  118. ParamBuffer++;
  119. Length = AsciiToInteger( ParamBuffer );
  120. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  121. break;
  122. //
  123. // Update the file handle index.
  124. //
  125. case 'i' :
  126. case 'I' :
  127. //
  128. // Move to the next character, as long as there
  129. // are no white spaces continue analyzing letters.
  130. // On the first bad letter, skip to the next
  131. // parameter.
  132. //
  133. ParamBuffer++;
  134. FileIndex = AsciiToInteger( ParamBuffer );
  135. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  136. ParamReceived = TRUE;
  137. break;
  138. //
  139. // Update the key value.
  140. //
  141. case 'k' :
  142. case 'K' :
  143. //
  144. // Move to the next character, as long as there
  145. // are no white spaces continue analyzing letters.
  146. // On the first bad letter, skip to the next
  147. // parameter.
  148. //
  149. ParamBuffer++;
  150. Key = AsciiToInteger( ParamBuffer );
  151. KeyPtr = &Key;
  152. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  153. break;
  154. //
  155. // Update the offset of the read.
  156. //
  157. case 'o' :
  158. case 'O' :
  159. //
  160. // Move to the next character, as long as there
  161. // are no white spaces continue analyzing letters.
  162. // On the first bad letter, skip to the next
  163. // parameter.
  164. //
  165. ParamBuffer++;
  166. ByteOffset.QuadPart = AsciiToLargeInteger( ParamBuffer );
  167. ByteOffsetPtr = &ByteOffset;
  168. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  169. break;
  170. //
  171. // Check whether we should use an event to signal
  172. // completion.
  173. //
  174. case 'e' :
  175. case 'E' :
  176. //
  177. // Legal values for use event are T/t or F/f.
  178. //
  179. ParamBuffer++;
  180. if (*ParamBuffer == 'T'
  181. || *ParamBuffer == 't') {
  182. UseEvent = TRUE;
  183. ParamBuffer++;
  184. } else if (*ParamBuffer == 'F'
  185. || *ParamBuffer == 'f') {
  186. UseEvent = FALSE;
  187. ParamBuffer++;
  188. }
  189. break;
  190. case 'v' :
  191. case 'V' :
  192. //
  193. // Legal values for params are T/t or F/f.
  194. //
  195. ParamBuffer++;
  196. if( *ParamBuffer == 'T'
  197. || *ParamBuffer == 't' ) {
  198. VerboseResults = TRUE;
  199. ParamBuffer++;
  200. } else if( *ParamBuffer == 'F'
  201. || *ParamBuffer == 'f' ) {
  202. VerboseResults = FALSE;
  203. ParamBuffer++;
  204. }
  205. break;
  206. case 'y' :
  207. case 'Y' :
  208. //
  209. // Set the display parms flag and jump over this
  210. // character.
  211. //
  212. DisplayParms = TRUE;
  213. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  214. break;
  215. case 'z' :
  216. case 'Z' :
  217. //
  218. // Set flag for more input and jump over this char.
  219. //
  220. LastInput = FALSE;
  221. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  222. break;
  223. default :
  224. //
  225. // Swallow to the next white space and continue the
  226. // loop.
  227. //
  228. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  229. }
  230. }
  231. //
  232. // Else the text is invalid, skip the entire block.
  233. //
  234. //
  235. //
  236. // Else if there is no input then exit.
  237. //
  238. } else if( LastInput ) {
  239. break;
  240. //
  241. // Else try to read another line for open parameters.
  242. //
  243. } else {
  244. }
  245. }
  246. //
  247. // If no parameters were received then display the syntax message.
  248. //
  249. if (!ParamReceived) {
  250. printf( "\n Usage: rd [options]* -i<index> [options]*\n" );
  251. printf( "\n Options:" );
  252. printf( "\n -i<digits> File index" );
  253. printf( "\n -l<digits> Read length" );
  254. printf( "\n -b<digits> Buffer index" );
  255. printf( "\n -k<digits> Locked bytes key value" );
  256. printf( "\n -o<digits> Read offset" );
  257. printf( "\n -e[t|f] Use event on completion" );
  258. printf( "\n -v[t|f] Verbose results" );
  259. printf( "\n -y Display parameters to query" );
  260. printf( "\n -z Additional input line" );
  261. printf( "\n\n" );
  262. //
  263. // Else call our read routine.
  264. //
  265. } else {
  266. NTSTATUS Status;
  267. SIZE_T RegionSize;
  268. ULONG TempIndex;
  269. PASYNC_READ AsyncRead;
  270. HANDLE ThreadHandle;
  271. ULONG ThreadId;
  272. RegionSize = sizeof( ASYNC_READ );
  273. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  274. AsyncIndex = (USHORT) TempIndex;
  275. if (!NT_SUCCESS( Status )) {
  276. printf("\n\tInputRead: Unable to allocate async structure" );
  277. } else {
  278. AsyncRead = (PASYNC_READ) Buffers[AsyncIndex].Buffer;
  279. AsyncRead->FileIndex = (USHORT) FileIndex;
  280. AsyncRead->UseEvent = UseEvent;
  281. AsyncRead->ApcRoutine = ApcRoutine;
  282. AsyncRead->ApcContext = ApcContext;
  283. AsyncRead->BufferIndex = BufferIndex;
  284. AsyncRead->BufferIndexPtr = BufferIndexPtr
  285. ? &AsyncRead->BufferIndex
  286. : BufferIndexPtr;
  287. AsyncRead->Length = Length;
  288. AsyncRead->ByteOffset = ByteOffset;
  289. AsyncRead->ByteOffsetPtr = ByteOffsetPtr
  290. ? &AsyncRead->ByteOffset
  291. : ByteOffsetPtr;
  292. AsyncRead->Key = Key;
  293. AsyncRead->KeyPtr = KeyPtr
  294. ? &AsyncRead->Key
  295. : KeyPtr;
  296. AsyncRead->DisplayParms = DisplayParms;
  297. AsyncRead->VerboseResults = VerboseResults;
  298. AsyncRead->AsyncIndex = AsyncIndex;
  299. if (!SynchronousCmds) {
  300. ThreadHandle = CreateThread( NULL,
  301. 0,
  302. FullRead,
  303. AsyncRead,
  304. 0,
  305. &ThreadId );
  306. if (ThreadHandle == 0) {
  307. printf( "\nInputRead: Spawning thread fails -> %d\n", GetLastError() );
  308. return;
  309. }
  310. } else {
  311. FullRead( AsyncRead );
  312. }
  313. }
  314. }
  315. return;
  316. }
  317. VOID
  318. FullRead(
  319. IN OUT PASYNC_READ AsyncRead
  320. )
  321. {
  322. NTSTATUS Status;
  323. IO_STATUS_BLOCK Iosb;
  324. HANDLE ThisEvent;
  325. USHORT ThisEventIndex;
  326. USHORT ThisBufferIndex;
  327. BOOLEAN UnwindReadBuffer = FALSE;
  328. BOOLEAN UnwindEvent = FALSE;
  329. Status = STATUS_SUCCESS;
  330. if (AsyncRead->DisplayParms) {
  331. bprint "\nRead Parameters" );
  332. bprint "\n File Handle Index -> %d", AsyncRead->FileIndex );
  333. bprint "\n UseEvent -> %d", AsyncRead->UseEvent );
  334. bprint "\n ApcRoutine -> %08lx", AsyncRead->ApcRoutine );
  335. bprint "\n ApcContext -> %08lx", AsyncRead->ApcContext );
  336. bprint "\n Buffer Index Ptr -> %08lx", AsyncRead->BufferIndexPtr );
  337. if (AsyncRead->BufferIndexPtr) {
  338. bprint "\n BufferIndex value -> %04x", AsyncRead->BufferIndex );
  339. }
  340. bprint "\n Length -> %08lx", AsyncRead->Length );
  341. bprint "\n Byte Offset Ptr -> %08lx", AsyncRead->ByteOffsetPtr );
  342. if (AsyncRead->ByteOffsetPtr) {
  343. bprint "\n Byte Offset High -> %08lx", AsyncRead->ByteOffset.HighPart );
  344. bprint "\n Byte Offset Low -> %08lx", AsyncRead->ByteOffset.LowPart );
  345. }
  346. bprint "\n Key Ptr -> %08lx", AsyncRead->KeyPtr );
  347. if (AsyncRead->KeyPtr) {
  348. bprint "\n Key -> %ul", AsyncRead->Key );
  349. }
  350. bprint "\n\n" );
  351. }
  352. try {
  353. SIZE_T ThisLength;
  354. //
  355. // If we need a buffer, allocate it now.
  356. //
  357. if (AsyncRead->BufferIndexPtr == NULL) {
  358. ULONG TempIndex;
  359. ThisLength = AsyncRead->Length;
  360. Status = AllocateBuffer( 0L, &ThisLength, &TempIndex );
  361. ThisBufferIndex = (USHORT) TempIndex;
  362. if (!NT_SUCCESS( Status )) {
  363. bprint "\n\tFullRead: Unable to allocate a read buffer" );
  364. try_return( Status );
  365. }
  366. bprint "\n\tFullRead: Reading into buffer -> %04x", ThisBufferIndex );
  367. bprint "\n" );
  368. UnwindReadBuffer = TRUE;
  369. } else {
  370. ThisBufferIndex = AsyncRead->BufferIndex;
  371. }
  372. //
  373. // Check that the buffer index is valid.
  374. //
  375. if (ThisBufferIndex >= MAX_BUFFERS) {
  376. bprint "\n\tFullRead: The read buffer index is invalid" );
  377. try_return( Status = STATUS_INVALID_HANDLE );
  378. }
  379. //
  380. // Check that the file index is valid.
  381. //
  382. if (AsyncRead->FileIndex >= MAX_HANDLES) {
  383. bprint "\n\tFullRead: The file index is invalid" );
  384. try_return( Status = STATUS_INVALID_HANDLE );
  385. }
  386. //
  387. // If we need an event, allocate and set it now.
  388. //
  389. if (AsyncRead->UseEvent == TRUE) {
  390. Status = ObtainEvent( &ThisEventIndex );
  391. if (!NT_SUCCESS( Status )) {
  392. bprint "\n\tFullRead: Unable to allocate an event" );
  393. try_return( Status );
  394. }
  395. UnwindEvent = TRUE;
  396. ThisEvent = Events[ThisEventIndex].Handle;
  397. } else {
  398. ThisEvent = 0;
  399. }
  400. //
  401. // Call the read routine.
  402. //
  403. Status = NtReadFile( Handles[AsyncRead->FileIndex].Handle,
  404. ThisEvent,
  405. AsyncRead->ApcRoutine,
  406. AsyncRead->ApcContext,
  407. &Iosb,
  408. Buffers[ThisBufferIndex].Buffer,
  409. AsyncRead->Length,
  410. AsyncRead->ByteOffsetPtr,
  411. AsyncRead->KeyPtr );
  412. UnwindReadBuffer = FALSE;
  413. if (AsyncRead->VerboseResults) {
  414. bprint "\nReadFile: Status -> %08lx", Status );
  415. if (AsyncRead->UseEvent && NT_SUCCESS( Status )) {
  416. if ((Status = NtWaitForSingleObject( ThisEvent,
  417. FALSE,
  418. NULL )) != STATUS_SUCCESS) {
  419. bprint "\n\tReadFile: Wait for event failed -> %08lx", Status );
  420. bprint "\n" );
  421. try_return( Status );
  422. }
  423. }
  424. if (NT_SUCCESS( Status )) {
  425. bprint "\n Iosb.Information -> %08lx", Iosb.Information );
  426. bprint "\n Iosb.Status -> %08lx", Iosb.Status );
  427. }
  428. bprint "\n" );
  429. }
  430. try_return( Status );
  431. try_exit: NOTHING;
  432. } finally {
  433. if (UnwindReadBuffer) {
  434. DeallocateBuffer( ThisBufferIndex );
  435. }
  436. if (UnwindEvent) {
  437. FreeEvent( ThisEventIndex );
  438. }
  439. DeallocateBuffer( AsyncRead->AsyncIndex );
  440. }
  441. if (!SynchronousCmds) {
  442. NtTerminateThread( 0, STATUS_SUCCESS );
  443. }
  444. }