00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
00075
00076
00077 PUCHAR
StartDescription[] =
00078 {
00079
"Boot loader",
00080
"System",
00081
"2",
00082
"3",
00083
00084
00085
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
00102
00103
00104 #define WORK_BUFFER_SIZE 4096
00105
00106
00107
00108
00109
00110 #define FUDGE 8
00111
00112
00113
00114
00115
00116 #define REGISTRY_BASE "\\REGISTRY\\MACHINE"
00117
00118
00119
00120
00121
00122 #define DEFAULT_TYPE REG_SZ
00123
00124
00125
00126
00127
00128 #define FT_REGISTRY_ROOT "\\REGISTRY\\MACHINE\\SYSTEM\\NTFT"
00129
00130
00131
00132
00133
00134 #define FT_STRIPE_BASE "Stripe%d"
00135
00136
00137
00138
00139
00140 #define FT_MIRROR_BASE "Mirror%d"
00141
00142
00143
00144
00145
00146 #define FT_VOLSET_BASE "VolSet%d"
00147
00148
00149
00150
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
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
00222
00223
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
00264
00265
00266
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
00300
00301
00302 UCHAR
WorkingDirectory[512];
00303
00304
00305
00306
00307
00308 UCHAR
CurrentDirectory[512];
00309
00310
00311
00312
00313
00314 UCHAR
CommandLine[512];
00315
00316
00317
00318
00319
00320 PUCHAR
SetPrompts[] = {
00321
00322
"Name => ",
00323
"Value => ",
00324
"Index => ",
00325
NULL
00326 };
00327
00328
00329
00330
00331
00332 PUCHAR
Version =
"Version 1.30";
00333
00334
00335
00336
00337
00338 ULONG
Debug = 0;
00339
00340
00341
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
00365
00366
00367
00368
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
00418
00419
00420
00421
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
00462
00463
00464
00465
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
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
00509
00510
00511
RtlInitString(&classString,
00512 KeyClass);
00513 (
VOID)
RtlAnsiStringToUnicodeString(&unicodeClassName,
00514 &classString,
00515 (BOOLEAN)
TRUE);
00516
00517
00518
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
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
00565
00566
00567
00568
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
00613
00614
00615
00616
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
00657
00658
00659
00660
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
00686
00687
00688
00689
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
00706
00707
00708
00709 i = -1;
00710
while ((*cp) && (*cp !=
'\n')) {
00711 i++;
00712 cp++;
00713 }
00714
00715
if (i >= 8) {
00716
00717
00718
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
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
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
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
00806
00807
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
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
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 = 0
L;
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
00912
00913
00914
00915
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
00975
00976
00977
00978
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
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
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
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 }
01117
01118
01119 PUCHAR
01120 GetArgumentString(
01121 BOOLEAN Batch,
01122 PUCHAR Prompt,
01123 BOOLEAN ConvertToLower
01124 )
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 {
01146
01147
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
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
01193
01194
01195 putchar(
' ');
01196 putchar(
'\b');
01197 i--;
01198
01199 }
else {
01200
01201
01202
01203
01204
01205 putchar(
' ');
01206 }
01207
01208 }
else {
01209
01210
01211
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 }
01230
01231
01232 ULONG
01233 ParseArgumentNumeric(
01234 PUCHAR *ArgumentPtr
01235 )
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
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
01264
01265
01266 argument++;
01267 }
01268
01269
01270
01271
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
01291
01292
01293 *ArgumentPtr = &argument[i + 1];
01294
01295
01296
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 }
01322
01323
01324
VOID
01325 PromptUser(
01326 BOOLEAN Batch
01327 )
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345 {
01346
if (!Batch) {
01347
01348 printf(
"\n%s> ",
CurrentDirectory);
01349 }
01350
01351 }
01352
01353
01354
int
01355 GetCommand(
01356 BOOLEAN Batch,
01357 PUCHAR *ArgumentPtr
01358 )
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
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
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
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
01432
01433
01434 putchar(
' ');
01435 }
01436 }
else {
01437
01438
01439
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
01458
01459
01460 command[i] =
'\0';
01461
01462
if (
Debug) {
01463 printf(
"command => %s$\n", command);
01464 }
01465
01466
01467
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
01496
01497
01498 commandIndex++;
01499
continue;
01500 }
01501
01502
01503
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 }
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
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
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
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
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
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
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
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
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
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 "
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
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
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
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
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
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981 {
01982
ChangeMemberState(Type,
01983
Group,
01984 Member,
01985 Regenerating);
01986 }
01987
01988
01989
VOID
01990 FixDisk()
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
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
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
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
02238
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
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
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
02295
02296
02297
02298
02299
02300
02301
02302
02303
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
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
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
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
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 = 0
L;
02435 ansiString.Buffer = &tempBuffer[0];
02436
02437
RtlUnicodeStringToAnsiString(&ansiString,
02438 &unicodeValueName,
02439 (BOOLEAN)
FALSE);
02440
02441
02442
02443
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
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
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
02503
02504
02505 batch =
FALSE;
02506
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
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
02634
02635
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
02654
02655
02656 argumentString += 2;
02657
02658
02659
02660
02661
02662
while (*cptr !=
'\0') {
02663 cptr++;
02664 }
02665
02666
02667
02668
02669
02670
while (*cptr !=
'\\') {
02671 cptr--;
02672 }
02673
02674
if (cptr ==
CurrentDirectory) {
02675
02676
02677
02678
02679
02680
02681
continue;
02682 }
02683
02684
02685
02686
02687
02688 *cptr =
'\0';
02689
02690
if (*argumentString ==
'\0') {
02691
02692
02693
02694
02695
02696
break;
02697 }
02698
02699
02700
02701
02702
02703 argumentString++;
02704
02705 }
else {
02706
02707
02708
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }