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.

554 lines
15 KiB

  1. #include "brian.h"
  2. typedef struct _ASYNC_FSCTRL {
  3. USHORT FileIndex;
  4. BOOLEAN UseEvent;
  5. PIO_APC_ROUTINE ApcRoutine;
  6. PVOID ApcContext;
  7. ULONG IoControlCode;
  8. PULONG InputBuffer;
  9. ULONG InputBufferLength;
  10. PULONG OutputBuffer;
  11. ULONG OutputBufferLength;
  12. BOOLEAN VerboseResults;
  13. USHORT AsyncIndex;
  14. } ASYNC_FSCTRL, *PASYNC_FSCTRL;
  15. VOID
  16. RequestSparse (
  17. IN PASYNC_FSCTRL Fsctrl
  18. );
  19. //
  20. // Local procedures
  21. //
  22. VOID
  23. InputSparse(
  24. IN PCHAR ParamBuffer
  25. )
  26. {
  27. BOOLEAN HaveFileIndex = FALSE;
  28. BOOLEAN HaveIoControlCode = FALSE;
  29. USHORT FileIndex;
  30. BOOLEAN UseEvent = TRUE;
  31. PIO_APC_ROUTINE ApcRoutine = NULL;
  32. PVOID ApcContext = NULL;
  33. ULONG IoControlCode = 0;
  34. PULONG InputBuffer = NULL;
  35. ULONG InputBufferLength = 0;
  36. PULONG OutputBuffer = NULL;
  37. ULONG OutputBufferLength = 0;
  38. BOOLEAN VerboseResults = FALSE;
  39. BOOLEAN DisplayParms = FALSE;
  40. USHORT AsyncIndex;
  41. BOOLEAN LastInput = TRUE;
  42. //
  43. // While there is more input, analyze the parameter and update the
  44. // query flags.
  45. //
  46. while(TRUE) {
  47. ULONG DummyCount;
  48. //
  49. // Swallow leading white spaces.
  50. //
  51. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  52. if (*ParamBuffer) {
  53. ULONG TempIndex;
  54. //
  55. // If the next parameter is legal then check the paramter value.
  56. // Update the parameter value.
  57. //
  58. if((*ParamBuffer == '-'
  59. || *ParamBuffer == '/')
  60. && (ParamBuffer++, *ParamBuffer != '\0')) {
  61. //
  62. // Switch on the next character.
  63. //
  64. switch (*ParamBuffer) {
  65. BOOLEAN SwitchBool;
  66. //
  67. // Update buffers to use.
  68. //
  69. case 'b' :
  70. case 'B' :
  71. //
  72. // Move to the next character, as long as there
  73. // are no white spaces continue analyzing letters.
  74. // On the first bad letter, skip to the next
  75. // parameter.
  76. //
  77. ParamBuffer++;
  78. if (*ParamBuffer == '\0') {
  79. break;
  80. }
  81. switch (*ParamBuffer) {
  82. case 'i':
  83. case 'I':
  84. TempIndex = AsciiToInteger( ++ParamBuffer );
  85. if (TempIndex >= MAX_BUFFERS) {
  86. bprint "\n\tInputSparse: Invalid Input buffer" );
  87. } else {
  88. InputBuffer = (PULONG) Buffers[TempIndex].Buffer;
  89. InputBufferLength = Buffers[TempIndex].Length;
  90. }
  91. break;
  92. case 'o':
  93. case 'O':
  94. TempIndex = AsciiToInteger( ++ParamBuffer );
  95. if (TempIndex >= MAX_BUFFERS) {
  96. bprint "\n\tInputSparse: Invalid output buffer" );
  97. } else {
  98. OutputBuffer = (PULONG) Buffers[TempIndex].Buffer;
  99. OutputBufferLength = Buffers[TempIndex].Length;
  100. }
  101. break;
  102. }
  103. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  104. break;
  105. //
  106. // Update buffer lengths.
  107. //
  108. case 'l' :
  109. case 'L' :
  110. //
  111. // Move to the next character, as long as there
  112. // are no white spaces continue analyzing letters.
  113. // On the first bad letter, skip to the next
  114. // parameter.
  115. //
  116. ParamBuffer++;
  117. if (*ParamBuffer == '\0') {
  118. break;
  119. }
  120. switch (*ParamBuffer) {
  121. case 'i':
  122. case 'I':
  123. InputBufferLength = AsciiToInteger( ++ParamBuffer );
  124. break;
  125. case 'o':
  126. case 'O':
  127. OutputBufferLength = AsciiToInteger( ++ParamBuffer );
  128. break;
  129. }
  130. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  131. break;
  132. //
  133. // Update the file handle index.
  134. //
  135. case 'i' :
  136. case 'I' :
  137. //
  138. // Move to the next character, as long as there
  139. // are no white spaces continue analyzing letters.
  140. // On the first bad letter, skip to the next
  141. // parameter.
  142. //
  143. ParamBuffer++;
  144. FileIndex = (USHORT) (AsciiToInteger( ParamBuffer ));
  145. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  146. HaveFileIndex = TRUE;
  147. break;
  148. //
  149. // Check whether we should use an event to signal
  150. // completion.
  151. //
  152. case 'e' :
  153. case 'E' :
  154. //
  155. // Legal values for use event are T/t or F/f.
  156. //
  157. ParamBuffer++;
  158. if (*ParamBuffer == 'T'
  159. || *ParamBuffer == 't') {
  160. UseEvent = TRUE;
  161. ParamBuffer++;
  162. } else if (*ParamBuffer == 'F'
  163. || *ParamBuffer == 'f') {
  164. UseEvent = FALSE;
  165. ParamBuffer++;
  166. }
  167. break;
  168. //
  169. // Modify the operation
  170. //
  171. case 'o' :
  172. case 'O' :
  173. ParamBuffer++;
  174. SwitchBool = TRUE;
  175. while (*ParamBuffer
  176. && *ParamBuffer != ' '
  177. && *ParamBuffer != '\t') {
  178. //
  179. // Perform switch on character.
  180. //
  181. switch (*ParamBuffer) {
  182. case 'a' :
  183. case 'A' :
  184. IoControlCode = FSCTL_SET_SPARSE;
  185. HaveIoControlCode = TRUE;
  186. break;
  187. case 'b' :
  188. case 'B' :
  189. IoControlCode = FSCTL_SET_ZERO_DATA;
  190. HaveIoControlCode = TRUE;
  191. break;
  192. case 'c' :
  193. case 'C' :
  194. IoControlCode = FSCTL_QUERY_ALLOCATED_RANGES;
  195. HaveIoControlCode = TRUE;
  196. break;
  197. default :
  198. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  199. SwitchBool = FALSE;
  200. }
  201. if (!SwitchBool) {
  202. break;
  203. }
  204. ParamBuffer++;
  205. }
  206. break;
  207. case 'v' :
  208. case 'V' :
  209. //
  210. // Legal values for params are T/t or F/f.
  211. //
  212. ParamBuffer++;
  213. if (*ParamBuffer == 'T'
  214. || *ParamBuffer == 't') {
  215. VerboseResults = TRUE;
  216. ParamBuffer++;
  217. } else if (*ParamBuffer == 'F'
  218. || *ParamBuffer == 'f') {
  219. VerboseResults = FALSE;
  220. ParamBuffer++;
  221. }
  222. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  223. break;
  224. case 'y' :
  225. case 'Y' :
  226. //
  227. // Set the display parms flag and jump over this
  228. // character.
  229. //
  230. DisplayParms = TRUE;
  231. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  232. break;
  233. case 'z' :
  234. case 'Z' :
  235. //
  236. // Set flag for more input and jump over this char.
  237. //
  238. LastInput = FALSE;
  239. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  240. break;
  241. default :
  242. //
  243. // Swallow to the next white space and continue the
  244. // loop.
  245. //
  246. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  247. }
  248. }
  249. //
  250. // Else the text is invalid, skip the entire block.
  251. //
  252. //
  253. //
  254. // Else if there is no input then exit.
  255. //
  256. } else if (LastInput) {
  257. break;
  258. //
  259. // Else try to read another line for open parameters.
  260. //
  261. } else {
  262. }
  263. }
  264. if (!HaveFileIndex || !HaveIoControlCode) {
  265. printf( "\n Usage: Sparse -i<digits> -o<char> -b<i|o><digits> -l<i|o><digits>\n" );
  266. printf( "\n Options:" );
  267. printf( "\n -i<digits> Open file handle" );
  268. printf( "\n -o<chars> Sparse operation" );
  269. printf( "\n -oa Set Sparse" );
  270. printf( "\n -ob Zero Range" );
  271. printf( "\n -oc Query Allocated Ranges" );
  272. printf( "\n -b[i|o]<digits> I/O buffers" );
  273. printf( "\n -l[i|o]<digits> I/O buffer lengths" );
  274. printf( "\n -e[t|f] Use event results" );
  275. printf( "\n -v[t|f] Verbose results" );
  276. printf( "\n -y Display parameters to query" );
  277. printf( "\n -z Additional input line" );
  278. printf( "\n\n" );
  279. //
  280. // Else process the call.
  281. //
  282. } else {
  283. NTSTATUS Status;
  284. SIZE_T RegionSize;
  285. ULONG TempIndex;
  286. PASYNC_FSCTRL AsyncFsctrl;
  287. HANDLE ThreadHandle;
  288. ULONG ThreadId;
  289. RegionSize = sizeof( ASYNC_FSCTRL );
  290. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  291. AsyncIndex = (USHORT) TempIndex;
  292. if (!NT_SUCCESS( Status )) {
  293. printf("\n\tInputSparse: Unable to allocate async structure" );
  294. } else {
  295. AsyncFsctrl = (PASYNC_FSCTRL) Buffers[AsyncIndex].Buffer;
  296. AsyncFsctrl->FileIndex = FileIndex;
  297. AsyncFsctrl->UseEvent = UseEvent;
  298. AsyncFsctrl->ApcRoutine = ApcRoutine;
  299. AsyncFsctrl->ApcContext = ApcContext;
  300. AsyncFsctrl->IoControlCode = IoControlCode;
  301. AsyncFsctrl->InputBuffer = InputBuffer;
  302. AsyncFsctrl->InputBufferLength = InputBufferLength;
  303. AsyncFsctrl->OutputBuffer = OutputBuffer;
  304. AsyncFsctrl->OutputBufferLength = OutputBufferLength;
  305. AsyncFsctrl->VerboseResults = VerboseResults;
  306. AsyncFsctrl->AsyncIndex = AsyncIndex;
  307. if (DisplayParms) {
  308. printf( "\nSparse Operation Parameters" );
  309. printf( "\n Handle index -> %ld", FileIndex );
  310. printf( "\n Sparse operation -> %ld", IoControlCode );
  311. printf( "\n\n" );
  312. }
  313. if (!SynchronousCmds) {
  314. ThreadHandle = CreateThread( NULL,
  315. 0,
  316. RequestSparse,
  317. AsyncFsctrl,
  318. 0,
  319. &ThreadId );
  320. if (ThreadHandle == 0) {
  321. printf( "\nInputSparse: Spawning thread fails -> %d\n", GetLastError() );
  322. }
  323. } else {
  324. RequestSparse( AsyncFsctrl );
  325. }
  326. }
  327. }
  328. return;
  329. }
  330. VOID
  331. RequestSparse (
  332. IN PASYNC_FSCTRL Fsctrl
  333. )
  334. {
  335. HANDLE ThisEvent;
  336. USHORT ThisEventIndex = 0;
  337. NTSTATUS Status = STATUS_SUCCESS;
  338. IO_STATUS_BLOCK IoSb;
  339. IoSb.Status = 0;
  340. IoSb.Information = 0;
  341. if (Fsctrl->UseEvent) {
  342. Status = ObtainEvent( &ThisEventIndex );
  343. if (!NT_SUCCESS( Status )) {
  344. bprint "\n\tRequestSparse: Unable to allocate an event" );
  345. } else {
  346. ThisEvent = Events[ThisEventIndex].Handle;
  347. }
  348. }
  349. if (NT_SUCCESS( Status )) {
  350. IoSb.Status = 0;
  351. IoSb.Information = 0;
  352. Status = NtFsControlFile( Handles[Fsctrl->FileIndex].Handle,
  353. ThisEvent,
  354. Fsctrl->ApcRoutine,
  355. Fsctrl->ApcContext,
  356. &IoSb,
  357. Fsctrl->IoControlCode,
  358. Fsctrl->InputBuffer,
  359. Fsctrl->InputBufferLength,
  360. Fsctrl->OutputBuffer,
  361. Fsctrl->OutputBufferLength );
  362. if (Fsctrl->VerboseResults) {
  363. bprint "\nRequestSparse: Status -> %08lx\n", Status );
  364. if (Fsctrl->UseEvent && NT_SUCCESS( Status )) {
  365. if ((Status = NtWaitForSingleObject( ThisEvent,
  366. FALSE,
  367. NULL )) != STATUS_SUCCESS) {
  368. bprint "\n\tRequestSparse: Wait for event failed -> %08lx", Status );
  369. }
  370. }
  371. if (NT_SUCCESS( Status )) {
  372. bprint "\nRequestSparse: IoSb.Status -> %08lx", IoSb.Status );
  373. bprint "\nRequestSparse: IoSb.Information -> %08lx", IoSb.Information );
  374. }
  375. bprint "\n" );
  376. }
  377. }
  378. if (ThisEventIndex != 0) {
  379. FreeEvent( ThisEventIndex );
  380. }
  381. DeallocateBuffer( Fsctrl->AsyncIndex );
  382. if (!SynchronousCmds) {
  383. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  384. bprint "\nRequestSparse: Thread not terminated\n" );
  385. }
  386. }