source: trunk/source/lib/wtkfinit.c

Last change on this file was 263, checked in by cla, 18 years ago
  • added missing APIENTRY keyword to function headers
File size: 43.9 KB
Line 
1/****************************** Module Header ******************************\
2*
3* Module Name: wtkfinit.c
4*
5* Source for access functions for text initialization files
6*
7* Copyright (c) WPS Toolkit Project - Christian Langanke 2000
8*
9* $Id: wtkfinit.c,v 1.4 2003-04-24 15:41:42 cla Exp $
10*
11* ===========================================================================
12*
13* This file is part of the WPS Toolkit package and is free software.  You can
14* redistribute it and/or modify it under the terms of the GNU Library General
15* Public License as published by the Free Software Foundation, in version 2
16* as it comes in the "COPYING.LIB" file of the WPS Toolkit main distribution.
17* This library is distributed in the hope that it will be useful, but WITHOUT
18* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
20* License for more details.
21*
22* ===========================================================================
23*
24\***************************************************************************/
25
26#define INCL_DOS
27#define INCL_ERRORS
28#include <os2.h>
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "wtkfinit.h"
35#include "wpstk.ih"
36
37// ---------------------------------------------------------------------------
38
39// define max line size (+ LF + ZEROBYTE)
40#define WTK_INIT_MAX_LINESIZE         (512 + 2)
41#define WTK_INIT_CHARS_COMMENT        ";"
42#define WTK_INIT_CHARS_DELIMITER      "="
43
44#define WTK_INIT_STR_COMMENT          "//"
45#define WTK_INIT_CHAR_SECTION_START   '['
46#define WTK_INIT_CHAR_SECTION_END     ']'
47
48// ---------------------------------------------------------------------------
49
50#pragma pack(1)
51
52// ---- init file data entities
53//      all PSZs point to malloced memory (strdup)
54//      same applies to "first" and "next" fields
55
56typedef struct _KEY
57   {
58         PSZ            pszKeyName;
59         PSZ            pszKeyValue;
60         PSZ            pszComment;
61         PSZ            pszValueComment;
62         PSZ            pszTailComment;
63         CHAR           chDelimiter;
64         ULONG          ulKeyIndent;
65         ULONG          ulKeyNameLen;
66         ULONG          ulValueIndent;
67         ULONG          ulValueCommentIndent;
68  struct _KEY          *pkeyNext;
69   } KEY, *PKEY;
70
71typedef struct _SECTION
72   {
73         PSZ            pszSectionName;
74         PSZ            pszComment;
75         PSZ            pszTailComment;
76         PKEY           pkeyFirst;
77  struct _SECTION      *psectionNext;
78   } SECTION, *PSECTION;
79
80// ---- global init file description structure
81//      pointer mapped to HINIT
82
83typedef struct _INIT
84   {
85         FILE           *pfile;
86         CHAR           szFilename[ _MAX_PATH];
87         ULONG          ulOpenMode;
88         ULONG          ulUpdateMode;
89         BOOL           fModified;
90         CHAR           chDelimiter;
91         CHAR           chComment;
92         PSECTION       psectionFirst;
93         KEY            keyLast;
94   } INIT, *PINIT;
95
96#pragma pack()
97
98// ---------------------------------------------------------------------------
99
100static VOID _freeKEY( PKEY pkey)
101{
102if (pkey)
103   {
104   if (pkey->pszKeyName)      free( pkey->pszKeyName);
105   if (pkey->pszKeyValue)     free( pkey->pszKeyValue);
106   if (pkey->pszComment)      free( pkey->pszComment);
107   if (pkey->pszValueComment) free( pkey->pszValueComment);
108   if (pkey->pszTailComment)  free( pkey->pszTailComment);
109
110   _freeKEY( pkey->pkeyNext);
111   memset( pkey, 0, sizeof( KEY));
112   free( pkey);
113   }
114}
115
116static VOID _freeSECTION( PSECTION psec)
117{
118if (psec)
119   {
120   if (psec->pszSectionName)  free( psec->pszSectionName);
121   if (psec->pszComment)      free( psec->pszComment);
122   if (psec->pszTailComment)  free( psec->pszTailComment);
123
124   _freeKEY( psec->pkeyFirst);
125   _freeSECTION( psec->psectionNext);
126   memset( psec, 0, sizeof( SECTION));
127   free( psec);
128   }
129}
130
131static VOID _freeINIT( PINIT pinit)
132{
133if (pinit)
134   {
135   if (pinit->pfile)          fclose( pinit->pfile);
136
137   _freeSECTION( pinit->psectionFirst);
138   memset( pinit, 0, sizeof( INIT));
139   free( pinit);
140   }
141}
142
143// ----------------------------------------------------------------------
144
145static APIRET _writeKEY( FILE *pfile, PKEY pkey, ULONG ulUpdateMode)
146{
147         APIRET         rc = NO_ERROR;
148         ULONG          i;
149
150if (pkey)
151   {
152   if (!(ulUpdateMode & WTK_INIT_UPDATE_DISCARDCOMMENTS))
153      fprintf( pfile, "%s", pkey->pszComment);
154
155   for (i = 0; i < pkey->ulKeyIndent; i++)
156      {
157      fprintf( pfile, " ");
158      }
159
160   fprintf( pfile, "%-*s%c",
161            pkey->ulKeyNameLen,
162            pkey->pszKeyName,
163            pkey->chDelimiter);
164
165   for (i = 0; i < pkey->ulValueIndent; i++)
166      {
167      fprintf( pfile, " ");
168      }
169   fprintf( pfile, "%s", pkey->pszKeyValue);
170
171   if (pkey->pszValueComment)
172      {
173      for (i = 0; i < pkey->ulValueCommentIndent; i++)
174         {
175         fprintf( pfile, " ");
176         }
177      fprintf( pfile, "%s", pkey->pszValueComment);
178      }
179
180   fprintf( pfile, "\n");
181
182   if (pkey->pszTailComment)
183      fprintf( pfile, "%s", pkey->pszTailComment);
184
185   _writeKEY( pfile, pkey->pkeyNext, ulUpdateMode);
186   }
187
188return rc;
189}
190
191
192static APIRET _writeSECTION( FILE *pfile, PSECTION psec, ULONG ulUpdateMode)
193{
194         APIRET         rc = NO_ERROR;
195
196if (psec)
197   {
198   if (!(ulUpdateMode & WTK_INIT_UPDATE_DISCARDCOMMENTS))
199      fprintf( pfile, "%s", psec->pszComment);
200   fprintf( pfile, "[%s]\n", psec->pszSectionName);
201
202   if (psec->pszTailComment)
203      fprintf( pfile, "%s", psec->pszTailComment);
204
205   _writeKEY( pfile,      psec->pkeyFirst,    ulUpdateMode);
206   _writeSECTION( pfile,  psec->psectionNext, ulUpdateMode);
207   }
208
209return rc;
210}
211
212// ----------------------------------------------------------------------
213
214static PKEY _findKEY( PSECTION psec, PSZ pszKeyName)
215{
216         PKEY           pkey = NULL;
217
218if ((psec) && (pszKeyName))
219   {
220   pkey = psec->pkeyFirst;
221   while (pkey)
222      {
223      if (!stricmp( pkey->pszKeyName, pszKeyName))
224         break;
225      pkey = pkey->pkeyNext;
226      }
227   }
228return pkey;
229}
230
231static PSECTION _findSECTION( PINIT pinit, PSZ pszSectionName)
232{
233         PSECTION       psec = NULL;
234
235if ((pinit) && (pszSectionName))
236   {
237   psec = pinit->psectionFirst;
238   while (psec)
239      {
240      if (!stricmp( psec->pszSectionName, pszSectionName))
241         break;
242      psec = psec->psectionNext;
243      }
244   }
245return psec;
246}
247
248// ----------------------------------------------------------------------
249
250static APIRET _collectKEY( PSECTION psec, PSZ pszBuffer, ULONG ulBuflen, PULONG pulProfileSize)
251{
252         APIRET         rc = NO_ERROR;
253         PKEY           pkey;
254
255         PSZ            pszThisValue     = pszBuffer;
256         ULONG          ulValueLen;
257         ULONG          ulRemainingSpace = ulBuflen;
258
259if (psec)
260   {
261   pkey = psec->pkeyFirst;
262   *pulProfileSize = 0;
263   while (pkey)
264      {
265      ulValueLen = strlen( pkey->pszKeyName) + 1;
266      *pulProfileSize += ulValueLen;
267
268      if (pszBuffer)
269         {
270         if (ulRemainingSpace < ulValueLen + 1)
271            {
272            rc = ERROR_BUFFER_OVERFLOW;
273            break;
274            }
275
276         // store value
277         strcpy( pszThisValue, pkey->pszKeyName);
278         ulRemainingSpace -= ulValueLen;
279         pszThisValue += ulValueLen;
280         }
281
282      // next section
283      pkey = pkey->pkeyNext;
284
285      }
286
287   // do NOT count double zero byte - like PrfQueryProfileString
288   // (*pulProfileSize)++;
289
290   }
291
292return rc;
293}
294
295static APIRET _collectSECTION( PINIT pinit, PSZ pszBuffer, ULONG ulBuflen, PULONG pulProfileSize)
296{
297         APIRET         rc = NO_ERROR;
298         PSECTION       psec;
299
300         PSZ            pszThisValue     = pszBuffer;
301         ULONG          ulValueLen;
302         ULONG          ulRemainingSpace = ulBuflen;
303
304if (pinit)
305   {
306   psec = pinit->psectionFirst;
307   *pulProfileSize = 0;
308   while (psec)
309      {
310      ulValueLen = strlen( psec->pszSectionName) + 1;
311      *pulProfileSize += ulValueLen;
312
313      if (pszBuffer)
314         {
315         if (ulRemainingSpace < ulValueLen + 1)
316            {
317            rc = ERROR_BUFFER_OVERFLOW;
318            break;
319            }
320
321         // store value
322         strcpy( pszThisValue, psec->pszSectionName);
323         ulRemainingSpace -= ulValueLen;
324         pszThisValue += ulValueLen;
325         }
326
327
328      // next section
329      psec = psec->psectionNext;
330      }
331
332   // do NOT count double zero byte - like PrfQueryProfileString
333   // (*pulProfileSize)++;
334
335   }
336
337return rc;
338}
339
340// ----------------------------------------------------------------------
341
342static PKEY _createKEY( PINIT pinit, PSECTION psec, PSZ pszKeyName, PSZ pszNewValue)
343{
344         PKEY           pkey = NULL;
345         PKEY           pkeyLast;
346         PKEY          *pkeyParent;
347
348if (psec)
349   {
350   pkeyLast   = psec->pkeyFirst;
351   pkeyParent = &psec->pkeyFirst;
352   while (*pkeyParent)
353      {
354      if (pkeyLast->pkeyNext)
355         pkeyLast   = pkeyLast->pkeyNext;
356      pkeyParent = &((*pkeyParent)->pkeyNext);
357      }
358
359   // create new key
360   pkey = malloc( sizeof( KEY));
361   if (pkey)
362      {
363      *pkeyParent = pkey;
364      memset( pkey, 0, sizeof( KEY));
365      pkey->chDelimiter   = pinit->chDelimiter;
366      pkey->pszComment    = strdup( "");
367      pkey->pszKeyName    = strdup( pszKeyName);
368      pkey->pszKeyValue = strdup( pszNewValue);
369      if ((!pkey->pszKeyName) || (!pkey->pszKeyValue))
370         {
371         free( pkey);
372         *pkeyParent = NULL;
373         }
374
375      // use ident vars either from last key of
376      // this section or from last saved key of this file
377      if (!pkeyLast)
378         pkeyLast = &pinit->keyLast;
379      pkey->ulKeyIndent   = pkeyLast->ulKeyIndent;
380      pkey->ulKeyNameLen  = pkeyLast->ulKeyNameLen;
381      pkey->ulValueIndent = pkeyLast->ulValueIndent;
382      }
383   }
384
385return pkey;
386}
387
388// ----------------------------------------------------------------------
389
390static PSECTION _createSECTION( PINIT pinit, PSZ pszSectionName)
391{
392         PSECTION       psec = NULL;
393         PSECTION      *psecParent;
394
395if (pinit)
396   {
397   psecParent = &pinit->psectionFirst;
398   while (*psecParent)
399      {
400      psecParent = &((*psecParent)->psectionNext);
401      }
402
403   // create new section
404   psec = malloc( sizeof( SECTION));
405   if (psec)
406      {
407      *psecParent = psec;
408      memset( psec, 0, sizeof( SECTION));
409      psec->pszComment     = strdup( "\n");
410      psec->pszSectionName = strdup( pszSectionName);
411      if (!psec->pszSectionName)
412         {
413         free( psec);
414         *psecParent = NULL;
415         }
416      }
417
418   }
419return psec;
420}
421
422// ----------------------------------------------------------------------
423
424static BOOL _removeKEY( PINIT pinit, PSECTION psec, PSZ pszKeyName)
425{
426         BOOL           fRemoved = FALSE;
427         PKEY           pkey;
428         PKEY          *pkeyParent;
429         PSZ           *ppszLastTailComment;
430
431         ULONG          i;
432         ULONG          ulDeleteCommentLen = 0;
433         ULONG          ulCommentCharsLen;
434         PSZ            pszNewTailComment;
435
436if (psec)
437   {
438   pkeyParent          = &psec->pkeyFirst;
439   ppszLastTailComment = &psec->pszTailComment;
440   pkey                = psec->pkeyFirst;
441   while (pkey)
442      {
443      if (!stricmp( pkey->pszKeyName, pszKeyName))
444         break;
445      pkeyParent          = &pkey->pkeyNext;
446      ppszLastTailComment = &pkey->pszTailComment;
447      pkey                = pkey->pkeyNext;
448      }
449
450   if (pkey)
451      {
452      if (pinit->ulUpdateMode & WTK_INIT_UPDATE_SOFTDELETEKEYS)
453         {
454         // softdelete: add line to tail comment of key before
455         // - determine len and get memory for new tail comment
456         if (pkey->pszComment)
457            ulDeleteCommentLen += strlen( pkey->pszComment)    + 1;
458
459         ulDeleteCommentLen += pkey->ulKeyIndent               +
460                               pkey->ulKeyNameLen              +
461                               strlen(  pkey->pszKeyName)      + 1 +
462                                                                 1 +  // delimter char
463                               pkey->ulValueIndent             +
464                               strlen(  pkey->pszKeyValue)     + 1;
465
466         if (pkey->pszValueComment)
467            ulDeleteCommentLen += strlen( pkey->pszValueComment) + 1;
468         if (*ppszLastTailComment)
469            ulDeleteCommentLen += strlen( *ppszLastTailComment) + 1;
470
471         pszNewTailComment = malloc( ulDeleteCommentLen);
472         if (!pszNewTailComment)
473            return FALSE;
474
475         // assemble new comment
476         if (*ppszLastTailComment)
477            strcpy( pszNewTailComment, *ppszLastTailComment);
478         else
479            *pszNewTailComment = 0;
480
481         if (pkey->pszComment)
482            strcat( pszNewTailComment, pkey->pszComment);
483
484         if (pinit->chComment == '/')
485            {
486            strcat( pszNewTailComment, "//");
487            ulCommentCharsLen = 2;
488            }
489         else
490            {
491            sprintf( pszNewTailComment + strlen( pszNewTailComment), "%c", pinit->chComment);
492            ulCommentCharsLen = 1;
493            }
494
495         if (pkey->ulKeyIndent > ulCommentCharsLen)
496            {
497            for (i = 0; i < pkey->ulKeyIndent - ulCommentCharsLen; i++)
498               {
499               strcat( pszNewTailComment, " ");
500               }
501            }
502
503         sprintf( pszNewTailComment + strlen( pszNewTailComment),
504                  "%-*s%c",
505                  pkey->ulKeyNameLen,
506                  pkey->pszKeyName,
507                  pkey->chDelimiter);
508
509         for (i = 0; i < pkey->ulValueIndent; i++)
510            {
511            strcat( pszNewTailComment, " ");
512            }
513         sprintf( pszNewTailComment + strlen( pszNewTailComment), "%s\n", pkey->pszKeyValue);
514
515         // replace/add new tail comment
516         if (*ppszLastTailComment)
517            free( *ppszLastTailComment);
518         *ppszLastTailComment = pszNewTailComment;
519
520         }
521
522      // now delete key entry
523      *pkeyParent = pkey->pkeyNext;
524      memset( pkey, 0, sizeof( KEY));
525      free( pkey);
526      fRemoved = TRUE;
527
528      } // if (pkey)
529   }
530
531return fRemoved;
532}
533
534// ----------------------------------------------------------------------
535
536static BOOL _removeSECTION( PINIT pinit, PSZ pszSectionName)
537{
538         BOOL           fRemoved = FALSE;
539         PSECTION       psec;
540         PSECTION      *psecParent;
541
542if (pinit)
543   {
544   psecParent = &pinit->psectionFirst;
545   psec       = pinit->psectionFirst;
546   while (psec)
547      {
548      if (!stricmp( psec->pszSectionName, pszSectionName))
549         break;
550      psecParent = &psec->psectionNext;
551      psec       = psec->psectionNext;
552      }
553
554   if (psec)
555      {
556      *psecParent = psec->psectionNext;
557      memset( psec, 0, sizeof( SECTION));
558      free( psec);
559      fRemoved = TRUE;
560      }
561   }
562
563return fRemoved;
564}
565
566// ======================================================================
567
568/*
569@@WtkOpenInitProfile@SYNTAX
570This function opens an existing text initialization file or a pseudo in-memory file.
571
572@@WtkOpenInitProfile@PARM@pszName@in
573Address of the ASCIIZ path name of the text initialization file.
574:p.
575The path name may contain :hp2.?&colon.:ehp2. for the drive in order to
576search the file on the boot drive.
577:p.
578The name may not include wildcards.
579
580@@WtkOpenInitProfile@PARM@phinit@out
581The address of a buffer in into which the handle to the
582requested text initialization file is to be returned.
583
584@@WtkOpenInitProfile@PARM@ulOpenMode@in
585A variable specifying the mode for opening the text initialization file.
586:p.
587Specify one of the following flags for opening text initialization files:
588:parml.
589:pt.WTK_INIT_OPEN_READONLY
590:pd.open the text initialization file in readonly mode. Any changes by :hp2.WtkWriteInitProfileString:ehp2.
591will be ignored.
592:pt.WTK_INIT_OPEN_READWRITE
593:pd.open the text initialization file exclusively in readwrite mode. This means that the file may
594not be in read or write access, otherwise opening the file will fail.
595:pt.WTK_INIT_OPEN_INMEMORY
596:pd.open the text initialization file in memory only. No updates can be saved, the flag
597fUpdate is ignored on :hp2.WtkCloseInitProfile:ehp2..
598:eparml.
599:p.
600Specify additional flags like:
601:parml.
602:pt.WTK_INIT_OPEN_ALLOWERRORS
603:pd.allows parse errors, especially for comment layouts. When saving files that have been read
604in ignoring parse errors, the contents of the new file may be invalid.
605:eparml.
606
607@@WtkOpenInitProfile@PARM@ulUpdateMode@in
608A variable specifying the update mode for a text initialization file.
609:p.
610Specify one of the following flags:
611:parml.
612:pt.WTK_INIT_UPDATE_DISCARDCOMMENTS
613:pd.discards any comments when a file is saved
614:pt.WTK_INIT_UPDATE_SOFTDELETEKEYS
615:pd.delete comments of deleted keys as well
616:eparml.
617
618@@WtkOpenInitProfile@PARM@pip@in
619A structure defining optional parameters for parsing a text initialization file.
620:p.
621By defining this parameter structure, the parser of :hp2.WtkOpenInitProfile:ehp2. can
622be forced to use custom comment and delimiter characters as well as default indent values.
623:p.
624However, in order to parse standard Win-16 text initialization files, it is
625recommended to use the standard parameters for parsing. For that, specify
626NULL for this parameter.
627
628@@WtkOpenInitProfile@RETURN
629Return Code.
630:p.
631WtkOpenInitProfile returns one of the following return codes&colon.
632
633:parml compact break=none.
634:pt.0
635:pd.NO_ERROR
636:pt.8
637:pd.ERROR_NOT_ENOUGH_MEMORY
638:pt.13
639:pd.ERROR_INVALID_DATA
640:pt.87
641:pd.ERROR_INVALID_PARAMETER
642:pt.110
643:pd.ERROR_OPEN_FAILED
644:eparml.
645:p.
646or return codes of the following functions
647:ul compact.
648:li.DosOpen
649:eul.
650
651@@WtkOpenInitProfile@REMARKS
652This function supports boot drive recognition.
653Specify :hp2.?&colon.:ehp2. for the drive in order to
654search the file on the boot drive.
655
656@@
657*/
658
659APIRET APIENTRY WtkOpenInitProfile( PSZ pszName, PHINIT phinit,
660                                    ULONG ulOpenMode, ULONG ulUpdateMode, PINITPARMS pip)
661{
662         APIRET         rc = NO_ERROR;
663         PINIT          pinit = NULL;
664         INITPARMS      ip;
665         PSZ            p;
666
667         CHAR           szName[ _MAX_PATH];
668
669         PSZ            pszOpenMode;
670         BOOL           fInMemory = FALSE;
671         BOOL           fAllowErrors = FALSE;
672
673static   PSZ            pszLineComment = WTK_INIT_STR_COMMENT;
674static   PSZ            pszNewline     = "\n";
675
676         PSECTION      *ppsecParentPtr = NULL;
677         PSECTION       psec           = NULL;
678
679         PKEY          *ppkeyParentPtr = NULL;
680         PKEY           pkey           = NULL;
681
682         PSZ            pszLine    = NULL;
683         PSZ            pszComment = NULL;
684         PSZ            pszValue;
685
686         PSZ            pszThisDelimiter;
687         PSZ            pszCheckLine;
688         PSZ            pszValueComment;
689
690do
691   {
692   // check parms
693   if (!phinit)
694      {
695      rc = ERROR_INVALID_PARAMETER;
696      break;
697      }
698
699   // check special bits of open mode
700   if (ulOpenMode != WTK_INIT_OPEN_INMEMORY)
701      {
702      if (ulOpenMode & WTK_INIT_OPEN_ALLOWERRORS)
703         {
704         fAllowErrors = TRUE;
705         ulOpenMode &= ~WTK_INIT_OPEN_ALLOWERRORS;
706         }
707      }
708
709   // check open modes
710   switch (ulOpenMode)
711      {
712      case WTK_INIT_OPEN_READONLY:  pszOpenMode = "r";            break;
713      case WTK_INIT_OPEN_READWRITE: pszOpenMode = "r+";           break;
714      case WTK_INIT_OPEN_INMEMORY:  fInMemory = TRUE;             break;
715      default:                  rc = ERROR_INVALID_PARAMETER; break;
716      }
717   if (rc != NO_ERROR)
718      break;
719
720   // filename required, if it is not an in-memory init only
721   // for in-memory operatin, filename must be NULL
722   if (((!fInMemory) && (!pszName)) ||
723       ((fInMemory) && (pszName)))
724      {
725      rc = ERROR_INVALID_PARAMETER;
726      break;
727      }
728
729   // copy name and replace ?: with bootdrive
730   if (pszName)
731      {
732      strcpy( szName, pszName);
733      __PatchBootDrive( szName);
734      }
735
736
737   // use defaults
738   if (!pip)
739      {
740      memset( &ip, 0, sizeof( ip));
741      pip = &ip;
742      }
743
744   if (!pip->pszCommentChars)
745      pip->pszCommentChars = WTK_INIT_CHARS_COMMENT;
746   if (!pip->pszDelimiterChars)
747      pip->pszDelimiterChars = WTK_INIT_CHARS_DELIMITER;
748
749   // check memory for temporary fields
750   pszLine    = malloc( WTK_INIT_MAX_LINESIZE);
751   pszComment = malloc( 2 * WTK_INIT_MAX_LINESIZE);
752   if ((!pszLine) || (!pszComment))
753      {
754      rc = ERROR_NOT_ENOUGH_MEMORY;
755      break;
756      }
757   *pszLine = 0;
758   *pszComment = 0;
759
760   // get memory for data struct
761   pinit = malloc( sizeof( INIT));
762   if (!pinit)
763      {
764      rc = ERROR_NOT_ENOUGH_MEMORY;
765      break;
766      }
767   memset( pinit, 0, sizeof( INIT));
768   if (!fInMemory)
769      strcpy( pinit->szFilename, szName);
770   pinit->ulOpenMode            = ulOpenMode;
771   pinit->ulUpdateMode          = ulUpdateMode;
772   pinit->chComment             = *(pip->pszCommentChars);
773   pinit->chDelimiter           = *(pip->pszDelimiterChars);
774   pinit->keyLast.ulKeyIndent   = pip->ulKeyIndent;
775   pinit->keyLast.ulKeyNameLen  = pip->ulKeyNameLen;
776   pinit->keyLast.ulValueIndent = pip->ulValueIndent;
777
778
779   // --------------------------------------------------------
780
781   // do not read a file, if it is an in-memory init
782   if (fInMemory)
783      {
784      // report pointer as handle
785      *phinit = (HINIT) pinit;
786      break;
787      }
788
789   // --------------------------------------------------------
790
791   // store address for ptr to first section
792   ppsecParentPtr = &pinit->psectionFirst;
793
794   // open the file
795   pinit->pfile = fopen( szName, pszOpenMode);
796
797   // second try in write mode
798   if ((!pinit->pfile) && (ulOpenMode == WTK_INIT_OPEN_READWRITE))
799      pinit->pfile = fopen( szName, "w+");
800
801   if (!pinit->pfile)
802      {
803      rc = ERROR_OPEN_FAILED;
804      break;
805      }
806
807   while (!feof( pinit->pfile))
808      {
809      // read line
810      if (!fgets( pszLine, WTK_INIT_MAX_LINESIZE, pinit->pfile))
811         break;
812
813      // - - - - - - - - - - - - - - - - - - - -
814
815      // handle comments and empty lines
816      pszCheckLine = __skipblanks( pszLine);
817
818      if (strchr( pip->pszCommentChars, * pszCheckLine))
819         {
820
821         // extra check for C++ comments
822         if ((*pszCheckLine != '/') || (*(pszCheckLine + 1) == '/'))
823            {
824            strcat( pszComment, pszLine);
825            continue;
826            }
827         }
828      if (!strncmp( pszCheckLine, pszNewline, strlen( pszNewline)))
829         {
830         strcat( pszComment, pszLine);
831         continue;
832         }
833
834      // cut off NEWLINE
835      *(pszLine + strlen( pszLine) - 1) = 0;
836
837      // handle new section
838      if (*pszLine == WTK_INIT_CHAR_SECTION_START)
839         {
840         strcpy( pszLine, pszLine + 1);
841         p = strchr( pszLine, WTK_INIT_CHAR_SECTION_END);
842         if (!p)
843            {
844            if (fAllowErrors)
845               continue;
846            else
847               {
848               rc = ERROR_INVALID_DATA;
849               break;
850               }
851            }
852         *p = 0;
853
854         // open a new section
855         psec = malloc( sizeof( SECTION));
856         if (!psec)
857            {
858            rc = ERROR_NOT_ENOUGH_MEMORY;
859            break;
860            }
861         memset( psec, 0, sizeof( SECTION));
862         *ppsecParentPtr = psec;
863         ppsecParentPtr = &psec->psectionNext;
864
865         psec->pszSectionName = strdup( pszLine);
866         psec->pszComment     = strdup( pszComment);
867         if ((!psec->pszSectionName) ||
868             (!psec->pszComment))
869            {
870            rc = ERROR_NOT_ENOUGH_MEMORY;
871            break;
872            }
873         *pszComment = 0;
874
875         // store address for ptr to first key
876         ppkeyParentPtr = &psec->pkeyFirst;
877
878         // we are done so far
879         continue;
880
881         }
882
883      // - - - - - - - - - - - - - - - - - - - -
884
885      // handle new key
886      if (!ppkeyParentPtr)
887         {
888         rc = ERROR_INVALID_DATA;
889         break;
890         }
891
892      // open a new key
893      pkey = malloc( sizeof( KEY));
894      if (!pkey)
895         {
896         rc = ERROR_NOT_ENOUGH_MEMORY;
897         break;
898         }
899      memset( pkey, 0, sizeof( KEY));
900      *ppkeyParentPtr = pkey;
901      ppkeyParentPtr = &pkey->pkeyNext;
902
903      // handle all specified delimter characters like ':' and '='
904      pszThisDelimiter = pip->pszDelimiterChars;
905      pszValue         = NULL;
906      while ((*pszThisDelimiter) && (!pszValue))
907         {
908         pszValue = strchr( pszLine, *pszThisDelimiter);
909         pkey->chDelimiter = *pszThisDelimiter;
910         pszThisDelimiter++;
911         }
912      if (!pszValue)
913         {
914         if (fAllowErrors)
915            continue;
916         else
917            {
918            rc = ERROR_INVALID_DATA;
919            break;
920            }
921         }
922
923      // store key data
924      pkey->pszComment    = strdup( pszComment);
925
926      pkey->ulKeyIndent   = __skipblanks( pszLine) - pszLine;
927
928      pkey->pszKeyValue   = strdup(  pszValue + 1);
929      pkey->ulValueIndent = __skipblanks( pkey->pszKeyValue)- pkey->pszKeyValue;
930      strcpy( pkey->pszKeyValue, pkey->pszKeyValue + pkey->ulValueIndent);
931
932      *pszValue = 0;
933      pkey->ulKeyNameLen  = strlen( pszLine) -  pkey->ulKeyIndent;
934      pkey->pszKeyName    = strdup( __stripblanks( pszLine));
935
936      if ((!pkey->pszKeyName)  ||
937          (!pkey->pszKeyValue) ||
938          (!pkey->pszComment))
939         {
940         rc = ERROR_NOT_ENOUGH_MEMORY;
941         break;
942         }
943      *pszComment = 0;
944
945      // take care for c++ comments at the end of a key value
946      // create a copy and detach it from the key value
947      if (strchr( pip->pszCommentChars, '/'))
948         {
949         pszValueComment = strstr( pkey->pszKeyValue, "//");
950         if (pszValueComment)
951            {
952               pkey->pszValueComment = strdup( pszValueComment);
953            p = pszValueComment - 1;
954            while (*p <= 32)
955               {
956               p--;
957               }
958            pkey->ulValueCommentIndent = pszValueComment - p - 1;
959            *(p + 1) = 0;
960            }
961         }
962
963      // take care for multiline values, being enclosed in double quotes
964      if (*pkey->pszKeyValue == '"') 
965         while (*(pkey->pszKeyValue + strlen( pkey->pszKeyValue) - 1) != '"')
966            {
967            // read next line
968            if (!fgets( pszLine, WTK_INIT_MAX_LINESIZE, pinit->pfile))
969               break;
970            __stripblanks( pszLine);
971   
972            pkey->pszKeyValue = realloc( pkey->pszKeyValue, strlen( pkey->pszKeyValue) + strlen( pszLine) + 1);
973            strcat( pkey->pszKeyValue, pszLine);
974            }
975
976      // save key data for appending new sections and keys
977      memcpy( &pinit->keyLast, pkey, sizeof( KEY));
978
979      } // while (!feof( pinit->pfile))
980
981   // take care for errors
982   if (rc != NO_ERROR)
983      break;
984
985   // --------------------------------------------------------
986
987   // report pointer as handle
988   *phinit = (HINIT) pinit;
989
990   } while (FALSE);
991
992// cleanup
993if (rc != NO_ERROR)
994   _freeINIT( pinit);
995if (pszLine)    free( pszLine);
996if (pszComment) free( pszComment);
997return rc;
998}
999
1000// ----------------------------------------------------------------------
1001
1002/*
1003@@WtkCloseInitProfile@SYNTAX
1004This function closes a text initialization file previously opened with :hp2.WtkOpenInitProfile:ehp2..
1005
1006@@WtkCloseInitProfile@PARM@hinit@in
1007Handle to the text initialization file.
1008
1009@@WtkCloseInitProfile@PARM@fUpdate@in
1010Flag specifiying wether the file should be updated.
1011:p.
1012Specify one of the following flags:
1013:parml.
1014:pt.WTK_INIT_CLOSE_DISCARD
1015:pd.any changes are discarded
1016:pt.WTK_INIT_CLOSE_UPDATE
1017:pd.changes previously applied by :hp2.WtkWriteInitProfileString:ehp2. are written to disk.
1018This requires that the initialization file
1019:ul compact.
1020:li.is not a pseudo in-memory file
1021:li.has been opened in readwrite mode
1022:eul.
1023:eparml.
1024
1025@@WtkCloseInitProfile@RETURN
1026Return Code.
1027:p.
1028WtkCloseInitProfile returns one of the following return codes&colon.
1029
1030:parml compact break=none.
1031:pt.0
1032:pd.NO_ERROR
1033:pt.87
1034:pd.ERROR_INVALID_PARAMETER
1035:eparml.
1036
1037@@WtkCloseInitProfile@REMARKS
1038Regardless to the fUpdate parameter, WtkCloseInitProfile does not perform any update operations if
1039:ul compact.
1040:li.the initialization file referred to by the specified file handle is a pseudo in-memory file
1041:li.the initialization file was opened in WTK_INIT_OPEN_READONLY mode.
1042:li.the initialization file has not been modified in memory yet
1043:eul.
1044
1045@@
1046*/
1047
1048APIRET APIENTRY WtkCloseInitProfile( HINIT hinit, BOOL fUpdate)
1049{
1050         APIRET         rc = NO_ERROR;
1051         PINIT          pinit = (PINIT) hinit;
1052
1053do
1054   {
1055   // check parms
1056   if (!hinit)
1057      {
1058      rc = ERROR_INVALID_PARAMETER;
1059      break;
1060      }
1061
1062   // update not required ?
1063   if ((!pinit->fModified) ||
1064       (!fUpdate)          ||
1065       (pinit->ulOpenMode != WTK_INIT_OPEN_READWRITE) ||
1066       (!pinit->pfile))
1067      break;
1068
1069   // goto start of file
1070   rewind( pinit->pfile);
1071   DosSetFileSize( fileno( pinit->pfile), 0);
1072   _writeSECTION( pinit->pfile, pinit->psectionFirst, pinit->ulUpdateMode);
1073   fprintf( pinit->pfile, "\n");
1074
1075   } while (FALSE);
1076
1077// cleanup
1078if (rc == NO_ERROR)
1079   _freeINIT( pinit);
1080return rc;
1081}
1082
1083// ----------------------------------------------------------------------
1084
1085/*
1086@@WtkCloseInitProfileBackup@SYNTAX
1087This function closes a text initialization file previously opened with :hp2.WtkOpenInitProfile:ehp2. and
1088creates a backup file.
1089
1090@@WtkCloseInitProfileBackup@PARM@hinit@in
1091Handle to the text initialization file.
1092
1093@@WtkCloseInitProfileBackup@PARM@fUpdateOriginal@in
1094Flag specifiying which file should hold the updates.
1095:p.
1096Specify either
1097:parml.
1098:pt.TRUE
1099:pd.to update the original file and keep the old version in the backup file
1100:pt.FALSE
1101:pd.to update the backup file and leave the original file unchanged
1102:eparml.
1103
1104@@WtkCloseInitProfileBackup@PARM@pszBackupFile@in
1105Address of the ASCIIZ path name of the backup file.
1106
1107@@WtkCloseInitProfileBackup@RETURN
1108Return Code.
1109:p.
1110WtkCloseInitProfile returns one of the following return codes&colon.
1111
1112:parml compact break=none.
1113:pt.0
1114:pd.NO_ERROR
1115:pt.1
1116:pd.ERROR_INVALID_FUNCTION
1117:pt.87
1118:pd.ERROR_INVALID_PARAMETER
1119:eparml.
1120
1121@@WtkCloseInitProfileBackup@REMARKS
1122WtkCloseInitProfileBackup returns ERROR_INVALID_FUNCTION, if called to close a pseudo in-memory file.
1123:p.
1124WtkCloseInitProfileBackup does not perform any update operations if
1125:ul compact.
1126:li.the initialization file was opened in WTK_INIT_OPEN_READONLY mode.
1127:li.the initialization file has not been modified in memory yet
1128:eul.
1129
1130@@
1131*/
1132
1133APIRET APIENTRY WtkCloseInitProfileBackup( HINIT hinit, BOOL fUpdateOriginal, PSZ pszBackupFile)
1134{
1135         APIRET         rc = NO_ERROR;
1136         PINIT          pinit = (PINIT) hinit;
1137         FILE          *pfile = NULL;
1138
1139do
1140   {
1141   // check parms
1142   if (!hinit)
1143      {
1144      rc = ERROR_INVALID_PARAMETER;
1145      break;
1146      }
1147
1148   // in-memory init cannot be written to file
1149   if (!pinit->pfile)
1150      {
1151      rc = ERROR_INVALID_FUNCTION;
1152      break;
1153      }
1154
1155   // backup wanted ? So we need a backup filename
1156   if ((!fUpdateOriginal) && (!pszBackupFile))
1157      {
1158      rc = ERROR_INVALID_PARAMETER;
1159      break;
1160      }
1161
1162
1163   // update not required ?
1164   if ((!pinit->fModified) ||
1165       (pinit->ulOpenMode != WTK_INIT_OPEN_READWRITE))
1166      break;
1167
1168   // close original file anyway
1169   fclose( pinit->pfile);
1170   pinit->pfile  = NULL;
1171
1172   // create backup, if original shall be rewritten
1173   if (fUpdateOriginal)
1174      {
1175      rc = DosCopy( pinit->szFilename, pszBackupFile, DCPY_EXISTING);
1176      if (rc != NO_ERROR)
1177         break;
1178      }
1179
1180   // (re)open original/backup file for write
1181   pfile = fopen( (fUpdateOriginal) ? pinit->szFilename : pszBackupFile, "w");
1182   if (!pfile)
1183      {
1184      rc = ERROR_OPEN_FAILED;
1185      break;
1186      }
1187
1188   // write file
1189   _writeSECTION( pfile, pinit->psectionFirst, pinit->ulUpdateMode);
1190   fprintf( pfile, "\n");
1191
1192   } while (FALSE);
1193
1194// cleanup
1195if ((!fUpdateOriginal) && (pfile))
1196   fclose( pfile);
1197if (rc == NO_ERROR)
1198   _freeINIT( pinit);
1199return rc;
1200}
1201
1202// ----------------------------------------------------------------------
1203
1204/*
1205@@WtkInitProfileModified@SYNTAX
1206This function queries wether a text initialization file has previously been modified in memory.
1207
1208@@WtkInitProfileModified@PARM@hinit@in
1209Handle to the text initialization file.
1210
1211@@WtkInitProfileModified@RETURN
1212Change status indicator
1213:p.
1214:parml.
1215:pt.TRUE
1216:pd.the file has previously been modified in memory and differs from file contents read from harddisk etc.
1217:pt.FALSE
1218:pd.the file has not been modified in memory
1219:eparml.
1220
1221@@WtkInitProfileModified@REMARKS
1222none
1223
1224@@
1225*/
1226
1227BOOL APIENTRY WtkInitProfileModified( HINIT hinit)
1228{
1229         BOOL           fResult = FALSE;
1230         PINIT          pinit = (PINIT) hinit;
1231
1232do
1233   {
1234   // check parms
1235   if (!hinit)
1236      break;
1237
1238   fResult = pinit->fModified;
1239   } while (FALSE);
1240
1241return fResult;
1242}
1243
1244// ----------------------------------------------------------------------
1245
1246/*
1247@@WtkQueryInitProfileString@SYNTAX
1248This function retrieves a string from the specified text initialization file.
1249
1250@@WtkQueryInitProfileString@PARM@hinit@in
1251Handle to the text initialization file.
1252
1253@@WtkQueryInitProfileString@PARM@pszSectionName@in
1254Section name.
1255:p.
1256The name of the section for which the text initialization file data is required.
1257:p.
1258The search performed on the application name is always case-dependent.
1259:p.
1260If this parameter is NULL, this function enumerates all the application names
1261present in the initialization profile and returns the names as a list in the pszBuffer
1262parameter. Each application name is terminated with a NULL character and the
1263last name is terminated with two successive NULL characters. In this instance,
1264the ulResult parameter contains the total length of the list excluding the
1265final NULL character.
1266
1267@@WtkQueryInitProfileString@PARM@pszKeyName@in
1268Key name.
1269:p.
1270The name of the key for which the text initialization file data is returned.
1271:p.
1272The search on key name is always case-dependent.
1273:p.
1274If this parameter equals NULL, and if the pszSectionName parameter is not equal to
1275NULL, this function enumerates all key names associated with the named
1276application and returns the key names (not their values) as a list in the
1277pBuffer parameter. Each key name is terminated with a NULL character and
1278the last name is terminated with two successive NULL characters. In this
1279instance, the ulResult parameter contains the total length of the list
1280excluding the final NULL character.
1281 
1282@@WtkQueryInitProfileString@PARM@pszDefault@in
1283Default string.
1284:p.
1285The string that is returned in the pszBuffer parameter, if the key defined by the
1286pszKey parameter cannot be found in the text initialization file.
1287:p.
1288If the pointer to this parameter is passed as NULL, then nothing is copied into
1289the pszKeyName parameter if the key cannot be found. ulResult is returned as 0 in
1290this case.
1291
1292@@WtkQueryInitProfileString@PARM@pszBuffer@in
1293text initialization file string.
1294:p.
1295The text string obtained from the text initialization file for the key defined by
1296the pszKeyName parameter.
1297
1298@@WtkQueryInitProfileString@PARM@ulBuflen@in
1299Maximum string length.
1300:p.
1301The maximum number of characters that can be put into the pszBuffer
1302parameter, in bytes. If the data from the profile is longer than
1303this, it is truncated.
1304
1305@@WtkQueryInitProfileString@RETURN
1306String length returned.
1307:p.
1308The actual number of characters (including the null
1309termination character) returned in the pszBuffer parameter, in bytes.
1310
1311@@WtkQueryInitProfileString@REMARKS
1312The call searches the text initialization file for a key matching the name
1313specified by the pszKeyName parameter under the section specified by the pszSectionName
1314parameter. If the key is found, the corresponding string is copied. If the key does
1315not exist, the default character string, specified by the pszDefault parameter, is
1316copied.
1317:p.
1318This function is case-dependent; thus the strings in the pszSectionName
1319parameter and the pszKeyName parameter must match exactly. This avoids
1320any code-page dependency. The application storing the data must do any
1321case-independent matching.
1322
1323@@
1324*/
1325
1326ULONG APIENTRY WtkQueryInitProfileString( HINIT hinit, PSZ pszSectionName, PSZ pszKeyName,
1327                                          PSZ pszDefault, PSZ pszBuffer, ULONG ulBuflen)
1328{
1329         APIRET         rc = NO_ERROR;
1330         ULONG          ulValueLen = 0;
1331         PINIT          pinit = (PINIT) hinit;
1332
1333         PSECTION       psec;
1334         PKEY           pkey;
1335         PSZ            pszResult;
1336
1337do
1338   {
1339   // check parms
1340   if ((!hinit)       ||
1341       (!pszBuffer))
1342      {
1343      rc = ERROR_INVALID_PARAMETER;
1344      break;
1345      }
1346   memset( pszBuffer, 0, ulBuflen);
1347
1348   // find section and/or key
1349   if (pszSectionName)
1350      psec = _findSECTION( pinit, pszSectionName);
1351   else
1352      {
1353      rc = _collectSECTION( pinit, pszBuffer, ulBuflen, &ulValueLen);
1354      break;
1355      }
1356   if (!psec)
1357      break;
1358
1359   if (pszKeyName)
1360      pkey = _findKEY( psec, pszKeyName);
1361   else
1362      {
1363      rc = _collectKEY( psec, pszBuffer, ulBuflen, &ulValueLen);
1364      break;
1365      }
1366   if (!pkey)
1367      break;
1368
1369   // key not found ?
1370   if (pkey)
1371      pszResult = pkey->pszKeyValue;
1372   else
1373      pszResult = pszDefault;
1374
1375   // report result
1376   if (pszResult)
1377      {
1378      memcpy( pszBuffer, pkey->pszKeyValue, ulBuflen);
1379      ulValueLen = strlen( pszBuffer) + 1;
1380      }
1381
1382   } while (FALSE);
1383
1384// cleanup
1385return ulValueLen;
1386
1387}
1388
1389// ----------------------------------------------------------------------
1390
1391/*
1392@@WtkQueryInitProfileSize@SYNTAX
1393This function obtains the size in bytes of the value of a specified key for a
1394specified application in the text initialization file.
1395
1396@@WtkQueryInitProfileSize@PARM@hinit@in
1397Handle to the text initialization file.
1398
1399@@WtkQueryInitProfileSize@PARM@pszSectionName@in
1400Section name.
1401:p.
1402The name of the section for which the text initialization file data is required.
1403:p.   
1404If the pszSectionName parameter is NULL, then the pulDataLen parameter returns the
1405length of the buffer required to hold the enumerated list of application names,
1406as returned by the WtkQueryInitProfileString function when its pszSectionName parameter is
1407NULL. In this case, the pszKeyName parameter is ignored.
1408
1409@@WtkQueryInitProfileSize@PARM@pszKeyName@in
1410Key name.
1411:p.
1412The name of the key for which the text initialization file data is returned.
1413:p.
1414If the pszKey parameter is NULL, and if the pszSectionName parameter is not NULL, the
1415pulDataLen returns the length of the buffer required to hold the enumerated
1416list of key names for that application name, as returned by the
1417PrfQueryProfileString function when its pszKeyName parameter is NULL, and its
1418pszSectionName parameter is not NULL.
1419 
1420@@WtkQueryInitProfileSize@PARM@pulDataLen@out
1421Data length.
1422:p.
1423This parameter is the length of the value data related to the pszKey
1424parameter. If an error occurs, this parameter is undefined.
1425
1426@@WtkQueryInitProfileSize@RETURN
1427Success indicator.
1428:p.
1429:parml.
1430:pt.TRUE
1431:pd.Successful completion
1432:pt.FALSE
1433:pd.Error occurred.
1434:eparml.
1435
1436@@WtkQueryInitProfileSize@REMARKS
1437The pszSectionName parameter and pszKeyName parameter are case sensitive and must match
1438the names stored in the file exactly. There is no case-independent searching.
1439:p.
1440This function can be used before using the WtkQueryInitProfileString call, to allocate
1441space for the returned data.
1442
1443@@
1444*/
1445
1446BOOL APIENTRY WtkQueryInitProfileSize( HINIT hinit, PSZ pszSectionName, PSZ pszKeyName, PULONG pulDataLen)
1447{
1448         APIRET         rc = NO_ERROR;
1449         PINIT          pinit = (PINIT) hinit;
1450
1451         PSECTION       psec;
1452         PKEY           pkey;
1453
1454do
1455   {
1456   // check parms
1457   if ((!hinit)        ||
1458       (!pulDataLen))
1459      {
1460      rc = ERROR_INVALID_PARAMETER;
1461      break;
1462      }
1463
1464   // find section and/or key
1465   if (pszSectionName)
1466      psec = _findSECTION( pinit, pszSectionName);
1467   else
1468      {
1469      rc = _collectSECTION( pinit, NULL, 0, pulDataLen);
1470      break;
1471      }
1472   if (!psec)
1473      {
1474      rc = ERROR_INVALID_DATA;
1475      break;
1476      }
1477
1478   if (pszKeyName)
1479      pkey = _findKEY( psec, pszKeyName);
1480   else
1481      {
1482      rc = _collectKEY( psec, NULL, 0, pulDataLen);
1483      break;
1484      }
1485   if (!pkey)
1486      {
1487      rc = ERROR_INVALID_DATA;
1488      break;
1489      }
1490
1491   if (pkey)
1492      *pulDataLen = strlen( pkey->pszKeyValue) + 1;
1493   else
1494      rc = ERROR_FILE_NOT_FOUND;
1495
1496
1497   } while (FALSE);
1498
1499// cleanup
1500return (rc == NO_ERROR);
1501
1502}
1503
1504// ----------------------------------------------------------------------
1505
1506/*
1507@@WtkWriteInitProfileString@SYNTAX
1508This function writes a string of character data into the specified text initialization file.
1509
1510@@WtkWriteInitProfileString@PARM@hinit@in
1511Handle to the text initialization file.
1512
1513@@WtkWriteInitProfileString@PARM@pszSectionName@in
1514Section name.
1515:p.
1516The case-dependent name of the section for which profile data is to be
1517written.
1518
1519@@WtkWriteInitProfileString@PARM@pszKeyName@in
1520Key name.
1521:p.
1522The case-dependent name of the key for which profile data is to be written.
1523:p.
1524This parameter can be NULL, in which case all the pszKeyName pairs
1525associated with the pszSectionName parameter are deleted.
1526
1527@@WtkWriteInitProfileString@PARM@pszNewValue@in
1528Text string.
1529:p.
1530This is the value of the pszKeyName pair that is written to the text initialization file.
1531:p.
1532If this parameter is NULL, the string associated with the pszKeyName is deleted
1533(that is, the entry is deleted).
1534:p.
1535If this parameter is not NULL, the string is used as the value of the pszKeyName,
1536even if the string has zero length.
1537
1538@@WtkWriteInitProfileString@RETURN
1539Success indicator.
1540:p.
1541:parml.
1542:pt.TRUE
1543:pd.Successful completion
1544:pt.FALSE
1545:pd.Error occurred.
1546:eparml.
1547
1548@@WtkWriteInitProfileString@REMARKS
1549If there is no section in the file that matches the pszSectionName, a new
1550sectionis created when the pszKeyName entry is made.
1551:p.
1552If the key name does not exist for the section, a new pszKeyName
1553entry is created for that section. If the pszKeyName already exists
1554in the file, the existing value is overwritten.
1555
1556@@
1557*/
1558
1559APIRET APIENTRY WtkWriteInitProfileString( HINIT hinit, PSZ pszSectionName, PSZ pszKeyName, PSZ pszNewValue)
1560{
1561         APIRET         rc = NO_ERROR;
1562         PINIT          pinit = (PINIT) hinit;
1563         PSECTION       psec;
1564         PKEY           pkey;
1565
1566         BOOL           fNotChanged = FALSE;
1567         PSZ            pszOldValue;
1568         BOOL           fRemoved = FALSE;
1569
1570do
1571   {
1572   // check parms
1573   if ((!hinit)           ||
1574       (!pszSectionName))
1575      {
1576      rc = ERROR_INVALID_PARAMETER;
1577      break;
1578      }
1579
1580   // find section and key
1581   psec = _findSECTION( pinit, pszSectionName);
1582   pkey = _findKEY( psec, pszKeyName);
1583
1584   // key was found (thus section was found)
1585   // handle following situations here
1586   // section   keyname  keyvalue    action
1587   //  given     given    given      update key
1588   //  given     given    NULL       delete key
1589
1590   // handle keys first
1591   if (pkey)
1592      {
1593      // create/update key
1594      if (pszNewValue)
1595         {
1596         if (!strcmp( pkey->pszKeyValue, pszNewValue))
1597            fNotChanged = TRUE;
1598         else
1599            {
1600            // just replace value
1601            pszOldValue = pkey->pszKeyValue;
1602            pkey->pszKeyValue = strdup( pszNewValue);
1603            if (!pkey->pszKeyValue)
1604               {
1605               pkey->pszKeyValue = pszOldValue;
1606               rc = ERROR_NOT_ENOUGH_MEMORY;
1607               break;
1608               }
1609            else
1610               free( pszOldValue);
1611            }
1612         }
1613      else
1614         {
1615         // remove key
1616         fRemoved = _removeKEY( pinit, psec, pszKeyName);
1617         rc = (fRemoved) ? NO_ERROR : ERROR_FILE_NOT_FOUND;
1618         }
1619
1620      } // if (pkey)
1621
1622   // key was not found
1623   // handle following situations here
1624   // section   keyname  keyvalue    action
1625   //  given     given    given      create section and/or key
1626
1627   // shall a new section and/or key be created ?
1628
1629   else if (pszNewValue)
1630      {
1631      if (!psec)
1632         {
1633         // add new section if required
1634         psec = _createSECTION( pinit, pszSectionName);
1635         if (!psec)
1636            {
1637            rc = ERROR_NOT_ENOUGH_MEMORY;
1638            break;
1639            }
1640         }
1641
1642      // add new key
1643      pkey = _createKEY( pinit, psec, pszKeyName, pszNewValue);
1644      if (!pkey)
1645         {
1646         rc = ERROR_NOT_ENOUGH_MEMORY;
1647         break;
1648         }
1649      }
1650
1651   // handle following situations here
1652   // section   keyname  keyvalue    action
1653   //  given     NULL     NULL       delete section
1654
1655   else if (!pszKeyName)
1656      {
1657      // keyName not given, delete section
1658      fRemoved = _removeSECTION( pinit, pszSectionName);
1659      rc = (fRemoved) ? NO_ERROR : ERROR_FILE_NOT_FOUND;
1660      }
1661
1662   else
1663      // this occurs, when a key should be deleted,
1664      // that does not exist
1665      rc = ERROR_FILE_NOT_FOUND;
1666
1667   } while (FALSE);
1668
1669// check if something has been modified
1670if ((pinit) && (rc == NO_ERROR) && (!fNotChanged))
1671   pinit->fModified = TRUE;
1672
1673return rc;
1674
1675}
1676
Note: See TracBrowser for help on using the repository browser.