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.

643 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cdp.c
  5. Abstract:
  6. A user mode app that allows simple commands to be sent to a
  7. selected scsi device.
  8. Environment:
  9. User mode only
  10. Revision History:
  11. 03-26-96 : Created
  12. --*/
  13. //
  14. // this module may be compiled at warning level 4 with the following
  15. // warnings disabled:
  16. //
  17. #pragma warning(disable:4200) // array[0]
  18. #pragma warning(disable:4201) // nameless struct/unions
  19. #pragma warning(disable:4214) // bit fields other than int
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include <bootstatus.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <assert.h>
  28. #include <windows.h>
  29. // #include "bootstatus.h"
  30. #ifdef DBG
  31. #define dbg(x) x
  32. #define HELP_ME() printf("Reached line %4d\n", __LINE__);
  33. #else
  34. #define dbg(x) /* x */
  35. #define HELP_ME() /* printf("Reached line %4d\n", __LINE__); */
  36. #endif
  37. #define ARGUMENT_USED(x) (x == NULL)
  38. //
  39. // The default size of the safemode.dat file - it must be large enough that the
  40. // data stream isn't a resident attribute of the metadata or the loader's
  41. // NTFS implementation can't write to it.
  42. //
  43. #define DEFAULT_SAFEMODE_FILE_SIZE 0x800
  44. typedef struct {
  45. PCHAR Name;
  46. PCHAR Description;
  47. BOOLEAN LockData;
  48. ULONG (*Function)(HANDLE BootStatusData, int argc, char *argv[]);
  49. } COMMAND;
  50. DWORD TestCommand(HANDLE BootStatusData, int argc, char *argv[]);
  51. DWORD Disable(HANDLE BootStatusData, int argc, char *argv[]);
  52. DWORD Enable(HANDLE BootStatusData, int argc, char *argv[]);
  53. DWORD Create(HANDLE BootStatusData, int argc, char *argv[]);
  54. DWORD CreateEx(HANDLE BootStatusData, int argc, char *argv[]);
  55. DWORD SetFlags(HANDLE BootStatusData, int argc, char *argv[]);
  56. DWORD ClearFlags(HANDLE BootStatusData, int argc, char *argv[]);
  57. DWORD ListSettings(HANDLE BootStatusData, int argc, char *argv[]);
  58. DWORD ListCommand(int argc, char *argv[]);
  59. //
  60. // List of commands
  61. // all command names are case sensitive
  62. // arguments are passed into command routines
  63. // list must be terminated with NULL command
  64. // command will not be listed in help if description == NULL
  65. //
  66. COMMAND CommandArray[] = {
  67. {"create", "Creates the boot status data file", FALSE, Create},
  68. {"createex", "Tests creation code", FALSE, CreateEx},
  69. {"disable", "Disables Auto Advanced Boot", TRUE, Disable},
  70. {"enable", "Enables Auto Advanced Boot", TRUE, Enable},
  71. {"set", "Sets the boot status flags", TRUE, SetFlags},
  72. {"settings","Lists the Auto Advanced Boot settings", TRUE, ListSettings},
  73. {NULL, NULL, FALSE, NULL}
  74. };
  75. int __cdecl main(int argc, char *argv[])
  76. {
  77. int i = 0;
  78. HANDLE bootStatusData;
  79. BOOLEAN bsdLocked = FALSE;
  80. if(argc < 2) {
  81. printf("Usage: %s <command> [parameters]\n", argv[0]);
  82. printf("possible commands: \n");
  83. ListCommand(argc, argv);
  84. printf("\n");
  85. return -1;
  86. }
  87. //
  88. // Iterate through the command array and find the correct function to
  89. // call.
  90. //
  91. while(CommandArray[i].Name != NULL) {
  92. if(strcmp(argv[1], CommandArray[i].Name) == 0) {
  93. NTSTATUS status;
  94. if(CommandArray[i].LockData) {
  95. status = RtlLockBootStatusData(&bootStatusData);
  96. if(!NT_SUCCESS(status)) {
  97. printf("Error %#08lx opening boot status bootStatusData\n",
  98. status);
  99. return -1;
  100. }
  101. bsdLocked = TRUE;
  102. } else {
  103. bootStatusData = NULL;
  104. }
  105. (CommandArray[i].Function)(bootStatusData, (argc - 1), &(argv[1]));
  106. break;
  107. }
  108. i++;
  109. }
  110. if(CommandArray[i].Name == NULL) {
  111. printf("Unknown command %s\n", argv[1]);
  112. }
  113. if(bsdLocked) {
  114. RtlUnlockBootStatusData(bootStatusData);
  115. }
  116. return 0;
  117. }
  118. DWORD TestCommand(HANDLE BootStatusData, int argc, char *argv[])
  119. /*++
  120. Routine Description:
  121. Tests the command "parsing"
  122. Arguments:
  123. device - a file handle to send the ioctl to
  124. argc - the number of additional arguments. should be zero
  125. argv - the additional arguments
  126. Return Value:
  127. STATUS_SUCCESS if successful
  128. The value of GetLastError() from the point of failure
  129. --*/
  130. {
  131. int i;
  132. UNREFERENCED_PARAMETER(BootStatusData);
  133. printf("Test - %d additional arguments\n", argc);
  134. for(i = 0; i < argc; i++) {
  135. printf("arg %d: %s\n", i, argv[i]);
  136. }
  137. return STATUS_SUCCESS;
  138. }
  139. DWORD ListCommand(int argc, char *argv[])
  140. /*++
  141. Routine Description:
  142. Prints out the command list
  143. Arguments:
  144. device - unused
  145. argc - unused
  146. argv - unused
  147. Return Value:
  148. STATUS_SUCCESS
  149. --*/
  150. {
  151. int i = 0;
  152. UNREFERENCED_PARAMETER(argc);
  153. UNREFERENCED_PARAMETER(argv);
  154. while(CommandArray[i].Name != NULL) {
  155. if(CommandArray[i].Description != NULL) {
  156. printf("\t%s - %s\n",
  157. CommandArray[i].Name,
  158. CommandArray[i].Description);
  159. }
  160. i++;
  161. }
  162. return STATUS_SUCCESS;
  163. }
  164. DWORD
  165. Create(
  166. HANDLE Unused,
  167. int argc,
  168. char *argv[]
  169. )
  170. {
  171. BOOLEAN enabled;
  172. NTSTATUS status;
  173. status = RtlCreateBootStatusDataFile();
  174. if(!NT_SUCCESS(status)) {
  175. printf("Error %#08lx creating boot status data\n", status);
  176. }
  177. return status;
  178. }
  179. DWORD
  180. Enable(
  181. HANDLE BootStatusData,
  182. int argc,
  183. char *argv[]
  184. )
  185. {
  186. BOOLEAN enabled;
  187. NTSTATUS status;
  188. status = RtlGetSetBootStatusData(BootStatusData,
  189. TRUE,
  190. RtlBsdItemAabEnabled,
  191. &enabled,
  192. sizeof(BOOLEAN),
  193. NULL);
  194. if(!NT_SUCCESS(status)) {
  195. printf("Error %#08lx reading boot status data\n", status);
  196. return status;
  197. }
  198. printf("Enabling Automatic Advanced Boot\n");
  199. printf("Previous setting was %s\n", enabled ? "enabled" : "disabled");
  200. enabled = TRUE;
  201. status = RtlGetSetBootStatusData(BootStatusData,
  202. FALSE,
  203. RtlBsdItemAabEnabled,
  204. &enabled,
  205. sizeof(BOOLEAN),
  206. NULL);
  207. if(!NT_SUCCESS(status)) {
  208. printf("Error %#08lx writing boot status data\n", status);
  209. }
  210. return status;
  211. }
  212. DWORD
  213. Disable(
  214. HANDLE BootStatusData,
  215. int argc,
  216. char *argv[]
  217. )
  218. {
  219. BOOLEAN enabled;
  220. NTSTATUS status;
  221. status = RtlGetSetBootStatusData(BootStatusData,
  222. TRUE,
  223. RtlBsdItemAabEnabled,
  224. &enabled,
  225. sizeof(BOOLEAN),
  226. NULL);
  227. if(!NT_SUCCESS(status)) {
  228. printf("Error %#08lx reading boot status data\n", status);
  229. return status;
  230. }
  231. printf("Disabling Automatic Advanced Boot\n");
  232. printf("Previous setting was %s\n", enabled ? "enabled" : "disabled");
  233. enabled = FALSE;
  234. status = RtlGetSetBootStatusData(BootStatusData,
  235. FALSE,
  236. RtlBsdItemAabEnabled,
  237. &enabled,
  238. sizeof(BOOLEAN),
  239. NULL);
  240. if(!NT_SUCCESS(status)) {
  241. printf("Error %#08lx writing boot status data\n", status);
  242. }
  243. return status;
  244. }
  245. DWORD
  246. ListSettings(
  247. HANDLE BootStatusData,
  248. int argc,
  249. char *argv[]
  250. )
  251. {
  252. BOOLEAN flag;
  253. NTSTATUS status;
  254. status = RtlGetSetBootStatusData(BootStatusData,
  255. TRUE,
  256. RtlBsdItemAabEnabled,
  257. &flag,
  258. sizeof(BOOLEAN),
  259. NULL);
  260. if(!NT_SUCCESS(status)) {
  261. printf("Error %#08lx reading boot status data\n", status);
  262. return status;
  263. }
  264. printf("Automatic Advanced Boot is %s\n", flag ? "enabled" : "disabled");
  265. status = RtlGetSetBootStatusData(BootStatusData,
  266. TRUE,
  267. RtlBsdItemAabTimeout,
  268. &flag,
  269. sizeof(BOOLEAN),
  270. NULL);
  271. if(!NT_SUCCESS(status)) {
  272. printf("Error %#08lx reading boot status data\n", status);
  273. return status;
  274. }
  275. printf("Automatic Advanced Boot timeout is %d seconds\n", (UCHAR) flag);
  276. status = RtlGetSetBootStatusData(BootStatusData,
  277. TRUE,
  278. RtlBsdItemBootGood,
  279. &flag,
  280. sizeof(BOOLEAN),
  281. NULL);
  282. if(!NT_SUCCESS(status)) {
  283. printf("Error %#08lx reading boot status data\n", status);
  284. return status;
  285. }
  286. printf("LastBootSucceeded = %#x\n", flag);
  287. status = RtlGetSetBootStatusData(BootStatusData,
  288. TRUE,
  289. RtlBsdItemBootShutdown,
  290. &flag,
  291. sizeof(BOOLEAN),
  292. NULL);
  293. if(!NT_SUCCESS(status)) {
  294. printf("Error %#08lx reading boot status data\n", status);
  295. return status;
  296. }
  297. printf("LastBootShutdown = %#x\n", flag);
  298. return STATUS_SUCCESS;
  299. }
  300. DWORD SetFlags(HANDLE BootStatusData, int argc, char *argv[])
  301. {
  302. int count;
  303. if(argc <= 1) {
  304. printf("usage: autosafeboot set <Boot|Shutdown>=<value> ...");
  305. return 0;
  306. }
  307. for(count = 1; count < argc; count++) {
  308. PUCHAR nameString;
  309. PUCHAR valueString;
  310. ULONG index;
  311. UCHAR value;
  312. index = -1;
  313. //
  314. // match the string.
  315. //
  316. nameString = argv[count];
  317. valueString = strrchr(nameString, '=');
  318. if(valueString == NULL) {
  319. printf("** element \"%s\" not understood\n", nameString);
  320. continue;
  321. }
  322. valueString[0] = '\0';
  323. valueString += 1;
  324. value = (UCHAR) atoi(valueString);
  325. if(_stricmp(nameString, "boot") == 0) {
  326. printf("Setting LastBootSucceeded to %#x\n", value);
  327. index = RtlBsdItemBootGood;
  328. } else if(_stricmp(nameString, "shutdown") == 0) {
  329. printf("Setting LastBootShutdown to %#x\n", value);
  330. index = RtlBsdItemBootShutdown;
  331. }
  332. if(index != -1) {
  333. NTSTATUS status;
  334. status = RtlGetSetBootStatusData(BootStatusData,
  335. FALSE,
  336. index,
  337. &value,
  338. sizeof(UCHAR),
  339. NULL);
  340. if(!NT_SUCCESS(status)) {
  341. printf("Error %#08lx reading boot status data\n", status);
  342. continue;
  343. }
  344. } else {
  345. printf("** element \"%s=%s\" not understood\n", nameString, valueString);
  346. }
  347. }
  348. return 0;
  349. }
  350. NTSTATUS
  351. MyCreateBootStatusDataFile(
  352. PUCHAR DataFileName
  353. )
  354. {
  355. OBJECT_ATTRIBUTES objectAttributes;
  356. WCHAR fileNameBuffer[MAXIMUM_FILENAME_LENGTH+1];
  357. ANSI_STRING ansiFileName;
  358. UNICODE_STRING fileName;
  359. HANDLE dataFileHandle;
  360. IO_STATUS_BLOCK ioStatusBlock;
  361. LARGE_INTEGER t;
  362. UCHAR zero = 0;
  363. BSD_BOOT_STATUS_DATA defaultValues;
  364. NTSTATUS status;
  365. RtlZeroMemory(fileNameBuffer, sizeof(fileNameBuffer));
  366. RtlInitAnsiString(&ansiFileName, DataFileName);
  367. fileName.Length = 0;
  368. fileName.MaximumLength = sizeof(fileNameBuffer);
  369. fileName.Buffer = fileNameBuffer;
  370. RtlAnsiStringToUnicodeString(&fileName, &ansiFileName, FALSE);
  371. InitializeObjectAttributes(&objectAttributes,
  372. &fileName,
  373. OBJ_CASE_INSENSITIVE,
  374. NULL,
  375. NULL);
  376. //
  377. // The file must be large enough that it doesn't reside in the MFT entry
  378. // or the loader won't be able to write to it.
  379. //
  380. t.QuadPart = 2048;
  381. //
  382. // Create the file.
  383. //
  384. status = NtCreateFile(&dataFileHandle,
  385. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  386. &objectAttributes,
  387. &(ioStatusBlock),
  388. &t,
  389. FILE_ATTRIBUTE_SYSTEM,
  390. 0,
  391. FILE_CREATE,
  392. FILE_SYNCHRONOUS_IO_NONALERT,
  393. NULL,
  394. 0);
  395. ASSERT(status != STATUS_PENDING);
  396. if(!NT_SUCCESS(status)) {
  397. return status;
  398. }
  399. //
  400. // Write a single zero byte to the 0x7ffth byte in the file to make
  401. // sure that 2k are actually allocated. This is to ensure that the
  402. // file will not become attribute resident even after a conversion
  403. // from FAT to NTFS.
  404. //
  405. t.QuadPart = t.QuadPart - 1;
  406. status = NtWriteFile(dataFileHandle,
  407. NULL,
  408. NULL,
  409. NULL,
  410. &ioStatusBlock,
  411. &zero,
  412. 1,
  413. &t,
  414. NULL);
  415. ASSERT(status != STATUS_PENDING);
  416. if(!NT_SUCCESS(status)) {
  417. goto CreateDone;
  418. }
  419. //
  420. // Now write out the default values to the beginning of the file.
  421. //
  422. defaultValues.Version = sizeof(BSD_BOOT_STATUS_DATA);
  423. RtlGetNtProductType(&(defaultValues.ProductType));
  424. defaultValues.AutoAdvancedBoot = FALSE;
  425. defaultValues.AdvancedBootMenuTimeout = 30;
  426. defaultValues.LastBootSucceeded = TRUE;
  427. defaultValues.LastBootShutdown = FALSE;
  428. t.QuadPart = 0;
  429. status = NtWriteFile(dataFileHandle,
  430. NULL,
  431. NULL,
  432. NULL,
  433. &ioStatusBlock,
  434. &defaultValues,
  435. sizeof(BSD_BOOT_STATUS_DATA),
  436. &t,
  437. NULL);
  438. ASSERT(status != STATUS_PENDING);
  439. if(!NT_SUCCESS(status)) {
  440. //
  441. // The data file was created and we can assume the contents were zeroed
  442. // even if we couldn't write out the defaults. Since this wouldn't
  443. // enable auto-advanced boot we'll leave the data file in place with
  444. // its zeroed contents.
  445. //
  446. }
  447. CreateDone:
  448. NtClose(dataFileHandle);
  449. return status;
  450. }
  451. DWORD
  452. CreateEx(
  453. HANDLE Unused,
  454. int argc,
  455. char *argv[]
  456. )
  457. {
  458. BOOLEAN enabled;
  459. NTSTATUS status;
  460. if(argc < 2) {
  461. printf("Error - must supply file name\n");
  462. return -1;
  463. }
  464. printf("Will Create file %s\n", argv[1]);
  465. status = MyCreateBootStatusDataFile(argv[1]);
  466. if(!NT_SUCCESS(status)) {
  467. printf("Error %#08lx creating boot status data\n", status);
  468. }
  469. return status;
  470. }