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.

558 lines
16 KiB

  1. #include "brian.h"
  2. typedef struct _ASYNC_DEVCTRL {
  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_DEVCTRL, *PASYNC_DEVCTRL;
  15. VOID
  16. RequestDevCtrl (
  17. IN PASYNC_DEVCTRL DevCtrl
  18. );
  19. //
  20. // Local procedures
  21. //
  22. VOID
  23. InputDevctrl (
  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\tInputDevCtrl: 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\tInputDevCtrl: 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 = IOCTL_CDROM_DISK_TYPE;
  185. HaveIoControlCode = TRUE;
  186. break;
  187. case 'b' :
  188. case 'B' :
  189. IoControlCode = IOCTL_CDROM_READ_TOC;
  190. HaveIoControlCode = TRUE;
  191. break;
  192. case 'c' :
  193. case 'C' :
  194. IoControlCode = IOCTL_DISK_EJECT_MEDIA;
  195. HaveIoControlCode = TRUE;
  196. break;
  197. case 'd' :
  198. case 'D' :
  199. IoControlCode = IOCTL_STORAGE_EJECT_MEDIA;
  200. HaveIoControlCode = TRUE;
  201. break;
  202. default :
  203. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  204. SwitchBool = FALSE;
  205. }
  206. if (!SwitchBool) {
  207. break;
  208. }
  209. ParamBuffer++;
  210. }
  211. break;
  212. case 'v' :
  213. case 'V' :
  214. //
  215. // Legal values for params are T/t or F/f.
  216. //
  217. ParamBuffer++;
  218. if (*ParamBuffer == 'T'
  219. || *ParamBuffer == 't') {
  220. VerboseResults = TRUE;
  221. ParamBuffer++;
  222. } else if (*ParamBuffer == 'F'
  223. || *ParamBuffer == 'f') {
  224. VerboseResults = FALSE;
  225. ParamBuffer++;
  226. }
  227. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  228. break;
  229. case 'y' :
  230. case 'Y' :
  231. //
  232. // Set the display parms flag and jump over this
  233. // character.
  234. //
  235. DisplayParms = TRUE;
  236. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  237. break;
  238. case 'z' :
  239. case 'Z' :
  240. //
  241. // Set flag for more input and jump over this char.
  242. //
  243. LastInput = FALSE;
  244. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  245. break;
  246. default :
  247. //
  248. // Swallow to the next white space and continue the
  249. // loop.
  250. //
  251. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  252. }
  253. }
  254. //
  255. // Else the text is invalid, skip the entire block.
  256. //
  257. //
  258. //
  259. // Else if there is no input then exit.
  260. //
  261. } else if (LastInput) {
  262. break;
  263. //
  264. // Else try to read another line for open parameters.
  265. //
  266. } else {
  267. }
  268. }
  269. if (!HaveFileIndex || !HaveIoControlCode) {
  270. printf( "\n Usage: ioctl -i<digits> -o<char> -b<i|o><digits> -l<i|o><digits>\n" );
  271. printf( "\n Options:" );
  272. printf( "\n -i<digits> Open file handle" );
  273. printf( "\n -o<chars> DevCtrl operation" );
  274. printf( "\n -oa Cdrom disk type" );
  275. printf( "\n -ob Cdrom read TOC" );
  276. printf( "\n -oc Disk eject media" );
  277. printf( "\n -od Storage eject media" );
  278. printf( "\n -b[i|o]<digits> I/O buffers" );
  279. printf( "\n -l[i|o]<digits> I/O buffer lengths" );
  280. printf( "\n -e[t|f] Use event results" );
  281. printf( "\n -v[t|f] Verbose results" );
  282. printf( "\n -y Display parameters to query" );
  283. printf( "\n -z Additional input line" );
  284. printf( "\n\n" );
  285. //
  286. // Else process the call.
  287. //
  288. } else {
  289. NTSTATUS Status;
  290. SIZE_T RegionSize;
  291. ULONG TempIndex;
  292. PASYNC_DEVCTRL AsyncDevCtrl;
  293. HANDLE ThreadHandle;
  294. ULONG ThreadId;
  295. RegionSize = sizeof( ASYNC_DEVCTRL );
  296. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  297. AsyncIndex = (USHORT) TempIndex;
  298. if (!NT_SUCCESS( Status )) {
  299. printf("\n\tInputDevCtrl: Unable to allocate async structure" );
  300. } else {
  301. AsyncDevCtrl = (PASYNC_DEVCTRL) Buffers[AsyncIndex].Buffer;
  302. AsyncDevCtrl->FileIndex = FileIndex;
  303. AsyncDevCtrl->UseEvent = UseEvent;
  304. AsyncDevCtrl->ApcRoutine = ApcRoutine;
  305. AsyncDevCtrl->ApcContext = ApcContext;
  306. AsyncDevCtrl->IoControlCode = IoControlCode;
  307. AsyncDevCtrl->InputBuffer = InputBuffer;
  308. AsyncDevCtrl->InputBufferLength = InputBufferLength;
  309. AsyncDevCtrl->OutputBuffer = OutputBuffer;
  310. AsyncDevCtrl->OutputBufferLength = OutputBufferLength;
  311. AsyncDevCtrl->VerboseResults = VerboseResults;
  312. AsyncDevCtrl->AsyncIndex = AsyncIndex;
  313. if (DisplayParms) {
  314. printf( "\nDevCtrl Operation Parameters" );
  315. printf( "\n Handle index -> %ld", FileIndex );
  316. printf( "\n DevCtrl operation -> %ld", IoControlCode );
  317. printf( "\n\n" );
  318. }
  319. if (!SynchronousCmds) {
  320. ThreadHandle = CreateThread( NULL,
  321. 0,
  322. RequestDevCtrl,
  323. AsyncDevCtrl,
  324. 0,
  325. &ThreadId );
  326. if (ThreadHandle == 0) {
  327. printf( "\nInputDevCtrl: Spawning thread fails -> %d\n", GetLastError() );
  328. }
  329. } else {
  330. RequestDevCtrl( AsyncDevCtrl );
  331. }
  332. }
  333. }
  334. return;
  335. }
  336. VOID
  337. RequestDevCtrl (
  338. IN PASYNC_DEVCTRL DevCtrl
  339. )
  340. {
  341. HANDLE ThisEvent;
  342. USHORT ThisEventIndex = 0;
  343. NTSTATUS Status = STATUS_SUCCESS;
  344. IO_STATUS_BLOCK IoSb;
  345. IoSb.Status = 0;
  346. IoSb.Information = 0;
  347. if (DevCtrl->UseEvent) {
  348. Status = ObtainEvent( &ThisEventIndex );
  349. if (!NT_SUCCESS( Status )) {
  350. bprint "\n\tRequestDevCtrl: Unable to allocate an event" );
  351. } else {
  352. ThisEvent = Events[ThisEventIndex].Handle;
  353. }
  354. }
  355. if (NT_SUCCESS( Status )) {
  356. Status = NtDeviceIoControlFile( Handles[DevCtrl->FileIndex].Handle,
  357. ThisEvent,
  358. DevCtrl->ApcRoutine,
  359. DevCtrl->ApcContext,
  360. &IoSb,
  361. DevCtrl->IoControlCode,
  362. DevCtrl->InputBuffer,
  363. DevCtrl->InputBufferLength,
  364. DevCtrl->OutputBuffer,
  365. DevCtrl->OutputBufferLength );
  366. if (DevCtrl->VerboseResults) {
  367. bprint "\nRequestDevCtrl: Status -> %08lx\n", Status );
  368. if (DevCtrl->UseEvent && NT_SUCCESS( Status )) {
  369. if ((Status = NtWaitForSingleObject( ThisEvent,
  370. FALSE,
  371. NULL )) != STATUS_SUCCESS) {
  372. bprint "\n\tDevctrl: Wait for event failed -> %08lx", Status );
  373. }
  374. }
  375. if (NT_SUCCESS( Status )) {
  376. bprint "\nRequestDevCtrl: IoSb.Status -> %08lx", IoSb.Status );
  377. bprint "\nRequestDevCtrl: IoSb.Information -> %08lx", IoSb.Information );
  378. }
  379. bprint "\n" );
  380. }
  381. }
  382. if (ThisEventIndex != 0) {
  383. FreeEvent( ThisEventIndex );
  384. }
  385. DeallocateBuffer( DevCtrl->AsyncIndex );
  386. if (!SynchronousCmds) {
  387. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  388. bprint "\nRequestDevCtrl: Thread not terminated\n" );
  389. }
  390. }