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.

487 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. fspyUser.c
  5. Abstract:
  6. This file contains the implementation for the main function of the
  7. user application piece of IoTest. This function is responsible for
  8. controlling the command mode available to the user to control the
  9. kernel mode driver.
  10. // @@BEGIN_DDKSPLIT
  11. Author:
  12. George Jenkins (GeorgeJe)
  13. // @@END_DDKSPLIT
  14. Environment:
  15. User mode
  16. // @@BEGIN_DDKSPLIT
  17. Revision History:
  18. Molly Brown (MollyBro) 21-Apr-1999
  19. Broke out the logging code and added command mode functionality.
  20. // @@END_DDKSPLIT
  21. --*/
  22. #include <windows.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <winioctl.h>
  26. #include <string.h>
  27. #include <crtdbg.h>
  28. #include "ioTest.h"
  29. #include "ioTestLog.h"
  30. #include "ioTestLib.h"
  31. #define SUCCESS 0
  32. #define USAGE_ERROR 1
  33. #define EXIT_INTERPRETER 2
  34. #define EXIT_PROGRAM 4
  35. #define INTERPRETER_EXIT_COMMAND1 "go"
  36. #define INTERPRETER_EXIT_COMMAND2 "g"
  37. #define PROGRAM_EXIT_COMMAND "exit"
  38. #define ToggleFlag(V, F) (V = (((V) & (F)) ? (V & (~F)) : (V | F)))
  39. DWORD
  40. InterpretCommand(
  41. int argc,
  42. char *argv[],
  43. PLOG_CONTEXT Context
  44. );
  45. BOOL
  46. ListDevices(
  47. PLOG_CONTEXT Context
  48. );
  49. VOID
  50. DisplayError (
  51. DWORD Code
  52. );
  53. int _cdecl main(int argc, char *argv[])
  54. {
  55. SC_HANDLE hSCManager = NULL;
  56. SC_HANDLE hService = NULL;
  57. SERVICE_STATUS_PROCESS serviceInfo;
  58. DWORD bytesNeeded;
  59. HANDLE hDevice = INVALID_HANDLE_VALUE;
  60. DWORD result;
  61. LOG_CONTEXT context;
  62. //
  63. // Initialize handle in case of error
  64. //
  65. context.ShutDown = NULL;
  66. context.VerbosityFlags = 0;
  67. //
  68. // Start the kernel mode driver through the service manager
  69. //
  70. hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS) ;
  71. hService = OpenService( hSCManager,
  72. IOTEST_SERVICE_NAME,
  73. IOTEST_SERVICE_ACCESS);
  74. if (!QueryServiceStatusEx( hService,
  75. SC_STATUS_PROCESS_INFO,
  76. (UCHAR *)&serviceInfo,
  77. sizeof(serviceInfo),
  78. &bytesNeeded)) {
  79. result = GetLastError();
  80. DisplayError( result );
  81. goto Main_Exit;
  82. }
  83. if(serviceInfo.dwCurrentState != SERVICE_RUNNING) {
  84. //
  85. // Service hasn't been started yet, so try to start service
  86. //
  87. if (!StartService(hService, 0, NULL)) {
  88. result = GetLastError();
  89. printf("ERROR starting IoTest...\n");
  90. DisplayError( result );
  91. goto Main_Exit;
  92. }
  93. }
  94. //
  95. // Open the device that is used to talk to IoTest.
  96. //
  97. hDevice = CreateFile( IOTEST_W32_DEVICE_NAME,
  98. GENERIC_READ | GENERIC_WRITE,
  99. 0,
  100. NULL,
  101. OPEN_EXISTING,
  102. FILE_ATTRIBUTE_NORMAL,
  103. NULL);
  104. if (hDevice == INVALID_HANDLE_VALUE) {
  105. result = GetLastError();
  106. printf("ERROR opening device...\n");
  107. DisplayError( result );
  108. goto Main_Exit;
  109. }
  110. //
  111. // Initialize the fields of the LOG_CONTEXT.
  112. //
  113. context.Device = hDevice;
  114. context.CleaningUp = FALSE;
  115. context.LogToScreen = TRUE;
  116. context.LogToFile = FALSE;
  117. context.OutputFile = NULL;
  118. //
  119. // Check the valid parameters for startup
  120. //
  121. InterpretCommand(argc - 1, &(argv[1]), &context);
  122. //
  123. // Wait for everyone to shut down
  124. //
  125. if (context.LogToFile) {
  126. fclose(context.OutputFile);
  127. }
  128. Main_Exit:
  129. //
  130. // Clean up the data that is alway around and exit
  131. //
  132. if(hSCManager) {
  133. CloseServiceHandle(hSCManager);
  134. }
  135. if(hService) {
  136. CloseServiceHandle(hService);
  137. }
  138. if (hDevice != INVALID_HANDLE_VALUE) {
  139. CloseHandle(hDevice);
  140. }
  141. return 0;
  142. }
  143. DWORD
  144. InterpretCommand(
  145. int argc,
  146. char *argv[],
  147. PLOG_CONTEXT Context
  148. )
  149. {
  150. int parmIndex;
  151. CHAR *parm;
  152. BOOL bResult;
  153. DWORD result;
  154. DWORD returnValue = SUCCESS;
  155. CHAR buffer[BUFFER_SIZE];
  156. DWORD bufferLength;
  157. if (argc == 0) {
  158. goto InterpretCommand_Usage;
  159. }
  160. //
  161. // Interprete the command line parameters
  162. //
  163. for (parmIndex = 0; parmIndex < argc; parmIndex++) {
  164. parm = argv[parmIndex];
  165. if (parm[0] == '/') {
  166. //
  167. // Have the beginning of a switch
  168. //
  169. switch (parm[1]) {
  170. case 'l':
  171. case 'L':
  172. //
  173. // List all devices that are currently being monitored
  174. //
  175. bResult = ListDevices(Context);
  176. if (!bResult) {
  177. result = GetLastError();
  178. printf("ERROR listing devices...\n");
  179. DisplayError( result );
  180. }
  181. break;
  182. case 'n':
  183. case 'N':
  184. //
  185. // Run RENAME test on specified drive
  186. //
  187. parmIndex++;
  188. if (parmIndex >= argc) {
  189. //
  190. // Not enough parameters
  191. //
  192. goto InterpretCommand_Usage;
  193. }
  194. parm = argv[parmIndex];
  195. printf("\tPerforming RENAME test on %s\n", parm);
  196. bufferLength = MultiByteToWideChar(
  197. CP_ACP,
  198. MB_ERR_INVALID_CHARS,
  199. parm,
  200. -1,
  201. (LPWSTR)buffer,
  202. BUFFER_SIZE/sizeof(WCHAR));
  203. RenameTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), FALSE );
  204. RenameTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), TRUE );
  205. break;
  206. case 'r':
  207. case 'R':
  208. //
  209. // Run READ test on specified drive
  210. //
  211. parmIndex++;
  212. if (parmIndex >= argc) {
  213. //
  214. // Not enough parameters
  215. //
  216. goto InterpretCommand_Usage;
  217. }
  218. parm = argv[parmIndex];
  219. printf("\tPerforming READ test on %s\n", parm);
  220. bufferLength = MultiByteToWideChar(
  221. CP_ACP,
  222. MB_ERR_INVALID_CHARS,
  223. parm,
  224. -1,
  225. (LPWSTR)buffer,
  226. BUFFER_SIZE/sizeof(WCHAR));
  227. ReadTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), FALSE );
  228. ReadTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), TRUE );
  229. break;
  230. case 'h':
  231. case 'H':
  232. //
  233. // Run SHARE test on specified drive
  234. //
  235. parmIndex++;
  236. if (parmIndex >= argc) {
  237. //
  238. // Not enough parameters
  239. //
  240. goto InterpretCommand_Usage;
  241. }
  242. parm = argv[parmIndex];
  243. printf("\tPerforming SHARE test on %s\n", parm);
  244. bufferLength = MultiByteToWideChar(
  245. CP_ACP,
  246. MB_ERR_INVALID_CHARS,
  247. parm,
  248. -1,
  249. (LPWSTR)buffer,
  250. BUFFER_SIZE/sizeof(WCHAR));
  251. ShareTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), FALSE );
  252. ShareTest( Context, (LPWSTR)buffer, bufferLength * sizeof(WCHAR), TRUE );
  253. break;
  254. case 's':
  255. case 'S':
  256. //
  257. // Output logging results to screen, save new value to
  258. // instate when command interpreter is exited.
  259. //
  260. if (Context->NextLogToScreen) {
  261. printf("\tTurning off logging to screen\n");
  262. } else {
  263. printf("\tTurning on logging to screen\n");
  264. }
  265. Context->NextLogToScreen = !Context->NextLogToScreen;
  266. break;
  267. case 'f':
  268. case 'F':
  269. //
  270. // Output logging results to file
  271. //
  272. if (Context->LogToFile) {
  273. printf("\tStop logging to file \n");
  274. Context->LogToFile = FALSE;
  275. _ASSERT(Context->OutputFile);
  276. fclose(Context->OutputFile);
  277. Context->OutputFile = NULL;
  278. } else {
  279. parmIndex++;
  280. if (parmIndex >= argc) {
  281. // Not enough parameters
  282. goto InterpretCommand_Usage;
  283. }
  284. parm = argv[parmIndex];
  285. printf("\tLog to file %s\n", parm);
  286. Context->OutputFile = fopen(parm, "w");
  287. _ASSERT(Context->OutputFile);
  288. Context->LogToFile = TRUE;
  289. }
  290. break;
  291. case '?':
  292. default:
  293. //
  294. // Invalid switch, goto usage
  295. //
  296. goto InterpretCommand_Usage;
  297. }
  298. } else {
  299. //
  300. // Invalid parameter
  301. //
  302. goto InterpretCommand_Usage;
  303. }
  304. }
  305. InterpretCommand_Exit:
  306. return returnValue;
  307. InterpretCommand_Usage:
  308. printf("Usage: [[/r <drive>]...] [[/n <drive>]...] [[/h <drive>]...] [/l] [/s] [/f <file name>] \n"
  309. "\t[/r <drive>] runs the READ test on <drive>\n"
  310. "\t[/n <drive>] runs the RENAME test on <drive>\n"
  311. "\t[/h <drive>] runs the SHARE test on <drive>\n"
  312. "\n"
  313. "\t[/l] lists all the drives the monitor is currently attached to\n"
  314. "\t[/s] turns on and off showing logging output on the screen\n"
  315. "\t[/f <file name>] turns on and off logging to the specified file\n"
  316. );
  317. returnValue = USAGE_ERROR;
  318. goto InterpretCommand_Exit;
  319. }
  320. BOOL
  321. ListDevices(
  322. PLOG_CONTEXT Context
  323. )
  324. {
  325. CHAR buffer[BUFFER_SIZE];
  326. ULONG bytesReturned;
  327. BOOL returnValue;
  328. returnValue = DeviceIoControl(
  329. Context->Device,
  330. IOTEST_ListDevices,
  331. NULL,
  332. 0,
  333. buffer,
  334. BUFFER_SIZE,
  335. &bytesReturned,
  336. NULL);
  337. if (returnValue) {
  338. PATTACHED_DEVICE device = (PATTACHED_DEVICE) buffer;
  339. printf("DEVICE NAME | LOGGING STATUS\n");
  340. printf("--------------------------------------------------\n");
  341. if (bytesReturned == 0) {
  342. printf("No devices attached\n");
  343. } else {
  344. while ((BYTE *)device < buffer + bytesReturned) {
  345. switch (device->DeviceType) {
  346. case TOP_FILTER:
  347. printf(
  348. "TOP %-30S| %s\n",
  349. device->DeviceNames,
  350. (device->LoggingOn)?"ON":"OFF");
  351. break;
  352. case BOTTOM_FILTER:
  353. printf(
  354. "BOT %-30S| %s\n",
  355. device->DeviceNames,
  356. (device->LoggingOn)?"ON":"OFF");
  357. break;
  358. }
  359. device ++;
  360. }
  361. }
  362. }
  363. return returnValue;
  364. }
  365. VOID
  366. DisplayError (
  367. DWORD Code
  368. )
  369. /*++
  370. Routine Description:
  371. This routine will display an error message based off of the Win32 error
  372. code that is passed in. This allows the user to see an understandable
  373. error message instead of just the code.
  374. Arguments:
  375. Code - The error code to be translated.
  376. Return Value:
  377. None.
  378. --*/
  379. {
  380. WCHAR buffer[80] ;
  381. DWORD count ;
  382. //
  383. // Translate the Win32 error code into a useful message.
  384. //
  385. count = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
  386. NULL,
  387. Code,
  388. 0,
  389. buffer,
  390. sizeof (buffer),
  391. NULL) ;
  392. //
  393. // Make sure that the message could be translated.
  394. //
  395. if (count == 0) {
  396. printf("\nError could not be translated.\n Code: %d\n", Code) ;
  397. return;
  398. }
  399. else {
  400. //
  401. // Display the translated error.
  402. //
  403. printf("%S\n", buffer) ;
  404. return;
  405. }
  406. }