ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

inicache.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.