Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninfget.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 static unsigned int 00017 InfpSubstituteString(PINFCACHE Inf, 00018 const WCHAR *text, 00019 WCHAR *buffer, 00020 unsigned int size); 00021 00022 /* retrieve the string substitution for a given string, or NULL if not found */ 00023 /* if found, len is set to the substitution length */ 00024 static PCWSTR 00025 InfpGetSubstitutionString(PINFCACHE Inf, 00026 PCWSTR str, 00027 unsigned int *len, 00028 BOOL no_trailing_slash) 00029 { 00030 static const WCHAR percent = '%'; 00031 00032 INFSTATUS Status = INF_STATUS_NOT_FOUND; 00033 PINFCONTEXT Context = NULL; 00034 PWCHAR Data = NULL; 00035 WCHAR ValueName[MAX_INF_STRING_LENGTH +1]; 00036 WCHAR StringLangId[13]; 00037 00038 if (!*len) /* empty string (%%) is replaced by single percent */ 00039 { 00040 *len = 1; 00041 return &percent; 00042 } 00043 00044 memcpy(ValueName, str, *len * sizeof(WCHAR)); 00045 ValueName[*len] = 0; 00046 00047 DPRINT("Value name: %S\n", ValueName); 00048 00049 if (Inf->LanguageId != 0) 00050 { 00051 swprintf(StringLangId, 00052 L"Strings.%04hx", 00053 Inf->LanguageId); 00054 00055 Status = InfpFindFirstLine(Inf, 00056 StringLangId, 00057 ValueName, 00058 &Context); 00059 if (Status != INF_STATUS_SUCCESS) 00060 { 00061 swprintf(StringLangId, 00062 L"Strings.%04hx", 00063 MAKELANGID(PRIMARYLANGID(Inf->LanguageId), SUBLANG_NEUTRAL)); 00064 00065 Status = InfpFindFirstLine(Inf, 00066 StringLangId, 00067 ValueName, 00068 &Context); 00069 if (Status != INF_STATUS_SUCCESS) 00070 { 00071 Status = InfpFindFirstLine(Inf, 00072 L"Strings", 00073 ValueName, 00074 &Context); 00075 } 00076 } 00077 } 00078 else 00079 { 00080 Status = InfpFindFirstLine(Inf, 00081 L"Strings", 00082 ValueName, 00083 &Context); 00084 } 00085 00086 if (Status != INF_STATUS_SUCCESS || Context == NULL) 00087 return NULL; 00088 00089 Status = InfpGetData(Context, 00090 NULL, 00091 &Data); 00092 00093 InfpFreeContext(Context); 00094 00095 if (Status == STATUS_SUCCESS) 00096 { 00097 *len = strlenW(Data); 00098 DPRINT("Substitute: %S Length: %ul\n", Data, *len); 00099 return Data; 00100 } 00101 00102 return NULL; 00103 } 00104 00105 00106 /* do string substitutions on the specified text */ 00107 /* the buffer is assumed to be large enough */ 00108 /* returns necessary length not including terminating null */ 00109 static unsigned int 00110 InfpSubstituteString(PINFCACHE Inf, 00111 PCWSTR text, 00112 PWSTR buffer, 00113 unsigned int size) 00114 { 00115 const WCHAR *start, *subst, *p; 00116 unsigned int len, total = 0; 00117 int inside = 0; 00118 00119 if (!buffer) size = MAX_INF_STRING_LENGTH + 1; 00120 for (p = start = text; *p; p++) 00121 { 00122 if (*p != '%') continue; 00123 inside = !inside; 00124 if (inside) /* start of a %xx% string */ 00125 { 00126 len = (unsigned int)(p - start); 00127 if (len > size - 1) len = size - 1; 00128 if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); 00129 total += len; 00130 size -= len; 00131 start = p; 00132 } 00133 else /* end of the %xx% string, find substitution */ 00134 { 00135 len = (unsigned int)(p - start - 1); 00136 subst = InfpGetSubstitutionString( Inf, start + 1, &len, p[1] == '\\' ); 00137 if (!subst) 00138 { 00139 subst = start; 00140 len = (unsigned int)(p - start + 1); 00141 } 00142 if (len > size - 1) len = size - 1; 00143 if (buffer) memcpy( buffer + total, subst, len * sizeof(WCHAR) ); 00144 total += len; 00145 size -= len; 00146 start = p + 1; 00147 } 00148 } 00149 00150 if (start != p) /* unfinished string, copy it */ 00151 { 00152 len = (unsigned int)(p - start); 00153 if (len > size - 1) len = size - 1; 00154 if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); 00155 total += len; 00156 } 00157 if (buffer && size) buffer[total] = 0; 00158 return total; 00159 } 00160 00161 00162 INFSTATUS 00163 InfpFindFirstLine(PINFCACHE Cache, 00164 PCWSTR Section, 00165 PCWSTR Key, 00166 PINFCONTEXT *Context) 00167 { 00168 PINFCACHESECTION CacheSection; 00169 PINFCACHELINE CacheLine; 00170 00171 if (Cache == NULL || Section == NULL || Context == NULL) 00172 { 00173 DPRINT1("Invalid parameter\n"); 00174 return INF_STATUS_INVALID_PARAMETER; 00175 } 00176 00177 CacheSection = InfpFindSection(Cache, Section); 00178 if (NULL == CacheSection) 00179 { 00180 DPRINT("Section not found\n"); 00181 return INF_STATUS_NOT_FOUND; 00182 } 00183 00184 if (Key != NULL) 00185 { 00186 CacheLine = InfpFindKeyLine(CacheSection, Key); 00187 } 00188 else 00189 { 00190 CacheLine = CacheSection->FirstLine; 00191 } 00192 00193 if (NULL == CacheLine) 00194 { 00195 DPRINT("Key not found\n"); 00196 return INF_STATUS_NOT_FOUND; 00197 } 00198 00199 *Context = MALLOC(sizeof(INFCONTEXT)); 00200 if (NULL == *Context) 00201 { 00202 DPRINT1("MALLOC() failed\n"); 00203 return INF_STATUS_NO_MEMORY; 00204 } 00205 (*Context)->Inf = (PVOID)Cache; 00206 (*Context)->Section = (PVOID)CacheSection; 00207 (*Context)->Line = (PVOID)CacheLine; 00208 00209 return INF_STATUS_SUCCESS; 00210 } 00211 00212 00213 INFSTATUS 00214 InfpFindNextLine(PINFCONTEXT ContextIn, 00215 PINFCONTEXT ContextOut) 00216 { 00217 PINFCACHELINE CacheLine; 00218 00219 if (ContextIn == NULL || ContextOut == NULL) 00220 return INF_STATUS_INVALID_PARAMETER; 00221 00222 if (ContextIn->Line == NULL) 00223 return INF_STATUS_INVALID_PARAMETER; 00224 00225 CacheLine = (PINFCACHELINE)ContextIn->Line; 00226 if (CacheLine->Next == NULL) 00227 return INF_STATUS_NOT_FOUND; 00228 00229 if (ContextIn != ContextOut) 00230 { 00231 ContextOut->Inf = ContextIn->Inf; 00232 ContextOut->Section = ContextIn->Section; 00233 } 00234 ContextOut->Line = (PVOID)(CacheLine->Next); 00235 00236 return INF_STATUS_SUCCESS; 00237 } 00238 00239 00240 INFSTATUS 00241 InfpFindFirstMatchLine(PINFCONTEXT ContextIn, 00242 PCWSTR Key, 00243 PINFCONTEXT ContextOut) 00244 { 00245 PINFCACHELINE CacheLine; 00246 00247 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0) 00248 return INF_STATUS_INVALID_PARAMETER; 00249 00250 if (ContextIn->Inf == NULL || ContextIn->Section == NULL) 00251 return INF_STATUS_INVALID_PARAMETER; 00252 00253 CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine; 00254 while (CacheLine != NULL) 00255 { 00256 if (CacheLine->Key != NULL && strcmpiW (CacheLine->Key, Key) == 0) 00257 { 00258 00259 if (ContextIn != ContextOut) 00260 { 00261 ContextOut->Inf = ContextIn->Inf; 00262 ContextOut->Section = ContextIn->Section; 00263 } 00264 ContextOut->Line = (PVOID)CacheLine; 00265 00266 return INF_STATUS_SUCCESS; 00267 } 00268 00269 CacheLine = CacheLine->Next; 00270 } 00271 00272 return INF_STATUS_NOT_FOUND; 00273 } 00274 00275 00276 INFSTATUS 00277 InfpFindNextMatchLine(PINFCONTEXT ContextIn, 00278 PCWSTR Key, 00279 PINFCONTEXT ContextOut) 00280 { 00281 PINFCACHELINE CacheLine; 00282 00283 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0) 00284 return INF_STATUS_INVALID_PARAMETER; 00285 00286 if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL) 00287 return INF_STATUS_INVALID_PARAMETER; 00288 00289 CacheLine = (PINFCACHELINE)ContextIn->Line; 00290 while (CacheLine != NULL) 00291 { 00292 if (CacheLine->Key != NULL && strcmpiW (CacheLine->Key, Key) == 0) 00293 { 00294 00295 if (ContextIn != ContextOut) 00296 { 00297 ContextOut->Inf = ContextIn->Inf; 00298 ContextOut->Section = ContextIn->Section; 00299 } 00300 ContextOut->Line = (PVOID)CacheLine; 00301 00302 return INF_STATUS_SUCCESS; 00303 } 00304 00305 CacheLine = CacheLine->Next; 00306 } 00307 00308 return INF_STATUS_NOT_FOUND; 00309 } 00310 00311 00312 LONG 00313 InfpGetLineCount(HINF InfHandle, 00314 PCWSTR Section) 00315 { 00316 PINFCACHE Cache; 00317 PINFCACHESECTION CacheSection; 00318 00319 if (InfHandle == NULL || Section == NULL) 00320 { 00321 DPRINT("Invalid parameter\n"); 00322 return -1; 00323 } 00324 00325 Cache = (PINFCACHE)InfHandle; 00326 00327 /* Iterate through list of sections */ 00328 CacheSection = Cache->FirstSection; 00329 while (CacheSection != NULL) 00330 { 00331 /* Are the section names the same? */ 00332 if (strcmpiW(CacheSection->Name, Section) == 0) 00333 { 00334 return CacheSection->LineCount; 00335 } 00336 00337 /* Get the next section */ 00338 CacheSection = CacheSection->Next; 00339 } 00340 00341 DPRINT("Section not found\n"); 00342 00343 return -1; 00344 } 00345 00346 00347 /* InfpGetLineText */ 00348 00349 00350 LONG 00351 InfpGetFieldCount(PINFCONTEXT Context) 00352 { 00353 if (Context == NULL || Context->Line == NULL) 00354 return 0; 00355 00356 return ((PINFCACHELINE)Context->Line)->FieldCount; 00357 } 00358 00359 00360 INFSTATUS 00361 InfpGetBinaryField(PINFCONTEXT Context, 00362 ULONG FieldIndex, 00363 PUCHAR ReturnBuffer, 00364 ULONG ReturnBufferSize, 00365 PULONG RequiredSize) 00366 { 00367 PINFCACHELINE CacheLine; 00368 PINFCACHEFIELD CacheField; 00369 ULONG Index; 00370 ULONG Size; 00371 PUCHAR Ptr; 00372 00373 if (Context == NULL || Context->Line == NULL || FieldIndex == 0) 00374 { 00375 DPRINT("Invalid parameter\n"); 00376 return INF_STATUS_INVALID_PARAMETER; 00377 } 00378 00379 if (RequiredSize != NULL) 00380 *RequiredSize = 0; 00381 00382 CacheLine = (PINFCACHELINE)Context->Line; 00383 00384 if (FieldIndex > (ULONG)CacheLine->FieldCount) 00385 return INF_STATUS_NOT_FOUND; 00386 00387 CacheField = CacheLine->FirstField; 00388 for (Index = 1; Index < FieldIndex; Index++) 00389 CacheField = CacheField->Next; 00390 00391 Size = (ULONG)CacheLine->FieldCount - FieldIndex + 1; 00392 00393 if (RequiredSize != NULL) 00394 *RequiredSize = Size; 00395 00396 if (ReturnBuffer != NULL) 00397 { 00398 if (ReturnBufferSize < Size) 00399 return INF_STATUS_BUFFER_OVERFLOW; 00400 00401 /* Copy binary data */ 00402 Ptr = ReturnBuffer; 00403 while (CacheField != NULL) 00404 { 00405 *Ptr = (UCHAR)strtoulW(CacheField->Data, NULL, 16); 00406 00407 Ptr++; 00408 CacheField = CacheField->Next; 00409 } 00410 } 00411 00412 return INF_STATUS_SUCCESS; 00413 } 00414 00415 00416 INFSTATUS 00417 InfpGetIntField(PINFCONTEXT Context, 00418 ULONG FieldIndex, 00419 INT *IntegerValue) 00420 { 00421 PINFCACHELINE CacheLine; 00422 PINFCACHEFIELD CacheField; 00423 ULONG Index; 00424 PWCHAR Ptr; 00425 00426 if (Context == NULL || Context->Line == NULL || IntegerValue == NULL) 00427 { 00428 DPRINT("Invalid parameter\n"); 00429 return INF_STATUS_INVALID_PARAMETER; 00430 } 00431 00432 CacheLine = (PINFCACHELINE)Context->Line; 00433 00434 if (FieldIndex > (ULONG)CacheLine->FieldCount) 00435 { 00436 DPRINT("Invalid parameter\n"); 00437 return INF_STATUS_INVALID_PARAMETER; 00438 } 00439 00440 if (FieldIndex == 0) 00441 { 00442 Ptr = CacheLine->Key; 00443 } 00444 else 00445 { 00446 CacheField = CacheLine->FirstField; 00447 for (Index = 1; Index < FieldIndex; Index++) 00448 CacheField = CacheField->Next; 00449 00450 Ptr = CacheField->Data; 00451 } 00452 00453 *IntegerValue = (LONG)strtolW(Ptr, NULL, 0); 00454 00455 return INF_STATUS_SUCCESS; 00456 } 00457 00458 00459 INFSTATUS 00460 InfpGetMultiSzField(PINFCONTEXT Context, 00461 ULONG FieldIndex, 00462 PWSTR ReturnBuffer, 00463 ULONG ReturnBufferSize, 00464 PULONG RequiredSize) 00465 { 00466 PINFCACHELINE CacheLine; 00467 PINFCACHEFIELD CacheField; 00468 PINFCACHEFIELD FieldPtr; 00469 ULONG Index; 00470 ULONG Size; 00471 PWCHAR Ptr; 00472 00473 if (Context == NULL || Context->Line == NULL || FieldIndex == 0) 00474 { 00475 DPRINT("Invalid parameter\n"); 00476 return INF_STATUS_INVALID_PARAMETER; 00477 } 00478 00479 if (RequiredSize != NULL) 00480 *RequiredSize = 0; 00481 00482 CacheLine = (PINFCACHELINE)Context->Line; 00483 00484 if (FieldIndex > (ULONG)CacheLine->FieldCount) 00485 return INF_STATUS_INVALID_PARAMETER; 00486 00487 CacheField = CacheLine->FirstField; 00488 for (Index = 1; Index < FieldIndex; Index++) 00489 CacheField = CacheField->Next; 00490 00491 /* Calculate the required buffer size */ 00492 FieldPtr = CacheField; 00493 Size = 0; 00494 while (FieldPtr != NULL) 00495 { 00496 Size += ((ULONG)strlenW(FieldPtr->Data) + 1); 00497 FieldPtr = FieldPtr->Next; 00498 } 00499 Size++; 00500 00501 if (RequiredSize != NULL) 00502 *RequiredSize = Size; 00503 00504 if (ReturnBuffer != NULL) 00505 { 00506 if (ReturnBufferSize < Size) 00507 return INF_STATUS_BUFFER_OVERFLOW; 00508 00509 /* Copy multi-sz string */ 00510 Ptr = ReturnBuffer; 00511 FieldPtr = CacheField; 00512 while (FieldPtr != NULL) 00513 { 00514 Size = (ULONG)strlenW(FieldPtr->Data) + 1; 00515 00516 strcpyW(Ptr, FieldPtr->Data); 00517 00518 Ptr = Ptr + Size; 00519 FieldPtr = FieldPtr->Next; 00520 } 00521 *Ptr = 0; 00522 } 00523 00524 return INF_STATUS_SUCCESS; 00525 } 00526 00527 00528 INFSTATUS 00529 InfpGetStringField(PINFCONTEXT Context, 00530 ULONG FieldIndex, 00531 PWSTR ReturnBuffer, 00532 ULONG ReturnBufferSize, 00533 PULONG RequiredSize) 00534 { 00535 PINFCACHELINE CacheLine; 00536 PINFCACHEFIELD CacheField; 00537 ULONG Index; 00538 PWCHAR Ptr; 00539 ULONG Size; 00540 00541 if (Context == NULL || Context->Line == NULL || FieldIndex == 0) 00542 { 00543 DPRINT("Invalid parameter\n"); 00544 return INF_STATUS_INVALID_PARAMETER; 00545 } 00546 00547 if (RequiredSize != NULL) 00548 *RequiredSize = 0; 00549 00550 CacheLine = (PINFCACHELINE)Context->Line; 00551 00552 if (FieldIndex > (ULONG)CacheLine->FieldCount) 00553 return INF_STATUS_INVALID_PARAMETER; 00554 00555 if (FieldIndex == 0) 00556 { 00557 Ptr = CacheLine->Key; 00558 } 00559 else 00560 { 00561 CacheField = CacheLine->FirstField; 00562 for (Index = 1; Index < FieldIndex; Index++) 00563 CacheField = CacheField->Next; 00564 00565 Ptr = CacheField->Data; 00566 } 00567 00568 // Size = (ULONG)strlenW(Ptr) + 1; 00569 Size = InfpSubstituteString(Context->Inf, 00570 Ptr, 00571 NULL, 00572 0); 00573 00574 if (RequiredSize != NULL) 00575 *RequiredSize = Size + 1; 00576 00577 if (ReturnBuffer != NULL) 00578 { 00579 if (ReturnBufferSize <= Size) 00580 return INF_STATUS_BUFFER_OVERFLOW; 00581 00582 // strcpyW(ReturnBuffer, Ptr); 00583 InfpSubstituteString(Context->Inf, 00584 Ptr, 00585 ReturnBuffer, 00586 ReturnBufferSize); 00587 } 00588 00589 return INF_STATUS_SUCCESS; 00590 } 00591 00592 00593 INFSTATUS 00594 InfpGetData(PINFCONTEXT Context, 00595 PWCHAR *Key, 00596 PWCHAR *Data) 00597 { 00598 PINFCACHELINE CacheKey; 00599 00600 if (Context == NULL || Context->Line == NULL || Data == NULL) 00601 { 00602 DPRINT("Invalid parameter\n"); 00603 return INF_STATUS_INVALID_PARAMETER; 00604 } 00605 00606 CacheKey = (PINFCACHELINE)Context->Line; 00607 if (Key != NULL) 00608 *Key = CacheKey->Key; 00609 00610 if (Data != NULL) 00611 { 00612 if (CacheKey->FirstField == NULL) 00613 { 00614 *Data = NULL; 00615 } 00616 else 00617 { 00618 *Data = CacheKey->FirstField->Data; 00619 } 00620 } 00621 00622 return INF_STATUS_SUCCESS; 00623 } 00624 00625 00626 INFSTATUS 00627 InfpGetDataField(PINFCONTEXT Context, 00628 ULONG FieldIndex, 00629 PWCHAR *Data) 00630 { 00631 PINFCACHELINE CacheLine; 00632 PINFCACHEFIELD CacheField; 00633 ULONG Index; 00634 00635 if (Context == NULL || Context->Line == NULL || Data == NULL) 00636 { 00637 DPRINT("Invalid parameter\n"); 00638 return INF_STATUS_INVALID_PARAMETER; 00639 } 00640 00641 CacheLine = (PINFCACHELINE)Context->Line; 00642 00643 if (FieldIndex > (ULONG)CacheLine->FieldCount) 00644 return INF_STATUS_INVALID_PARAMETER; 00645 00646 if (FieldIndex == 0) 00647 { 00648 *Data = CacheLine->Key; 00649 } 00650 else 00651 { 00652 CacheField = CacheLine->FirstField; 00653 for (Index = 1; Index < FieldIndex; Index++) 00654 CacheField = CacheField->Next; 00655 00656 *Data = CacheField->Data; 00657 } 00658 00659 return INF_STATUS_SUCCESS; 00660 } 00661 00662 VOID 00663 InfpFreeContext(PINFCONTEXT Context) 00664 { 00665 FREE(Context); 00666 } 00667 00668 /* EOF */ Generated on Sun May 27 2012 04:36:14 for ReactOS by
1.7.6.1
|