Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninicache.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 2002 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 /* $Id: inicache.c 47686 2010-06-07 21:38:49Z spetreolle $ 00020 * COPYRIGHT: See COPYING in the top level directory 00021 * PROJECT: ReactOS text-mode setup 00022 * FILE: subsys/system/usetup/inicache.c 00023 * PURPOSE: INI file parser that caches contents of INI file in memory 00024 * PROGRAMMER: Royce Mitchell III 00025 * Eric Kohl 00026 */ 00027 00028 /* INCLUDES *****************************************************************/ 00029 00030 #include "usetup.h" 00031 00032 #define NDEBUG 00033 #include <debug.h> 00034 00035 /* PRIVATE FUNCTIONS ********************************************************/ 00036 00037 static PINICACHEKEY 00038 IniCacheFreeKey(PINICACHEKEY Key) 00039 { 00040 PINICACHEKEY Next; 00041 00042 if (Key == NULL) 00043 { 00044 return(NULL); 00045 } 00046 00047 Next = Key->Next; 00048 if (Key->Name != NULL) 00049 { 00050 RtlFreeHeap(ProcessHeap, 00051 0, 00052 Key->Name); 00053 Key->Name = NULL; 00054 } 00055 00056 if (Key->Data != NULL) 00057 { 00058 RtlFreeHeap(ProcessHeap, 00059 0, 00060 Key->Data); 00061 Key->Data = NULL; 00062 } 00063 00064 RtlFreeHeap(ProcessHeap, 00065 0, 00066 Key); 00067 00068 return(Next); 00069 } 00070 00071 00072 static PINICACHESECTION 00073 IniCacheFreeSection(PINICACHESECTION Section) 00074 { 00075 PINICACHESECTION Next; 00076 00077 if (Section == NULL) 00078 { 00079 return(NULL); 00080 } 00081 00082 Next = Section->Next; 00083 while (Section->FirstKey != NULL) 00084 { 00085 Section->FirstKey = IniCacheFreeKey(Section->FirstKey); 00086 } 00087 Section->LastKey = NULL; 00088 00089 if (Section->Name != NULL) 00090 { 00091 RtlFreeHeap(ProcessHeap, 00092 0, 00093 Section->Name); 00094 Section->Name = NULL; 00095 } 00096 00097 RtlFreeHeap(ProcessHeap, 00098 0, 00099 Section); 00100 00101 return(Next); 00102 } 00103 00104 00105 static PINICACHEKEY 00106 IniCacheFindKey(PINICACHESECTION Section, 00107 PWCHAR Name, 00108 ULONG NameLength) 00109 { 00110 PINICACHEKEY Key; 00111 00112 Key = Section->FirstKey; 00113 while (Key != NULL) 00114 { 00115 if (NameLength == wcslen(Key->Name)) 00116 { 00117 if (_wcsnicmp(Key->Name, Name, NameLength) == 0) 00118 break; 00119 } 00120 00121 Key = Key->Next; 00122 } 00123 00124 return(Key); 00125 } 00126 00127 00128 static PINICACHEKEY 00129 IniCacheAddKey(PINICACHESECTION Section, 00130 PCHAR Name, 00131 ULONG NameLength, 00132 PCHAR Data, 00133 ULONG DataLength) 00134 { 00135 PINICACHEKEY Key; 00136 ULONG i; 00137 00138 Key = NULL; 00139 00140 if (Section == NULL || 00141 Name == NULL || 00142 NameLength == 0 || 00143 Data == NULL || 00144 DataLength == 0) 00145 { 00146 DPRINT("Invalid parameter\n"); 00147 return(NULL); 00148 } 00149 00150 Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, 00151 0, 00152 sizeof(INICACHEKEY)); 00153 if (Key == NULL) 00154 { 00155 DPRINT("RtlAllocateHeap() failed\n"); 00156 return(NULL); 00157 } 00158 00159 RtlZeroMemory(Key, 00160 sizeof(INICACHEKEY)); 00161 00162 00163 Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, 00164 0, 00165 (NameLength + 1) * sizeof(WCHAR)); 00166 if (Key->Name == NULL) 00167 { 00168 DPRINT("RtlAllocateHeap() failed\n"); 00169 RtlFreeHeap(ProcessHeap, 00170 0, 00171 Key); 00172 return(NULL); 00173 } 00174 00175 /* Copy value name */ 00176 for (i = 0; i < NameLength; i++) 00177 { 00178 Key->Name[i] = (WCHAR)Name[i]; 00179 } 00180 Key->Name[NameLength] = 0; 00181 00182 00183 Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap, 00184 0, 00185 (DataLength + 1) * sizeof(WCHAR)); 00186 if (Key->Data == NULL) 00187 { 00188 DPRINT("RtlAllocateHeap() failed\n"); 00189 RtlFreeHeap(ProcessHeap, 00190 0, 00191 Key->Name); 00192 RtlFreeHeap(ProcessHeap, 00193 0, 00194 Key); 00195 return(NULL); 00196 } 00197 00198 /* Copy value data */ 00199 for (i = 0; i < DataLength; i++) 00200 { 00201 Key->Data[i] = (WCHAR)Data[i]; 00202 } 00203 Key->Data[DataLength] = 0; 00204 00205 00206 if (Section->FirstKey == NULL) 00207 { 00208 Section->FirstKey = Key; 00209 Section->LastKey = Key; 00210 } 00211 else 00212 { 00213 Section->LastKey->Next = Key; 00214 Key->Prev = Section->LastKey; 00215 Section->LastKey = Key; 00216 } 00217 00218 return(Key); 00219 } 00220 00221 #if 0 00222 static PINICACHESECTION 00223 IniCacheFindSection(PINICACHE Cache, 00224 PWCHAR Name, 00225 ULONG NameLength) 00226 { 00227 PINICACHESECTION Section = NULL; 00228 00229 if (Cache == NULL || Name == NULL || NameLength == 0) 00230 { 00231 return(NULL); 00232 } 00233 00234 Section = Cache->FirstSection; 00235 00236 /* iterate through list of sections */ 00237 while (Section != NULL) 00238 { 00239 if (NameLength == wcslen(Section->Name)) 00240 { 00241 /* are the contents the same too? */ 00242 if (_wcsnicmp(Section->Name, Name, NameLength) == 0) 00243 break; 00244 } 00245 00246 /* get the next section*/ 00247 Section = Section->Next; 00248 } 00249 00250 return(Section); 00251 } 00252 #endif 00253 00254 static PINICACHESECTION 00255 IniCacheAddSection(PINICACHE Cache, 00256 PCHAR Name, 00257 ULONG NameLength) 00258 { 00259 PINICACHESECTION Section = NULL; 00260 ULONG i; 00261 00262 if (Cache == NULL || Name == NULL || NameLength == 0) 00263 { 00264 DPRINT("Invalid parameter\n"); 00265 return(NULL); 00266 } 00267 00268 Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, 00269 0, 00270 sizeof(INICACHESECTION)); 00271 if (Section == NULL) 00272 { 00273 DPRINT("RtlAllocateHeap() failed\n"); 00274 return(NULL); 00275 } 00276 RtlZeroMemory(Section, 00277 sizeof(INICACHESECTION)); 00278 00279 /* Allocate and initialize section name */ 00280 Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, 00281 0, 00282 (NameLength + 1) * sizeof(WCHAR)); 00283 if (Section->Name == NULL) 00284 { 00285 DPRINT("RtlAllocateHeap() failed\n"); 00286 RtlFreeHeap(ProcessHeap, 00287 0, 00288 Section); 00289 return(NULL); 00290 } 00291 00292 /* Copy section name */ 00293 for (i = 0; i < NameLength; i++) 00294 { 00295 Section->Name[i] = (WCHAR)Name[i]; 00296 } 00297 Section->Name[NameLength] = 0; 00298 00299 /* Append section */ 00300 if (Cache->FirstSection == NULL) 00301 { 00302 Cache->FirstSection = Section; 00303 Cache->LastSection = Section; 00304 } 00305 else 00306 { 00307 Cache->LastSection->Next = Section; 00308 Section->Prev = Cache->LastSection; 00309 Cache->LastSection = Section; 00310 } 00311 00312 return(Section); 00313 } 00314 00315 00316 static PCHAR 00317 IniCacheSkipWhitespace(PCHAR Ptr) 00318 { 00319 while (*Ptr != 0 && isspace(*Ptr)) 00320 Ptr++; 00321 00322 return((*Ptr == 0) ? NULL : Ptr); 00323 } 00324 00325 00326 static PCHAR 00327 IniCacheSkipToNextSection(PCHAR Ptr) 00328 { 00329 while (*Ptr != 0 && *Ptr != '[') 00330 { 00331 while (*Ptr != 0 && *Ptr != L'\n') 00332 { 00333 Ptr++; 00334 } 00335 Ptr++; 00336 } 00337 00338 return((*Ptr == 0) ? NULL : Ptr); 00339 } 00340 00341 00342 static PCHAR 00343 IniCacheGetSectionName(PCHAR Ptr, 00344 PCHAR *NamePtr, 00345 PULONG NameSize) 00346 { 00347 ULONG Size = 0; 00348 CHAR Name[256]; 00349 00350 *NamePtr = NULL; 00351 *NameSize = 0; 00352 00353 /* skip whitespace */ 00354 while (*Ptr != 0 && isspace(*Ptr)) 00355 { 00356 Ptr++; 00357 } 00358 00359 *NamePtr = Ptr; 00360 00361 while (*Ptr != 0 && *Ptr != ']') 00362 { 00363 Size++; 00364 Ptr++; 00365 } 00366 00367 Ptr++; 00368 00369 while (*Ptr != 0 && *Ptr != L'\n') 00370 { 00371 Ptr++; 00372 } 00373 Ptr++; 00374 00375 *NameSize = Size; 00376 00377 strncpy(Name, *NamePtr, Size); 00378 Name[Size] = 0; 00379 00380 DPRINT("SectionName: '%s'\n", Name); 00381 00382 return(Ptr); 00383 } 00384 00385 00386 static PCHAR 00387 IniCacheGetKeyName(PCHAR Ptr, 00388 PCHAR *NamePtr, 00389 PULONG NameSize) 00390 { 00391 ULONG Size = 0; 00392 00393 *NamePtr = NULL; 00394 *NameSize = 0; 00395 00396 while(Ptr && *Ptr) 00397 { 00398 *NamePtr = NULL; 00399 *NameSize = 0; 00400 Size = 0; 00401 00402 /* skip whitespace and empty lines */ 00403 while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r') 00404 { 00405 Ptr++; 00406 } 00407 if (*Ptr == 0) 00408 { 00409 continue; 00410 } 00411 00412 *NamePtr = Ptr; 00413 00414 while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';') 00415 { 00416 Size++; 00417 Ptr++; 00418 } 00419 if (*Ptr == ';') 00420 { 00421 while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n') 00422 { 00423 Ptr++; 00424 } 00425 } 00426 else 00427 { 00428 *NameSize = Size; 00429 break; 00430 } 00431 } 00432 00433 return(Ptr); 00434 } 00435 00436 00437 static PCHAR 00438 IniCacheGetKeyValue(PCHAR Ptr, 00439 PCHAR *DataPtr, 00440 PULONG DataSize, 00441 BOOLEAN String) 00442 { 00443 ULONG Size = 0; 00444 00445 *DataPtr = NULL; 00446 *DataSize = 0; 00447 00448 /* Skip whitespace */ 00449 while (*Ptr != 0 && isspace(*Ptr)) 00450 { 00451 Ptr++; 00452 } 00453 00454 /* Check and skip '=' */ 00455 if (*Ptr != '=') 00456 { 00457 return(NULL); 00458 } 00459 Ptr++; 00460 00461 /* Skip whitespace */ 00462 while (*Ptr != 0 && isspace(*Ptr)) 00463 { 00464 Ptr++; 00465 } 00466 00467 if (*Ptr == '"' && String) 00468 { 00469 Ptr++; 00470 00471 /* Get data */ 00472 *DataPtr = Ptr; 00473 while (*Ptr != '"') 00474 { 00475 Ptr++; 00476 Size++; 00477 } 00478 Ptr++; 00479 while (*Ptr && *Ptr != '\r' && *Ptr != '\n') 00480 { 00481 Ptr++; 00482 } 00483 } 00484 else 00485 { 00486 /* Get data */ 00487 *DataPtr = Ptr; 00488 while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';') 00489 { 00490 Ptr++; 00491 Size++; 00492 } 00493 } 00494 00495 /* Skip to next line */ 00496 if (*Ptr == '\r') 00497 Ptr++; 00498 if (*Ptr == '\n') 00499 Ptr++; 00500 00501 *DataSize = Size; 00502 00503 return(Ptr); 00504 } 00505 00506 00507 00508 00509 /* PUBLIC FUNCTIONS *********************************************************/ 00510 00511 NTSTATUS 00512 IniCacheLoad(PINICACHE *Cache, 00513 PUNICODE_STRING FileName, 00514 BOOLEAN String) 00515 { 00516 OBJECT_ATTRIBUTES ObjectAttributes; 00517 FILE_STANDARD_INFORMATION FileInfo; 00518 IO_STATUS_BLOCK IoStatusBlock; 00519 HANDLE FileHandle; 00520 NTSTATUS Status; 00521 PCHAR FileBuffer; 00522 ULONG FileLength; 00523 PCHAR Ptr; 00524 LARGE_INTEGER FileOffset; 00525 00526 PINICACHESECTION Section; 00527 PINICACHEKEY Key; 00528 00529 PCHAR SectionName; 00530 ULONG SectionNameSize; 00531 00532 PCHAR KeyName; 00533 ULONG KeyNameSize; 00534 00535 PCHAR KeyValue; 00536 ULONG KeyValueSize; 00537 00538 *Cache = NULL; 00539 00540 /* Open ini file */ 00541 InitializeObjectAttributes(&ObjectAttributes, 00542 FileName, 00543 0, 00544 NULL, 00545 NULL); 00546 00547 Status = NtOpenFile(&FileHandle, 00548 GENERIC_READ | SYNCHRONIZE, 00549 &ObjectAttributes, 00550 &IoStatusBlock, 00551 FILE_SHARE_READ, 00552 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); 00553 if (!NT_SUCCESS(Status)) 00554 { 00555 DPRINT("NtOpenFile() failed (Status %lx)\n", Status); 00556 return(Status); 00557 } 00558 00559 DPRINT("NtOpenFile() successful\n"); 00560 00561 /* Query file size */ 00562 Status = NtQueryInformationFile(FileHandle, 00563 &IoStatusBlock, 00564 &FileInfo, 00565 sizeof(FILE_STANDARD_INFORMATION), 00566 FileStandardInformation); 00567 if (!NT_SUCCESS(Status)) 00568 { 00569 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); 00570 NtClose(FileHandle); 00571 return(Status); 00572 } 00573 00574 FileLength = FileInfo.EndOfFile.u.LowPart; 00575 00576 DPRINT("File size: %lu\n", FileLength); 00577 00578 /* Allocate file buffer */ 00579 FileBuffer = (CHAR*) RtlAllocateHeap(ProcessHeap, 00580 0, 00581 FileLength + 1); 00582 if (FileBuffer == NULL) 00583 { 00584 DPRINT1("RtlAllocateHeap() failed\n"); 00585 NtClose(FileHandle); 00586 return(STATUS_INSUFFICIENT_RESOURCES); 00587 } 00588 00589 /* Read file */ 00590 FileOffset.QuadPart = 0ULL; 00591 Status = NtReadFile(FileHandle, 00592 NULL, 00593 NULL, 00594 NULL, 00595 &IoStatusBlock, 00596 FileBuffer, 00597 FileLength, 00598 &FileOffset, 00599 NULL); 00600 00601 /* Append string terminator */ 00602 FileBuffer[FileLength] = 0; 00603 00604 NtClose(FileHandle); 00605 00606 if (!NT_SUCCESS(Status)) 00607 { 00608 DPRINT("NtReadFile() failed (Status %lx)\n", Status); 00609 RtlFreeHeap(ProcessHeap, 00610 0, 00611 FileBuffer); 00612 return(Status); 00613 } 00614 00615 00616 /* Allocate inicache header */ 00617 *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, 00618 0, 00619 sizeof(INICACHE)); 00620 if (*Cache == NULL) 00621 { 00622 DPRINT("RtlAllocateHeap() failed\n"); 00623 return(STATUS_INSUFFICIENT_RESOURCES); 00624 } 00625 00626 /* Initialize inicache header */ 00627 RtlZeroMemory(*Cache, 00628 sizeof(INICACHE)); 00629 00630 /* Parse ini file */ 00631 Section = NULL; 00632 Ptr = FileBuffer; 00633 while (Ptr != NULL && *Ptr != 0) 00634 { 00635 Ptr = IniCacheSkipWhitespace(Ptr); 00636 if (Ptr == NULL) 00637 continue; 00638 00639 if (*Ptr == '[') 00640 { 00641 Section = NULL; 00642 Ptr++; 00643 00644 Ptr = IniCacheGetSectionName(Ptr, 00645 &SectionName, 00646 &SectionNameSize); 00647 00648 DPRINT1("[%.*s]\n", SectionNameSize, SectionName); 00649 00650 Section = IniCacheAddSection(*Cache, 00651 SectionName, 00652 SectionNameSize); 00653 if (Section == NULL) 00654 { 00655 DPRINT("IniCacheAddSection() failed\n"); 00656 Ptr = IniCacheSkipToNextSection(Ptr); 00657 continue; 00658 } 00659 } 00660 else 00661 { 00662 if (Section == NULL) 00663 { 00664 Ptr = IniCacheSkipToNextSection(Ptr); 00665 continue; 00666 } 00667 00668 Ptr = IniCacheGetKeyName(Ptr, 00669 &KeyName, 00670 &KeyNameSize); 00671 00672 Ptr = IniCacheGetKeyValue(Ptr, 00673 &KeyValue, 00674 &KeyValueSize, 00675 String); 00676 00677 DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue); 00678 00679 Key = IniCacheAddKey(Section, 00680 KeyName, 00681 KeyNameSize, 00682 KeyValue, 00683 KeyValueSize); 00684 if (Key == NULL) 00685 { 00686 DPRINT("IniCacheAddKey() failed\n"); 00687 } 00688 } 00689 } 00690 00691 /* Free file buffer */ 00692 RtlFreeHeap(ProcessHeap, 00693 0, 00694 FileBuffer); 00695 00696 return(Status); 00697 } 00698 00699 00700 VOID 00701 IniCacheDestroy(PINICACHE Cache) 00702 { 00703 if (Cache == NULL) 00704 { 00705 return; 00706 } 00707 00708 while (Cache->FirstSection != NULL) 00709 { 00710 Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection); 00711 } 00712 Cache->LastSection = NULL; 00713 00714 RtlFreeHeap(ProcessHeap, 00715 0, 00716 Cache); 00717 } 00718 00719 00720 PINICACHESECTION 00721 IniCacheGetSection(PINICACHE Cache, 00722 PWCHAR Name) 00723 { 00724 PINICACHESECTION Section = NULL; 00725 00726 if (Cache == NULL || Name == NULL) 00727 { 00728 DPRINT("Invalid parameter\n"); 00729 return(NULL); 00730 } 00731 00732 /* Iterate through list of sections */ 00733 Section = Cache->FirstSection; 00734 while (Section != NULL) 00735 { 00736 DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name); 00737 00738 /* Are the section names the same? */ 00739 if (_wcsicmp(Section->Name, Name) == 0) 00740 return(Section); 00741 00742 /* Get the next section */ 00743 Section = Section->Next; 00744 } 00745 00746 DPRINT("Section not found\n"); 00747 00748 return(NULL); 00749 } 00750 00751 00752 NTSTATUS 00753 IniCacheGetKey(PINICACHESECTION Section, 00754 PWCHAR KeyName, 00755 PWCHAR *KeyData) 00756 { 00757 PINICACHEKEY Key; 00758 00759 if (Section == NULL || KeyName == NULL || KeyData == NULL) 00760 { 00761 DPRINT("Invalid parameter\n"); 00762 return(STATUS_INVALID_PARAMETER); 00763 } 00764 00765 *KeyData = NULL; 00766 00767 Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName)); 00768 if (Key == NULL) 00769 { 00770 return(STATUS_INVALID_PARAMETER); 00771 } 00772 00773 *KeyData = Key->Data; 00774 00775 return(STATUS_SUCCESS); 00776 } 00777 00778 00779 PINICACHEITERATOR 00780 IniCacheFindFirstValue(PINICACHESECTION Section, 00781 PWCHAR *KeyName, 00782 PWCHAR *KeyData) 00783 { 00784 PINICACHEITERATOR Iterator; 00785 PINICACHEKEY Key; 00786 00787 if (Section == NULL || KeyName == NULL || KeyData == NULL) 00788 { 00789 DPRINT("Invalid parameter\n"); 00790 return(NULL); 00791 } 00792 00793 Key = Section->FirstKey; 00794 if (Key == NULL) 00795 { 00796 DPRINT("Invalid parameter\n"); 00797 return(NULL); 00798 } 00799 00800 *KeyName = Key->Name; 00801 *KeyData = Key->Data; 00802 00803 Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap, 00804 0, 00805 sizeof(INICACHEITERATOR)); 00806 if (Iterator == NULL) 00807 { 00808 DPRINT("RtlAllocateHeap() failed\n"); 00809 return(NULL); 00810 } 00811 00812 Iterator->Section = Section; 00813 Iterator->Key = Key; 00814 00815 return(Iterator); 00816 } 00817 00818 00819 BOOLEAN 00820 IniCacheFindNextValue(PINICACHEITERATOR Iterator, 00821 PWCHAR *KeyName, 00822 PWCHAR *KeyData) 00823 { 00824 PINICACHEKEY Key; 00825 00826 if (Iterator == NULL || KeyName == NULL || KeyData == NULL) 00827 { 00828 DPRINT("Invalid parameter\n"); 00829 return(FALSE); 00830 } 00831 00832 Key = Iterator->Key->Next; 00833 if (Key == NULL) 00834 { 00835 DPRINT("No more entries\n"); 00836 return(FALSE); 00837 } 00838 00839 *KeyName = Key->Name; 00840 *KeyData = Key->Data; 00841 00842 Iterator->Key = Key; 00843 00844 return(TRUE); 00845 } 00846 00847 00848 VOID 00849 IniCacheFindClose(PINICACHEITERATOR Iterator) 00850 { 00851 if (Iterator == NULL) 00852 return; 00853 00854 RtlFreeHeap(ProcessHeap, 00855 0, 00856 Iterator); 00857 } 00858 00859 00860 PINICACHEKEY 00861 IniCacheInsertKey(PINICACHESECTION Section, 00862 PINICACHEKEY AnchorKey, 00863 INSERTATION_TYPE InsertationType, 00864 PWCHAR Name, 00865 PWCHAR Data) 00866 { 00867 PINICACHEKEY Key; 00868 00869 Key = NULL; 00870 00871 if (Section == NULL || 00872 Name == NULL || 00873 *Name == 0 || 00874 Data == NULL || 00875 *Data == 0) 00876 { 00877 DPRINT("Invalid parameter\n"); 00878 return(NULL); 00879 } 00880 00881 /* Allocate key buffer */ 00882 Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, 00883 0, 00884 sizeof(INICACHEKEY)); 00885 if (Key == NULL) 00886 { 00887 DPRINT("RtlAllocateHeap() failed\n"); 00888 return(NULL); 00889 } 00890 RtlZeroMemory(Key, 00891 sizeof(INICACHEKEY)); 00892 00893 /* Allocate name buffer */ 00894 Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, 00895 0, 00896 (wcslen(Name) + 1) * sizeof(WCHAR)); 00897 if (Key->Name == NULL) 00898 { 00899 DPRINT("RtlAllocateHeap() failed\n"); 00900 RtlFreeHeap(ProcessHeap, 00901 0, 00902 Key); 00903 return(NULL); 00904 } 00905 00906 /* Copy value name */ 00907 wcscpy(Key->Name, Name); 00908 00909 /* Allocate data buffer */ 00910 Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap, 00911 0, 00912 (wcslen(Data) + 1) * sizeof(WCHAR)); 00913 if (Key->Data == NULL) 00914 { 00915 DPRINT("RtlAllocateHeap() failed\n"); 00916 RtlFreeHeap(ProcessHeap, 00917 0, 00918 Key->Name); 00919 RtlFreeHeap(ProcessHeap, 00920 0, 00921 Key); 00922 return(NULL); 00923 } 00924 00925 /* Copy value data */ 00926 wcscpy(Key->Data, Data); 00927 00928 /* Insert key into section */ 00929 if (Section->FirstKey == NULL) 00930 { 00931 Section->FirstKey = Key; 00932 Section->LastKey = Key; 00933 } 00934 else if ((InsertationType == INSERT_FIRST) || 00935 ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey)))) 00936 { 00937 /* Insert at the head of the list */ 00938 Section->FirstKey->Prev = Key; 00939 Key->Next = Section->FirstKey; 00940 Section->FirstKey = Key; 00941 } 00942 else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL)) 00943 { 00944 /* Insert before the anchor key */ 00945 Key->Next = AnchorKey; 00946 Key->Prev = AnchorKey->Prev; 00947 AnchorKey->Prev->Next = Key; 00948 AnchorKey->Prev = Key; 00949 } 00950 else if ((InsertationType == INSERT_LAST) || 00951 ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey)))) 00952 { 00953 Section->LastKey->Next = Key; 00954 Key->Prev = Section->LastKey; 00955 Section->LastKey = Key; 00956 } 00957 else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL)) 00958 { 00959 /* Insert before the anchor key */ 00960 Key->Next = AnchorKey->Next; 00961 Key->Prev = AnchorKey; 00962 AnchorKey->Next->Prev = Key; 00963 AnchorKey->Next = Key; 00964 } 00965 00966 return(Key); 00967 } 00968 00969 00970 PINICACHE 00971 IniCacheCreate(VOID) 00972 { 00973 PINICACHE Cache; 00974 00975 /* Allocate inicache header */ 00976 Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, 00977 0, 00978 sizeof(INICACHE)); 00979 if (Cache == NULL) 00980 { 00981 DPRINT("RtlAllocateHeap() failed\n"); 00982 return(NULL); 00983 } 00984 00985 /* Initialize inicache header */ 00986 RtlZeroMemory(Cache, 00987 sizeof(INICACHE)); 00988 00989 return(Cache); 00990 } 00991 00992 00993 NTSTATUS 00994 IniCacheSave(PINICACHE Cache, 00995 PWCHAR FileName) 00996 { 00997 UNICODE_STRING Name; 00998 PINICACHESECTION Section; 00999 PINICACHEKEY Key; 01000 ULONG BufferSize; 01001 PCHAR Buffer; 01002 PCHAR Ptr; 01003 ULONG Len; 01004 NTSTATUS Status; 01005 01006 OBJECT_ATTRIBUTES ObjectAttributes; 01007 IO_STATUS_BLOCK IoStatusBlock; 01008 LARGE_INTEGER Offset; 01009 HANDLE FileHandle; 01010 01011 01012 /* Calculate required buffer size */ 01013 BufferSize = 0; 01014 Section = Cache->FirstSection; 01015 while (Section != NULL) 01016 { 01017 BufferSize += (Section->Name ? wcslen(Section->Name) : 0) 01018 + 4; /* "[]\r\n" */ 01019 01020 Key = Section->FirstKey; 01021 while (Key != NULL) 01022 { 01023 BufferSize += wcslen(Key->Name) 01024 + (Key->Data ? wcslen(Key->Data) : 0) 01025 + 3; /* "=\r\n" */ 01026 Key = Key->Next; 01027 } 01028 01029 Section = Section->Next; 01030 if (Section != NULL) 01031 BufferSize += 2; /* extra "\r\n" at end of each section */ 01032 } 01033 BufferSize++; /* Null-terminator */ 01034 01035 DPRINT("BufferSize: %lu\n", BufferSize); 01036 01037 /* Allocate file buffer */ 01038 Buffer = (CHAR*) RtlAllocateHeap(ProcessHeap, 01039 0, 01040 BufferSize); 01041 if (Buffer == NULL) 01042 { 01043 DPRINT1("RtlAllocateHeap() failed\n"); 01044 return(STATUS_INSUFFICIENT_RESOURCES); 01045 } 01046 RtlZeroMemory(Buffer, BufferSize); 01047 01048 /* Fill file buffer */ 01049 Ptr = Buffer; 01050 Section = Cache->FirstSection; 01051 while (Section != NULL) 01052 { 01053 Len = sprintf(Ptr, "[%S]\r\n", Section->Name); 01054 Ptr += Len; 01055 01056 Key = Section->FirstKey; 01057 while (Key != NULL) 01058 { 01059 Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data); 01060 Ptr += Len; 01061 Key = Key->Next; 01062 } 01063 01064 Section = Section->Next; 01065 if (Section != NULL) 01066 { 01067 Len = sprintf(Ptr, "\r\n"); 01068 Ptr += Len; 01069 } 01070 } 01071 01072 /* Create ini file */ 01073 RtlInitUnicodeString(&Name, 01074 FileName); 01075 01076 InitializeObjectAttributes(&ObjectAttributes, 01077 &Name, 01078 0, 01079 NULL, 01080 NULL); 01081 01082 Status = NtCreateFile(&FileHandle, 01083 GENERIC_WRITE, 01084 &ObjectAttributes, 01085 &IoStatusBlock, 01086 NULL, 01087 FILE_ATTRIBUTE_NORMAL, 01088 0, 01089 FILE_SUPERSEDE, 01090 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 01091 NULL, 01092 0); 01093 if (!NT_SUCCESS(Status)) 01094 { 01095 DPRINT("NtCreateFile() failed (Status %lx)\n", Status); 01096 RtlFreeHeap(ProcessHeap, 01097 0, 01098 Buffer); 01099 return(Status); 01100 } 01101 01102 Offset.QuadPart = 0LL; 01103 Status = NtWriteFile(FileHandle, 01104 NULL, 01105 NULL, 01106 NULL, 01107 &IoStatusBlock, 01108 Buffer, 01109 BufferSize, 01110 &Offset, 01111 NULL); 01112 if (!NT_SUCCESS(Status)) 01113 { 01114 DPRINT("NtWriteFile() failed (Status %lx)\n", Status); 01115 NtClose(FileHandle); 01116 RtlFreeHeap(ProcessHeap, 01117 0, 01118 Buffer); 01119 return(Status); 01120 } 01121 01122 NtClose(FileHandle); 01123 01124 RtlFreeHeap(ProcessHeap, 01125 0, 01126 Buffer); 01127 01128 return(STATUS_SUCCESS); 01129 } 01130 01131 01132 PINICACHESECTION 01133 IniCacheAppendSection(PINICACHE Cache, 01134 PWCHAR Name) 01135 { 01136 PINICACHESECTION Section = NULL; 01137 01138 if (Cache == NULL || Name == NULL || *Name == 0) 01139 { 01140 DPRINT("Invalid parameter\n"); 01141 return(NULL); 01142 } 01143 01144 Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, 01145 0, 01146 sizeof(INICACHESECTION)); 01147 if (Section == NULL) 01148 { 01149 DPRINT("RtlAllocateHeap() failed\n"); 01150 return(NULL); 01151 } 01152 RtlZeroMemory(Section, 01153 sizeof(INICACHESECTION)); 01154 01155 /* Allocate and initialize section name */ 01156 Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, 01157 0, 01158 (wcslen(Name) + 1) * sizeof(WCHAR)); 01159 if (Section->Name == NULL) 01160 { 01161 DPRINT("RtlAllocateHeap() failed\n"); 01162 RtlFreeHeap(ProcessHeap, 01163 0, 01164 Section); 01165 return(NULL); 01166 } 01167 01168 /* Copy section name */ 01169 wcscpy(Section->Name, Name); 01170 01171 /* Append section */ 01172 if (Cache->FirstSection == NULL) 01173 { 01174 Cache->FirstSection = Section; 01175 Cache->LastSection = Section; 01176 } 01177 else 01178 { 01179 Cache->LastSection->Next = Section; 01180 Section->Prev = Cache->LastSection; 01181 Cache->LastSection = Section; 01182 } 01183 01184 return(Section); 01185 } 01186 01187 /* EOF */ Generated on Sun May 27 2012 04:17:59 for ReactOS by
1.7.6.1
|