test: geninst.c Source File

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

# geninst.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1998  Microsoft Corporation
    00004
    00005
    00006 Module Name:
    00007
    00008     geninst.c
    00009
    00010 Abstract:
    00011
    00012     This modules contains routines to implement GenInstall of an inf section.
    00013     This is based on the code from the setupapi. Currently, it only supports
    00014     a subset of GenInstall functionality i.e AddReg and DelReg and BitReg.
    00015
    00016 Author:
    00017
    00018     Santosh Jodh (santoshj) 08-Aug-1998
    00019
    00020
    00021 Environment:
    00022
    00023     Kernel mode.
    00024
    00025 Revision History:
    00026
    00027 --*/
    00028
    00029
    00030 #include "cmp.h"
    00031 #include "stdlib.h"
    00032 #include "parseini.h"
    00033 #include "geninst.h"
    00034
    00035 typedef
    00036 BOOLEAN
    00037 (* PFN_INFRULE)(
    00038     IN PVOID InfHandle,
    00039     IN PCHAR Section,
    00040     IN PVOID RefData
    00041     );
    00042
    00043 typedef
    00044 BOOLEAN
    00045 (* PFN_REGLINE)(
    00046     IN PVOID InfHandle,
    00047     IN PCHAR Section,
    00048     IN ULONG LineIndex
    00049     );
    00050
    00051 BOOLEAN
    00052 CmpProcessReg(
    00053     IN PVOID InfHandle,
    00054     IN PCHAR Section,
    00055     IN PVOID RefData
    00056     );
    00057
    00058 NTSTATUS
    00059 CmpProcessAddRegLine(
    00060     IN PVOID InfHandle,
    00061     IN PCHAR Section,
    00062     IN ULONG LineIndex
    00063     );
    00064
    00065 NTSTATUS
    00066 CmpProcessDelRegLine(
    00067     IN PVOID InfHandle,
    00068     IN PCHAR Section,
    00069     IN ULONG LineIndex
    00070     );
    00071
    00072 NTSTATUS
    00073 CmpProcessBitRegLine(
    00074     IN PVOID InfHandle,
    00075     IN PCHAR Section,
    00076     IN ULONG LineIndex
    00077     );
    00078
    00079 NTSTATUS
    00080 CmpGetAddRegInfData(
    00081     IN PVOID InfHandle,
    00082     IN PCHAR Section,
    00083     IN ULONG LineIndex,
    00084     IN ULONG ValueIndex,
    00085     IN ULONG ValueType,
    00086     OUT PVOID *Data,
    00087     OUT PULONG DataSize
    00088     );
    00089
    00090 NTSTATUS
    00091 CmpOpenRegKey(
    00092     IN OUT PHANDLE Key,
    00093     IN OUT PULONG Disposition,
    00094     IN PCHAR Root,
    00095     IN PCHAR SubKey,
    00096     IN ULONG DesiredAccess,
    00097     IN BOOLEAN Create
    00098     );
    00099
    00100 NTSTATUS
    00101 CmpAppendStringToMultiSz(
    00102     IN HANDLE Key,
    00103     IN PCHAR ValueName,
    00104     IN OUT PVOID *Data,
    00105     IN OUT PULONG DataSize
    00106     );
    00107
    00108 //
    00109 // Copied from setupapi.h
    00110 //
    00111 // Flags for AddReg section lines in INF.  The corresponding value
    00112 // is <ValueType> in the AddReg line format given below:
    00113 //
    00114 // <RegRootString>,<SubKey>,<ValueName>,<ValueType>,<Value>...
    00115 //
    00116 // The low word contains basic flags concerning the general data type
    00117 // and AddReg action. The high word contains values that more specifically
    00118 // identify the data type of the registry value.  The high word is ignored
    00119 // by the 16-bit Windows 95 SETUPX APIs.
    00120 //
    00121
    00122 #define FLG_ADDREG_BINVALUETYPE     ( 0x00000001 )
    00123 #define FLG_ADDREG_NOCLOBBER        ( 0x00000002 )
    00124 #define FLG_ADDREG_DELVAL           ( 0x00000004 )
    00125 #define FLG_ADDREG_APPEND           ( 0x00000008 ) // Currently supported only
    00126                                                    // for REG_MULTI_SZ values.
    00127 #define FLG_ADDREG_KEYONLY          ( 0x00000010 ) // Just create the key, ignore value
    00128 #define FLG_ADDREG_OVERWRITEONLY    ( 0x00000020 ) // Set only if value already exists
    00129
    00130 #define FLG_ADDREG_TYPE_MASK        ( 0xFFFF0000 | FLG_ADDREG_BINVALUETYPE )
    00131 #define FLG_ADDREG_TYPE_SZ          ( 0x00000000                           )
    00132 #define FLG_ADDREG_TYPE_MULTI_SZ    ( 0x00010000                           )
    00133 #define FLG_ADDREG_TYPE_EXPAND_SZ   ( 0x00020000                           )
    00134 #define FLG_ADDREG_TYPE_BINARY      ( 0x00000000 | FLG_ADDREG_BINVALUETYPE )
    00135 #define FLG_ADDREG_TYPE_DWORD       ( 0x00010000 | FLG_ADDREG_BINVALUETYPE )
    00136 #define FLG_ADDREG_TYPE_NONE        ( 0x00020000 | FLG_ADDREG_BINVALUETYPE )
    00137
    00138 #define FLG_BITREG_CLEAR            ( 0x00000000 )
    00139 #define FLG_BITREG_SET              ( 0x00000001 )
    00140 #define FLG_BITREG_TYPE_BINARY      ( 0x00000000 )
    00141 #define FLG_BITREG_TYPE_DWORD       ( 0x00000002 )
    00142
    00143 //
    00144 // We currently only support AddReg and DelReg sections.
    00145 //
    00146
    00147 #define NUM_OF_INF_RULES    3
    00148
    00149 //
    00150 // GenInstall methods we support.
    00151 //
    00152
    00153 struct {
    00154     PCHAR       Name;
    00155     PFN_INFRULE Action;
    00156     PVOID       RefData;
    00157 } gInfRuleTable[NUM_OF_INF_RULES] =
    00158 {
    00159     {"AddReg", CmpProcessReg, CmpProcessAddRegLine},
    00160     {"DelReg", CmpProcessReg, CmpProcessDelRegLine},
    00161     {"BitReg", CmpProcessReg, CmpProcessBitRegLine}
    00162 };
    00163
    00164 #ifdef ALLOC_PRAGMA
    00165 #pragma alloc_text(INIT,CmpAppendStringToMultiSz)
    00166 #pragma alloc_text(INIT,CmpOpenRegKey)
    00167 #pragma alloc_text(INIT,CmpGetAddRegInfData)
    00168 #pragma alloc_text(INIT,CmpProcessReg)
    00169 #pragma alloc_text(INIT,CmpProcessAddRegLine)
    00170 #pragma alloc_text(INIT,CmpProcessDelRegLine)
    00171 #pragma alloc_text(INIT,CmpProcessBitRegLine)
    00172 #pragma alloc_text(INIT,CmpGenInstall)
    00173 #endif
    00174
    00175 BOOLEAN
    00176 CmpGenInstall(
    00177     IN PVOID InfHandle,
    00178     IN PCHAR Section
    00179     )
    00180
    00181 /*++
    00182
    00183     Routine Description:
    00184
    00185         This routine does a GenInstall of the section in the inf.
    00186
    00187     Input Parameters:
    00188
    00189         InfHandle - Handle to the inf to be read.
    00190
    00191         Section - Name of the section to be read.
    00192
    00193     Return Value:
    00194
    00195         TRUE iff the entire section was processed successfully.
    00196
    00197 --*/
    00198
    00199 {
    00200     ULONG   ruleNumber;
    00201     ULONG   i;
    00202     PCHAR   ruleName;
    00203     PCHAR   regSection;
    00204     BOOLEAN result = FALSE;
    00205
    00206     if (CmpSearchInfSection(InfHandle, Section))
    00207     {
    00208         //
    00209         // Go through all the rules in the section and try to process
    00210         // each of them.
    00211         //
    00212
    00213         for (   ruleNumber = 0;
    00214                 ruleName = CmpGetKeyName(InfHandle, Section, ruleNumber);
    00215                 ruleNumber++)
    00216         {
    00217
    00218             //
    00219             // Search for the proceesing function in our table.
    00220             //
    00221
    00222             for (   i = 0;
    00223                     i < NUM_OF_INF_RULES &&
    00224                         _stricmp(ruleName, gInfRuleTable[i].Name);
    00225                     i++);
    00226
    00227             if (    i >= NUM_OF_INF_RULES ||
    00228                     (regSection = CmpGetSectionLineIndex(   InfHandle,
    00229                                                             Section,
    00230                                                             ruleNumber,
    00231                                                             0)) == NULL ||
    00232                     !CmpSearchInfSection(InfHandle, Section))
    00233             {
    00234                 result = FALSE;
    00235                 break;
    00236             }
    00237
    00238             if (!(*gInfRuleTable[i].Action)(InfHandle, regSection, gInfRuleTable[i].RefData))
    00239             {
    00240                 result = FALSE;
    00241             }
    00242         }
    00243
    00244         //
    00245         // All inf rules processed.
    00246         //
    00247
    00248         if (ruleNumber)
    00249         {
    00250             result = TRUE;
    00251         }
    00252     }
    00253
    00254     return (result);
    00255 }
    00256
    00257 BOOLEAN
    00258 CmpProcessReg(
    00259     IN PVOID InfHandle,
    00260     IN PCHAR Section,
    00261     IN PVOID RefData
    00262     )
    00263
    00264 /*++
    00265
    00266     Routine Description:
    00267
    00268         This routine processes a AddReg section in the inf.
    00269
    00270     Input Parameters:
    00271
    00272         InfHandle - Handle to the inf to be read.
    00273
    00274         Section - Name of the section to be read.
    00275
    00276     Return Value:
    00277
    00278         TRUE iff the entire section was processed successfully.
    00279
    00280 --*/
    00281
    00282 {
    00283     ULONG       lineIndex;
    00284     NTSTATUS    status = STATUS_SUCCESS;
    00285     NTSTATUS    temp;
    00286
    00287     //
    00288     // Process all the lines in the xxxReg Section.
    00289     //
    00290
    00291     for (   lineIndex = 0;
    00292             CmpSearchInfLine(InfHandle, Section, lineIndex);
    00293             lineIndex++)
    00294     {
    00295         temp = (*(PFN_REGLINE)RefData)(InfHandle, Section, lineIndex);
    00296         if (!NT_SUCCESS(temp))
    00297         {
    00298             status = temp;
    00299         }
    00300     }
    00301
    00302     if (NT_SUCCESS(status))
    00303     {
    00304         return (TRUE);
    00305     }
    00306
    00307     return (FALSE);
    00308 }
    00309
    00310 NTSTATUS
    00311 CmpProcessAddRegLine(
    00312     IN PVOID InfHandle,
    00313     IN PCHAR Section,
    00314     IN ULONG LineIndex
    00315     )
    00316
    00317 /*++
    00318
    00319     Routine Description:
    00320
    00321         This routine processes a AddReg line in the inf.
    00322
    00323     Input Parameters:
    00324
    00325         InfHandle - Handle to the inf to be read.
    00326
    00327         Section - Name of the section to be read.
    00328
    00329         LineIndex - Index of the line to be read.
    00330
    00331     Return Value:
    00332
    00333         Standard NT status value.
    00334
    00335 --*/
    00336
    00337 {
    00338     NTSTATUS            status = STATUS_UNSUCCESSFUL;
    00339     PCHAR               rootKeyName;
    00340     PCHAR               subKeyName;
    00341     PCHAR               valueName;
    00342     ULONG               flags;
    00343     ULONG               valueType;
    00344     PCHAR               buffer;
    00345     HANDLE              key;
    00346     ULONG               disposition;
    00347     BOOLEAN             dontSet;
    00348     PVOID               data = 0;
    00349     ULONG               dataSize = 0;
    00350     ANSI_STRING         ansiString;
    00351     UNICODE_STRING      unicodeString;
    00352     OBJECT_ATTRIBUTES   objectAttributes;
    00353
    00354     //
    00355     // Get the root-key name.
    00356     //
    00357
    00358     rootKeyName = CmpGetSectionLineIndex(   InfHandle,
    00359                                             Section,
    00360                                             LineIndex,
    00361                                             0);
    00362     if (rootKeyName)
    00363     {
    00364         //
    00365         // Get the optional sub-key name.
    00366         //
    00367
    00368         subKeyName = CmpGetSectionLineIndex(    InfHandle,
    00369                                                 Section,
    00370                                                 LineIndex,
    00371                                                 1);
    00372
    00373         //
    00374         // Value name is optional. Can be NULL or "".
    00375         //
    00376
    00377         valueName = CmpGetSectionLineIndex( InfHandle,
    00378                                             Section,
    00379                                             LineIndex,
    00380                                             2);
    00381         //
    00382         // If we don't have a value name, the type is REG_SZ to force
    00383         // the right behavior in RegSetValueEx. Otherwise get the data type.
    00384         //
    00385
    00386         valueType = REG_SZ;
    00387
    00388         //
    00389         // Read in the flags.
    00390         //
    00391
    00392         if (!CmpGetIntField(    InfHandle,
    00393                                 Section,
    00394                                 LineIndex,
    00395                                 3,
    00396                                 &flags))
    00397         {
    00398             flags = 0;
    00399         }
    00400
    00401         //
    00402         // Convert the flags to the registry type.
    00403         //
    00404
    00405         switch(flags & FLG_ADDREG_TYPE_MASK)
    00406         {
    00407
    00408             case FLG_ADDREG_TYPE_SZ:
    00409
    00410                 valueType = REG_SZ;
    00411                 break;
    00412
    00413             case FLG_ADDREG_TYPE_MULTI_SZ:
    00414
    00415                 valueType = REG_MULTI_SZ;
    00416                 break;
    00417
    00418             case FLG_ADDREG_TYPE_EXPAND_SZ:
    00419
    00420                 valueType = REG_EXPAND_SZ;
    00421                 break;
    00422
    00423             case FLG_ADDREG_TYPE_BINARY:
    00424
    00425                 valueType = REG_BINARY;
    00426                 break;
    00427
    00428             case FLG_ADDREG_TYPE_DWORD:
    00429
    00430                 valueType = REG_DWORD;
    00431                 break;
    00432
    00433             case FLG_ADDREG_TYPE_NONE:
    00434
    00435                 valueType = REG_NONE;
    00436                 break;
    00437
    00438             default :
    00439
    00440                 //
    00441                 // If the FLG_ADDREG_BINVALUETYPE is set, then the highword
    00442                 // can contain just about any random reg data type ordinal value.
    00443                 //
    00444
    00445                 if(flags & FLG_ADDREG_BINVALUETYPE)
    00446                 {
    00447                     //
    00448                     // Disallow the following reg data types:
    00449                     //
    00450                     //    REG_NONE, REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ
    00451                     //
    00452
    00453                     valueType = HIGHWORD(flags);
    00454
    00455                     if(valueType < REG_BINARY || valueType == REG_MULTI_SZ)
    00456                     {
    00457                         return (STATUS_INVALID_PARAMETER);
    00458                     }
    00459
    00460                 }
    00461                 else
    00462                 {
    00463                     return (STATUS_INVALID_PARAMETER);
    00464                 }
    00465                 break;
    00466         }
    00467
    00468         //
    00469         // Presently, the append behavior flag is only supported for
    00470         // REG_MULTI_SZ values.
    00471         //
    00472
    00473         if((flags & FLG_ADDREG_APPEND) && valueType != REG_MULTI_SZ)
    00474         {
    00475             return (STATUS_INVALID_PARAMETER);
    00476         }
    00477
    00478         //
    00479         // W9x compatibility.
    00480         //
    00481
    00482         if( (!valueName || *valueName == '\0') && valueType == REG_EXPAND_SZ)
    00483         {
    00484             valueType = REG_SZ;
    00485         }
    00486
    00487         status = CmpGetAddRegInfData(   InfHandle,
    00488                                         Section,
    00489                                         LineIndex,
    00490                                         4,
    00491                                         valueType,
    00492                                         &data,
    00493                                         &dataSize);
    00494
    00495         if (NT_SUCCESS(status))
    00496         {
    00497             //
    00498             // Open the specified key if possible.
    00499             //
    00500
    00501             status = CmpOpenRegKey( &key,
    00502                                     &disposition,
    00503                                     rootKeyName,
    00504                                     subKeyName,
    00505                                     KEY_QUERY_VALUE | KEY_SET_VALUE,
    00506                                     (BOOLEAN)!(flags & FLG_ADDREG_OVERWRITEONLY));
    00507             //
    00508             // This variable gets set to TRUE if we dont actually want to set
    00509             // the value.
    00510             //
    00511
    00512             dontSet = FALSE;
    00513             if (NT_SUCCESS(status))
    00514             {
    00515                 if (flags & FLG_ADDREG_APPEND)
    00516                 {
    00517                     status = CmpAppendStringToMultiSz(  key,
    00518                                                         valueName,
    00519                                                         &data,
    00520                                                         &dataSize);
    00521                 }
    00522                 if (NT_SUCCESS(status))
    00523                 {
    00524                     //
    00525                     // W9x compatibility.
    00526                     //
    00527
    00528                     if (disposition == REG_OPENED_EXISTING_KEY)
    00529                     {
    00530                         if (    (flags & FLG_ADDREG_NOCLOBBER) &&
    00531                                 (valueName == NULL || *valueName == '\0'))
    00532                         {
    00533                             RtlInitAnsiString(&ansiString, "");
    00534                             status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    00535                             if (NT_SUCCESS(status))
    00536                             {
    00537
    00538                                 status = NtQueryValueKey(   key,
    00539                                                             &unicodeString,
    00540                                                             KeyValueBasicInformation,
    00541                                                             NULL,
    00542                                                             0,
    00543                                                             &disposition);
    00544                                 if (NT_SUCCESS(status) || status == STATUS_BUFFER_TOO_SMALL)
    00545                                 {
    00546                                     flags &= ~FLG_ADDREG_NOCLOBBER;
    00547                                 }
    00548                                 status = STATUS_SUCCESS;
    00549
    00550                                 RtlFreeUnicodeString(&unicodeString);
    00551                             }
    00552                         }
    00553
    00554                         if (flags & FLG_ADDREG_DELVAL)
    00555                         {
    00556                             //
    00557                             // setupx compatibility.
    00558                             //
    00559
    00560                             dontSet = TRUE;
    00561                             if (valueName)
    00562                             {
    00563                                 //
    00564                                 // Delete the specified value.
    00565                                 //
    00566
    00567                                 RtlInitAnsiString(&ansiString, valueName);
    00568                                 status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    00569                                 if (NT_SUCCESS(status))
    00570                                 {
    00571                                     status = NtDeleteValueKey(key, &unicodeString);
    00572                                     RtlFreeUnicodeString(&unicodeString);
    00573                                 }
    00574                             }
    00575                         }
    00576                     }
    00577                     else
    00578                     {
    00579                         flags &= ~FLG_ADDREG_NOCLOBBER;
    00580                     }
    00581
    00582                     if (!dontSet)
    00583                     {
    00584                         //
    00585                         // Respect the key only flag.
    00586                         //
    00587
    00588                         if (!(flags & FLG_ADDREG_KEYONLY))
    00589                         {
    00590                             //
    00591                             // If no clobber flag is set, make sure that the value does not
    00592                             // already exist.
    00593                             //
    00594
    00595                             RtlInitAnsiString(&ansiString, valueName);
    00596                             status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    00597                             if (NT_SUCCESS(status))
    00598                             {
    00599                                 NTSTATUS    existStatus;
    00600
    00601                                 if (flags & FLG_ADDREG_NOCLOBBER)
    00602                                 {
    00603                                     existStatus = NtQueryValueKey(  key,
    00604                                                                     &unicodeString,
    00605                                                                     KeyValueBasicInformation,
    00606                                                                     NULL,
    00607                                                                     0,
    00608                                                                     &disposition);
    00609                                     if (NT_SUCCESS(existStatus) || existStatus == STATUS_BUFFER_TOO_SMALL) {
    00610                                         dontSet = TRUE;
    00611                                     }
    00612                                 }
    00613                                 else
    00614                                 {
    00615                                     if (flags & FLG_ADDREG_OVERWRITEONLY)
    00616                                     {
    00617                                         existStatus = NtQueryValueKey(  key,
    00618                                                                         &unicodeString,
    00619                                                                         KeyValueBasicInformation,
    00620                                                                         NULL,
    00621                                                                         0,
    00622                                                                         &disposition);
    00623                                         if (!NT_SUCCESS(existStatus) && existStatus != STATUS_BUFFER_TOO_SMALL) {
    00624                                             dontSet = TRUE;
    00625                                         }
    00626                                     }
    00627                                 }
    00628
    00629                                 if (!dontSet)
    00630                                 {
    00631                                     status = NtSetValueKey( key,
    00632                                                             &unicodeString,
    00633                                                             0,
    00634                                                             valueType,
    00635                                                             data,
    00636                                                             dataSize);
    00637                                 }
    00638
    00639                                 RtlFreeUnicodeString(&unicodeString);
    00640                             }
    00641                         }
    00642                     }
    00643                 }
    00644
    00645                 NtClose(key);
    00646             }
    00647             else if (flags & FLG_ADDREG_OVERWRITEONLY)
    00648             {
    00649                 status = STATUS_SUCCESS;
    00650             }
    00651         }
    00652     }
    00653
    00654     return (status);
    00655 }
    00656
    00657 NTSTATUS
    00658 CmpProcessDelRegLine(
    00659     IN PVOID InfHandle,
    00660     IN PCHAR Section,
    00661     IN ULONG LineIndex
    00662     )
    00663
    00664 /*++
    00665
    00666     Routine Description:
    00667
    00668         This routine processes a DelReg line in the inf.
    00669
    00670     Input Parameters:
    00671
    00672         InfHandle - Handle to the inf to be read.
    00673
    00674         Section - Name of the section to be read.
    00675
    00676         LineIndex - Index of the line to be read.
    00677
    00678     Return Value:
    00679
    00680         Standard NT status value.
    00681
    00682 --*/
    00683
    00684 {
    00685     NTSTATUS            status = STATUS_UNSUCCESSFUL;
    00686     PCHAR               rootKeyName;
    00687     PCHAR               subKeyName;
    00688     PCHAR               valueName;
    00689     HANDLE              key;
    00690     ULONG               disposition;
    00691     ANSI_STRING         ansiString;
    00692     UNICODE_STRING      unicodeString;
    00693
    00694     //
    00695     // Read the required fields.
    00696     //
    00697
    00698     rootKeyName = CmpGetSectionLineIndex(   InfHandle,
    00699                                             Section,
    00700                                             LineIndex,
    00701                                             0);
    00702
    00703     subKeyName = CmpGetSectionLineIndex(    InfHandle,
    00704                                             Section,
    00705                                             LineIndex,
    00706                                             1);
    00707
    00708     if (rootKeyName && subKeyName)
    00709     {
    00710         //
    00711         // Read the optional field.
    00712         //
    00713
    00714         valueName = CmpGetSectionLineIndex( InfHandle,
    00715                                             Section,
    00716                                             LineIndex,
    00717                                             2);
    00718
    00719         //
    00720         // Open the specified registry key.
    00721         //
    00722
    00723         status = CmpOpenRegKey( &key,
    00724                                 &disposition,
    00725                                 rootKeyName,
    00726                                 subKeyName,
    00727                                 KEY_ALL_ACCESS,
    00728                                 FALSE);
    00729
    00730         //
    00731         // Proceed if we successfully opened the registry key.
    00732         //
    00733
    00734         if (NT_SUCCESS(status))
    00735         {
    00736
    00737             //
    00738             // If the key was successfully opened, do the DelReg.
    00739             //
    00740
    00741             if (valueName)
    00742             {
    00743                 //
    00744                 // Delete the specified value.
    00745                 //
    00746
    00747                 RtlInitAnsiString(&ansiString, valueName);
    00748                 status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    00749                 if (NT_SUCCESS(status))
    00750                 {
    00751                     status = NtDeleteValueKey(key, &unicodeString);
    00752                     RtlFreeUnicodeString(&unicodeString);
    00753                 }
    00754             }
    00755             else
    00756             {
    00757                 //
    00758                 // No value specified. The subkey needs to be deleted.
    00759                 //
    00760
    00761                 status = NtDeleteKey(key);
    00762             }
    00763
    00764             //
    00765             // Close the key handle.
    00766             //
    00767
    00768             NtClose(key);
    00769         }
    00770     }
    00771
    00772     return (status);
    00773 }
    00774
    00775 NTSTATUS
    00776 CmpProcessBitRegLine(
    00777     IN PVOID InfHandle,
    00778     IN PCHAR Section,
    00779     IN ULONG LineIndex
    00780     )
    00781
    00782 /*++
    00783
    00784     Routine Description:
    00785
    00786         This routine processes a BitReg line in the inf.
    00787
    00788     Input Parameters:
    00789
    00790         InfHandle - Handle to the inf to be read.
    00791
    00792         Section - Name of the section to be read.
    00793
    00794         LineIndex - Index of the line to be read.
    00795
    00796     Return Value:
    00797
    00798         Standard NT status value.
    00799
    00800 --*/
    00801
    00802 {
    00803     NTSTATUS                    status = STATUS_UNSUCCESSFUL;
    00804     PCHAR                       rootKeyName;
    00805     PCHAR                       subKeyName;
    00806     PCHAR                       valueName;
    00807     ULONG                       flags;
    00808     ULONG                       mask;
    00809     ULONG                       field;
    00810     HANDLE                      key;
    00811     ULONG                       disposition;
    00812     ANSI_STRING                 ansiString;
    00813     UNICODE_STRING              unicodeString;
    00814     PCHAR                       buffer;
    00815     ULONG                       size;
    00816     PKEY_VALUE_FULL_INFORMATION valueInfo;
    00817
    00818     //
    00819     // Get the root-key name.
    00820     //
    00821
    00822     rootKeyName = CmpGetSectionLineIndex(   InfHandle,
    00823                                             Section,
    00824                                             LineIndex,
    00825                                             0);
    00826     if (rootKeyName)
    00827     {
    00828         //
    00829         // Get the optional sub-key name.
    00830         //
    00831
    00832         subKeyName = CmpGetSectionLineIndex(    InfHandle,
    00833                                                 Section,
    00834                                                 LineIndex,
    00835                                                 1);
    00836
    00837         //
    00838         // Value name is optional. Can be NULL or "".
    00839         //
    00840
    00841         valueName = CmpGetSectionLineIndex( InfHandle,
    00842                                             Section,
    00843                                             LineIndex,
    00844                                             2);
    00845         if (valueName && *valueName)
    00846         {
    00847             //
    00848             // Read in the flags.
    00849             //
    00850
    00851             if (!CmpGetIntField(    InfHandle,
    00852                                     Section,
    00853                                     LineIndex,
    00854                                     3,
    00855                                     &flags))
    00856             {
    00857                 flags = 0;
    00858             }
    00859
    00860             if (!CmpGetIntField(    InfHandle,
    00861                                     Section,
    00862                                     LineIndex,
    00863                                     4,
    00864                                     &mask))
    00865             {
    00866                 mask = 0;
    00867             }
    00868
    00869             if (!(flags & FLG_BITREG_TYPE_DWORD))
    00870             {
    00871                 if (!CmpGetIntField(    InfHandle,
    00872                                         Section,
    00873                                         LineIndex,
    00874                                         5,
    00875                                         &field))
    00876                 {
    00877                     return (status);
    00878                 }
    00879             }
    00880
    00881             //
    00882             // Open the specified registry key.
    00883             //
    00884
    00885             status = CmpOpenRegKey( &key,
    00886                                     &disposition,
    00887                                     rootKeyName,
    00888                                     subKeyName,
    00889                                     KEY_ALL_ACCESS,
    00890                                     FALSE);
    00891             if (NT_SUCCESS(status))
    00892             {
    00893                 //
    00894                 // Read the existing data.
    00895                 //
    00896
    00897                 RtlInitAnsiString(&ansiString, valueName);
    00898                 status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    00899                 if (NT_SUCCESS(status))
    00900                 {
    00901                     size = 0;
    00902                     status = NtQueryValueKey(   key,
    00903                                                 &unicodeString,
    00904                                                 KeyValueFullInformation,
    00905                                                 NULL,
    00906                                                 0,
    00907                                                 &size);
    00908                     if (size)
    00909                     {
    00910                         status = STATUS_NO_MEMORY;
    00911                         buffer = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG);
    00912                         if (buffer)
    00913                         {
    00914                             status = NtQueryValueKey(   key,
    00915                                                         &unicodeString,
    00916                                                         KeyValueFullInformation,
    00917                                                         buffer,
    00918                                                         size,
    00919                                                         &size);
    00920                             if (NT_SUCCESS(status))
    00921                             {
    00922                                 valueInfo = (PKEY_VALUE_FULL_INFORMATION)buffer;
    00923                                 if (flags & FLG_BITREG_TYPE_DWORD)
    00924                                 {
    00925                                     if (valueInfo->Type == REG_DWORD && valueInfo->DataLength == sizeof(ULONG))
    00926                                     {
    00927                                         if (flags & FLG_BITREG_SET)
    00928                                         {
    00929                                             *(PULONG)(buffer + valueInfo->DataOffset) |= mask;
    00930                                         }
    00931                                         else
    00932                                         {
    00933                                             *(PULONG)(buffer + valueInfo->DataOffset) &= ~mask;
    00934                                         }
    00935                                     }
    00936                                 }
    00937                                 else
    00938                                 {
    00939                                     if (valueInfo->Type == REG_BINARY && field < valueInfo->DataLength)
    00940                                     {
    00941                                         if (flags & FLG_BITREG_SET)
    00942                                         {
    00943                                             *(PUCHAR)(buffer + valueInfo->DataOffset + field) |= mask;
    00944                                         }
    00945                                         else
    00946                                         {
    00947                                             *(PUCHAR)(buffer + valueInfo->DataOffset + field) &= ~mask;
    00948                                         }
    00949                                     }
    00950                                 }
    00951                                 status = NtSetValueKey( key,
    00952                                                         &unicodeString,
    00953                                                         0,
    00954                                                         valueInfo->Type,
    00955                                                         buffer + valueInfo->DataOffset,
    00956                                                         valueInfo->DataLength);
    00957                             }
    00958                             else
    00959                             {
    00960                                 DbgPrint("Value cannot be read for BitReg in %s line %d\n", Section, LineIndex);
    00961                                 ASSERT(NT_SUCCESS(status));
    00962                             }
    00963                             ExFreePool(buffer);
    00964                         }
    00965                         else
    00966                         {
    00967                             ASSERT(buffer);
    00968                             status = STATUS_NO_MEMORY;
    00969                         }
    00970                     }
    00971
    00972                     RtlFreeUnicodeString(&unicodeString);
    00973                 }
    00974                 //
    00975                 // Close the key handle.
    00976                 //
    00977
    00978                 NtClose(key);
    00979             }
    00980         }
    00981     }
    00982
    00983     return (status);
    00984 }
    00985
    00986 NTSTATUS
    00987 CmpGetAddRegInfData(
    00988     IN PVOID InfHandle,
    00989     IN PCHAR Section,
    00990     IN ULONG LineIndex,
    00991     IN ULONG ValueIndex,
    00992     IN ULONG ValueType,
    00993     OUT PVOID *Data,
    00994     OUT PULONG DataSize
    00995     )
    00996
    00997 /*++
    00998
    00999     Routine Description:
    01000
    01001         This routine reads AddReg data from the inf.
    01002
    01003     Input Parameters:
    01004
    01005         InfHandle - Handle to the inf to be read.
    01006
    01007         Section - Name of the section to be read.
    01008
    01009         LineIndex - Index of the line to be read.
    01010
    01011         ValueIndex - Index of the value to be read.
    01012
    01013         ValueType - Data type to be read.
    01014
    01015         Data - Receives pointer to the buffer in which data has been read.
    01016
    01017         DataSize - Receives the size of the data buffer.
    01018
    01019     Return Value:
    01020
    01021         Standard NT status value.
    01022
    01023 --*/
    01024
    01025 {
    01026     NTSTATUS        status = STATUS_UNSUCCESSFUL;
    01027     PCHAR           str;
    01028     ULONG           count;
    01029     ULONG           i;
    01030     ANSI_STRING     ansiString;
    01031     UNICODE_STRING  unicodeString;
    01032
    01033     //
    01034     // Validate the required fields.
    01035     //
    01036
    01037     ASSERT(Data);
    01038     ASSERT(DataSize);
    01039
    01040     switch (ValueType)
    01041     {
    01042         case REG_DWORD:
    01043
    01044             *DataSize = sizeof(ULONG);
    01045             *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG);
    01046             if (*Data)
    01047             {
    01048                 //
    01049                 // DWORD data is specified as four bytes in W9x.
    01050                 //
    01051
    01052                 if (CmpGetSectionLineIndexValueCount(   InfHandle,
    01053                                                         Section,
    01054                                                         LineIndex) == 8)
    01055                 {
    01056                     if (!CmpGetBinaryField( InfHandle,
    01057                                             Section,
    01058                                             LineIndex,
    01059                                             ValueIndex,
    01060                                             *Data,
    01061                                             *DataSize,
    01062                                             NULL))
    01063                     {
    01064                         *((PULONG)*Data) = 0;
    01065                     }
    01066
    01067                     status = STATUS_SUCCESS;
    01068                 }
    01069                 else
    01070                 {
    01071                     //
    01072                     // Get the DWORD value.
    01073                     //
    01074
    01075                     if (!CmpGetIntField(    InfHandle,
    01076                                             Section,
    01077                                             LineIndex,
    01078                                             4,
    01079                                             *Data))
    01080                     {
    01081                         *((PULONG)*Data) = 0;
    01082                     }
    01083
    01084                     status = STATUS_SUCCESS;
    01085                 }
    01086             }
    01087             else
    01088             {
    01089                 ASSERT(*Data);
    01090                 status = STATUS_NO_MEMORY;
    01091             }
    01092
    01093             break;
    01094
    01095         case REG_SZ:
    01096         case REG_EXPAND_SZ:
    01097
    01098             //
    01099             // Null terminated string. Gets converted to unicode before being
    01100             // added into the registry.
    01101             //
    01102
    01103             str = CmpGetSectionLineIndex(   InfHandle,
    01104                                             Section,
    01105                                             LineIndex,
    01106                                             ValueIndex);
    01107             if (str)
    01108             {
    01109                 RtlInitAnsiString(&ansiString, str);
    01110                 *DataSize = (ansiString.Length << 1) + sizeof(UNICODE_NULL);
    01111                 unicodeString.MaximumLength = (USHORT)*DataSize;
    01112                 unicodeString.Buffer = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG);
    01113                 *Data = NULL;
    01114                 if (unicodeString.Buffer)
    01115                 {
    01116                     status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
    01117                     if (NT_SUCCESS(status))
    01118                     {
    01119                         *Data = unicodeString.Buffer;
    01120                         status = STATUS_SUCCESS;
    01121                     }
    01122                 }
    01123                 else
    01124                 {
    01125                     ASSERT(unicodeString.Buffer);
    01126                     status = STATUS_NO_MEMORY;
    01127                 }
    01128             }
    01129             else
    01130             {
    01131                 ASSERT(str);
    01132                 status = STATUS_NO_MEMORY;
    01133             }
    01134
    01135             break;
    01136
    01137         case REG_MULTI_SZ:
    01138
    01139             *DataSize = 0;
    01140             *Data = NULL;
    01141
    01142             //
    01143             // Loop to determine the total memory that needs to be allocated.
    01144             //
    01145
    01146             count = CmpGetSectionLineIndexValueCount(   InfHandle,
    01147                                                         Section,
    01148                                                         LineIndex);
    01149             if (count > ValueIndex)
    01150             {
    01151                 count -= ValueIndex;
    01152                 for (i = 0; i < count; i++)
    01153                 {
    01154                     str = CmpGetSectionLineIndex(   InfHandle,
    01155                                                     Section,
    01156                                                     LineIndex,
    01157                                                     ValueIndex + i);
    01158                     if (str == NULL)
    01159                     {
    01160                         break;
    01161                     }
    01162
    01163                     *DataSize += ((strlen(str) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
    01164                 }
    01165
    01166                 if (i == count)
    01167                 {
    01168                     //
    01169                     // Account for the terminating NULL.
    01170                     //
    01171
    01172                     *DataSize += sizeof(UNICODE_NULL);
    01173                     *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG);
    01174                     if (*Data)
    01175                     {
    01176                         for (   i = 0, unicodeString.Buffer = *Data;
    01177                                 i < count;
    01178                                 i++, (PCHAR)unicodeString.Buffer += unicodeString.MaximumLength)
    01179                         {
    01180                             str = CmpGetSectionLineIndex(   InfHandle,
    01181                                                             Section,
    01182                                                             LineIndex,
    01183                                                             ValueIndex + i);
    01184                             if (str == NULL)
    01185                             {
    01186                                 break;
    01187                             }
    01188                             RtlInitAnsiString(&ansiString, str);
    01189                             unicodeString.MaximumLength = (ansiString.Length * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
    01190                             status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
    01191                             if (!NT_SUCCESS(status))
    01192                             {
    01193                                 break;
    01194                             }
    01195                         }
    01196
    01197                         //
    01198                         // Terminate the multi-sz string.
    01199                         //
    01200
    01201                         if (i == count)
    01202                         {
    01203                             unicodeString.Buffer[0] = UNICODE_NULL;
    01204                             status = STATUS_SUCCESS;
    01205                         }
    01206                     }
    01207                     else
    01208                     {
    01209                         ASSERT(*Data);
    01210                         status = STATUS_NO_MEMORY;
    01211                     }
    01212                 }
    01213             }
    01214
    01215             break;
    01216
    01217         case REG_BINARY:
    01218         default:
    01219
    01220             //
    01221             // Free form binary data.
    01222             //
    01223
    01224             if (CmpGetBinaryField(  InfHandle,
    01225                                     Section,
    01226                                     LineIndex,
    01227                                     ValueIndex,
    01228                                     NULL,
    01229                                     0,
    01230                                     DataSize) && *DataSize)
    01231             {
    01232                 *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG);
    01233                 if (*Data)
    01234                 {
    01235                     if (CmpGetBinaryField( InfHandle,
    01236                                             Section,
    01237                                             LineIndex,
    01238                                             4,
    01239                                             *Data,
    01240                                             *DataSize,
    01241                                             NULL))
    01242                     {
    01243                         status = STATUS_SUCCESS;
    01244                     }
    01245                 }
    01246                 else
    01247                 {
    01248                     ASSERT(*Data);
    01249                     status = STATUS_NO_MEMORY;
    01250                 }
    01251             }
    01252             else
    01253             {
    01254                 status = STATUS_UNSUCCESSFUL;
    01255             }
    01256
    01257             break;
    01258     }
    01259
    01260     return (status);
    01261 }
    01262
    01263 NTSTATUS
    01264 CmpOpenRegKey(
    01265     IN OUT PHANDLE Key,
    01266     IN OUT PULONG Disposition,
    01267     IN PCHAR Root,
    01268     IN PCHAR SubKey,
    01269     IN ULONG DesiredAccess,
    01270     IN BOOLEAN Create
    01271     )
    01272
    01273 /*++
    01274
    01275     Routine Description:
    01276
    01277         This routine opens\creates a handle to the registry key.
    01278
    01279     Input Parameters:
    01280
    01281         Key - Receives the handle to the key.
    01282
    01283         Disposition - Receives the disposition of the key.
    01284
    01285         Root - Abbreviated name of the root key.
    01286
    01287         SubKey - Name of the subkey under the root.
    01288
    01289         DesiredAccess - Desired access flags for the key.
    01290
    01291         Create - TRUE if the key needs to be created instead of opened.
    01292
    01293     Return Value:
    01294
    01295         Standard NT status value.
    01296
    01297 --*/
    01298
    01299 {
    01300     NTSTATUS            status = STATUS_OBJECT_NAME_INVALID;
    01301     ULONG               size;
    01302     PCHAR               str;
    01303     ANSI_STRING         ansiString;
    01304     UNICODE_STRING      unicodeString;
    01305     OBJECT_ATTRIBUTES   objectAttributes;
    01306
    01307     str = NULL;
    01308     size = strlen(SubKey) + 1;
    01309
    01310     //
    01311     // Check if we understand the specified root name.
    01312     //
    01313
    01314     if (_stricmp(Root, "HKLM") == 0)
    01315     {
    01316         size += strlen("\\Registry\\Machine\\");
    01317         str = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG);
    01318         if (str)
    01319         {
    01320             strcpy(str, "\\Registry\\Machine\\");
    01321             strcat(str, SubKey);
    01322         }
    01323         else
    01324         {
    01325             ASSERT(str);
    01326             status = STATUS_NO_MEMORY;
    01327         }
    01328     }
    01329     else
    01330     {
    01331         ASSERT(_stricmp(Root, "HKLM") == 0);
    01332     }
    01333
    01334     //
    01335     // Proceed if we have a valid key name.
    01336     //
    01337
    01338     if (str)
    01339     {
    01340         RtlInitAnsiString(&ansiString, str);
    01341         status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    01342         if (NT_SUCCESS(status))
    01343         {
    01344             InitializeObjectAttributes( &objectAttributes,
    01345                                         &unicodeString,
    01346                                         OBJ_CASE_INSENSITIVE,
    01347                                         NULL,
    01348                                         NULL);
    01349             if (Create)
    01350             {
    01351                 //
    01352                 // Create a new key or open an existing one.
    01353                 //
    01354
    01355                 status = NtCreateKey(   Key,
    01356                                         DesiredAccess,
    01357                                         &objectAttributes,
    01358                                         0,
    01359                                         NULL,
    01360                                         REG_OPTION_NON_VOLATILE,
    01361                                         Disposition ? Disposition : &size);
    01362             }
    01363             else
    01364             {
    01365                 //
    01366                 // Open existing key.
    01367                 //
    01368
    01369                 if (Disposition)
    01370                 {
    01371                     *Disposition = REG_OPENED_EXISTING_KEY;
    01372                 }
    01373                 status = NtOpenKey( Key,
    01374                                     DesiredAccess,
    01375                                     &objectAttributes);
    01376             }
    01377
    01378             RtlFreeUnicodeString(&unicodeString);
    01379         }
    01380         else
    01381         {
    01382             ASSERT(NT_SUCCESS(status));
    01383         }
    01384
    01385         ExFreePool(str);
    01386     }
    01387
    01388     return (status);
    01389 }
    01390
    01391 NTSTATUS
    01392 CmpAppendStringToMultiSz(
    01393     IN HANDLE Key,
    01394     IN PCHAR ValueName,
    01395     IN OUT PVOID *Data,
    01396     IN OUT PULONG DataSize
    01397     )
    01398
    01399 /*++
    01400
    01401     Routine Description:
    01402
    01403         This routine opens\creates a handle to the registry key.
    01404
    01405     Input Parameters:
    01406
    01407         Key - Receives the handle to the key.
    01408
    01409         ValueName - Name of the value to be appended to.
    01410
    01411         Data - Buffer containing the multi-sz to be appended.
    01412
    01413         DataSize - Size of the data.
    01414
    01415     Return Value:
    01416
    01417         Standard NT status value.
    01418
    01419 --*/
    01420
    01421 {
    01422     NTSTATUS                    status;
    01423     ULONG                       size;
    01424     ANSI_STRING                 ansiString;
    01425     UNICODE_STRING              unicodeString;
    01426     PKEY_VALUE_FULL_INFORMATION valueInfo;
    01427     PVOID                       buffer;
    01428     PVOID                       str;
    01429
    01430     ASSERT(DataSize && *DataSize);
    01431     ASSERT(*Data);
    01432
    01433     RtlInitAnsiString(&ansiString, ValueName);
    01434     status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
    01435     if (NT_SUCCESS(status))
    01436     {
    01437         size = 0;
    01438         status = NtQueryValueKey(   Key,
    01439                                     &unicodeString,
    01440                                     KeyValueFullInformation,
    01441                                     NULL,
    01442                                     0,
    01443                                     &size);
    01444         if (size)
    01445         {
    01446             buffer = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG);
    01447             if (buffer)
    01448             {
    01449                 status = NtQueryValueKey(   Key,
    01450                                             &unicodeString,
    01451                                             KeyValueFullInformation,
    01452                                             buffer,
    01453                                             size,
    01454                                             &size);
    01455                 if (NT_SUCCESS(status))
    01456                 {
    01457                     valueInfo = (PKEY_VALUE_FULL_INFORMATION)buffer;
    01458                     str = ExAllocatePoolWithTag(    PagedPool,
    01459                                                     valueInfo->DataLength +
    01460                                                         *DataSize - sizeof(UNICODE_NULL),
    01461                                                     CM_GENINST_TAG);
    01462                     if (str)
    01463                     {
    01464                         memcpy( str,
    01465                                 (PCHAR)buffer + valueInfo->DataOffset,
    01466                                 valueInfo->DataLength);
    01467                         memcpy( (PCHAR)str + valueInfo->DataLength - sizeof(UNICODE_NULL),
    01468                                 *Data,
    01469                                 *DataSize);
    01470                         ExFreePool(*Data);
    01471                         *Data = str;
    01472                         *DataSize += valueInfo->DataLength - sizeof(UNICODE_NULL);
    01473                     }
    01474                     else
    01475                     {
    01476                         DbgPrint("CmpAppendStringToMultiSz: Failed to allocate memory!\n");
    01477                         ASSERT(str);
    01478                         status = STATUS_NO_MEMORY;
    01479                     }
    01480                 }
    01481                 ExFreePool(buffer);
    01482             }
    01483             else
    01484             {
    01485                 DbgPrint("CmpAppendStringToMultiSz: Failed to allocate memory!\n");
    01486                 ASSERT(buffer);
    01487                 status = STATUS_NO_MEMORY;
    01488             }
    01489         }
    01490         RtlFreeUnicodeString(&unicodeString);
    01491     }
    01492
    01493     return (status);
    01494 }