Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

editreg.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 editreg.c 00008 00009 Abstract: 00010 00011 This program acts as an interactive shell allowing a user to view 00012 and manipulate the configuration registry. Also, it has some specific 00013 commands for support of the NTFT component of the registry. 00014 00015 Author: 00016 00017 Mike Glass 00018 Bob Rinne 00019 00020 Environment: 00021 00022 User process. 00023 00024 Notes: 00025 00026 The commands "disk", "fix", "restore" are commands that know where 00027 the configuration information is for the NTFT component of the NT 00028 system. 00029 00030 Revision History: 00031 00032 --*/ 00033 00034 #include "cmp.h" 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <ctype.h> 00039 #include "ntdskreg.h" 00040 #include "ntddft.h" 00041 00042 // 00043 // Tempory stuff to get types and values to print in help. 00044 // 00045 00046 PUCHAR TypeNames[] = 00047 { 00048 "REG_NONE", 00049 "REG_SZ", 00050 "REG_BINARY", 00051 "REG_DWORD", 00052 "REG_DWORD_LITTLE_ENDIAN", 00053 "REG_DWORD_BIG_ENDIAN", 00054 "REG_LINK", 00055 "REG_MULTI_SZ", 00056 "REG_RESOURCE_LIST", 00057 NULL 00058 }; 00059 00060 ULONG TypeNumbers[] = 00061 { 00062 REG_NONE, 00063 REG_SZ, 00064 REG_BINARY, 00065 REG_DWORD, 00066 REG_DWORD_LITTLE_ENDIAN, 00067 REG_DWORD_BIG_ENDIAN, 00068 REG_LINK, 00069 REG_MULTI_SZ, 00070 REG_RESOURCE_LIST 00071 }; 00072 00073 // 00074 // Special support for the driver load lists in the registry. 00075 // 00076 00077 PUCHAR StartDescription[] = 00078 { 00079 "Boot loader", 00080 "System", 00081 "2", 00082 "3", 00083 00084 // 00085 // Anything above 3 is not loaded. 00086 // 00087 00088 NULL 00089 }; 00090 00091 PUCHAR TypeDescription[] = 00092 { 00093 "System driver", 00094 "File system", 00095 "Service", 00096 NULL 00097 }; 00098 00099 00100 // 00101 // Constants and defines. 00102 // 00103 00104 #define WORK_BUFFER_SIZE 4096 00105 00106 // 00107 // Amount to fudge when mallocing for strings. 00108 // 00109 00110 #define FUDGE 8 00111 00112 // 00113 // Registry base. 00114 // 00115 00116 #define REGISTRY_BASE "\\REGISTRY\\MACHINE" 00117 00118 // 00119 // Default type value when key value set. 00120 // 00121 00122 #define DEFAULT_TYPE REG_SZ 00123 00124 // 00125 // Base location for component descriptions of FT elements. 00126 // 00127 00128 #define FT_REGISTRY_ROOT "\\REGISTRY\\MACHINE\\SYSTEM\\NTFT" 00129 00130 // 00131 // Subkey name located in the FT_REGISTRY_ROOT for stripes. 00132 // 00133 00134 #define FT_STRIPE_BASE "Stripe%d" 00135 00136 // 00137 // Subkey name located in the FT_REGISTRY_ROOT for mirrors. 00138 // 00139 00140 #define FT_MIRROR_BASE "Mirror%d" 00141 00142 // 00143 // Subkey name located in the FT_REGISTRY_ROOT for volume sets. 00144 // 00145 00146 #define FT_VOLSET_BASE "VolSet%d" 00147 00148 00149 // 00150 // Constants for the command values. 00151 // 00152 00153 #define INVALID -1 00154 #define DIR 0 00155 #define CREATE 1 00156 #define LIST 2 00157 #define CHDIR 3 00158 #define HELP 4 00159 #define QUIT 5 00160 #define DDEBUG 6 00161 #define SETVALUE 7 00162 #define DELKEY 8 00163 #define DELVALUE 9 00164 #define DIRLONG 10 00165 #define INLONG 11 00166 #define INSHORT 12 00167 #define INBYTE 13 00168 #define DUMP 14 00169 #define DISKREG 15 00170 #define FIXDISK 16 00171 #define RESTORE 17 00172 #define DRIVERS 18 00173 #define ORPHAN 19 00174 #define REGEN 20 00175 #define INIT 21 00176 #define MAKEFT 22 00177 00178 #define CTRL_C 0x03 00179 00180 // 00181 // Table of recognized commands. 00182 // 00183 00184 PUCHAR Commands[] = { 00185 "dir", 00186 "keys", 00187 "lc", 00188 "ls", 00189 "create", 00190 "set", 00191 "unset", 00192 "erase", 00193 "delete", 00194 "rm", 00195 "list", 00196 "values", 00197 "display", 00198 "cd", 00199 "chdir", 00200 "help", 00201 "?", 00202 "quit", 00203 "exit", 00204 "debug", 00205 "longs", 00206 "shorts", 00207 "bytes", 00208 "dump", 00209 "disks", 00210 "fix", 00211 "restore", 00212 "drivers", 00213 "orphan", 00214 "regenerate", 00215 "initialize", 00216 "makeft", 00217 NULL 00218 }; 00219 00220 // 00221 // Using the index from the match on the commands in Commands[], this 00222 // table gives the proper command value to be executed. This allows 00223 // for multiple entries in Commands[] for the same command code. 00224 // 00225 00226 int CommandMap[] = { 00227 00228 DIRLONG, 00229 DIR, 00230 DIR, 00231 DIR, 00232 CREATE, 00233 SETVALUE, 00234 DELVALUE, 00235 DELVALUE, 00236 DELKEY, 00237 DELKEY, 00238 LIST, 00239 LIST, 00240 LIST, 00241 CHDIR, 00242 CHDIR, 00243 HELP, 00244 HELP, 00245 QUIT, 00246 QUIT, 00247 DDEBUG, 00248 INLONG, 00249 INSHORT, 00250 INBYTE, 00251 DUMP, 00252 DISKREG, 00253 FIXDISK, 00254 RESTORE, 00255 DRIVERS, 00256 ORPHAN, 00257 REGEN, 00258 INIT, 00259 MAKEFT 00260 }; 00261 00262 // 00263 // CommandHelp is an array of help strings for each of the commands. 00264 // The array is indexed by the result of CommandMap[i] for the Commands[] 00265 // array. This way the same help message will print for each of the 00266 // commands aliases. 00267 // 00268 00269 PUCHAR CommandHelp[] = { 00270 00271 "Displays keys.", 00272 "Create a new key.", 00273 "Displays values withing a key.", 00274 "Change current location in registry.", 00275 "This help information.", 00276 "Exit the program.", 00277 "Set internal debug on for this program.", 00278 "Set a new value within a key.", 00279 "Delete a key.", 00280 "Unset (erase) a key value.", 00281 "Unset (erase) a key value.", 00282 "Change dump format to Longs (default).", 00283 "Change dump format to Shorts.", 00284 "Change dump format to Bytes.", 00285 "Toggle dump mode (force hex dump for all value types).", 00286 "Display the disk registry.", 00287 "Set disk signatures in registry.", 00288 "Restore an FT orphan to working state.", 00289 "List the information on the drivers from the registry.", 00290 "Orphan a member of an FT set.", 00291 "Mark a FT set member for regeneration on next boot.", 00292 "Mark a stripe with parity for initialization on next boot.", 00293 "Construct an FT set from existing partitions", 00294 NULL 00295 00296 }; 00297 00298 // 00299 // Space for working location string in registry. 00300 // 00301 00302 UCHAR WorkingDirectory[512]; 00303 00304 // 00305 // Space for current location string in registry. 00306 // 00307 00308 UCHAR CurrentDirectory[512]; 00309 00310 // 00311 // Space for command input. 00312 // 00313 00314 UCHAR CommandLine[512]; 00315 00316 // 00317 // Prompt strings for getting definition for an FT_COPY request. 00318 // 00319 00320 PUCHAR SetPrompts[] = { 00321 00322 "Name => ", 00323 "Value => ", 00324 "Index => ", 00325 NULL 00326 }; 00327 00328 // 00329 // Version indicator. Should be changed every time a major edit occurs. 00330 // 00331 00332 PUCHAR Version = "Version 1.30"; 00333 00334 // 00335 // Debug print level. 00336 // 00337 00338 ULONG Debug = 0; 00339 00340 // 00341 // Dump control values. 00342 // 00343 00344 typedef enum _DUMP_CONTROL { 00345 00346 InBytes, 00347 InShorts, 00348 InLongs 00349 00350 } DUMP_CONTROL, *PDUMP_CONTROL; 00351 00352 ULONG ForceDump = 0; 00353 00354 DUMP_CONTROL DumpControl = InLongs; 00355 00356 NTSTATUS 00357 FtOpenKey( 00358 PHANDLE HandlePtr, 00359 PUCHAR KeyName 00360 ) 00361 00362 /*++ 00363 00364 Routine Description: 00365 00366 Arguments: 00367 00368 Return Value: 00369 00370 --*/ 00371 00372 { 00373 NTSTATUS status; 00374 STRING keyString; 00375 OBJECT_ATTRIBUTES objectAttributes; 00376 UNICODE_STRING unicodeKeyName; 00377 00378 RtlInitString(&keyString, 00379 KeyName); 00380 00381 (VOID)RtlAnsiStringToUnicodeString(&unicodeKeyName, 00382 &keyString, 00383 (BOOLEAN) TRUE); 00384 00385 memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES)); 00386 InitializeObjectAttributes(&objectAttributes, 00387 &unicodeKeyName, 00388 OBJ_CASE_INSENSITIVE, 00389 NULL, 00390 NULL); 00391 00392 status = NtOpenKey(HandlePtr, 00393 MAXIMUM_ALLOWED, 00394 &objectAttributes); 00395 00396 RtlFreeUnicodeString(&unicodeKeyName); 00397 00398 if (Debug == 1) { 00399 if (!NT_SUCCESS(status)) { 00400 printf("Failed NtOpenKey for %s => %x\n", 00401 KeyName, 00402 status); 00403 } 00404 } 00405 00406 return status; 00407 } 00408 00409 00410 NTSTATUS 00411 FtDeleteKey( 00412 PUCHAR KeyName 00413 ) 00414 00415 /*++ 00416 00417 Routine Description: 00418 00419 Arguments: 00420 00421 Return Value: 00422 00423 --*/ 00424 00425 { 00426 NTSTATUS status; 00427 HANDLE keyToDelete; 00428 00429 status = FtOpenKey(&keyToDelete, 00430 KeyName); 00431 00432 if (!NT_SUCCESS(status)) { 00433 printf("Key %s not found (0x%x).\n", KeyName, status); 00434 return status; 00435 } 00436 00437 status = NtDeleteKey(keyToDelete); 00438 00439 if (Debug == 1) { 00440 if (!NT_SUCCESS(status)) { 00441 printf("Could not delete key %s => %x\n", 00442 KeyName, 00443 status); 00444 } 00445 } 00446 00447 NtClose(keyToDelete); 00448 return status; 00449 } 00450 00451 00452 NTSTATUS 00453 FtCreateKey( 00454 PUCHAR KeyName, 00455 PUCHAR KeyClass, 00456 ULONG Index 00457 ) 00458 00459 /*++ 00460 00461 Routine Description: 00462 00463 Arguments: 00464 00465 Return Value: 00466 00467 --*/ 00468 00469 { 00470 NTSTATUS status; 00471 STRING keyString; 00472 UNICODE_STRING unicodeKeyName; 00473 STRING classString; 00474 UNICODE_STRING unicodeClassName; 00475 OBJECT_ATTRIBUTES objectAttributes; 00476 ULONG disposition; 00477 HANDLE tempHandle; 00478 00479 #if DBG 00480 if ((KeyName == NULL) || 00481 (KeyClass == NULL)) { 00482 printf("FtCreateKey: Invalid parameter 0x%x, 0x%x\n", 00483 KeyName, 00484 KeyClass); 00485 ASSERT(0); 00486 } 00487 #endif 00488 00489 // 00490 // Initialize the object for the key. 00491 // 00492 00493 RtlInitString(&keyString, 00494 KeyName); 00495 00496 (VOID)RtlAnsiStringToUnicodeString(&unicodeKeyName, 00497 &keyString, 00498 (BOOLEAN) TRUE); 00499 00500 memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES)); 00501 InitializeObjectAttributes(&objectAttributes, 00502 &unicodeKeyName, 00503 OBJ_CASE_INSENSITIVE, 00504 NULL, 00505 NULL); 00506 00507 // 00508 // Setup the unicode class value. 00509 // 00510 00511 RtlInitString(&classString, 00512 KeyClass); 00513 (VOID)RtlAnsiStringToUnicodeString(&unicodeClassName, 00514 &classString, 00515 (BOOLEAN) TRUE); 00516 00517 // 00518 // Create the key. 00519 // 00520 00521 status = NtCreateKey(&tempHandle, 00522 MAXIMUM_ALLOWED, 00523 &objectAttributes, 00524 Index, 00525 &unicodeClassName, 00526 REG_OPTION_NON_VOLATILE, 00527 &disposition); 00528 00529 if (NT_SUCCESS(status)) { 00530 switch (disposition) 00531 { 00532 case REG_CREATED_NEW_KEY: 00533 break; 00534 00535 case REG_OPENED_EXISTING_KEY: 00536 printf("Warning: Creation was for an existing key!\n"); 00537 break; 00538 00539 default: 00540 printf("New disposition returned == 0x%x\n", disposition); 00541 break; 00542 } 00543 } 00544 00545 // 00546 // Free all allocated space. 00547 // 00548 00549 RtlFreeUnicodeString(&unicodeKeyName); 00550 RtlFreeUnicodeString(&unicodeClassName); 00551 NtClose(tempHandle); 00552 return status; 00553 } 00554 00555 00556 NTSTATUS 00557 FtDeleteValue( 00558 HANDLE KeyHandle, 00559 PUCHAR ValueName 00560 ) 00561 00562 /*++ 00563 00564 Routine Description: 00565 00566 Arguments: 00567 00568 Return Value: 00569 00570 --*/ 00571 00572 { 00573 NTSTATUS status; 00574 STRING valueString; 00575 UNICODE_STRING unicodeValueName; 00576 00577 RtlInitString(&valueString, 00578 ValueName); 00579 status = RtlAnsiStringToUnicodeString(&unicodeValueName, 00580 &valueString, 00581 (BOOLEAN) TRUE); 00582 if (!NT_SUCCESS(status)) { 00583 printf("FtDeleteValue: internal conversion error 0x%x\n", status); 00584 return status; 00585 } 00586 00587 status = NtDeleteValueKey(KeyHandle, 00588 &unicodeValueName); 00589 if (Debug == 1) { 00590 if (!NT_SUCCESS(status)) { 00591 printf("Could not delete value %s => %x\n", 00592 ValueName, 00593 status); 00594 } 00595 } 00596 00597 RtlFreeUnicodeString(&unicodeValueName); 00598 return status; 00599 } 00600 00601 NTSTATUS 00602 FtSetValue( 00603 HANDLE KeyHandle, 00604 PUCHAR ValueName, 00605 PVOID DataBuffer, 00606 ULONG DataLength, 00607 ULONG Type 00608 ) 00609 00610 /*++ 00611 00612 Routine Description: 00613 00614 Arguments: 00615 00616 Return Value: 00617 00618 --*/ 00619 00620 { 00621 NTSTATUS status; 00622 STRING valueString; 00623 UNICODE_STRING unicodeValueName; 00624 00625 RtlInitString(&valueString, 00626 ValueName); 00627 RtlAnsiStringToUnicodeString(&unicodeValueName, 00628 &valueString, 00629 (BOOLEAN) TRUE); 00630 status = NtSetValueKey(KeyHandle, 00631 &unicodeValueName, 00632 0, 00633 Type, 00634 DataBuffer, 00635 DataLength); 00636 if (Debug == 1) { 00637 if (!NT_SUCCESS(status)) { 00638 printf("Could not set value %s => %x\n", 00639 ValueName, 00640 status); 00641 } 00642 } 00643 00644 RtlFreeUnicodeString(&unicodeValueName); 00645 return status; 00646 } 00647 00648 00649 PUCHAR 00650 FindTypeString( 00651 ULONG Type 00652 ) 00653 00654 /*++ 00655 00656 Routine Description: 00657 00658 Arguments: 00659 00660 Return Value: 00661 00662 --*/ 00663 00664 { 00665 int i; 00666 00667 for (i = 0; TypeNames[i] != NULL; i++) { 00668 00669 if (TypeNumbers[i] == Type) { 00670 return TypeNames[i]; 00671 } 00672 } 00673 return "(Unknown)"; 00674 } 00675 00676 00677 BOOLEAN 00678 ProcessHex( 00679 PUCHAR String, 00680 PULONG Value 00681 ) 00682 00683 /*++ 00684 00685 Routine Description: 00686 00687 Arguments: 00688 00689 Return Value: 00690 00691 --*/ 00692 00693 { 00694 ULONG workValue; 00695 int i; 00696 PUCHAR cp; 00697 00698 if (String == NULL) { 00699 return FALSE; 00700 } 00701 00702 cp = String; 00703 00704 // 00705 // 'i' is an index value. It contains the maximum index into the String. 00706 // Therefore it is initialized to -1. 00707 // 00708 00709 i = -1; 00710 while ((*cp) && (*cp != '\n')) { 00711 i++; 00712 cp++; 00713 } 00714 00715 if (i >= 8) { 00716 00717 // 00718 // String to long for a long. 00719 // 00720 00721 return FALSE; 00722 } 00723 00724 workValue = 0; 00725 cp = String; 00726 while (*cp) { 00727 *cp = (UCHAR) tolower(*cp); 00728 00729 switch (*cp) { 00730 00731 case '0': 00732 case '1': 00733 case '2': 00734 case '3': 00735 case '4': 00736 case '5': 00737 case '6': 00738 case '7': 00739 case '8': 00740 case '9': 00741 workValue |= (((*cp) - '0') << (i * 4)); 00742 break; 00743 00744 case 'a': 00745 case 'b': 00746 case 'c': 00747 case 'd': 00748 case 'e': 00749 case 'f': 00750 workValue |= ((((*cp) - 'a') + 10) << (i * 4)); 00751 break; 00752 00753 default: 00754 00755 // 00756 // Illegal value, just punt. 00757 // 00758 00759 return FALSE; 00760 break; 00761 } 00762 cp++; 00763 i--; 00764 } 00765 00766 *Value = workValue; 00767 return TRUE; 00768 } 00769 00770 00771 VOID 00772 Dump( 00773 PVOID Buffer, 00774 ULONG Length 00775 ) 00776 00777 /*++ 00778 00779 Routine Description: 00780 00781 Dump the value data from a buffer in the format specified. 00782 00783 Arguments: 00784 00785 Buffer - pointer to the data. 00786 Length - length of the data. 00787 00788 Return Value: 00789 00790 None. 00791 00792 --*/ 00793 { 00794 PUCHAR location; 00795 PUCHAR internalBuffer; 00796 int i; 00797 int j; 00798 int numberLines; 00799 UCHAR outHexLine[128]; 00800 UCHAR outPrintable[64]; 00801 00802 numberLines = (Length + 15) / 16; 00803 00804 // 00805 // Since the amount of data displayed has been rounded up, this 00806 // routine mallocs enough space and copies the data in. This way 00807 // it won't fault if the data is at the end of memory. 00808 // 00809 00810 internalBuffer = (PUCHAR) malloc(numberLines * 16); 00811 RtlMoveMemory(internalBuffer, Buffer, Length); 00812 location = (PUCHAR) internalBuffer; 00813 00814 for (i = 0; i < numberLines; i++) { 00815 00816 sprintf(outHexLine, "%8x: ", (i * 16)); 00817 sprintf(outPrintable, "*"); 00818 switch (DumpControl) { 00819 00820 case InBytes: 00821 00822 for (j = 0; j < 16; j++) { 00823 sprintf(outHexLine, "%s%2X ", outHexLine, *location); 00824 sprintf(outPrintable, "%s%c", outPrintable, 00825 (isprint(location[0])) ? location[0] : '.'); 00826 location++; 00827 } 00828 break; 00829 00830 case InShorts: 00831 00832 for (j = 0; j < 8; j++) { 00833 sprintf(outHexLine, "%s%4X ", outHexLine, 00834 *((PUSHORT)location)); 00835 sprintf(outPrintable, "%s%c%c", outPrintable, 00836 (isprint(location[0])) ? location[0] : '.', 00837 (isprint(location[1])) ? location[1] : '.'); 00838 location += 2; 00839 } 00840 break; 00841 00842 default: 00843 case InLongs: 00844 00845 for (j = 0; j < 4; j++) { 00846 sprintf(outHexLine, "%s%8X ", outHexLine, 00847 *((PULONG)location)); 00848 sprintf(outPrintable, "%s%c%c%c%c", outPrintable, 00849 (isprint(location[0])) ? location[0] : '.', 00850 (isprint(location[1])) ? location[1] : '.', 00851 (isprint(location[2])) ? location[2] : '.', 00852 (isprint(location[3])) ? location[3] : '.'); 00853 location += 4; 00854 } 00855 break; 00856 } 00857 00858 printf("%s %s*\n", outHexLine, outPrintable); 00859 } 00860 printf("\n"); 00861 free(internalBuffer); 00862 } 00863 00864 00865 void 00866 UnicodePrint( 00867 PUNICODE_STRING UnicodeString 00868 ) 00869 00870 /*++ 00871 00872 Routine Description: 00873 00874 Print a unicode string. 00875 00876 Arguments: 00877 00878 UnicodeString - pointer to the string. 00879 00880 Return Value: 00881 00882 None. 00883 00884 --*/ 00885 { 00886 ANSI_STRING ansiString; 00887 PUCHAR tempbuffer = (PUCHAR) malloc(WORK_BUFFER_SIZE); 00888 00889 ansiString.MaximumLength = WORK_BUFFER_SIZE; 00890 ansiString.Length = 0L; 00891 ansiString.Buffer = tempbuffer; 00892 00893 RtlUnicodeStringToAnsiString(&ansiString, 00894 UnicodeString, 00895 (BOOLEAN) FALSE); 00896 printf("%s", ansiString.Buffer); 00897 free(tempbuffer); 00898 return; 00899 } 00900 00901 00902 NTSTATUS 00903 Directory( 00904 HANDLE KeyHandle, 00905 BOOLEAN LongListing 00906 ) 00907 00908 /*++ 00909 00910 00911 Routine Description: 00912 00913 Arguments: 00914 00915 Return Value: 00916 00917 --*/ 00918 00919 { 00920 NTSTATUS status; 00921 ULONG index; 00922 ULONG resultLength; 00923 UNICODE_STRING unicodeValueName; 00924 PKEY_BASIC_INFORMATION keyInformation; 00925 00926 keyInformation = (PKEY_BASIC_INFORMATION) malloc(WORK_BUFFER_SIZE); 00927 00928 for (index = 0; TRUE; index++) { 00929 00930 RtlZeroMemory(keyInformation, WORK_BUFFER_SIZE); 00931 00932 status = NtEnumerateKey(KeyHandle, 00933 index, 00934 KeyBasicInformation, 00935 keyInformation, 00936 WORK_BUFFER_SIZE, 00937 &resultLength); 00938 00939 if (status == STATUS_NO_MORE_ENTRIES) { 00940 00941 break; 00942 00943 } else if (!NT_SUCCESS(status)) { 00944 00945 printf("readreg: Error on Enumerate status = %x\n", status); 00946 break; 00947 00948 } 00949 00950 unicodeValueName.Length = (USHORT)keyInformation->NameLength; 00951 unicodeValueName.MaximumLength = (USHORT)keyInformation->NameLength; 00952 unicodeValueName.Buffer = (PWSTR)&keyInformation->Name[0]; 00953 UnicodePrint(&unicodeValueName); 00954 printf("\n"); 00955 00956 if (LongListing) { 00957 } 00958 } 00959 00960 free(keyInformation); 00961 return status; 00962 } 00963 00964 00965 NTSTATUS 00966 List( 00967 HANDLE KeyHandle, 00968 PUCHAR ItemName 00969 ) 00970 00971 /*++ 00972 00973 00974 Routine Description: 00975 00976 Arguments: 00977 00978 Return Value: 00979 00980 --*/ 00981 { 00982 NTSTATUS status; 00983 ULONG index; 00984 ULONG resultLength; 00985 ULONG type; 00986 PUCHAR typeString; 00987 UNICODE_STRING unicodeValueName; 00988 PKEY_VALUE_FULL_INFORMATION keyValueInformation; 00989 00990 UNREFERENCED_PARAMETER(ItemName); 00991 00992 resultLength = WORK_BUFFER_SIZE; 00993 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION)malloc(WORK_BUFFER_SIZE); 00994 00995 for (index = 0; TRUE; index++) { 00996 00997 while (1) { 00998 00999 RtlZeroMemory(keyValueInformation, resultLength); 01000 status = NtEnumerateValueKey(KeyHandle, 01001 index, 01002 KeyValueFullInformation, 01003 keyValueInformation, 01004 resultLength, 01005 &resultLength); 01006 01007 if (status == STATUS_BUFFER_OVERFLOW) { 01008 free(keyValueInformation); 01009 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) 01010 malloc(resultLength + 10); 01011 } else { 01012 break; 01013 } 01014 } 01015 01016 if (status == STATUS_NO_MORE_ENTRIES) { 01017 01018 break; 01019 01020 } else if (!NT_SUCCESS(status)) { 01021 01022 printf("readreg: Cannot list (%x)\n", status); 01023 break; 01024 01025 } 01026 01027 type = keyValueInformation->Type; 01028 typeString = FindTypeString(type); 01029 unicodeValueName.Length = (USHORT)keyValueInformation->NameLength; 01030 unicodeValueName.MaximumLength =(USHORT)keyValueInformation->NameLength; 01031 unicodeValueName.Buffer = (PWSTR)&keyValueInformation->Name[0]; 01032 printf("Name-> """); 01033 UnicodePrint(&unicodeValueName); 01034 printf("""\n"); 01035 printf("\ttype = %s (%d)\ttitle index = %d\tdata length = %d\n", 01036 typeString, 01037 type, 01038 keyValueInformation->TitleIndex, 01039 keyValueInformation->DataLength); 01040 printf("\tData:\n"); 01041 01042 if (ForceDump) { 01043 type = REG_BINARY; 01044 } 01045 01046 switch (type) { 01047 01048 case REG_DWORD: 01049 // case REG_DWORD_LITTLE_ENDIAN: 01050 printf("\tDWORD value == %d, (0x%x)\n", 01051 *((PULONG)((PUCHAR)keyValueInformation + 01052 keyValueInformation->DataOffset)), 01053 *((PULONG)((PUCHAR)keyValueInformation + 01054 keyValueInformation->DataOffset))); 01055 break; 01056 01057 case REG_SZ: 01058 01059 unicodeValueName.Length = (USHORT)keyValueInformation->DataLength; 01060 unicodeValueName.MaximumLength = (USHORT) 01061 keyValueInformation->DataLength; 01062 unicodeValueName.Buffer = (PWSTR) ((PUCHAR) keyValueInformation + 01063 keyValueInformation->DataOffset); 01064 UnicodePrint(&unicodeValueName); 01065 break; 01066 01067 case REG_BINARY: 01068 default: 01069 Dump(((PUCHAR)keyValueInformation +keyValueInformation->DataOffset), 01070 keyValueInformation->DataLength); 01071 } 01072 printf("\n"); 01073 } 01074 01075 free(keyValueInformation); 01076 return status; 01077 } 01078 01079 01080 UCHAR 01081 GetCharacter( 01082 BOOLEAN Batch 01083 ) 01084 01085 /*++ 01086 01087 Routine Description: 01088 01089 This routine returns a single character from the input stream. 01090 It discards leading blanks if the input is not from the console. 01091 01092 Arguments: 01093 01094 Batch - a boolean indicating if the input it coming from the console. 01095 01096 Return Value: 01097 01098 A character 01099 01100 --*/ 01101 01102 { 01103 UCHAR c; 01104 01105 if (Batch) { 01106 01107 while ((c = (UCHAR) getchar()) == ' ') 01108 ; 01109 01110 } else { 01111 01112 c = (UCHAR) getchar(); 01113 } 01114 01115 return c; 01116 } // GetCharacter 01117 01118 01119 PUCHAR 01120 GetArgumentString( 01121 BOOLEAN Batch, 01122 PUCHAR Prompt, 01123 BOOLEAN ConvertToLower 01124 ) 01125 01126 /*++ 01127 01128 Routine Description: 01129 01130 This routine prints the prompt if the input is coming from the console, 01131 then proceeds to collect the user input until a carraige return is typed. 01132 01133 Arguments: 01134 01135 Batch - a boolean indicating if the input is coming from the console. 01136 Prompt - String to prompt with. 01137 01138 Return Value: 01139 01140 A pointer to the input string. 01141 NULL if the user escaped. 01142 01143 --*/ 01144 01145 { 01146 // 01147 // The command line data area is used to store the argument string. 01148 // 01149 01150 PUCHAR argument = CommandLine; 01151 int i; 01152 UCHAR c; 01153 01154 if (!Batch) { 01155 01156 printf("%s", Prompt); 01157 } 01158 01159 while ((c = GetCharacter(Batch)) == ' ') { 01160 01161 // 01162 // Ignore leading spaces. 01163 // 01164 } 01165 01166 i = 0; 01167 while (c) { 01168 01169 putchar(c); 01170 01171 if (c == CTRL_C) { 01172 01173 return NULL; 01174 } 01175 01176 if ((c == '\n') || (c == '\r')) { 01177 01178 putchar('\n'); 01179 01180 if (i == 0) { 01181 return NULL; 01182 } else { 01183 break; 01184 } 01185 } 01186 01187 if (c == '\b') { 01188 01189 if (i > 0) { 01190 01191 // 01192 // blank over last char 01193 // 01194 01195 putchar(' '); 01196 putchar('\b'); 01197 i--; 01198 01199 } else { 01200 01201 // 01202 // space forward to keep prompt in the same place. 01203 // 01204 01205 putchar(' '); 01206 } 01207 01208 } else { 01209 01210 // 01211 // Collect the argument. 01212 // 01213 01214 if (ConvertToLower == TRUE) { 01215 argument[i] = (UCHAR) tolower(c); 01216 } else { 01217 argument[i] = (UCHAR) c; 01218 } 01219 i++; 01220 01221 } 01222 01223 c = GetCharacter(Batch); 01224 } 01225 01226 argument[i] = '\0'; 01227 return CommandLine; 01228 01229 } // GetArgumentString 01230 01231 01232 ULONG 01233 ParseArgumentNumeric( 01234 PUCHAR *ArgumentPtr 01235 ) 01236 01237 /*++ 01238 01239 Routine Description: 01240 01241 This routine prints the prompt if the input is coming from the console. 01242 01243 Arguments: 01244 01245 Batch - a boolean indicating if the input is coming from the console. 01246 01247 Return Value: 01248 01249 None 01250 01251 --*/ 01252 01253 { 01254 UCHAR c; 01255 ULONG number; 01256 int i; 01257 BOOLEAN complete = FALSE; 01258 PUCHAR argument = *ArgumentPtr; 01259 01260 while (*argument == ' ') { 01261 01262 // 01263 // skip spaces. 01264 // 01265 01266 argument++; 01267 } 01268 01269 // 01270 // Assume there is only one option to parse until proven 01271 // otherwise. 01272 // 01273 01274 *ArgumentPtr = NULL; 01275 01276 i = 0; 01277 01278 while (complete == FALSE) { 01279 01280 c = argument[i]; 01281 01282 switch (c) { 01283 01284 case '\n': 01285 case '\r': 01286 case '\t': 01287 case ' ': 01288 01289 // 01290 // Update the caller argument pointer to the remaining string. 01291 // 01292 01293 *ArgumentPtr = &argument[i + 1]; 01294 01295 // 01296 // fall through. 01297 // 01298 01299 case '\0': 01300 01301 argument[i] = '\0'; 01302 complete = TRUE; 01303 break; 01304 01305 default: 01306 01307 i++; 01308 break; 01309 } 01310 01311 } 01312 01313 if (i > 0) { 01314 number = (ULONG) atoi(argument); 01315 } else { 01316 number = (ULONG) -1; 01317 } 01318 01319 return number; 01320 01321 } // ParseArgumentNumeric 01322 01323 01324 VOID 01325 PromptUser( 01326 BOOLEAN Batch 01327 ) 01328 01329 /*++ 01330 01331 Routine Description: 01332 01333 This routine prints the prompt if the input is coming from the console. 01334 01335 Arguments: 01336 01337 Batch - a boolean indicating if the input is coming from the console. 01338 01339 Return Value: 01340 01341 None 01342 01343 --*/ 01344 01345 { 01346 if (!Batch) { 01347 01348 printf("\n%s> ", CurrentDirectory); 01349 } 01350 01351 } // PromptUser 01352 01353 01354 int 01355 GetCommand( 01356 BOOLEAN Batch, 01357 PUCHAR *ArgumentPtr 01358 ) 01359 /*++ 01360 01361 Routine Description: 01362 01363 This routine processes the user input and returns the code for the 01364 command entered. If the command has an argument, either the default 01365 value for the argument (if none is given) or the value provided by the 01366 user is returned. 01367 01368 Arguments: 01369 01370 Batch - a boolean indicating if the input it coming from the console. 01371 01372 Return Value: 01373 01374 A command code 01375 01376 --*/ 01377 01378 { 01379 int i; 01380 int commandIndex; 01381 int commandCode; 01382 UCHAR c; 01383 PUCHAR commandPtr; 01384 PUCHAR command = CommandLine; 01385 int argumentIndex = -1; 01386 PUCHAR argument = NULL; 01387 01388 PromptUser(Batch); 01389 01390 while ((c = GetCharacter(Batch)) == ' ') { 01391 01392 // 01393 // Ignore leading spaces. 01394 // 01395 } 01396 01397 i = 0; 01398 while (c) { 01399 01400 putchar(c); 01401 01402 if ((c == '\n') || (c == '\r')) { 01403 putchar('\n'); 01404 if (i == 0) { 01405 PromptUser(Batch); 01406 c = GetCharacter(Batch); 01407 continue; 01408 } 01409 break; 01410 } 01411 01412 if (c == '\b') { 01413 01414 if (i > 0) { 01415 01416 // 01417 // blank over last char 01418 // 01419 01420 putchar(' '); 01421 putchar('\b'); 01422 i--; 01423 01424 if (argumentIndex == i) { 01425 argumentIndex = -1; 01426 argument = NULL; 01427 } 01428 } else { 01429 01430 // 01431 // space forward to keep prompt in the same place. 01432 // 01433 01434 putchar(' '); 01435 } 01436 } else { 01437 01438 // 01439 // Collect the command. 01440 // 01441 01442 command[i] = (UCHAR)tolower(c); 01443 i++; 01444 } 01445 01446 if ((c == ' ') && (argument == NULL)) { 01447 01448 argument = &command[i]; 01449 argumentIndex = i; 01450 command[i - 1] = '\0'; 01451 } 01452 01453 c = GetCharacter(Batch); 01454 } 01455 01456 // 01457 // add end of string. 01458 // 01459 01460 command[i] = '\0'; 01461 01462 if (Debug) { 01463 printf("command => %s$\n", command); 01464 } 01465 01466 // 01467 // Identify the command and return its code. 01468 // 01469 01470 commandIndex = 0; 01471 01472 for (commandPtr = Commands[commandIndex]; 01473 commandPtr != NULL; 01474 commandPtr = Commands[commandIndex]) { 01475 01476 if (Debug) { 01477 printf("Testing => %s$ ... ", commandPtr); 01478 } 01479 01480 i = 0; 01481 while (commandPtr[i] == command[i]) { 01482 if (command[i] == '\0') { 01483 break; 01484 } 01485 i++; 01486 } 01487 01488 if (Debug) { 01489 printf(" i == %d, command[i] == 0x%x\n", i, command[i]); 01490 } 01491 01492 if (command[i]) { 01493 01494 // 01495 // Not complete there was a mismatch on the command. 01496 // 01497 01498 commandIndex++; 01499 continue; 01500 } 01501 01502 // 01503 // Have a match on the command. 01504 // 01505 01506 if (Debug) { 01507 printf("Command match %d, argument %s\n", 01508 commandIndex, 01509 (argument == NULL) ? "(none)" : argument); 01510 } 01511 01512 commandCode = CommandMap[commandIndex]; 01513 *ArgumentPtr = argument; 01514 return commandCode; 01515 } 01516 01517 printf("Command was invalid\n"); 01518 return INVALID; 01519 } // GetCommand 01520 01521 01522 VOID 01523 NotImplemented() 01524 01525 /*++ 01526 01527 --*/ 01528 01529 { 01530 printf("Sorry, function not implemented yet.\n"); 01531 } 01532 01533 NTSTATUS 01534 FtReturnValue( 01535 IN HANDLE Handle, 01536 IN PUCHAR ValueName, 01537 IN PUCHAR Buffer, 01538 IN ULONG BufferLength 01539 ) 01540 01541 /*++ 01542 01543 Routine Description: 01544 01545 Formatted display of the disk registry information. 01546 01547 Arguments: 01548 01549 None. 01550 01551 Return Values: 01552 01553 None. 01554 01555 --*/ 01556 01557 { 01558 NTSTATUS status; 01559 ULONG resultLength; 01560 ULONG length; 01561 STRING valueString; 01562 UNICODE_STRING unicodeValueName; 01563 PUCHAR internalBuffer; 01564 PKEY_VALUE_FULL_INFORMATION keyValueInformation; 01565 01566 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION)malloc(WORK_BUFFER_SIZE); 01567 if (keyValueInformation == NULL) { 01568 printf("FtReturnValue: cannot allocate memory.\n"); 01569 return STATUS_NO_MEMORY; 01570 } 01571 01572 RtlInitString(&valueString, 01573 ValueName); 01574 RtlAnsiStringToUnicodeString(&unicodeValueName, 01575 &valueString, 01576 (BOOLEAN) TRUE); 01577 status = NtQueryValueKey(Handle, 01578 &unicodeValueName, 01579 KeyValueFullInformation, 01580 keyValueInformation, 01581 WORK_BUFFER_SIZE, 01582 &resultLength); 01583 RtlFreeUnicodeString(&unicodeValueName); 01584 01585 if (NT_SUCCESS(status)) { 01586 length = (resultLength > BufferLength) ? BufferLength : resultLength; 01587 internalBuffer = 01588 ((PUCHAR)keyValueInformation + keyValueInformation->DataOffset); 01589 01590 RtlMoveMemory(Buffer, internalBuffer, length); 01591 } 01592 free(keyValueInformation); 01593 return status; 01594 } 01595 01596 VOID 01597 DiskDump() 01598 01599 /*++ 01600 01601 Routine Description: 01602 01603 Formatted display of the disk registry information. 01604 01605 Arguments: 01606 01607 None. 01608 01609 Return Values: 01610 01611 None. 01612 01613 --*/ 01614 01615 { 01616 ULONG outerLoop; 01617 ULONG innerLoop; 01618 HANDLE handle; 01619 NTSTATUS status; 01620 PDISK_CONFIG_HEADER configHeader; 01621 PDISK_REGISTRY diskRegistry; 01622 PDISK_DESCRIPTION diskDescription; 01623 PDISK_PARTITION diskPartition; 01624 PFT_REGISTRY ftRegistry; 01625 PFT_DESCRIPTION ftDescription; 01626 PFT_MEMBER_DESCRIPTION ftMember; 01627 01628 status = FtOpenKey(&handle, 01629 DISK_REGISTRY_KEY); 01630 01631 if (!NT_SUCCESS(status)) { 01632 printf("Currently there is no key in the registry" 01633 " for the disk information.\n"); 01634 return; 01635 } 01636 01637 configHeader = (PDISK_CONFIG_HEADER) malloc(WORK_BUFFER_SIZE); 01638 if (configHeader == NULL) { 01639 printf("Unable to allocate memory for the disk registy information.\n"); 01640 return; 01641 } 01642 01643 RtlZeroMemory(configHeader, WORK_BUFFER_SIZE); 01644 01645 status = FtReturnValue(handle, 01646 (PUCHAR) DISK_REGISTRY_VALUE, 01647 (PUCHAR) configHeader, 01648 WORK_BUFFER_SIZE); 01649 NtClose(handle); 01650 01651 if (!NT_SUCCESS(status)) { 01652 printf("There is no disk registry information (%x)\n", status); 01653 free(configHeader); 01654 return; 01655 } 01656 01657 // 01658 // Print the header. 01659 // 01660 01661 printf("Registry header information:\n"); 01662 printf("\tVersion = 0x%x, Checksum = 0x%x\n", 01663 configHeader->Version, 01664 configHeader->CheckSum); 01665 printf("\tDisk info Offset = 0x%x, Size = 0x%x\n", 01666 configHeader->DiskInformationOffset, 01667 configHeader->DiskInformationSize); 01668 printf("\tFT info Offset = 0x%x, Size = 0x%x\n", 01669 configHeader->FtInformationOffset, 01670 configHeader->FtInformationSize); 01671 01672 // 01673 // Print the information on disks. 01674 // 01675 01676 diskRegistry = (PDISK_REGISTRY) 01677 ((PUCHAR) configHeader + configHeader->DiskInformationOffset); 01678 printf("\nDisk information for %d disks:\n", 01679 diskRegistry->NumberOfDisks); 01680 01681 diskDescription = &diskRegistry->Disks[0]; 01682 for (outerLoop = 0; 01683 outerLoop < diskRegistry->NumberOfDisks; 01684 outerLoop++) { 01685 01686 printf("\nDisk %d signature 0x%08x has %d partitions:\n", 01687 outerLoop, 01688 diskDescription->Signature, 01689 diskDescription->NumberOfPartitions); 01690 01691 printf(" Ln Type Start Length FtGrp Member\n"); 01692 for (innerLoop = 0; 01693 innerLoop < diskDescription->NumberOfPartitions; 01694 innerLoop++) { 01695 diskPartition = &diskDescription->Partitions[innerLoop]; 01696 printf(" %c: %c %1d %3d %08x:%08x %08x:%08x %5d %4d %s\n", 01697 (diskPartition->DriveLetter != '\0') ? 01698 diskPartition->DriveLetter : ' ', 01699 (diskPartition->AssignDriveLetter) ? 'A' : ' ', 01700 diskPartition->LogicalNumber, 01701 diskPartition->FtType, 01702 diskPartition->StartingOffset.HighPart, 01703 diskPartition->StartingOffset.LowPart, 01704 diskPartition->Length.HighPart, 01705 diskPartition->Length.LowPart, 01706 diskPartition->FtGroup, 01707 diskPartition->FtMember, 01708 (diskPartition->FtState == Orphaned) ? "Orphan" : 01709 (diskPartition->FtState == Regenerating) ? "Regen" : 01710 (diskPartition->FtState == Initializing) ? "Init" : ""); 01711 01712 } 01713 01714 diskDescription = (PDISK_DESCRIPTION) 01715 &diskDescription->Partitions[diskDescription->NumberOfPartitions]; 01716 } 01717 01718 // 01719 // Print the information for FT. 01720 // 01721 01722 if (configHeader->FtInformationSize == 0) { 01723 printf("There is no FT configuration.\n"); 01724 free(configHeader); 01725 return; 01726 } 01727 01728 ftRegistry = (PFT_REGISTRY) 01729 ((PUCHAR) configHeader + configHeader->FtInformationOffset); 01730 01731 printf("\nNumber of FT components = %d\n", 01732 ftRegistry->NumberOfComponents); 01733 01734 ftDescription = &ftRegistry->FtDescription[0]; 01735 for (outerLoop = 0; 01736 outerLoop < ftRegistry->NumberOfComponents; 01737 outerLoop++) { 01738 01739 printf("Component %d has %d members and is type %d\n", 01740 outerLoop, 01741 ftDescription->NumberOfMembers, 01742 ftDescription->Type); 01743 01744 printf(" State Signature Start Length #\n"); 01745 for (innerLoop = 0; 01746 innerLoop < ftDescription->NumberOfMembers; 01747 innerLoop++) { 01748 ftMember = &ftDescription->FtMemberDescription[innerLoop]; 01749 01750 diskPartition = (PDISK_PARTITION) 01751 ((PUCHAR) configHeader + ftMember->OffsetToPartitionInfo); 01752 01753 printf("%5x %2x %08x %08x:%08x %08x:%08x %d\n", 01754 ftMember->OffsetToPartitionInfo, 01755 ftMember->State, 01756 ftMember->Signature, 01757 diskPartition->StartingOffset.HighPart, 01758 diskPartition->StartingOffset.LowPart, 01759 diskPartition->Length.HighPart, 01760 diskPartition->Length.LowPart, 01761 ftMember->LogicalNumber); 01762 } 01763 01764 ftDescription = (PFT_DESCRIPTION) 01765 &ftDescription->FtMemberDescription[ftDescription->NumberOfMembers]; 01766 } 01767 } 01768 01769 01770 VOID 01771 ChangeMemberState( 01772 IN ULONG Type, 01773 IN ULONG Group, 01774 IN ULONG Member, 01775 IN FT_PARTITION_STATE NewState 01776 ) 01777 01778 /*++ 01779 01780 Routine Description: 01781 01782 Set the FT state for a partition. 01783 01784 Arguments: 01785 01786 Type - the FT type. 01787 Group - the FT Group number for that type. 01788 Member - the member number within the group. 01789 01790 Return Values: 01791 01792 None. 01793 01794 --*/ 01795 01796 { 01797 BOOLEAN writeBackRegistry = FALSE; 01798 HANDLE handle; 01799 ULONG outerLoop; 01800 ULONG innerLoop; 01801 NTSTATUS status; 01802 PDISK_CONFIG_HEADER configHeader; 01803 PDISK_REGISTRY diskRegistry; 01804 PDISK_DESCRIPTION diskDescription; 01805 PDISK_PARTITION partitionDescription; 01806 01807 status = FtOpenKey(&handle, 01808 DISK_REGISTRY_KEY); 01809 01810 if (!NT_SUCCESS(status)) { 01811 printf("Currently there is no key in the registry" 01812 " for the disk information.\n"); 01813 return; 01814 } 01815 01816 configHeader = (PDISK_CONFIG_HEADER) malloc(WORK_BUFFER_SIZE); 01817 if (configHeader == NULL) { 01818 printf("Unable to allocate memory for the disk registy information.\n"); 01819 NtClose(handle); 01820 return; 01821 } 01822 01823 RtlZeroMemory(configHeader, WORK_BUFFER_SIZE); 01824 01825 status = FtReturnValue(handle, 01826 (PUCHAR) DISK_REGISTRY_VALUE, 01827 (PUCHAR) configHeader, 01828 WORK_BUFFER_SIZE); 01829 01830 if (!NT_SUCCESS(status)) { 01831 printf("There is no disk registry information (%x)\n", status); 01832 free(configHeader); 01833 NtClose(handle); 01834 return; 01835 } 01836 01837 diskRegistry = (PDISK_REGISTRY) 01838 ((PUCHAR) configHeader + configHeader->DiskInformationOffset); 01839 01840 diskDescription = &diskRegistry->Disks[0]; 01841 for (outerLoop = 0; 01842 outerLoop < diskRegistry->NumberOfDisks; 01843 outerLoop++) { 01844 01845 for (innerLoop = 0; 01846 innerLoop < diskDescription->NumberOfPartitions; 01847 innerLoop++) { 01848 01849 partitionDescription = &diskDescription->Partitions[innerLoop]; 01850 01851 if ((partitionDescription->FtType == (FT_TYPE) Type) && 01852 (partitionDescription->FtGroup == (USHORT) Group) && 01853 (partitionDescription->FtMember == (USHORT) Member)) { 01854 01855 partitionDescription->FtState = NewState; 01856 writeBackRegistry = TRUE; 01857 break; 01858 } 01859 } 01860 01861 if (writeBackRegistry == TRUE) { 01862 ULONG size; 01863 01864 if (configHeader->FtInformationSize == 0) { 01865 printf("Seems a little odd to be setting FT state " // no comma 01866 "with no FT information...\n"); 01867 size = configHeader->DiskInformationOffset + 01868 configHeader->DiskInformationSize; 01869 } else { 01870 size = configHeader->FtInformationOffset + 01871 configHeader->FtInformationSize; 01872 } 01873 01874 (VOID) FtSetValue(handle, 01875 (PUCHAR) DISK_REGISTRY_VALUE, 01876 (PUCHAR) configHeader, 01877 size, 01878 REG_BINARY); 01879 break; 01880 } 01881 diskDescription = (PDISK_DESCRIPTION) 01882 &diskDescription->Partitions[diskDescription->NumberOfPartitions]; 01883 } 01884 01885 NtClose(handle); 01886 free(configHeader); 01887 } 01888 01889 01890 VOID 01891 RestoreOrphan( 01892 IN ULONG Type, 01893 IN ULONG Group, 01894 IN ULONG Member 01895 ) 01896 01897 /*++ 01898 01899 Routine Description: 01900 01901 Set the FT state for a partition back to Healthy. 01902 01903 Arguments: 01904 01905 Type - the FT type. 01906 Group - the FT Group number for that type. 01907 Member - the member number within the group. 01908 01909 Return Values: 01910 01911 None. 01912 01913 --*/ 01914 01915 { 01916 ChangeMemberState(Type, 01917 Group, 01918 Member, 01919 Healthy); 01920 } 01921 01922 01923 VOID 01924 OrphanMember( 01925 IN ULONG Type, 01926 IN ULONG Group, 01927 IN ULONG Member 01928 ) 01929 01930 /*++ 01931 01932 Routine Description: 01933 01934 Set the FT state for a partition to Orphaned. 01935 01936 Arguments: 01937 01938 Type - the FT type. 01939 Group - the FT Group number for that type. 01940 Member - the member number within the group. 01941 01942 Return Values: 01943 01944 None. 01945 01946 --*/ 01947 01948 { 01949 ChangeMemberState(Type, 01950 Group, 01951 Member, 01952 Orphaned); 01953 } 01954 01955 01956 VOID 01957 RegenerateMember( 01958 IN ULONG Type, 01959 IN ULONG Group, 01960 IN ULONG Member 01961 ) 01962 01963 /*++ 01964 01965 Routine Description: 01966 01967 Set the FT state for a partition to regenerate. 01968 01969 Arguments: 01970 01971 Type - the FT type. 01972 Group - the FT Group number for that type. 01973 Member - the member number within the group. 01974 01975 Return Values: 01976 01977 None. 01978 01979 --*/ 01980 01981 { 01982 ChangeMemberState(Type, 01983 Group, 01984 Member, 01985 Regenerating); 01986 } 01987 01988 01989 VOID 01990 FixDisk() 01991 01992 /*++ 01993 01994 Routine Description: 01995 01996 Fix the disk signatures in the registry. 01997 01998 Arguments: 01999 02000 None. 02001 02002 Return Values: 02003 02004 None. 02005 02006 --*/ 02007 02008 { 02009 ULONG outerLoop; 02010 ULONG innerLoop; 02011 ULONG length; 02012 HANDLE handle; 02013 NTSTATUS status; 02014 PDISK_CONFIG_HEADER configHeader; 02015 PDISK_REGISTRY diskRegistry; 02016 PDISK_DESCRIPTION diskDescription; 02017 PFT_REGISTRY ftRegistry; 02018 PFT_DESCRIPTION ftDescription; 02019 PFT_MEMBER_DESCRIPTION ftMember; 02020 UCHAR prompt[128]; 02021 PUCHAR hexString; 02022 BOOLEAN changed = FALSE; 02023 02024 status = FtOpenKey(&handle, 02025 DISK_REGISTRY_KEY); 02026 02027 if (!NT_SUCCESS(status)) { 02028 printf("Currently there is no key in the registry" 02029 " for the disk information.\n"); 02030 return; 02031 } 02032 02033 configHeader = (PDISK_CONFIG_HEADER) malloc(WORK_BUFFER_SIZE); 02034 if (configHeader == NULL) { 02035 printf("Unable to allocate memory for the disk registy information.\n"); 02036 NtClose(handle); 02037 return; 02038 } 02039 02040 RtlZeroMemory(configHeader, WORK_BUFFER_SIZE); 02041 02042 status = FtReturnValue(handle, 02043 (PUCHAR) DISK_REGISTRY_VALUE, 02044 (PUCHAR) configHeader, 02045 WORK_BUFFER_SIZE); 02046 02047 if (!NT_SUCCESS(status)) { 02048 printf("There is no disk registry information (%x)\n", status); 02049 free(configHeader); 02050 NtClose(handle); 02051 return; 02052 } 02053 02054 diskRegistry = (PDISK_REGISTRY) 02055 ((PUCHAR) configHeader + configHeader->DiskInformationOffset); 02056 printf("\nDisk information for %d disks:\n", 02057 diskRegistry->NumberOfDisks); 02058 02059 diskDescription = &diskRegistry->Disks[0]; 02060 for (outerLoop = 0; 02061 outerLoop < diskRegistry->NumberOfDisks; 02062 outerLoop++) { 02063 02064 sprintf(prompt, 02065 "\nDisk %d signature 0x%08x = ", 02066 outerLoop, 02067 diskDescription->Signature); 02068 02069 hexString = GetArgumentString((BOOLEAN) FALSE, 02070 prompt, 02071 (BOOLEAN) TRUE); 02072 02073 if (hexString != NULL) { 02074 02075 changed = ProcessHex(hexString, &diskDescription->Signature); 02076 } 02077 02078 diskDescription = (PDISK_DESCRIPTION) 02079 &diskDescription->Partitions[diskDescription->NumberOfPartitions]; 02080 } 02081 02082 // 02083 // Print the information for FT. 02084 // 02085 02086 if (configHeader->FtInformationSize == 0) { 02087 printf("There is no FT configuration.\n"); 02088 free(configHeader); 02089 NtClose(handle); 02090 return; 02091 } 02092 02093 ftRegistry = (PFT_REGISTRY) 02094 ((PUCHAR) configHeader + configHeader->FtInformationOffset); 02095 02096 printf("\nNumber of FT components = %d\n", 02097 ftRegistry->NumberOfComponents); 02098 02099 ftDescription = &ftRegistry->FtDescription[0]; 02100 for (outerLoop = 0; 02101 outerLoop < ftRegistry->NumberOfComponents; 02102 outerLoop++) { 02103 02104 printf("Component %d has %d members and is type %d\n", 02105 outerLoop, 02106 ftDescription->NumberOfMembers, 02107 ftDescription->Type); 02108 02109 for (innerLoop = 0; 02110 innerLoop < ftDescription->NumberOfMembers; 02111 innerLoop++) { 02112 ftMember = &ftDescription->FtMemberDescription[innerLoop]; 02113 02114 sprintf(prompt, 02115 "FT Member Signature 0x%x = ", 02116 ftMember->Signature); 02117 02118 hexString = GetArgumentString((BOOLEAN) FALSE, 02119 prompt, 02120 (BOOLEAN) TRUE); 02121 02122 if (hexString != NULL) { 02123 02124 changed = ProcessHex(hexString, &ftMember->Signature); 02125 } 02126 } 02127 02128 ftDescription = (PFT_DESCRIPTION) 02129 &ftDescription->FtMemberDescription[ftDescription->NumberOfMembers]; 02130 } 02131 02132 if (changed == TRUE) { 02133 02134 printf("Attempting to update registry information.\n"); 02135 02136 // 02137 // Delete the current registry value and write the new one. 02138 // 02139 02140 status = FtDeleteValue(handle, 02141 DISK_REGISTRY_VALUE); 02142 02143 if (!NT_SUCCESS(status)) { 02144 printf("Could not delete value (0x%x).\n", status); 02145 } else { 02146 02147 length = (ULONG) ((PCHAR)ftDescription - (PUCHAR)configHeader); 02148 status = FtSetValue(handle, 02149 DISK_REGISTRY_VALUE, 02150 configHeader, 02151 length, 02152 REG_BINARY); 02153 if (!NT_SUCCESS(status)) { 02154 printf("Could not write value (0x%x)\n.", status); 02155 } 02156 } 02157 } 02158 02159 NtClose(handle); 02160 } 02161 02162 PDISK_CONFIG_HEADER 02163 GetDiskInfo() 02164 02165 /*++ 02166 02167 --*/ 02168 02169 { 02170 HANDLE handle; 02171 ULONG length; 02172 NTSTATUS status; 02173 PDISK_CONFIG_HEADER configHeader; 02174 02175 status = FtOpenKey(&handle, 02176 DISK_REGISTRY_KEY); 02177 02178 if (!NT_SUCCESS(status)) { 02179 printf("Currently there is no key in the registry" 02180 " for the disk information.\n"); 02181 return NULL; 02182 } 02183 02184 configHeader = (PDISK_CONFIG_HEADER) malloc(WORK_BUFFER_SIZE); 02185 if (configHeader == NULL) { 02186 printf("Unable to allocate memory for the disk registy information.\n"); 02187 NtClose(handle); 02188 return NULL; 02189 } 02190 02191 RtlZeroMemory(configHeader, WORK_BUFFER_SIZE); 02192 02193 status = FtReturnValue(handle, 02194 (PUCHAR) DISK_REGISTRY_VALUE, 02195 (PUCHAR) configHeader, 02196 WORK_BUFFER_SIZE); 02197 NtClose(handle); 02198 02199 if (!NT_SUCCESS(status)) { 02200 printf("There is no disk registry information (%x)\n", status); 02201 free(configHeader); 02202 return NULL; 02203 } 02204 02205 return configHeader; 02206 } 02207 02208 02209 BOOLEAN 02210 CreateFtMember( 02211 IN PDISK_CONFIG_HEADER ConfigHeader, 02212 IN ULONG Disk, 02213 IN ULONG Partition, 02214 IN ULONG Type, 02215 IN ULONG Group, 02216 IN ULONG Member 02217 ) 02218 02219 /*++ 02220 02221 --*/ 02222 02223 { 02224 ULONG innerLoop; 02225 ULONG outerLoop; 02226 ULONG length; 02227 NTSTATUS status; 02228 PDISK_REGISTRY diskRegistry; 02229 PDISK_DESCRIPTION diskDescription; 02230 PDISK_PARTITION diskPartition; 02231 02232 diskRegistry = (PDISK_REGISTRY) 02233 ((PUCHAR) ConfigHeader + ConfigHeader->DiskInformationOffset); 02234 diskDescription = &diskRegistry->Disks[0]; 02235 02236 // 02237 // Have to walk the disk information by hand to find a match on 02238 // disk number and partition 02239 // 02240 02241 for (outerLoop = 0; 02242 outerLoop < diskRegistry->NumberOfDisks; 02243 outerLoop++) { 02244 02245 if (outerLoop == Disk) { 02246 for (innerLoop = 0; 02247 innerLoop < diskDescription->NumberOfPartitions; 02248 innerLoop++) { 02249 diskPartition = &diskDescription->Partitions[innerLoop]; 02250 02251 if (diskPartition->LogicalNumber == Partition) { 02252 02253 // 02254 // Found a match. 02255 // 02256 02257 diskPartition->FtType = Type; 02258 diskPartition->FtMember = Member; 02259 diskPartition->FtGroup = Group; 02260 diskPartition->FtState = Healthy; 02261 diskPartition->AssignDriveLetter = FALSE; 02262 return TRUE; 02263 } 02264 } 02265 } 02266 02267 diskDescription = (PDISK_DESCRIPTION) 02268 &diskDescription->Partitions[diskDescription->NumberOfPartitions]; 02269 } 02270 02271 // 02272 // Didn't find it. 02273 // 02274 02275 return FALSE; 02276 } 02277 02278 02279 #define DRIVER_KEY "\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services" 02280 02281 #define TYPE_KEY "Type" 02282 #define START_KEY "Start" 02283 #define GROUP_KEY "Group" 02284 #define DEPENDENCIES "DependOnGroup" 02285 02286 #if 0 02287 VOID 02288 DisplayLoadInformation( 02289 IN PUNICODE_STRING DriverKey 02290 ) 02291 02292 /*++ 02293 02294 Routine Description: 02295 02296 02297 Arguments: 02298 02299 DriverKey - a Unicode string pointer for the driver key name. 02300 02301 Return Value: 02302 02303 None. 02304 02305 --*/ 02306 02307 { 02308 HANDLE keyHandle; 02309 UNICODE_STRING unicodeKeyName; 02310 UNICODE_STRING unicodeValueName; 02311 ULONG resultLength; 02312 PKEY_VALUE_FULL_INFORMATION keyValueInformation; 02313 02314 resultLength = WORK_BUFFER_SIZE; 02315 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION)malloc(WORK_BUFFER_SIZE); 02316 02317 // 02318 // Type 02319 // 02320 02321 // 02322 // Start 02323 // 02324 02325 // 02326 // Group 02327 // 02328 02329 // 02330 // DependOnGroup 02331 // 02332 02333 while (1) { 02334 02335 RtlZeroMemory(keyValueInformation, resultLength); 02336 status = NtEnumerateValueKey(KeyHandle, 02337 0, 02338 KeyValueFullInformation, 02339 keyValueInformation, 02340 resultLength, 02341 &resultLength); 02342 02343 if (status == STATUS_BUFFER_OVERFLOW) { 02344 free(keyValueInformation); 02345 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) 02346 malloc(resultLength + 10); 02347 } else { 02348 break; 02349 } 02350 } 02351 02352 free(keyValueInformation); 02353 NtClose(keyHandle); 02354 } 02355 #else 02356 VOID 02357 DisplayLoadInformation( 02358 IN PUCHAR DriverKey 02359 ) 02360 { 02361 UNREFERENCED_PARAMETER(DriverKey); 02362 } 02363 #endif 02364 02365 02366 02367 #define TEMP_BUFFER_SIZE 256 02368 VOID 02369 ListDrivers() 02370 02371 /*++ 02372 02373 Routine Description: 02374 02375 Got to the load list for the drivers, interpret and display what is there. 02376 02377 Arguments: 02378 02379 None. 02380 02381 Return Value: 02382 02383 NONE 02384 02385 --*/ 02386 02387 { 02388 int index; 02389 NTSTATUS status; 02390 HANDLE keyHandle; 02391 ULONG resultLength; 02392 UCHAR tempBuffer[TEMP_BUFFER_SIZE]; 02393 ANSI_STRING ansiString; 02394 UNICODE_STRING unicodeValueName; 02395 PKEY_BASIC_INFORMATION keyInformation; 02396 02397 keyInformation = (PKEY_BASIC_INFORMATION)malloc(WORK_BUFFER_SIZE); 02398 02399 status = FtOpenKey(&keyHandle, DRIVER_KEY); 02400 02401 if (!NT_SUCCESS(status)) { 02402 02403 printf("Could not open Services key (0x%x).\n", status); 02404 return; 02405 } 02406 02407 for (index = 0; TRUE; index++) { 02408 02409 RtlZeroMemory(keyInformation, WORK_BUFFER_SIZE); 02410 02411 status = NtEnumerateKey(keyHandle, 02412 index, 02413 KeyBasicInformation, 02414 keyInformation, 02415 WORK_BUFFER_SIZE, 02416 &resultLength); 02417 02418 if (status == STATUS_NO_MORE_ENTRIES) { 02419 02420 break; 02421 02422 } else if (!NT_SUCCESS(status)) { 02423 02424 printf("readreg: Error on Enumerate status = %x\n", status); 02425 break; 02426 02427 } 02428 02429 unicodeValueName.Length = (USHORT)keyInformation->NameLength; 02430 unicodeValueName.MaximumLength = (USHORT)keyInformation->NameLength; 02431 unicodeValueName.Buffer = (PWSTR)&keyInformation->Name[0]; 02432 02433 ansiString.MaximumLength = TEMP_BUFFER_SIZE; 02434 ansiString.Length = 0L; 02435 ansiString.Buffer = &tempBuffer[0]; 02436 02437 RtlUnicodeStringToAnsiString(&ansiString, 02438 &unicodeValueName, 02439 (BOOLEAN) FALSE); 02440 02441 // 02442 // Now have the key name for the driver - concatenate it and 02443 // call the routine to display what is in the key. 02444 // 02445 02446 sprintf(WorkingDirectory, 02447 "%s\\%s", 02448 DRIVER_KEY, 02449 tempBuffer); 02450 02451 DisplayLoadInformation(WorkingDirectory); 02452 } 02453 02454 free(keyInformation); 02455 NtClose(keyHandle); 02456 } 02457 02458 02459 VOID 02460 main() 02461 02462 /*++ 02463 02464 Routine Description: 02465 02466 The main entry point for the user process. 02467 This process will prompt the user for the action desired. This 02468 includes starting performance, stopping performance, and retreiving 02469 performance data collected by the FT driver. 02470 02471 Arguments: 02472 02473 Command line: 02474 No options. 02475 02476 Return Value: 02477 02478 NONE 02479 02480 --*/ 02481 02482 { 02483 NTSTATUS status; 02484 BOOLEAN batch; 02485 PUCHAR argumentString; 02486 int commandCode; 02487 HANDLE keyHandle; 02488 02489 02490 status = FtOpenKey(&keyHandle, REGISTRY_BASE); 02491 02492 if (!NT_SUCCESS(status)) { 02493 02494 printf("readreg: Unable to open registry base (0x%x)\n", status); 02495 exit(1); 02496 } 02497 02498 sprintf(CurrentDirectory, 02499 REGISTRY_BASE); 02500 02501 // 02502 // See if we are connected to CON 02503 // 02504 02505 batch = FALSE; 02506 // batch = (BOOLEAN)(!isatty(0)); 02507 02508 if (!batch) { 02509 printf("FT registry edit utility. %s:\n", Version); 02510 } 02511 02512 while(1) { 02513 while ((commandCode = GetCommand(batch, 02514 &argumentString)) == INVALID) { 02515 02516 // 02517 // Continue until we get a valid command. 02518 // 02519 02520 } 02521 02522 if (Debug) { 02523 printf("Command code == %d, argumentString = %s\n", 02524 commandCode, 02525 (argumentString == NULL) ? "(none)" : argumentString); 02526 } 02527 02528 switch (commandCode) { 02529 02530 case DIRLONG: 02531 02532 Directory(keyHandle, (BOOLEAN) TRUE); 02533 break; 02534 02535 case DIR: 02536 02537 Directory(keyHandle, (BOOLEAN) FALSE); 02538 break; 02539 02540 case CREATE: 02541 { 02542 ULONG index; 02543 PUCHAR keyClass; 02544 BOOLEAN classAllocated = FALSE; 02545 02546 if (argumentString == NULL) { 02547 argumentString = GetArgumentString(batch, 02548 "Key Name = ", 02549 (BOOLEAN) FALSE); 02550 } 02551 02552 if (argumentString == NULL) { 02553 break; 02554 } 02555 02556 sprintf(WorkingDirectory, 02557 "%s\\%s", 02558 CurrentDirectory, 02559 argumentString); 02560 02561 argumentString = GetArgumentString(batch, 02562 "Key Class = ", 02563 (BOOLEAN) FALSE); 02564 02565 if (argumentString == NULL) { 02566 keyClass = "Default Class"; 02567 } else { 02568 keyClass = (PUCHAR) malloc(strlen(argumentString) + FUDGE); 02569 classAllocated = TRUE; 02570 02571 sprintf(keyClass, 02572 "%s", 02573 argumentString); 02574 } 02575 02576 argumentString = GetArgumentString(batch, 02577 "Index = ", 02578 (BOOLEAN) TRUE); 02579 02580 if (argumentString == NULL) { 02581 index = 1; 02582 } else { 02583 index = ParseArgumentNumeric(&argumentString); 02584 } 02585 02586 if (Debug) { 02587 printf("Creating key %s, index %d with class %s\n", 02588 WorkingDirectory, 02589 index, 02590 keyClass); 02591 } 02592 02593 status = FtCreateKey(WorkingDirectory, 02594 keyClass, 02595 index); 02596 02597 if (!NT_SUCCESS(status)) { 02598 02599 printf("Could not create key %s (0x%x).\n", 02600 WorkingDirectory, 02601 status); 02602 } 02603 02604 if (classAllocated == TRUE) { 02605 free(keyClass); 02606 } 02607 02608 break; 02609 } 02610 02611 case LIST: 02612 02613 List(keyHandle, 02614 argumentString); 02615 break; 02616 02617 case CHDIR: 02618 02619 NtClose(keyHandle); 02620 02621 if (argumentString == NULL) { 02622 02623 argumentString = GetArgumentString(batch, 02624 "New location = ", 02625 (BOOLEAN) TRUE); 02626 } 02627 02628 if (argumentString != NULL) { 02629 02630 if (*argumentString == '\\') { 02631 02632 // 02633 // Root relative string. 02634 // Use text provided (i.e. %s is to avoid user crashing 02635 // by putting %s in the string). 02636 // 02637 02638 sprintf(WorkingDirectory, 02639 "%s", 02640 argumentString); 02641 02642 } else { 02643 02644 while ((*argumentString == '.') && 02645 (*(argumentString + 1) == '.')) { 02646 02647 if ((*(argumentString + 2) == '\\') || 02648 (*(argumentString + 2) == '\0')) { 02649 02650 PUCHAR cptr = CurrentDirectory; 02651 02652 // 02653 // move argumentString past ".." 02654 // 02655 02656 argumentString += 2; 02657 02658 // 02659 // Find end of current directory. 02660 // 02661 02662 while (*cptr != '\0') { 02663 cptr++; 02664 } 02665 02666 // 02667 // Backup to last component. 02668 // 02669 02670 while (*cptr != '\\') { 02671 cptr--; 02672 } 02673 02674 if (cptr == CurrentDirectory) { 02675 02676 // 02677 // Cannot backup anymore. Continue parsing 02678 // argument. 02679 // 02680 02681 continue; 02682 } 02683 02684 // 02685 // Remove component from path. 02686 // 02687 02688 *cptr = '\0'; 02689 02690 if (*argumentString == '\0') { 02691 02692 // 02693 // All done with argument. 02694 // 02695 02696 break; 02697 } 02698 02699 // 02700 // Step around backslash. 02701 // 02702 02703 argumentString++; 02704 02705 } else { 02706 02707 // 02708 // Assume it is a real name. 02709 // 02710 02711 break; 02712 } 02713 } 02714 02715 if (*argumentString != '\0') { 02716 sprintf(WorkingDirectory, 02717 "%s\\%s", 02718 CurrentDirectory, 02719 argumentString); 02720 } else { 02721 sprintf(WorkingDirectory, 02722 "%s", 02723 CurrentDirectory); 02724 } 02725 } 02726 02727 status = FtOpenKey(&keyHandle, 02728 WorkingDirectory); 02729 02730 if (NT_SUCCESS(status)) { 02731 02732 sprintf(CurrentDirectory, 02733 "%s", 02734 WorkingDirectory); 02735 } else { 02736 02737 (VOID) FtOpenKey(&keyHandle, 02738 CurrentDirectory); 02739 02740 // 02741 // No error checks because this was opened once before. 02742 // 02743 } 02744 02745 } 02746 02747 break; 02748 02749 case HELP: 02750 { 02751 int i; 02752 02753 printf("Valid commands are:\n"); 02754 02755 for (i = 0; Commands[i] != NULL; i++) { 02756 printf(" %10s - %s\n", 02757 Commands[i], 02758 CommandHelp[CommandMap[i]]); 02759 } 02760 break; 02761 } 02762 02763 case QUIT: 02764 02765 exit(0); 02766 break; 02767 02768 case DDEBUG: 02769 02770 if (argumentString == NULL) { 02771 02772 if (Debug) { 02773 02774 printf("Debug turned off.\n"); 02775 Debug = 0; 02776 } else { 02777 02778 Debug = 1; 02779 } 02780 } else { 02781 02782 Debug = atoi(argumentString); 02783 printf("Debug set to %d\n", Debug); 02784 } 02785 break; 02786 02787 case SETVALUE: 02788 { 02789 int i; 02790 BOOLEAN convertToUnicode = FALSE; 02791 PUCHAR valueName; 02792 PUCHAR valueData; 02793 ULONG valueLength; 02794 ULONG valueWord; 02795 PVOID valuePtr; 02796 ULONG type = DEFAULT_TYPE; 02797 STRING valueString; 02798 UNICODE_STRING unicodeValue; 02799 BOOLEAN dataAllocated = FALSE; 02800 BOOLEAN unicodeAllocated = FALSE; 02801 02802 if (argumentString == NULL) { 02803 02804 argumentString = GetArgumentString(batch, 02805 "Value Name = ", 02806 (BOOLEAN) FALSE); 02807 } 02808 02809 if (argumentString == NULL) { 02810 02811 break; 02812 } 02813 02814 valueName = (PUCHAR) malloc(strlen(argumentString) + FUDGE); 02815 02816 sprintf(valueName, 02817 "%s", 02818 argumentString); 02819 02820 // 02821 // print a help banner on type and get the type. 02822 // 02823 02824 for (i = 0; TypeNames[i] != NULL; i++) { 02825 02826 printf("%d - %s\n", TypeNumbers[i], TypeNames[i]); 02827 } 02828 printf("# - Other numbers are user defined\n"); 02829 argumentString = GetArgumentString(batch, 02830 "Numeric value for type = ", 02831 (BOOLEAN) TRUE); 02832 02833 if (argumentString != NULL) { 02834 type = ParseArgumentNumeric(&argumentString); 02835 } 02836 02837 switch(type) 02838 { 02839 default: 02840 case REG_SZ: 02841 if (type == REG_SZ) { 02842 convertToUnicode = TRUE; 02843 printf("Typed in string will be converted to unicode...\n"); 02844 argumentString = GetArgumentString(batch, 02845 "Value Data = ", 02846 (BOOLEAN) FALSE); 02847 } else { 02848 printf("For now the data must be typed in...\n"); 02849 argumentString = GetArgumentString(batch, 02850 "Value Data = ", 02851 (BOOLEAN) FALSE); 02852 } 02853 02854 if (argumentString == NULL) { 02855 valueData = "Default Data"; 02856 valueLength = strlen(valueData); 02857 } else { 02858 valueData = (PUCHAR) malloc(strlen(argumentString) + FUDGE); 02859 dataAllocated = TRUE; 02860 sprintf(valueData, 02861 "%s", 02862 argumentString); 02863 if (convertToUnicode == TRUE) { 02864 RtlInitString(&valueString, 02865 valueData); 02866 RtlAnsiStringToUnicodeString(&unicodeValue, 02867 &valueString, 02868 (BOOLEAN) TRUE); 02869 unicodeAllocated = TRUE; 02870 valueLength = unicodeValue.Length + 2; 02871 } else { 02872 valueLength = strlen(valueData); 02873 } 02874 } 02875 02876 break; 02877 02878 case REG_DWORD: 02879 argumentString = GetArgumentString(batch, 02880 "Value Data Word = ", 02881 (BOOLEAN) TRUE); 02882 if (argumentString == NULL) { 02883 valueWord = 0; 02884 } else { 02885 valueWord = ParseArgumentNumeric(&argumentString); 02886 } 02887 02888 valueLength = sizeof(ULONG); 02889 break; 02890 } 02891 02892 switch (type) { 02893 02894 case REG_DWORD: 02895 valuePtr = (PVOID) &valueWord; 02896 break; 02897 02898 case REG_SZ: 02899 valuePtr = (PVOID) unicodeValue.Buffer; 02900 break; 02901 02902 default: 02903 valuePtr = (PVOID) valueData; 02904 break; 02905 } 02906 status = FtSetValue(keyHandle, 02907 valueName, 02908 valuePtr, 02909 valueLength, 02910 type); 02911 02912 if (!NT_SUCCESS(status)) { 02913 printf("Could not set value %s (0x%x).\n", valueName, status); 02914 } 02915 02916 free(valueName); 02917 if (dataAllocated == TRUE) { 02918 free(valueData); 02919 } 02920 if (unicodeAllocated == TRUE) { 02921 RtlFreeUnicodeString(&unicodeValue); 02922 } 02923 break; 02924 } 02925 02926 case DELKEY: 02927 { 02928 if (argumentString == NULL) { 02929 02930 argumentString = GetArgumentString(batch, 02931 "Key Name = ", 02932 (BOOLEAN) TRUE); 02933 } 02934 02935 if (argumentString == NULL) { 02936 02937 break; 02938 } 02939 02940 sprintf(WorkingDirectory, 02941 "%s\\%s", 02942 CurrentDirectory, 02943 argumentString); 02944 02945 status = FtDeleteKey(WorkingDirectory); 02946 02947 if (!NT_SUCCESS(status)) { 02948 printf("Unable to delete key %s (0x%x)\n", 02949 WorkingDirectory, 02950 status); 02951 } 02952 02953 break; 02954 } 02955 02956 case DELVALUE: 02957 { 02958 if (argumentString == NULL) { 02959 02960 argumentString = GetArgumentString(batch, 02961 "Key Name = ", 02962 (BOOLEAN) TRUE); 02963 } 02964 02965 if (argumentString == NULL) { 02966 02967 break; 02968 } 02969 02970 status = FtDeleteValue(keyHandle, 02971 argumentString); 02972 02973 if (!NT_SUCCESS(status)) { 02974 02975 printf("Unable to delete value %s (0x%x)\n", 02976 argumentString, 02977 status); 02978 } 02979 break; 02980 } 02981 02982 case INLONG: 02983 DumpControl = InLongs; 02984 break; 02985 02986 case INSHORT: 02987 DumpControl = InShorts; 02988 break; 02989 02990 case INBYTE: 02991 DumpControl = InBytes; 02992 break; 02993 02994 case DUMP: 02995 02996 if (ForceDump) { 02997 ForceDump = 0; 02998 } else { 02999 ForceDump++; 03000 } 03001 break; 03002 03003 case DISKREG: 03004 DiskDump(); 03005 break; 03006 03007 case FIXDISK: 03008 FixDisk(); 03009 break; 03010 03011 case RESTORE: 03012 { 03013 ULONG type; 03014 ULONG group; 03015 ULONG member; 03016 03017 printf("FT types that can be restored are:\n"); 03018 printf("\t%d - for Mirrors\n", Mirror); 03019 printf("\t%d - for Stripes with parity\n", StripeWithParity); 03020 03021 // 03022 // Get the type 03023 // 03024 03025 if (argumentString == NULL) { 03026 argumentString = GetArgumentString(batch, 03027 "FT volume type = ", 03028 (BOOLEAN) TRUE); 03029 } 03030 if (argumentString != NULL) { 03031 type = ParseArgumentNumeric(&argumentString); 03032 } else { 03033 break; 03034 } 03035 03036 // 03037 // Get the group 03038 // 03039 03040 if (argumentString == NULL) { 03041 argumentString = GetArgumentString(batch, 03042 "FT group number = ", 03043 (BOOLEAN) TRUE); 03044 } 03045 if (argumentString != NULL) { 03046 group = ParseArgumentNumeric(&argumentString); 03047 } else { 03048 break; 03049 } 03050 03051 // 03052 // Get the member 03053 // 03054 03055 if (argumentString == NULL) { 03056 argumentString = GetArgumentString(batch, 03057 "FT member number = ", 03058 (BOOLEAN) TRUE); 03059 } 03060 if (argumentString != NULL) { 03061 member = ParseArgumentNumeric(&argumentString); 03062 } else { 03063 break; 03064 } 03065 03066 RestoreOrphan(type, group, member); 03067 break; 03068 } 03069 03070 case DRIVERS: 03071 NotImplemented(); 03072 // ListDrivers(); 03073 break; 03074 03075 case ORPHAN: 03076 { 03077 ULONG type; 03078 ULONG group; 03079 ULONG member; 03080 03081 printf("FT types that can be orphaned are:\n"); 03082 printf("\t%d - for Mirrors\n", Mirror); 03083 printf("\t%d - for Stripes with parity\n", StripeWithParity); 03084 03085 // 03086 // Get the type 03087 // 03088 03089 if (argumentString == NULL) { 03090 argumentString = GetArgumentString(batch, 03091 "FT volume type = ", 03092 (BOOLEAN) TRUE); 03093 } 03094 if (argumentString != NULL) { 03095 type = ParseArgumentNumeric(&argumentString); 03096 } else { 03097 break; 03098 } 03099 03100 // 03101 // Get the group 03102 // 03103 03104 if (argumentString == NULL) { 03105 argumentString = GetArgumentString(batch, 03106 "FT group number = ", 03107 (BOOLEAN) TRUE); 03108 } 03109 if (argumentString != NULL) { 03110 group = ParseArgumentNumeric(&argumentString); 03111 } else { 03112 break; 03113 } 03114 03115 // 03116 // Get the member 03117 // 03118 03119 if (argumentString == NULL) { 03120 argumentString = GetArgumentString(batch, 03121 "FT member number = ", 03122 (BOOLEAN) TRUE); 03123 } 03124 if (argumentString != NULL) { 03125 member = ParseArgumentNumeric(&argumentString); 03126 } else { 03127 break; 03128 } 03129 03130 OrphanMember(type, group, member); 03131 break; 03132 } 03133 03134 case REGEN: 03135 { 03136 ULONG type; 03137 ULONG group; 03138 ULONG member; 03139 03140 printf("FT types that can be regenerated are:\n"); 03141 printf("\t%d - for Mirrors\n", Mirror); 03142 printf("\t%d - for Stripes with parity\n", StripeWithParity); 03143 03144 // 03145 // Get the type 03146 // 03147 03148 if (argumentString == NULL) { 03149 argumentString = GetArgumentString(batch, 03150 "FT volume type = ", 03151 (BOOLEAN) TRUE); 03152 } 03153 if (argumentString != NULL) { 03154 type = ParseArgumentNumeric(&argumentString); 03155 } else { 03156 break; 03157 } 03158 03159 // 03160 // Get the group 03161 // 03162 03163 if (argumentString == NULL) { 03164 argumentString = GetArgumentString(batch, 03165 "FT group number = ", 03166 (BOOLEAN) TRUE); 03167 } 03168 if (argumentString != NULL) { 03169 group = ParseArgumentNumeric(&argumentString); 03170 } else { 03171 break; 03172 } 03173 03174 // 03175 // Get the member 03176 // 03177 03178 if (argumentString == NULL) { 03179 argumentString = GetArgumentString(batch, 03180 "FT member number = ", 03181 (BOOLEAN) TRUE); 03182 } 03183 if (argumentString != NULL) { 03184 member = ParseArgumentNumeric(&argumentString); 03185 } else { 03186 break; 03187 } 03188 03189 RegenerateMember(type, group, member); 03190 break; 03191 } 03192 03193 case INIT: 03194 { 03195 ULONG type; 03196 ULONG group; 03197 ULONG member; 03198 03199 printf("Only stripes with parity are initialized.\n"); 03200 03201 // 03202 // Get the group 03203 // 03204 03205 if (argumentString == NULL) { 03206 argumentString = GetArgumentString(batch, 03207 "Parity stripe group number = ", 03208 (BOOLEAN) TRUE); 03209 } 03210 if (argumentString != NULL) { 03211 group = ParseArgumentNumeric(&argumentString); 03212 } else { 03213 break; 03214 } 03215 03216 ChangeMemberState(StripeWithParity, 03217 group, 03218 0, 03219 Initializing); 03220 break; 03221 } 03222 03223 case MAKEFT: 03224 { 03225 ULONG type; 03226 ULONG group; 03227 ULONG member; 03228 ULONG disk; 03229 ULONG partition; 03230 PDISK_CONFIG_HEADER configHeader; 03231 BOOLEAN doUpdate = TRUE; 03232 03233 configHeader = GetDiskInfo(); 03234 if (configHeader == NULL) { 03235 break; 03236 } 03237 printf("\t%d for Mirrors\n", Mirror); 03238 printf("\t%d for Stripe Set\n", Stripe); 03239 printf("\t%d for Stripe with parity\n", StripeWithParity); 03240 printf("\t%d for Volume Set\n", VolumeSet); 03241 03242 if (argumentString == NULL) { 03243 argumentString = GetArgumentString(batch, 03244 "Which FT set to create? ", 03245 (BOOLEAN) TRUE); 03246 } 03247 if (argumentString != NULL) { 03248 type = ParseArgumentNumeric(&argumentString); 03249 } else { 03250 break; 03251 } 03252 03253 if (argumentString == NULL) { 03254 argumentString = GetArgumentString(batch, 03255 "Please give an FT group # - ", 03256 (BOOLEAN) TRUE); 03257 } 03258 if (argumentString != NULL) { 03259 group = ParseArgumentNumeric(&argumentString); 03260 } else { 03261 break; 03262 } 03263 03264 for (member = 0; TRUE; member++) { 03265 printf("Information for member %d\n", member); 03266 03267 if (argumentString == NULL) { 03268 argumentString = GetArgumentString(batch, 03269 "Disk Number = ", 03270 (BOOLEAN) TRUE); 03271 } 03272 03273 if (argumentString != NULL) { 03274 disk = ParseArgumentNumeric(&argumentString); 03275 } else { 03276 break; 03277 } 03278 03279 if (argumentString == NULL) { 03280 argumentString = GetArgumentString(batch, 03281 "Partition Number = ", 03282 (BOOLEAN) TRUE); 03283 } 03284 03285 if (argumentString != NULL) { 03286 partition = ParseArgumentNumeric(&argumentString); 03287 } else { 03288 break; 03289 } 03290 03291 if (CreateFtMember(configHeader, disk, partition, type, group, member) == FALSE) { 03292 printf("Failed to change member state\n"); 03293 printf("No update will be made\n"); 03294 doUpdate = FALSE; 03295 break; 03296 } 03297 } 03298 if (doUpdate == TRUE) { 03299 PDISK_REGISTRY diskRegistry; 03300 diskRegistry = (PDISK_REGISTRY) 03301 ((PUCHAR) configHeader + configHeader->DiskInformationOffset); 03302 DiskRegistrySet(diskRegistry); 03303 } 03304 free(configHeader); 03305 break; 03306 } 03307 03308 default: 03309 03310 printf("WDF homer?!?\n"); 03311 break; 03312 } 03313 } 03314 } // main

Generated on Sat May 15 19:39:49 2004 for test by doxygen 1.3.7