Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninfcore.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: .inf file parser 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * PROGRAMMER: Royce Mitchell III 00005 * Eric Kohl 00006 * Ge van Geldorp <gvg@reactos.org> 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include "inflib.h" 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 #define CONTROL_Z '\x1a' 00017 #define MAX_SECTION_NAME_LEN 255 00018 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */ 00019 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */ 00020 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1) 00021 00022 00023 /* parser definitions */ 00024 00025 enum parser_state 00026 { 00027 LINE_START, /* at beginning of a line */ 00028 SECTION_NAME, /* parsing a section name */ 00029 KEY_NAME, /* parsing a key name */ 00030 VALUE_NAME, /* parsing a value name */ 00031 EOL_BACKSLASH, /* backslash at end of line */ 00032 QUOTES, /* inside quotes */ 00033 LEADING_SPACES, /* leading spaces */ 00034 TRAILING_SPACES, /* trailing spaces */ 00035 COMMENT, /* inside a comment */ 00036 NB_PARSER_STATES 00037 }; 00038 00039 struct parser 00040 { 00041 const WCHAR *start; /* start position of item being parsed */ 00042 const WCHAR *end; /* end of buffer */ 00043 PINFCACHE file; /* file being built */ 00044 enum parser_state state; /* current parser state */ 00045 enum parser_state stack[4]; /* state stack */ 00046 int stack_pos; /* current pos in stack */ 00047 00048 PINFCACHESECTION cur_section; /* pointer to the section being parsed*/ 00049 PINFCACHELINE line; /* current line */ 00050 unsigned int line_pos; /* current line position in file */ 00051 INFSTATUS error; /* error code */ 00052 unsigned int token_len; /* current token len */ 00053 WCHAR token[MAX_FIELD_LEN+1]; /* current token */ 00054 }; 00055 00056 typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos ); 00057 00058 /* parser state machine functions */ 00059 static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ); 00060 static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ); 00061 static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ); 00062 static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ); 00063 static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ); 00064 static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ); 00065 static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ); 00066 static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ); 00067 static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ); 00068 00069 static const parser_state_func parser_funcs[NB_PARSER_STATES] = 00070 { 00071 line_start_state, /* LINE_START */ 00072 section_name_state, /* SECTION_NAME */ 00073 key_name_state, /* KEY_NAME */ 00074 value_name_state, /* VALUE_NAME */ 00075 eol_backslash_state, /* EOL_BACKSLASH */ 00076 quotes_state, /* QUOTES */ 00077 leading_spaces_state, /* LEADING_SPACES */ 00078 trailing_spaces_state, /* TRAILING_SPACES */ 00079 comment_state /* COMMENT */ 00080 }; 00081 00082 00083 /* PRIVATE FUNCTIONS ********************************************************/ 00084 00085 static PINFCACHELINE 00086 InfpFreeLine (PINFCACHELINE Line) 00087 { 00088 PINFCACHELINE Next; 00089 PINFCACHEFIELD Field; 00090 00091 if (Line == NULL) 00092 { 00093 return NULL; 00094 } 00095 00096 Next = Line->Next; 00097 if (Line->Key != NULL) 00098 { 00099 FREE (Line->Key); 00100 Line->Key = NULL; 00101 } 00102 00103 /* Remove data fields */ 00104 while (Line->FirstField != NULL) 00105 { 00106 Field = Line->FirstField->Next; 00107 FREE (Line->FirstField); 00108 Line->FirstField = Field; 00109 } 00110 Line->LastField = NULL; 00111 00112 FREE (Line); 00113 00114 return Next; 00115 } 00116 00117 00118 PINFCACHESECTION 00119 InfpFreeSection (PINFCACHESECTION Section) 00120 { 00121 PINFCACHESECTION Next; 00122 00123 if (Section == NULL) 00124 { 00125 return NULL; 00126 } 00127 00128 /* Release all keys */ 00129 Next = Section->Next; 00130 while (Section->FirstLine != NULL) 00131 { 00132 Section->FirstLine = InfpFreeLine (Section->FirstLine); 00133 } 00134 Section->LastLine = NULL; 00135 00136 FREE (Section); 00137 00138 return Next; 00139 } 00140 00141 00142 PINFCACHESECTION 00143 InfpFindSection(PINFCACHE Cache, 00144 PCWSTR Name) 00145 { 00146 PINFCACHESECTION Section = NULL; 00147 00148 if (Cache == NULL || Name == NULL) 00149 { 00150 return NULL; 00151 } 00152 00153 /* iterate through list of sections */ 00154 Section = Cache->FirstSection; 00155 while (Section != NULL) 00156 { 00157 if (strcmpiW(Section->Name, Name) == 0) 00158 { 00159 return Section; 00160 } 00161 00162 /* get the next section*/ 00163 Section = Section->Next; 00164 } 00165 00166 return NULL; 00167 } 00168 00169 00170 PINFCACHESECTION 00171 InfpAddSection(PINFCACHE Cache, 00172 PCWSTR Name) 00173 { 00174 PINFCACHESECTION Section = NULL; 00175 ULONG Size; 00176 00177 if (Cache == NULL || Name == NULL) 00178 { 00179 DPRINT("Invalid parameter\n"); 00180 return NULL; 00181 } 00182 00183 /* Allocate and initialize the new section */ 00184 Size = (ULONG)FIELD_OFFSET(INFCACHESECTION, 00185 Name[strlenW(Name) + 1]); 00186 Section = (PINFCACHESECTION)MALLOC(Size); 00187 if (Section == NULL) 00188 { 00189 DPRINT("MALLOC() failed\n"); 00190 return NULL; 00191 } 00192 ZEROMEMORY (Section, 00193 Size); 00194 00195 /* Copy section name */ 00196 strcpyW(Section->Name, Name); 00197 00198 /* Append section */ 00199 if (Cache->FirstSection == NULL) 00200 { 00201 Cache->FirstSection = Section; 00202 Cache->LastSection = Section; 00203 } 00204 else 00205 { 00206 Cache->LastSection->Next = Section; 00207 Section->Prev = Cache->LastSection; 00208 Cache->LastSection = Section; 00209 } 00210 00211 return Section; 00212 } 00213 00214 00215 PINFCACHELINE 00216 InfpAddLine(PINFCACHESECTION Section) 00217 { 00218 PINFCACHELINE Line; 00219 00220 if (Section == NULL) 00221 { 00222 DPRINT("Invalid parameter\n"); 00223 return NULL; 00224 } 00225 00226 Line = (PINFCACHELINE)MALLOC(sizeof(INFCACHELINE)); 00227 if (Line == NULL) 00228 { 00229 DPRINT("MALLOC() failed\n"); 00230 return NULL; 00231 } 00232 ZEROMEMORY(Line, 00233 sizeof(INFCACHELINE)); 00234 00235 /* Append line */ 00236 if (Section->FirstLine == NULL) 00237 { 00238 Section->FirstLine = Line; 00239 Section->LastLine = Line; 00240 } 00241 else 00242 { 00243 Section->LastLine->Next = Line; 00244 Line->Prev = Section->LastLine; 00245 Section->LastLine = Line; 00246 } 00247 Section->LineCount++; 00248 00249 return Line; 00250 } 00251 00252 00253 PVOID 00254 InfpAddKeyToLine(PINFCACHELINE Line, 00255 PCWSTR Key) 00256 { 00257 if (Line == NULL) 00258 { 00259 DPRINT1("Invalid Line\n"); 00260 return NULL; 00261 } 00262 00263 if (Line->Key != NULL) 00264 { 00265 DPRINT1("Line already has a key\n"); 00266 return NULL; 00267 } 00268 00269 Line->Key = (PWCHAR)MALLOC((strlenW(Key) + 1) * sizeof(WCHAR)); 00270 if (Line->Key == NULL) 00271 { 00272 DPRINT1("MALLOC() failed\n"); 00273 return NULL; 00274 } 00275 00276 strcpyW(Line->Key, Key); 00277 00278 return (PVOID)Line->Key; 00279 } 00280 00281 00282 PVOID 00283 InfpAddFieldToLine(PINFCACHELINE Line, 00284 PCWSTR Data) 00285 { 00286 PINFCACHEFIELD Field; 00287 ULONG Size; 00288 00289 Size = (ULONG)FIELD_OFFSET(INFCACHEFIELD, 00290 Data[strlenW(Data) + 1]); 00291 Field = (PINFCACHEFIELD)MALLOC(Size); 00292 if (Field == NULL) 00293 { 00294 DPRINT1("MALLOC() failed\n"); 00295 return NULL; 00296 } 00297 ZEROMEMORY (Field, 00298 Size); 00299 strcpyW(Field->Data, Data); 00300 00301 /* Append key */ 00302 if (Line->FirstField == NULL) 00303 { 00304 Line->FirstField = Field; 00305 Line->LastField = Field; 00306 } 00307 else 00308 { 00309 Line->LastField->Next = Field; 00310 Field->Prev = Line->LastField; 00311 Line->LastField = Field; 00312 } 00313 Line->FieldCount++; 00314 00315 return (PVOID)Field; 00316 } 00317 00318 00319 PINFCACHELINE 00320 InfpFindKeyLine(PINFCACHESECTION Section, 00321 PCWSTR Key) 00322 { 00323 PINFCACHELINE Line; 00324 00325 Line = Section->FirstLine; 00326 while (Line != NULL) 00327 { 00328 if (Line->Key != NULL && strcmpiW(Line->Key, Key) == 0) 00329 { 00330 return Line; 00331 } 00332 00333 Line = Line->Next; 00334 } 00335 00336 return NULL; 00337 } 00338 00339 00340 /* push the current state on the parser stack */ 00341 __inline static void push_state( struct parser *parser, enum parser_state state ) 00342 { 00343 // assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) ); 00344 parser->stack[parser->stack_pos++] = state; 00345 } 00346 00347 00348 /* pop the current state */ 00349 __inline static void pop_state( struct parser *parser ) 00350 { 00351 // assert( parser->stack_pos ); 00352 parser->state = parser->stack[--parser->stack_pos]; 00353 } 00354 00355 00356 /* set the parser state and return the previous one */ 00357 __inline static enum parser_state set_state( struct parser *parser, enum parser_state state ) 00358 { 00359 enum parser_state ret = parser->state; 00360 parser->state = state; 00361 return ret; 00362 } 00363 00364 00365 /* check if the pointer points to an end of file */ 00366 __inline static int is_eof( struct parser *parser, const WCHAR *ptr ) 00367 { 00368 return (ptr >= parser->end || *ptr == CONTROL_Z || *ptr == 0); 00369 } 00370 00371 00372 /* check if the pointer points to an end of line */ 00373 __inline static int is_eol( struct parser *parser, const WCHAR *ptr ) 00374 { 00375 return (ptr >= parser->end || 00376 *ptr == CONTROL_Z || 00377 *ptr == '\n' || 00378 (*ptr == '\r' && *(ptr + 1) == '\n') || 00379 *ptr == 0); 00380 } 00381 00382 00383 /* push data from current token start up to pos into the current token */ 00384 static int push_token( struct parser *parser, const WCHAR *pos ) 00385 { 00386 UINT len = (UINT)(pos - parser->start); 00387 const WCHAR *src = parser->start; 00388 WCHAR *dst = parser->token + parser->token_len; 00389 00390 if (len > MAX_FIELD_LEN - parser->token_len) 00391 len = MAX_FIELD_LEN - parser->token_len; 00392 00393 parser->token_len += len; 00394 for ( ; len > 0; len--, dst++, src++) 00395 { 00396 if (*src) 00397 { 00398 *dst = *src; 00399 } 00400 else 00401 { 00402 *dst = ' '; 00403 } 00404 } 00405 00406 *dst = 0; 00407 parser->start = pos; 00408 00409 return 0; 00410 } 00411 00412 00413 00414 /* add a section with the current token as name */ 00415 static PVOID add_section_from_token( struct parser *parser ) 00416 { 00417 PINFCACHESECTION Section; 00418 00419 if (parser->token_len > MAX_SECTION_NAME_LEN) 00420 { 00421 parser->error = INF_STATUS_SECTION_NAME_TOO_LONG; 00422 return NULL; 00423 } 00424 00425 Section = InfpFindSection(parser->file, 00426 parser->token); 00427 if (Section == NULL) 00428 { 00429 /* need to create a new one */ 00430 Section= InfpAddSection(parser->file, 00431 parser->token); 00432 if (Section == NULL) 00433 { 00434 parser->error = INF_STATUS_NOT_ENOUGH_MEMORY; 00435 return NULL; 00436 } 00437 } 00438 00439 parser->token_len = 0; 00440 parser->cur_section = Section; 00441 00442 return (PVOID)Section; 00443 } 00444 00445 00446 /* add a field containing the current token to the current line */ 00447 static struct field *add_field_from_token( struct parser *parser, int is_key ) 00448 { 00449 PVOID field; 00450 00451 if (!parser->line) /* need to start a new line */ 00452 { 00453 if (parser->cur_section == NULL) /* got a line before the first section */ 00454 { 00455 parser->error = INF_STATUS_WRONG_INF_STYLE; 00456 return NULL; 00457 } 00458 00459 parser->line = InfpAddLine(parser->cur_section); 00460 if (parser->line == NULL) 00461 goto error; 00462 } 00463 else 00464 { 00465 // assert(!is_key); 00466 } 00467 00468 if (is_key) 00469 { 00470 field = InfpAddKeyToLine(parser->line, parser->token); 00471 } 00472 else 00473 { 00474 field = InfpAddFieldToLine(parser->line, parser->token); 00475 } 00476 00477 if (field != NULL) 00478 { 00479 parser->token_len = 0; 00480 return field; 00481 } 00482 00483 error: 00484 parser->error = INF_STATUS_NOT_ENOUGH_MEMORY; 00485 return NULL; 00486 } 00487 00488 00489 /* close the current line and prepare for parsing a new one */ 00490 static void close_current_line( struct parser *parser ) 00491 { 00492 parser->line = NULL; 00493 } 00494 00495 00496 00497 /* handler for parser LINE_START state */ 00498 static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ) 00499 { 00500 const WCHAR *p; 00501 00502 for (p = pos; !is_eof( parser, p ); p++) 00503 { 00504 switch(*p) 00505 { 00506 case '\r': 00507 continue; 00508 00509 case '\n': 00510 parser->line_pos++; 00511 close_current_line( parser ); 00512 break; 00513 00514 case ';': 00515 push_state( parser, LINE_START ); 00516 set_state( parser, COMMENT ); 00517 return p + 1; 00518 00519 case '[': 00520 parser->start = p + 1; 00521 set_state( parser, SECTION_NAME ); 00522 return p + 1; 00523 00524 default: 00525 if (!isspaceW(*p)) 00526 { 00527 parser->start = p; 00528 set_state( parser, KEY_NAME ); 00529 return p; 00530 } 00531 break; 00532 } 00533 } 00534 close_current_line( parser ); 00535 return NULL; 00536 } 00537 00538 00539 /* handler for parser SECTION_NAME state */ 00540 static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ) 00541 { 00542 const WCHAR *p; 00543 00544 for (p = pos; !is_eol( parser, p ); p++) 00545 { 00546 if (*p == ']') 00547 { 00548 push_token( parser, p ); 00549 if (add_section_from_token( parser ) == NULL) 00550 return NULL; 00551 push_state( parser, LINE_START ); 00552 set_state( parser, COMMENT ); /* ignore everything else on the line */ 00553 return p + 1; 00554 } 00555 } 00556 parser->error = INF_STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */ 00557 return NULL; 00558 } 00559 00560 00561 /* handler for parser KEY_NAME state */ 00562 static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ) 00563 { 00564 const WCHAR *p, *token_end = parser->start; 00565 00566 for (p = pos; !is_eol( parser, p ); p++) 00567 { 00568 if (*p == ',') break; 00569 switch(*p) 00570 { 00571 00572 case '=': 00573 push_token( parser, token_end ); 00574 if (!add_field_from_token( parser, 1 )) return NULL; 00575 parser->start = p + 1; 00576 push_state( parser, VALUE_NAME ); 00577 set_state( parser, LEADING_SPACES ); 00578 return p + 1; 00579 case ';': 00580 push_token( parser, token_end ); 00581 if (!add_field_from_token( parser, 0 )) return NULL; 00582 push_state( parser, LINE_START ); 00583 set_state( parser, COMMENT ); 00584 return p + 1; 00585 case '"': 00586 push_token( parser, token_end ); 00587 parser->start = p + 1; 00588 push_state( parser, KEY_NAME ); 00589 set_state( parser, QUOTES ); 00590 return p + 1; 00591 case '\\': 00592 push_token( parser, token_end ); 00593 parser->start = p; 00594 push_state( parser, KEY_NAME ); 00595 set_state( parser, EOL_BACKSLASH ); 00596 return p; 00597 default: 00598 if (!isspaceW(*p)) token_end = p + 1; 00599 else 00600 { 00601 push_token( parser, p ); 00602 push_state( parser, KEY_NAME ); 00603 set_state( parser, TRAILING_SPACES ); 00604 return p; 00605 } 00606 break; 00607 } 00608 } 00609 push_token( parser, token_end ); 00610 set_state( parser, VALUE_NAME ); 00611 return p; 00612 } 00613 00614 00615 /* handler for parser VALUE_NAME state */ 00616 static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ) 00617 { 00618 const WCHAR *p, *token_end = parser->start; 00619 00620 for (p = pos; !is_eol( parser, p ); p++) 00621 { 00622 switch(*p) 00623 { 00624 case ';': 00625 push_token( parser, token_end ); 00626 if (!add_field_from_token( parser, 0 )) return NULL; 00627 push_state( parser, LINE_START ); 00628 set_state( parser, COMMENT ); 00629 return p + 1; 00630 case ',': 00631 push_token( parser, token_end ); 00632 if (!add_field_from_token( parser, 0 )) return NULL; 00633 parser->start = p + 1; 00634 push_state( parser, VALUE_NAME ); 00635 set_state( parser, LEADING_SPACES ); 00636 return p + 1; 00637 case '"': 00638 push_token( parser, token_end ); 00639 parser->start = p + 1; 00640 push_state( parser, VALUE_NAME ); 00641 set_state( parser, QUOTES ); 00642 return p + 1; 00643 case '\\': 00644 push_token( parser, token_end ); 00645 parser->start = p; 00646 push_state( parser, VALUE_NAME ); 00647 set_state( parser, EOL_BACKSLASH ); 00648 return p; 00649 default: 00650 if (!isspaceW(*p)) token_end = p + 1; 00651 else 00652 { 00653 push_token( parser, p ); 00654 push_state( parser, VALUE_NAME ); 00655 set_state( parser, TRAILING_SPACES ); 00656 return p; 00657 } 00658 break; 00659 } 00660 } 00661 push_token( parser, token_end ); 00662 if (!add_field_from_token( parser, 0 )) return NULL; 00663 set_state( parser, LINE_START ); 00664 return p; 00665 } 00666 00667 00668 /* handler for parser EOL_BACKSLASH state */ 00669 static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ) 00670 { 00671 const WCHAR *p; 00672 00673 for (p = pos; !is_eof( parser, p ); p++) 00674 { 00675 switch(*p) 00676 { 00677 case '\r': 00678 continue; 00679 00680 case '\n': 00681 parser->line_pos++; 00682 parser->start = p + 1; 00683 set_state( parser, LEADING_SPACES ); 00684 return p + 1; 00685 00686 case '\\': 00687 continue; 00688 00689 case ';': 00690 push_state( parser, EOL_BACKSLASH ); 00691 set_state( parser, COMMENT ); 00692 return p + 1; 00693 00694 default: 00695 if (isspaceW(*p)) 00696 continue; 00697 push_token( parser, p ); 00698 pop_state( parser ); 00699 return p; 00700 } 00701 } 00702 parser->start = p; 00703 pop_state( parser ); 00704 00705 return p; 00706 } 00707 00708 00709 /* handler for parser QUOTES state */ 00710 static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ) 00711 { 00712 const WCHAR *p, *token_end = parser->start; 00713 00714 for (p = pos; !is_eol( parser, p ); p++) 00715 { 00716 if (*p == '"') 00717 { 00718 if (p+1 < parser->end && p[1] == '"') /* double quotes */ 00719 { 00720 push_token( parser, p + 1 ); 00721 parser->start = token_end = p + 2; 00722 p++; 00723 } 00724 else /* end of quotes */ 00725 { 00726 push_token( parser, p ); 00727 parser->start = p + 1; 00728 pop_state( parser ); 00729 return p + 1; 00730 } 00731 } 00732 } 00733 push_token( parser, p ); 00734 pop_state( parser ); 00735 return p; 00736 } 00737 00738 00739 /* handler for parser LEADING_SPACES state */ 00740 static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ) 00741 { 00742 const WCHAR *p; 00743 00744 for (p = pos; !is_eol( parser, p ); p++) 00745 { 00746 if (*p == '\\') 00747 { 00748 parser->start = p; 00749 set_state( parser, EOL_BACKSLASH ); 00750 return p; 00751 } 00752 if (!isspaceW(*p)) 00753 break; 00754 } 00755 parser->start = p; 00756 pop_state( parser ); 00757 return p; 00758 } 00759 00760 00761 /* handler for parser TRAILING_SPACES state */ 00762 static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ) 00763 { 00764 const WCHAR *p; 00765 00766 for (p = pos; !is_eol( parser, p ); p++) 00767 { 00768 if (*p == '\\') 00769 { 00770 set_state( parser, EOL_BACKSLASH ); 00771 return p; 00772 } 00773 if (!isspaceW(*p)) 00774 break; 00775 } 00776 pop_state( parser ); 00777 return p; 00778 } 00779 00780 00781 /* handler for parser COMMENT state */ 00782 static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ) 00783 { 00784 const WCHAR *p = pos; 00785 00786 while (!is_eol( parser, p )) 00787 p++; 00788 pop_state( parser ); 00789 return p; 00790 } 00791 00792 00793 /* parse a complete buffer */ 00794 INFSTATUS 00795 InfpParseBuffer (PINFCACHE file, 00796 const WCHAR *buffer, 00797 const WCHAR *end, 00798 PULONG error_line) 00799 { 00800 struct parser parser; 00801 const WCHAR *pos = buffer; 00802 00803 parser.start = buffer; 00804 parser.end = end; 00805 parser.file = file; 00806 parser.line = NULL; 00807 parser.state = LINE_START; 00808 parser.stack_pos = 0; 00809 parser.cur_section = NULL; 00810 parser.line_pos = 1; 00811 parser.error = 0; 00812 parser.token_len = 0; 00813 00814 /* parser main loop */ 00815 while (pos) 00816 pos = (parser_funcs[parser.state])(&parser, pos); 00817 00818 if (parser.error) 00819 { 00820 if (error_line) 00821 *error_line = parser.line_pos; 00822 return parser.error; 00823 } 00824 00825 /* find the [strings] section */ 00826 file->StringsSection = InfpFindSection(file, 00827 L"Strings"); 00828 00829 return INF_STATUS_SUCCESS; 00830 } 00831 00832 /* EOF */ Generated on Sat May 26 2012 04:35:05 for ReactOS by
1.7.6.1
|