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

parseini.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1998 Microsoft Corporation 00004 00005 00006 Module Name: 00007 00008 parseini.c 00009 00010 Abstract: 00011 00012 This modules contains routines to parse an inf file. This is based on 00013 the code from the osloader. All indices are zero based. 00014 00015 Author: 00016 00017 Santosh Jodh (santoshj) 08-Aug-1998 00018 00019 00020 Environment: 00021 00022 Kernel mode. 00023 00024 Revision History: 00025 00026 --*/ 00027 00028 #include "cmp.h" 00029 #include "string.h" 00030 #include "ctype.h" 00031 #include "stdlib.h" 00032 #include "parseini.h" 00033 00034 typedef struct _value VALUE, *PVALUE; 00035 typedef struct _line LINE, *PLINE; 00036 typedef struct _section SECTION, *PSECTION; 00037 typedef struct _inf INF, *PINF; 00038 typedef struct _token TOKEN, *PTOKEN; 00039 typedef enum _tokentype TOKENTYPE, *PTOKENTTYPE; 00040 typedef enum _stringsSectionType STRINGSSECTIONTYPE;; 00041 00042 struct _value 00043 { 00044 PVALUE pNext; 00045 PCHAR pName; 00046 BOOLEAN Allocated; 00047 }; 00048 00049 struct _line 00050 { 00051 PLINE pNext; 00052 PCHAR pName; 00053 PVALUE pValue; 00054 BOOLEAN Allocated; 00055 }; 00056 00057 struct _section 00058 { 00059 PSECTION pNext; 00060 PCHAR pName; 00061 PLINE pLine; 00062 BOOLEAN Allocated; 00063 }; 00064 00065 struct _inf 00066 { 00067 PSECTION pSection; 00068 PSECTION pSectionRecord; 00069 PLINE pLineRecord; 00070 PVALUE pValueRecord; 00071 STRINGSSECTIONTYPE StringsSectionType; 00072 PSECTION StringsSection; 00073 }; 00074 00075 // 00076 // [Strings] section types. 00077 // 00078 enum _stringsSectionType 00079 { 00080 StringsSectionNone, 00081 StringsSectionPlain, 00082 StringsSectionLoosePrimaryMatch, 00083 StringsSectionExactPrimaryMatch, 00084 StringsSectionExactMatch 00085 }; 00086 00087 enum _tokentype 00088 { 00089 TOK_EOF, 00090 TOK_EOL, 00091 TOK_LBRACE, 00092 TOK_RBRACE, 00093 TOK_STRING, 00094 TOK_EQUAL, 00095 TOK_COMMA, 00096 TOK_ERRPARSE, 00097 TOK_ERRNOMEM 00098 }; 00099 00100 struct _token 00101 { 00102 TOKENTYPE Type; 00103 PCHAR pValue; 00104 BOOLEAN Allocated; 00105 }; 00106 00107 VOID 00108 CmpFreeValueList( 00109 IN PVALUE pValue 00110 ); 00111 00112 VOID 00113 CmpFreeLineList( 00114 IN PLINE pLine 00115 ); 00116 00117 VOID 00118 CmpFreeSectionList( 00119 IN PSECTION pSection 00120 ); 00121 00122 PCHAR 00123 CmpProcessForSimpleStringSub( 00124 IN PINF pInf, 00125 IN PCHAR String 00126 ); 00127 00128 BOOLEAN 00129 CmpAppendSection( 00130 IN PINF pInf, 00131 IN PCHAR pSectionName, 00132 IN BOOLEAN Allocated 00133 ); 00134 00135 BOOLEAN 00136 CmpAppendLine( 00137 IN PINF pInf, 00138 IN PCHAR pLineKey, 00139 IN BOOLEAN Allocated 00140 ); 00141 00142 BOOLEAN 00143 CmpAppendValue( 00144 IN PINF pInf, 00145 IN PCHAR pValueString, 00146 IN BOOLEAN Allocated 00147 ); 00148 00149 VOID 00150 CmpGetToken( 00151 IN OUT PCHAR *Stream, 00152 IN PCHAR MaxStream, 00153 IN OUT PULONG LineNumber, 00154 IN OUT PTOKEN Token 00155 ); 00156 00157 PINF 00158 CmpParseInfBuffer( 00159 IN PCHAR Buffer, 00160 IN ULONG Size, 00161 IN OUT PULONG ErrorLine 00162 ); 00163 00164 PVALUE 00165 CmpSearchValueInLine( 00166 IN PLINE pLine, 00167 IN ULONG ValueIndex 00168 ); 00169 00170 PLINE 00171 CmpSearchLineInSectionByIndex( 00172 IN PSECTION pSection, 00173 IN ULONG LineIndex 00174 ); 00175 00176 PSECTION 00177 CmpSearchSectionByName( 00178 IN PINF pInf, 00179 IN PCHAR SectionName 00180 ); 00181 00182 #ifdef ALLOC_PRAGMA 00183 #pragma alloc_text(INIT,CmpFreeValueList) 00184 #pragma alloc_text(INIT,CmpFreeLineList) 00185 #pragma alloc_text(INIT,CmpFreeSectionList) 00186 #pragma alloc_text(INIT,CmpProcessForSimpleStringSub) 00187 #pragma alloc_text(INIT,CmpAppendSection) 00188 #pragma alloc_text(INIT,CmpAppendLine) 00189 #pragma alloc_text(INIT,CmpAppendValue) 00190 #pragma alloc_text(INIT,CmpGetToken) 00191 #pragma alloc_text(INIT,CmpParseInfBuffer) 00192 #pragma alloc_text(INIT,CmpSearchValueInLine) 00193 #pragma alloc_text(INIT,CmpSearchLineInSectionByIndex) 00194 #pragma alloc_text(INIT,CmpSearchSectionByName) 00195 #pragma alloc_text(INIT,CmpSearchInfLine) 00196 #pragma alloc_text(INIT,CmpOpenInfFile) 00197 #pragma alloc_text(INIT,CmpCloseInfFile) 00198 #pragma alloc_text(INIT,CmpGetKeyName) 00199 #pragma alloc_text(INIT,CmpSearchInfSection) 00200 #pragma alloc_text(INIT,CmpGetSectionLineIndex) 00201 #pragma alloc_text(INIT,CmpGetSectionLineIndexValueCount) 00202 #pragma alloc_text(INIT,CmpGetIntField) 00203 #pragma alloc_text(INIT,CmpGetBinaryField) 00204 #endif 00205 00206 00207 // 00208 // Globals used by the token parser. 00209 // String terminators are the whitespace characters (isspace: space, tab, 00210 // linefeed, formfeed, vertical tab, carriage return) or the chars given below. 00211 // 00212 00213 CHAR StringTerminators[] = "[]=,\t \"\n\f\v\r"; 00214 PCHAR QStringTerminators = StringTerminators + 6; 00215 PCHAR EmptyValue; 00216 CHAR DblSpaceSection[] = "DBLSPACE_SECTION"; 00217 00218 BOOLEAN 00219 CmpAppendSection( 00220 IN PINF pInf, 00221 IN PCHAR pSectionName, 00222 IN BOOLEAN Allocated 00223 ) 00224 00225 /*++ 00226 00227 Routine Description: 00228 00229 This routine creates a new section or merges with an existing section in the inf. 00230 00231 Input Parameters: 00232 00233 pInf - Pointer to the inf to be processed. 00234 00235 pSectionName - Name of the section. 00236 00237 Allocated - TRUE if memory was allocated for the section name. 00238 00239 Return Value: 00240 00241 TRUE iff successful. 00242 00243 --*/ 00244 00245 { 00246 PSECTION pNewSection; 00247 PLINE pLineRecord; 00248 STRINGSSECTIONTYPE type; 00249 USHORT id; 00250 USHORT threadLang; 00251 PCHAR p; 00252 00253 // 00254 // Check to see if INF initialised and the parameters passed in is valid 00255 // 00256 00257 if ( pInf == (PINF)NULL || 00258 pSectionName == (PCHAR)NULL) 00259 { 00260 return (FALSE); 00261 } 00262 00263 // 00264 // See if we already have a section by this name. If so we want 00265 // to merge sections. 00266 // 00267 00268 for( pNewSection = pInf->pSection; 00269 pNewSection; 00270 pNewSection = pNewSection->pNext) 00271 { 00272 if(pNewSection->pName && _stricmp(pNewSection->pName,pSectionName) == 0) 00273 { 00274 break; 00275 } 00276 } 00277 00278 if(pNewSection) 00279 { 00280 // 00281 // Set pLineRecord to point to the last line currently in the section. 00282 // 00283 00284 for( pLineRecord = pNewSection->pLine; 00285 pLineRecord && pLineRecord->pNext; 00286 pLineRecord = pLineRecord->pNext); 00287 00288 pInf->pLineRecord = pLineRecord; 00289 } 00290 else 00291 { 00292 // 00293 // Allocate memory for the new section 00294 // 00295 00296 pNewSection = (PSECTION)ExAllocatePoolWithTag(PagedPool, sizeof(SECTION), CM_PARSEINI_TAG); 00297 00298 if (pNewSection == (PSECTION)NULL) 00299 { 00300 ASSERT(pNewSection); 00301 return (FALSE); 00302 } 00303 00304 // 00305 // Initialize the new section. 00306 // 00307 00308 pNewSection->pNext = NULL; 00309 pNewSection->pLine = NULL; 00310 pNewSection->pName = pSectionName; 00311 pNewSection->Allocated = Allocated; 00312 00313 // 00314 // Link it in. 00315 // 00316 00317 pNewSection->pNext = pInf->pSection; 00318 pInf->pSection = pNewSection; 00319 00320 if(_strnicmp(pSectionName, "Strings", 7) == 0) 00321 { 00322 type = StringsSectionNone; 00323 00324 if(pSectionName[7] == '.') 00325 { 00326 // 00327 // The langid part must be in the form of 4 hex digits. 00328 // 00329 00330 id = (USHORT)strtoul(pSectionName + 8, &p, 16); 00331 if(p == (pSectionName + 8 + 5) && *p == '\0') 00332 { 00333 threadLang = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale); 00334 00335 if(threadLang == id) 00336 { 00337 type = StringsSectionExactMatch; 00338 } 00339 else 00340 { 00341 if(id == PRIMARYLANGID(threadLang)) 00342 { 00343 type = StringsSectionExactPrimaryMatch; 00344 } 00345 else 00346 { 00347 if(PRIMARYLANGID(id) == PRIMARYLANGID(threadLang)) 00348 { 00349 type = StringsSectionLoosePrimaryMatch; 00350 } 00351 } 00352 } 00353 } 00354 } 00355 else 00356 { 00357 if(!pSectionName[7]) 00358 { 00359 type = StringsSectionPlain; 00360 } 00361 } 00362 00363 if(type > pInf->StringsSectionType) 00364 { 00365 pInf->StringsSection = pNewSection; 00366 } 00367 } 00368 00369 // 00370 // Reset the current line record. 00371 // 00372 00373 pInf->pLineRecord = NULL; 00374 } 00375 00376 pInf->pSectionRecord = pNewSection; 00377 pInf->pValueRecord = NULL; 00378 00379 return (TRUE); 00380 } 00381 00382 BOOLEAN 00383 CmpAppendLine( 00384 IN PINF pInf, 00385 IN PCHAR pLineKey, 00386 IN BOOLEAN Allocated 00387 ) 00388 00389 /*++ 00390 00391 Routine Description: 00392 00393 This routine creates a new line and appends it to the end of the line list. 00394 00395 Input Parameters: 00396 00397 pInf - Pointer to the inf to be processed. 00398 00399 pLineKey - Name of the line. 00400 00401 Allocated - TRUE if memory was allocated for the line name. 00402 00403 Return Value: 00404 00405 TRUE iff successful. 00406 00407 --*/ 00408 00409 { 00410 PLINE pNewLine; 00411 00412 // 00413 // Check to see if current section initialized. 00414 // 00415 00416 if (pInf->pSectionRecord == (PSECTION)NULL) 00417 { 00418 return (FALSE); 00419 } 00420 00421 // 00422 // Allocate memory for the new Line. 00423 // 00424 00425 pNewLine = (PLINE)ExAllocatePoolWithTag(PagedPool, sizeof(LINE), CM_PARSEINI_TAG); 00426 if (pNewLine == (PLINE)NULL) 00427 { 00428 ASSERT(pNewLine); 00429 return (FALSE); 00430 } 00431 00432 // 00433 // Link it in. 00434 // 00435 00436 pNewLine->pNext = (PLINE)NULL; 00437 pNewLine->pValue = (PVALUE)NULL; 00438 pNewLine->pName = pLineKey; 00439 pNewLine->Allocated = Allocated; 00440 00441 if (pInf->pLineRecord == (PLINE)NULL) 00442 { 00443 pInf->pSectionRecord->pLine = pNewLine; 00444 } 00445 else 00446 { 00447 pInf->pLineRecord->pNext = pNewLine; 00448 } 00449 00450 pInf->pLineRecord = pNewLine; 00451 00452 // 00453 // Reset the current value record 00454 // 00455 00456 pInf->pValueRecord = (PVALUE)NULL; 00457 00458 return (TRUE); 00459 } 00460 00461 BOOLEAN 00462 CmpAppendValue( 00463 IN PINF pInf, 00464 IN PCHAR pValueString, 00465 IN BOOLEAN Allocated 00466 ) 00467 00468 /*++ 00469 00470 Routine Description: 00471 00472 This routine creates a new value and appends it to the end of the value list. 00473 00474 Input Parameters: 00475 00476 pInf - Pointer to the inf to be processed. 00477 00478 pValueString - Name of the value. 00479 00480 Allocated - TRUE if memory was allocated for the value name. 00481 00482 Return Value: 00483 00484 TRUE iff successful. 00485 00486 --*/ 00487 00488 { 00489 PVALUE pNewValue; 00490 00491 // 00492 // Check to see if current line record has been initialised and 00493 // the parameter passed in is valid. 00494 // 00495 00496 if ( pInf->pLineRecord == (PLINE)NULL || 00497 pValueString == (PCHAR)NULL) 00498 { 00499 return (FALSE); 00500 } 00501 00502 // 00503 // Allocate memory for the new value record. 00504 // 00505 00506 pNewValue = (PVALUE)ExAllocatePoolWithTag(PagedPool, sizeof(VALUE), CM_PARSEINI_TAG); 00507 00508 if (pNewValue == (PVALUE)NULL) 00509 { 00510 ASSERT(pNewValue); 00511 return (FALSE); 00512 } 00513 00514 // 00515 // Link it in. 00516 // 00517 00518 pNewValue->pNext = (PVALUE)NULL; 00519 pNewValue->pName = pValueString; 00520 pNewValue->Allocated = Allocated; 00521 00522 if (pInf->pValueRecord == (PVALUE)NULL) 00523 { 00524 pInf->pLineRecord->pValue = pNewValue; 00525 } 00526 else 00527 { 00528 pInf->pValueRecord->pNext = pNewValue; 00529 } 00530 00531 pInf->pValueRecord = pNewValue; 00532 00533 return (TRUE); 00534 } 00535 00536 VOID 00537 CmpGetToken( 00538 IN OUT PCHAR *Stream, 00539 IN PCHAR MaxStream, 00540 IN OUT PULONG LineNumber, 00541 IN OUT PTOKEN Token 00542 ) 00543 00544 /*++ 00545 00546 Routine Description: 00547 00548 This function returns the Next token from the configuration stream. 00549 00550 Arguments: 00551 00552 Stream - Supplies the address of the configuration stream. Returns 00553 the address of where to start looking for tokens within the 00554 stream. 00555 00556 MaxStream - Supplies the address of the last character in the stream. 00557 00558 00559 Return Value: 00560 00561 None. 00562 00563 --*/ 00564 00565 { 00566 00567 PCHAR pch; 00568 PCHAR pchStart; 00569 PCHAR pchNew; 00570 ULONG length; 00571 BOOLEAN done; 00572 00573 Token->Allocated = FALSE; 00574 Token->pValue = NULL; 00575 00576 do 00577 { 00578 done = TRUE; 00579 00580 // 00581 // Skip whitespace (except for EOL). 00582 // 00583 00584 for ( pch = *Stream; 00585 pch < MaxStream && *pch != '\n' && isspace(*pch); 00586 pch++); 00587 00588 // 00589 // Check for comments and remove them. 00590 // 00591 00592 if ( pch < MaxStream && 00593 (*pch == '#' || *pch == ';')) 00594 { 00595 while (pch < MaxStream && *pch != '\n') 00596 { 00597 pch++; 00598 } 00599 } 00600 00601 // 00602 // Check to see if EOF has been reached, set the token to the right 00603 // value. 00604 // 00605 00606 if (pch >= MaxStream || *pch == 26) 00607 { 00608 *Stream = pch; 00609 Token->Type = TOK_EOF; 00610 Token->pValue = NULL; 00611 00612 return; 00613 } 00614 00615 switch (*pch) 00616 { 00617 case '[': 00618 00619 pch++; 00620 Token->Type = TOK_LBRACE; 00621 break; 00622 00623 case ']': 00624 00625 pch++; 00626 Token->Type = TOK_RBRACE; 00627 break; 00628 00629 case '=': 00630 00631 pch++; 00632 Token->Type = TOK_EQUAL; 00633 break; 00634 00635 case ',': 00636 00637 pch++; 00638 Token->Type = TOK_COMMA; 00639 break; 00640 00641 case '\n': 00642 00643 pch++; 00644 Token->Type = TOK_EOL; 00645 break; 00646 00647 case '\"': 00648 00649 pch++; 00650 00651 // 00652 // Determine quoted string. 00653 // 00654 00655 for ( pchStart = pch; 00656 pch < MaxStream && (strchr(QStringTerminators, *pch) == NULL); 00657 pch++); 00658 00659 if (pch >= MaxStream || *pch != '\"') 00660 { 00661 Token->Type = TOK_ERRPARSE; 00662 } 00663 else 00664 { 00665 00666 // 00667 // We require a quoted string to end with a double-quote. 00668 // (If the string ended with anything else, the if() above 00669 // would not have let us into the else clause.) The quote 00670 // character is irrelevent, however, and can be overwritten. 00671 // So we'll save some heap and use the string in-place. 00672 // No need to make a copy. 00673 // 00674 // Note that this alters the image of txtsetup.sif we pass 00675 // to setupdd.sys. Thus the inf parser in setupdd.sys must 00676 // be able to treat a nul character as if it were a terminating 00677 // double quote. 00678 // 00679 00680 *pch++ = '\0'; 00681 Token->Type = TOK_STRING; 00682 Token->pValue = pchStart; 00683 } 00684 break; 00685 00686 case '\\': 00687 00688 for ( pchNew = ++pch; 00689 pchNew < MaxStream && 00690 *pchNew != '\n' && isspace(*pchNew); 00691 pchNew++); 00692 00693 if (*pchNew == '\n') 00694 { 00695 pch = pchNew + 1; 00696 done = FALSE; 00697 break; 00698 } 00699 00700 default: 00701 00702 // 00703 // Determine regular string. 00704 // 00705 00706 for ( pchStart = pch; 00707 pch < MaxStream && (strchr(StringTerminators, *pch) == NULL); 00708 pch++); 00709 00710 if (pch == pchStart) 00711 { 00712 pch++; 00713 Token->Type = TOK_ERRPARSE; 00714 } 00715 else 00716 { 00717 length = (ULONG)(pch - pchStart); 00718 pchNew = ExAllocatePoolWithTag(PagedPool, length + 1, CM_PARSEINI_TAG); 00719 if (pchNew == NULL) 00720 { 00721 ASSERT(pchNew); 00722 Token->Type = TOK_ERRNOMEM; 00723 } 00724 else 00725 { 00726 strncpy(pchNew, pchStart, length); 00727 pchNew[length] = 0; 00728 Token->Type = TOK_STRING; 00729 Token->pValue = pchNew; 00730 Token->Allocated = TRUE; 00731 } 00732 } 00733 break; 00734 } 00735 00736 *Stream = pch; 00737 } 00738 while (!done); 00739 00740 return; 00741 } 00742 00743 PINF 00744 CmpParseInfBuffer( 00745 IN PCHAR Buffer, 00746 IN ULONG Size, 00747 IN OUT PULONG ErrorLine 00748 ) 00749 00750 /*++ 00751 00752 Routine Description: 00753 00754 Given a character buffer containing the INF file, this routine parses 00755 the INF into an internal form with Section records, Line records and 00756 Value records. 00757 00758 Arguments: 00759 00760 Buffer - contains to ptr to a buffer containing the INF file 00761 00762 Size - contains the size of the buffer. 00763 00764 ErrorLine - if a parse error occurs, this variable receives the line 00765 number of the line containing the error. 00766 00767 00768 Return Value: 00769 00770 PVOID - INF handle ptr to be used in subsequent INF calls. 00771 00772 --*/ 00773 00774 { 00775 PINF pInf; 00776 ULONG state; 00777 PCHAR stream; 00778 PCHAR maxStream; 00779 PCHAR pchSectionName; 00780 PCHAR pchValue; 00781 TOKEN token; 00782 BOOLEAN done; 00783 BOOLEAN error; 00784 ULONG infLine; 00785 BOOLEAN allocated; 00786 00787 // 00788 // Need EmptyValue to point at a NULL character. 00789 // 00790 00791 EmptyValue = StringTerminators + strlen(StringTerminators); 00792 00793 // 00794 // Allocate memory for the INF record. 00795 // 00796 00797 pInf = (PINF)ExAllocatePoolWithTag(PagedPool, sizeof(INF), CM_PARSEINI_TAG); 00798 00799 if (pInf == NULL) 00800 { 00801 ASSERT(pInf); 00802 return (pInf); 00803 } 00804 00805 pInf->pSection = NULL; 00806 pInf->pSectionRecord = NULL; 00807 pInf->pLineRecord = NULL; 00808 pInf->pValueRecord = NULL; 00809 pInf->StringsSectionType = StringsSectionNone; 00810 pInf->StringsSection = NULL; 00811 00812 // 00813 // Set initial state. 00814 // 00815 00816 state = 1; 00817 stream = Buffer; 00818 maxStream = Buffer + Size; 00819 pchSectionName = NULL; 00820 pchValue = NULL; 00821 done = FALSE; 00822 error = FALSE; 00823 infLine = 1; 00824 00825 // 00826 // Enter token processing loop. 00827 // 00828 00829 while (!done) 00830 { 00831 00832 CmpGetToken(&stream, maxStream, &infLine, &token); 00833 00834 switch (state) 00835 { 00836 // 00837 // STATE1: Start of file, this state remains till first 00838 // section is found 00839 // Valid Tokens: TOK_EOL, TOK_EOF, TOK_LBRACE 00840 // TOK_STRING when reading Dblspace.inf 00841 // 00842 00843 case 1: 00844 00845 switch (token.Type) 00846 { 00847 case TOK_EOL: 00848 00849 break; 00850 00851 case TOK_EOF: 00852 00853 done = TRUE; 00854 00855 break; 00856 00857 case TOK_LBRACE: 00858 00859 state = 2; 00860 00861 break; 00862 00863 case TOK_STRING: 00864 00865 pchSectionName = ExAllocatePoolWithTag(PagedPool, sizeof(DblSpaceSection), CM_PARSEINI_TAG); 00866 if (pchSectionName) 00867 { 00868 strcpy(pchSectionName, DblSpaceSection); 00869 pchValue = token.pValue; 00870 allocated = TRUE; 00871 token.Allocated = TRUE; 00872 if (CmpAppendSection(pInf, pchSectionName, TRUE)) 00873 { 00874 pchSectionName = NULL; 00875 state = 6; 00876 } 00877 else 00878 { 00879 error = done = TRUE; 00880 } 00881 } 00882 else 00883 { 00884 ASSERT(pchSectionName); 00885 error = done = TRUE; 00886 } 00887 00888 break; 00889 00890 default: 00891 00892 error = done = TRUE; 00893 00894 break; 00895 } 00896 00897 break; 00898 00899 // 00900 // STATE 2: Section LBRACE has been received, expecting STRING 00901 // 00902 // Valid Tokens: TOK_STRING, TOK_RBRACE 00903 // 00904 00905 case 2: 00906 00907 switch (token.Type) 00908 { 00909 case TOK_STRING: 00910 00911 state = 3; 00912 pchSectionName = token.pValue; 00913 allocated = token.Allocated; 00914 00915 break; 00916 00917 case TOK_RBRACE: 00918 00919 token.pValue = EmptyValue; 00920 token.Allocated = FALSE; 00921 allocated = FALSE; 00922 state = 4; 00923 00924 break; 00925 00926 default: 00927 00928 error = done = TRUE; 00929 00930 break; 00931 00932 } 00933 00934 break; 00935 00936 // 00937 // STATE 3: Section Name received, expecting RBRACE 00938 // 00939 // Valid Tokens: TOK_RBRACE 00940 // 00941 00942 case 3: 00943 00944 switch (token.Type) 00945 { 00946 case TOK_RBRACE: 00947 00948 state = 4; 00949 00950 break; 00951 00952 default: 00953 00954 error = done = TRUE; 00955 00956 break; 00957 } 00958 00959 break; 00960 00961 // 00962 // STATE 4: Section Definition Complete, expecting EOL 00963 // 00964 // Valid Tokens: TOK_EOL, TOK_EOF 00965 // 00966 00967 case 4: 00968 00969 switch (token.Type) 00970 { 00971 00972 case TOK_EOL: 00973 00974 if (!CmpAppendSection(pInf, pchSectionName, allocated)) 00975 { 00976 00977 error = done = TRUE; 00978 } 00979 else 00980 { 00981 pchSectionName = NULL; 00982 state = 5; 00983 } 00984 00985 break; 00986 00987 case TOK_EOF: 00988 00989 if (!CmpAppendSection(pInf, pchSectionName, allocated)) 00990 { 00991 error = done = TRUE; 00992 } 00993 else 00994 { 00995 pchSectionName = NULL; 00996 done = TRUE; 00997 } 00998 00999 break; 01000 01001 default: 01002 01003 error = done = TRUE; 01004 01005 break; 01006 } 01007 01008 break; 01009 01010 // 01011 // STATE 5: Expecting Section Lines 01012 // 01013 // Valid Tokens: TOK_EOL, TOK_EOF, TOK_STRING, TOK_LBRACE 01014 // 01015 01016 case 5: 01017 01018 switch (token.Type) 01019 { 01020 case TOK_EOL: 01021 01022 break; 01023 01024 case TOK_EOF: 01025 01026 done = TRUE; 01027 01028 break; 01029 01030 case TOK_STRING: 01031 01032 pchValue = token.pValue; 01033 allocated = token.Allocated; 01034 state = 6; 01035 01036 break; 01037 01038 case TOK_LBRACE: 01039 01040 state = 2; 01041 01042 break; 01043 01044 default: 01045 01046 error = done = TRUE; 01047 01048 break; 01049 } 01050 01051 break; 01052 01053 // 01054 // STATE 6: String returned, not sure whether it is key or value 01055 // 01056 // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA, TOK_EQUAL 01057 // 01058 01059 case 6: 01060 01061 switch (token.Type) 01062 { 01063 01064 case TOK_EOL: 01065 01066 if ( !CmpAppendLine(pInf, NULL, FALSE) || 01067 !CmpAppendValue(pInf, pchValue, allocated)) 01068 { 01069 error = done = TRUE; 01070 } 01071 else 01072 { 01073 pchValue = NULL; 01074 state = 5; 01075 } 01076 01077 break; 01078 01079 case TOK_EOF: 01080 01081 if ( !CmpAppendLine(pInf, NULL, FALSE) || 01082 !CmpAppendValue(pInf, pchValue, allocated)) 01083 { 01084 error = done = TRUE; 01085 } 01086 else 01087 { 01088 pchValue = NULL; 01089 done = TRUE; 01090 } 01091 01092 break; 01093 01094 case TOK_COMMA: 01095 01096 if ( !CmpAppendLine(pInf, NULL, FALSE) || 01097 !CmpAppendValue(pInf, pchValue, allocated)) 01098 { 01099 error = done = TRUE; 01100 } 01101 else 01102 { 01103 pchValue = NULL; 01104 state = 7; 01105 } 01106 01107 break; 01108 01109 case TOK_EQUAL: 01110 01111 if (!CmpAppendLine(pInf, pchValue, allocated)) 01112 { 01113 error = done = TRUE; 01114 } 01115 else 01116 { 01117 pchValue = NULL; 01118 state = 8; 01119 } 01120 01121 break; 01122 01123 default: 01124 01125 error = done = TRUE; 01126 01127 break; 01128 } 01129 01130 break; 01131 01132 // 01133 // STATE 7: Comma received, Expecting another string 01134 // 01135 // Valid Tokens: TOK_STRING TOK_COMMA 01136 // A comma means we have an empty value. 01137 // 01138 01139 case 7: 01140 01141 switch (token.Type) 01142 { 01143 01144 case TOK_COMMA: 01145 01146 token.pValue = EmptyValue; 01147 token.Allocated = FALSE; 01148 allocated = FALSE; 01149 if (!CmpAppendValue(pInf, token.pValue, FALSE)) 01150 { 01151 error = done = TRUE; 01152 } 01153 01154 // 01155 // State stays at 7 because we are expecting a string 01156 // 01157 01158 break; 01159 01160 case TOK_STRING: 01161 01162 if (!CmpAppendValue(pInf, token.pValue, token.Allocated)) 01163 { 01164 error = done = TRUE; 01165 } 01166 else 01167 { 01168 state = 9; 01169 } 01170 01171 break; 01172 01173 default: 01174 01175 error = done = TRUE; 01176 01177 break; 01178 } 01179 01180 break; 01181 01182 // 01183 // STATE 8: Equal received, Expecting another string 01184 // If none, assume there is a single empty string on the RHS 01185 // 01186 // Valid Tokens: TOK_STRING, TOK_EOL, TOK_EOF 01187 // 01188 01189 case 8: 01190 01191 switch (token.Type) 01192 { 01193 case TOK_EOF: 01194 01195 token.pValue = EmptyValue; 01196 token.Allocated = FALSE; 01197 allocated = FALSE; 01198 if(!CmpAppendValue(pInf, token.pValue, FALSE)) 01199 { 01200 error = TRUE; 01201 } 01202 01203 done = TRUE; 01204 01205 break; 01206 01207 case TOK_EOL: 01208 01209 token.pValue = EmptyValue; 01210 token.Allocated = FALSE; 01211 allocated = FALSE; 01212 if(!CmpAppendValue(pInf, token.pValue, FALSE)) 01213 { 01214 error = TRUE; 01215 done = TRUE; 01216 } 01217 else 01218 { 01219 state = 5; 01220 } 01221 01222 break; 01223 01224 case TOK_STRING: 01225 01226 if (!CmpAppendValue(pInf, token.pValue, FALSE)) 01227 { 01228 error = done = TRUE; 01229 } 01230 else 01231 { 01232 state = 9; 01233 } 01234 01235 break; 01236 01237 default: 01238 01239 error = done = TRUE; 01240 01241 break; 01242 } 01243 01244 break; 01245 01246 // 01247 // STATE 9: String received after equal, value string 01248 // 01249 // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA 01250 // 01251 01252 case 9: 01253 01254 switch (token.Type) 01255 { 01256 case TOK_EOL: 01257 01258 state = 5; 01259 01260 break; 01261 01262 case TOK_EOF: 01263 01264 done = TRUE; 01265 01266 break; 01267 01268 case TOK_COMMA: 01269 01270 state = 7; 01271 01272 break; 01273 01274 default: 01275 01276 error = done = TRUE; 01277 01278 break; 01279 } 01280 01281 break; 01282 01283 // 01284 // STATE 10: Value string definitely received 01285 // 01286 // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA 01287 // 01288 01289 case 10: 01290 01291 switch (token.Type) 01292 { 01293 case TOK_EOL: 01294 01295 state =5; 01296 01297 break; 01298 01299 case TOK_EOF: 01300 01301 done = TRUE; 01302 01303 break; 01304 01305 case TOK_COMMA: 01306 01307 state = 7; 01308 01309 break; 01310 01311 default: 01312 01313 error = done = TRUE; 01314 01315 break; 01316 } 01317 01318 break; 01319 01320 default: 01321 01322 error = done = TRUE; 01323 01324 break; 01325 01326 } // END switch(state) 01327 01328 01329 if (error) 01330 { 01331 *ErrorLine = infLine; 01332 if (pchSectionName != (PCHAR)NULL && allocated) 01333 { 01334 ExFreePool(pchSectionName); 01335 } 01336 01337 if (pchValue != (PCHAR)NULL && allocated) 01338 { 01339 ExFreePool(pchValue); 01340 } 01341 01342 ExFreePool(pInf); 01343 01344 pInf = (PINF)NULL; 01345 } 01346 else 01347 { 01348 // 01349 // Keep track of line numbers for error reporting. 01350 // 01351 01352 if (token.Type == TOK_EOL) 01353 { 01354 infLine++; 01355 } 01356 } 01357 01358 } // END while 01359 01360 if (pInf) 01361 { 01362 pInf->pSectionRecord = NULL; 01363 } 01364 01365 return(pInf); 01366 } 01367 01368 PCHAR 01369 CmpProcessForSimpleStringSub( 01370 IN PINF pInf, 01371 IN PCHAR String 01372 ) 01373 01374 /*++ 01375 01376 Routine Description: 01377 01378 This routine substitutes reference to string in the STRINGS section of the inf. 01379 01380 Input Parameters: 01381 01382 pInf - Pointer to the inf to be processed. 01383 01384 String - String to be substituted. 01385 01386 Return Value: 01387 01388 None. 01389 01390 --*/ 01391 01392 { 01393 ULONG len; 01394 PCHAR returnString; 01395 PSECTION pSection; 01396 PLINE pLine; 01397 01398 // 01399 // Assume no substitution necessary. 01400 // 01401 01402 returnString = String; 01403 len = strlen(String); 01404 pSection = pInf->StringsSection; 01405 01406 // 01407 // If it starts and end with % then look it up in the 01408 // strings section. Note the initial check before doing a 01409 // wcslen, to preserve performance in the 99% case where 01410 // there is no substitution. 01411 // 01412 01413 if( String[0] == '%' && 01414 len > 2 && 01415 String[len - 1] == '%' && 01416 pSection) 01417 { 01418 01419 for(pLine = pSection->pLine; pLine; pLine = pLine->pNext) 01420 { 01421 if( pLine->pName && 01422 _strnicmp(pLine->pName, String + 1, len - 2) == 0 && 01423 pLine->pName[len - 2] == '\0') 01424 { 01425 break; 01426 } 01427 } 01428 01429 if(pLine && pLine->pValue && pLine->pValue->pName) 01430 { 01431 returnString = pLine->pValue->pName; 01432 } 01433 } 01434 01435 return(returnString); 01436 } 01437 01438 VOID 01439 CmpFreeValueList( 01440 IN PVALUE pValue 01441 ) 01442 01443 /*++ 01444 01445 Routine Description: 01446 01447 This routine releases memory for the list of values. 01448 01449 Input Parameters: 01450 01451 pValue - Pointer to the value list to be freed. 01452 01453 Return Value: 01454 01455 None. 01456 01457 --*/ 01458 01459 { 01460 PVALUE pNext; 01461 01462 while (pValue) 01463 { 01464 // 01465 // Save the next pointer so we dont access memory after it has 01466 // been freed. 01467 // 01468 01469 pNext = pValue->pNext; 01470 01471 // 01472 // Free any data inside this value. 01473 // 01474 01475 if (pValue->Allocated && pValue->pName) 01476 { 01477 ExFreePool((PVOID)pValue->pName); 01478 } 01479 01480 // 01481 // Free memory for this value. 01482 // 01483 01484 ExFreePool(pValue); 01485 01486 // 01487 // Go to the next value. 01488 // 01489 01490 pValue = pNext; 01491 } 01492 } 01493 01494 VOID 01495 CmpFreeLineList( 01496 IN PLINE pLine 01497 ) 01498 01499 /*++ 01500 01501 Routine Description: 01502 01503 This routine releases memory for the list of lines and 01504 values under it. 01505 01506 Input Parameters: 01507 01508 pLine - Pointer to the line list to be freed. 01509 01510 Return Value: 01511 01512 None. 01513 01514 --*/ 01515 01516 { 01517 PLINE pNext; 01518 01519 while (pLine) 01520 { 01521 // 01522 // Save the next pointer so we dont access memory after it has 01523 // been freed. 01524 // 01525 01526 pNext = pLine->pNext; 01527 01528 // 01529 // Free any data inside this Line. 01530 // 01531 01532 if (pLine->Allocated && pLine->pName) 01533 { 01534 ExFreePool((PVOID)pLine->pName); 01535 } 01536 01537 // 01538 // Free the list of values inside this Line. 01539 // 01540 01541 CmpFreeValueList(pLine->pValue); 01542 01543 // 01544 // Free memory for this line itself. 01545 // 01546 01547 ExFreePool((PVOID)pLine); 01548 01549 // 01550 // Go to the next line. 01551 // 01552 01553 pLine = pNext; 01554 } 01555 } 01556 01557 VOID 01558 CmpFreeSectionList( 01559 IN PSECTION pSection 01560 ) 01561 01562 /*++ 01563 01564 Routine Description: 01565 01566 This routine releases memory for the list of sections and 01567 lines under it. 01568 01569 Input Parameters: 01570 01571 pSection - Pointer to the section list to be freed. 01572 01573 Return Value: 01574 01575 None. 01576 01577 --*/ 01578 01579 { 01580 PSECTION pNext; 01581 01582 while (pSection) 01583 { 01584 // 01585 // Save the next pointer so we dont access memory after it has 01586 // been freed. 01587 // 01588 01589 pNext = pSection->pNext; 01590 01591 // 01592 // Free any data inside this Line. 01593 // 01594 01595 if (pSection->Allocated && pSection->pName) 01596 { 01597 ExFreePool((PVOID)pSection->pName); 01598 } 01599 01600 // 01601 // Free the list of values inside this Line. 01602 // 01603 01604 CmpFreeLineList(pSection->pLine); 01605 01606 // 01607 // Free memory for this line itself. 01608 // 01609 01610 ExFreePool((PVOID)pSection); 01611 01612 // 01613 // Go to the next line. 01614 // 01615 01616 pSection = pNext; 01617 } 01618 01619 } 01620 01621 PVALUE 01622 CmpSearchValueInLine( 01623 IN PLINE pLine, 01624 IN ULONG ValueIndex 01625 ) 01626 01627 /*++ 01628 01629 Routine Description: 01630 01631 This routine searches for the specified value in the inf. 01632 01633 Input Parameters: 01634 01635 pLine - Pointer to the line to be searched. 01636 01637 ValueIndex - Index of the value to be searched. 01638 01639 Return Value: 01640 01641 Pointer to the value iff found. Else NULL. 01642 01643 --*/ 01644 01645 { 01646 ULONG i; 01647 PVALUE pValue = NULL; 01648 01649 if (pLine) 01650 { 01651 for ( i = 0, pValue = pLine->pValue; 01652 i < ValueIndex && pValue; 01653 i++, pValue = pValue->pNext); 01654 } 01655 01656 return (pValue); 01657 } 01658 01659 01660 PSECTION 01661 CmpSearchSectionByName( 01662 IN PINF pInf, 01663 IN PCHAR SectionName 01664 ) 01665 01666 /*++ 01667 01668 Routine Description: 01669 01670 This routine searches for the specified section in the inf. 01671 01672 Input Parameters: 01673 01674 pInf - Pointer to the inf to be searched. 01675 01676 SectionName - Name of the section to be searched. 01677 01678 Return Value: 01679 01680 Pointer to the section iff found. Else NULL. 01681 01682 --*/ 01683 01684 { 01685 PSECTION pSection = NULL; 01686 PSECTION pFirstSearchedSection; 01687 01688 // 01689 // Validate the parameters passed in. 01690 // 01691 01692 if (pInf && SectionName) 01693 { 01694 // 01695 // Traverse down the section list searching each section for the 01696 // section name mentioned. 01697 // 01698 01699 for ( pSection = pFirstSearchedSection = pInf->pSectionRecord; 01700 pSection && _stricmp(pSection->pName, SectionName); 01701 pSection = pSection->pNext); 01702 01703 // 01704 // If we did not find the section, search from the beginning. 01705 // 01706 01707 if (pSection == NULL) 01708 { 01709 for ( pSection = pInf->pSection; 01710 pSection && pSection != pFirstSearchedSection; 01711 pSection = pSection->pNext) 01712 { 01713 if (pSection->pName && _stricmp(pSection->pName, SectionName) == 0) 01714 { 01715 break; 01716 } 01717 } 01718 01719 if (pSection == pFirstSearchedSection) 01720 { 01721 pSection = NULL; 01722 } 01723 } 01724 01725 if (pSection) 01726 { 01727 pInf->pSectionRecord = pSection; 01728 } 01729 } 01730 01731 // 01732 // Return the section at which we stopped. 01733 // 01734 01735 return (pSection); 01736 } 01737 01738 PLINE 01739 CmpSearchLineInSectionByIndex( 01740 IN PSECTION pSection, 01741 IN ULONG LineIndex 01742 ) 01743 01744 /*++ 01745 01746 Routine Description: 01747 01748 This routine searches for the specified line in the inf. 01749 01750 Input Parameters: 01751 01752 pSection - Pointer to the section to be searched. 01753 01754 LineIndex - Index of the line to be searched. 01755 01756 Return Value: 01757 01758 Pointer to the line iff found. Else NULL. 01759 01760 --*/ 01761 01762 { 01763 PLINE pLine = NULL; 01764 ULONG i; 01765 01766 // 01767 // Validate the parameters passed in. 01768 // 01769 01770 if (pSection) 01771 { 01772 01773 // 01774 // Traverse down the current line list to the LineIndex line. 01775 // 01776 01777 for( i = 0, pLine = pSection->pLine; 01778 i < LineIndex && pLine; 01779 i++, pLine = pLine->pNext); 01780 } 01781 01782 // 01783 // Return the Line found 01784 // 01785 01786 return (pLine); 01787 } 01788 01789 PVOID 01790 CmpOpenInfFile( 01791 IN PVOID InfImage, 01792 IN ULONG ImageSize 01793 ) 01794 01795 /*++ 01796 01797 Routine Description: 01798 01799 This routine opens an handle to the inf. 01800 01801 Input Parameters: 01802 01803 InfImage - Pointer to the inf image read into memory. 01804 01805 ImageSize - Image size. 01806 01807 Return Value: 01808 01809 Returns handle to the inf iff successful. Else NULL. 01810 01811 --*/ 01812 01813 { 01814 PINF infHandle; 01815 ULONG errorLine = 0; 01816 01817 // 01818 // Parse the inf buffer. 01819 // 01820 01821 infHandle = CmpParseInfBuffer(InfImage, ImageSize, &errorLine); 01822 01823 if (infHandle == NULL) 01824 { 01825 DbgPrint("Error on line %d in CmpOpenInfFile!\n", errorLine); 01826 } 01827 01828 return (infHandle); 01829 } 01830 01831 VOID 01832 CmpCloseInfFile( 01833 PVOID InfHandle 01834 ) 01835 01836 /*++ 01837 01838 Routine Description: 01839 01840 This routine closes the inf handle by releasing any 01841 memory allocated for it during parsing. 01842 01843 Input Parameters: 01844 01845 InfHandle - Handle to the inf to be closed. 01846 01847 Return Value: 01848 01849 None. 01850 01851 --*/ 01852 01853 { 01854 if (InfHandle) 01855 { 01856 CmpFreeSectionList(((PINF)InfHandle)->pSection); 01857 ExFreePool(InfHandle); 01858 } 01859 } 01860 01861 BOOLEAN 01862 CmpSearchInfSection( 01863 IN PINF pInf, 01864 IN PCHAR Section 01865 ) 01866 01867 /*++ 01868 01869 Routine Description: 01870 01871 This routine searches for the specified section in the inf. 01872 01873 Input Parameters: 01874 01875 InfHandle - Handle to the inf to be read. 01876 01877 Section - Name of the section to be read. 01878 01879 Return Value: 01880 01881 TRUE iff section is found in the inf. 01882 01883 --*/ 01884 01885 { 01886 return (CmpSearchSectionByName(pInf, Section) != NULL); 01887 } 01888 01889 PCHAR 01890 CmpGetKeyName( 01891 IN PVOID InfHandle, 01892 IN PCHAR Section, 01893 IN ULONG LineIndex 01894 ) 01895 01896 /*++ 01897 01898 Routine Description: 01899 01900 This routine returns the name of the specified line in the inf. 01901 01902 Input Parameters: 01903 01904 InfHandle - Handle to the inf to be read. 01905 01906 Section - Name of the section to be read. 01907 01908 LineIndex - Index of the line to be read. 01909 01910 Return Value: 01911 01912 Pointer to the name of line in the inf iff successful. Else NULL. 01913 01914 --*/ 01915 01916 { 01917 PSECTION pSection; 01918 PLINE pLine; 01919 01920 // 01921 // First search the section. 01922 // 01923 01924 pSection = CmpSearchSectionByName((PINF)InfHandle, Section); 01925 if(pSection) 01926 { 01927 // 01928 // Get the line in the section. 01929 // 01930 01931 pLine = CmpSearchLineInSectionByIndex(pSection, LineIndex); 01932 if(pLine) 01933 { 01934 return(pLine->pName); 01935 } 01936 } 01937 01938 return (NULL); 01939 } 01940 01941 BOOLEAN 01942 CmpSearchInfLine( 01943 IN PVOID InfHandle, 01944 IN PCHAR Section, 01945 IN ULONG LineIndex 01946 ) 01947 01948 /*++ 01949 01950 Routine Description: 01951 01952 This routine searches for the specified line in the inf. 01953 01954 Input Parameters: 01955 01956 InfHandle - Handle to the inf to be read. 01957 01958 Section - Name of the section to be read. 01959 01960 LineIndex - Index of the line to be read. 01961 01962 Return Value: 01963 01964 TRUE iff line is found in the section in the inf. 01965 01966 --*/ 01967 01968 { 01969 PSECTION pSection; 01970 PLINE pLine = NULL; 01971 01972 // 01973 // First search the section. 01974 // 01975 01976 pSection = CmpSearchSectionByName((PINF)InfHandle, Section); 01977 if(pSection) 01978 { 01979 // 01980 // Search the line in the section. 01981 // 01982 01983 pLine = CmpSearchLineInSectionByIndex(pSection, LineIndex); 01984 } 01985 01986 return (pLine != NULL); 01987 } 01988 01989 01990 PCHAR 01991 CmpGetSectionLineIndex ( 01992 IN PVOID InfHandle, 01993 IN PCHAR Section, 01994 IN ULONG LineIndex, 01995 IN ULONG ValueIndex 01996 ) 01997 01998 /*++ 01999 02000 Routine Description: 02001 02002 This routine returns the value at the specified location in the inf. 02003 02004 Input Parameters: 02005 02006 InfHandle - Handle to the inf to be read. 02007 02008 Section - Name of the section to be read. 02009 02010 LineIndex - Index of the line to be read. 02011 02012 ValueIndex - Index of the value to be read. 02013 02014 Return Value: 02015 02016 Pointer to the value iff successful. Else NULL. 02017 02018 --*/ 02019 02020 { 02021 PSECTION pSection; 02022 PLINE pLine; 02023 PVALUE pValue; 02024 02025 // 02026 // Search the section in the inf. 02027 // 02028 02029 pSection = CmpSearchSectionByName((PINF)InfHandle, Section); 02030 if(pSection) 02031 { 02032 // 02033 // Search the line in the section. 02034 // 02035 02036 pLine = CmpSearchLineInSectionByIndex(pSection, LineIndex); 02037 if(pLine) 02038 { 02039 // 02040 // Search the value in the line. 02041 // 02042 02043 pValue = CmpSearchValueInLine(pLine, ValueIndex); 02044 if(pValue) 02045 { 02046 // 02047 // The value may need to be replaced by one of the strings 02048 // from the string section. 02049 // 02050 02051 return(CmpProcessForSimpleStringSub(InfHandle, pValue->pName)); 02052 } 02053 } 02054 } 02055 02056 return(NULL); 02057 } 02058 02059 ULONG 02060 CmpGetSectionLineIndexValueCount( 02061 IN PVOID InfHandle, 02062 IN PCHAR Section, 02063 IN ULONG LineIndex 02064 ) 02065 02066 /*++ 02067 02068 Routine Description: 02069 02070 This routine returns the number of values in the inf line. 02071 02072 Input Parameters: 02073 02074 InfHandle - Handle to the inf to be read. 02075 02076 Section - Name of the section to be read. 02077 02078 LineIndex - Index of the line to be read. 02079 02080 Return Value: 02081 02082 Number of values in the inf line. 02083 02084 --*/ 02085 02086 { 02087 PSECTION pSection; 02088 PLINE pLine; 02089 PVALUE pValue; 02090 ULONG count = 0; 02091 02092 // 02093 // Search the section in the inf. 02094 // 02095 02096 pSection = CmpSearchSectionByName((PINF)InfHandle, Section); 02097 if(pSection) 02098 { 02099 // 02100 // Search the line in the section. 02101 // 02102 02103 pLine = CmpSearchLineInSectionByIndex(pSection, LineIndex); 02104 if (pLine) 02105 { 02106 // 02107 // Count the number of values in this line. 02108 // 02109 02110 for( pValue = pLine->pValue; 02111 pValue; 02112 pValue = pValue->pNext, count++); 02113 } 02114 } 02115 02116 return (count); 02117 } 02118 02119 BOOLEAN 02120 CmpGetIntField( 02121 IN PVOID InfHandle, 02122 IN PCHAR Section, 02123 IN ULONG LineIndex, 02124 IN ULONG ValueIndex, 02125 IN OUT PULONG Data 02126 ) 02127 02128 /*++ 02129 02130 Routine Description: 02131 02132 This routine reads integer data from the inf. 02133 02134 Input Parameters: 02135 02136 InfHandle - Handle to the inf to be read. 02137 02138 Section - Name of the section to be read. 02139 02140 LineIndex - Index of the line to be read. 02141 02142 ValueIndex - Index of the value to be read. 02143 02144 Data - Receives the integer data. 02145 02146 Return Value: 02147 02148 TRUE iff successful. 02149 02150 --*/ 02151 02152 { 02153 PCHAR valueStr; 02154 02155 // 02156 // Get the specified value. 02157 // 02158 02159 valueStr = CmpGetSectionLineIndex( InfHandle, 02160 Section, 02161 LineIndex, 02162 ValueIndex); 02163 // 02164 // If valid value is found, convert it to an integer. 02165 // 02166 02167 if (valueStr && *valueStr) 02168 { 02169 *Data = strtoul(valueStr, NULL, 16); 02170 return (TRUE); 02171 } 02172 02173 return (FALSE); 02174 } 02175 02176 BOOLEAN 02177 CmpGetBinaryField( 02178 IN PVOID InfHandle, 02179 IN PCHAR Section, 02180 IN ULONG LineIndex, 02181 IN ULONG ValueIndex, 02182 IN OUT PVOID Buffer, 02183 IN ULONG BufferSize, 02184 IN OUT PULONG ActualSize 02185 ) 02186 02187 /*++ 02188 02189 Routine Description: 02190 02191 This routine reads binary data from the inf. 02192 02193 Input Parameters: 02194 02195 InfHandle - Handle to the inf to be read. 02196 02197 Section - Name of the section to be read. 02198 02199 LineIndex - Index of the line to be read. 02200 02201 ValueIndex - Index of the value to be read. 02202 02203 Buffer - Receives the binary data read. 02204 02205 BufferSize - Size of the buffer. 02206 02207 ActualSize - Receives the size of the data buffer required. 02208 02209 Return Value: 02210 02211 TRUE iff successful. 02212 02213 --*/ 02214 02215 { 02216 BOOLEAN result = FALSE; 02217 ULONG requiredSize; 02218 PSECTION pSection; 02219 PLINE pLine; 02220 PVALUE pValue; 02221 ULONG count; 02222 PCHAR valueStr; 02223 02224 // 02225 // Compute the size of buffer required to read in the binary data. 02226 // 02227 02228 requiredSize = (CmpGetSectionLineIndexValueCount( InfHandle, 02229 Section, 02230 LineIndex) - ValueIndex) * sizeof(UCHAR); 02231 // 02232 // Validate input parameters. 02233 // 02234 02235 if (Buffer && BufferSize >= requiredSize) 02236 { 02237 // 02238 // Search the section in the inf. 02239 // 02240 02241 pSection = CmpSearchSectionByName((PINF)InfHandle, Section); 02242 if(pSection) 02243 { 02244 // 02245 // Search the line in this section. 02246 // 02247 02248 pLine = CmpSearchLineInSectionByIndex(pSection, LineIndex); 02249 if (pLine) 02250 { 02251 // 02252 // Go to the specified value. 02253 // 02254 02255 for( pValue = pLine->pValue, count = 0; 02256 pValue && count < ValueIndex; 02257 pValue = pValue->pNext, count++); 02258 02259 // 02260 // Read in and convert the binary data. 02261 // 02262 02263 for ( ; 02264 pValue; 02265 pValue = pValue->pNext) 02266 { 02267 valueStr = CmpGetSectionLineIndex( InfHandle, 02268 Section, 02269 LineIndex, 02270 ValueIndex++); 02271 if (valueStr == NULL) 02272 { 02273 break; 02274 } 02275 *((PUCHAR)Buffer)++ = (UCHAR)strtoul(valueStr, NULL, 16); 02276 } 02277 if (valueStr) 02278 { 02279 result = TRUE; 02280 } 02281 } 02282 } 02283 } 02284 02285 // 02286 // The caller wants to know the buffer size required. 02287 // 02288 02289 if (ActualSize) 02290 { 02291 *ActualSize = requiredSize; 02292 result = TRUE; 02293 } 02294 02295 return (result); 02296 }

Generated on Sat May 15 19:41:08 2004 for test by doxygen 1.3.7