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.

609 lines
17 KiB

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