ReactOS  0.4.14-dev-55-g2da92ac
profile.c
Go to the documentation of this file.
1 /*
2  * Profile functions
3  *
4  * Copyright 1993 Miguel de Icaza
5  * Copyright 1996 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #ifdef __REACTOS__
23 
24 #include <k32.h>
25 
26 #define NDEBUG
27 #include <debug.h>
29 
30 #else /* __REACTOS__ */
31 
32 #include "config.h"
33 #include "wine/port.h"
34 
35 #include <string.h>
36 #include <stdarg.h>
37 
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "winerror.h"
42 #include "winternl.h"
43 #include "wine/unicode.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
46 
48 
49 #endif /* __REACTOS__ */
50 
51 static const char bom_utf8[] = {0xEF,0xBB,0xBF};
52 
53 typedef enum
54 {
59 } ENCODING;
60 
61 typedef struct tagPROFILEKEY
62 {
65  WCHAR name[1];
66 } PROFILEKEY;
67 
68 typedef struct tagPROFILESECTION
69 {
70  struct tagPROFILEKEY *key;
72  WCHAR name[1];
74 
75 
76 typedef struct
77 {
83 } PROFILE;
84 
85 
86 #define N_CACHED_PROFILES 10
87 
88 /* Cached profile files */
90 
91 #define CurProfile (MRUProfile[0])
92 
93 /* Check for comments in profile */
94 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
95 
96 static const WCHAR emptystringW[] = {0};
97 static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 };
98 
99 #ifdef __REACTOS__
100 
103 {
104  0, 0, &PROFILE_CritSect,
106  0, 0, 0
107 };
108 static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
109 
110 #else /* __REACTOS__ */
111 
114 {
115  0, 0, &PROFILE_CritSect,
117  0, 0, { (DWORD_PTR)(__FILE__ ": PROFILE_CritSect") }
118 };
119 static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
120 
121 #endif /* __REACTOS__ */
122 
123 static const char hex[16] = "0123456789ABCDEF";
124 
125 /***********************************************************************
126  * PROFILE_CopyEntry
127  *
128  * Copy the content of an entry into a buffer, removing quotes, and possibly
129  * translating environment variables.
130  */
132  BOOL strip_quote )
133 {
134  WCHAR quote = '\0';
135 
136  if(!buffer) return;
137 
138  if (strip_quote && ((*value == '\'') || (*value == '\"')))
139  {
140  if (value[1] && (value[strlenW(value)-1] == *value)) quote = *value++;
141  }
142 
143  lstrcpynW( buffer, value, len );
144  if (quote && (len >= lstrlenW(value))) buffer[strlenW(buffer)-1] = '\0';
145 }
146 
147 /* byte-swaps shorts in-place in a buffer. len is in WCHARs */
148 static inline void PROFILE_ByteSwapShortBuffer(WCHAR * buffer, int len)
149 {
150  int i;
151  USHORT * shortbuffer = buffer;
152  for (i = 0; i < len; i++)
153  shortbuffer[i] = RtlUshortByteSwap(shortbuffer[i]);
154 }
155 
156 /* writes any necessary encoding marker to the file */
158 {
159  DWORD dwBytesWritten;
160  WCHAR bom;
161  switch (encoding)
162  {
163  case ENCODING_ANSI:
164  break;
165  case ENCODING_UTF8:
166  WriteFile(hFile, bom_utf8, sizeof(bom_utf8), &dwBytesWritten, NULL);
167  break;
168  case ENCODING_UTF16LE:
169  bom = 0xFEFF;
170  WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL);
171  break;
172  case ENCODING_UTF16BE:
173  bom = 0xFFFE;
174  WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL);
175  break;
176  }
177 }
178 
180 {
181  char * write_buffer;
182  int write_buffer_len;
183  DWORD dwBytesWritten;
184 
185  TRACE("writing: %s\n", debugstr_wn(szLine, len));
186 
187  switch (encoding)
188  {
189  case ENCODING_ANSI:
190  write_buffer_len = WideCharToMultiByte(CP_ACP, 0, szLine, len, NULL, 0, NULL, NULL);
191  write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len);
192  if (!write_buffer) return;
193  len = WideCharToMultiByte(CP_ACP, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL);
194  WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL);
195  HeapFree(GetProcessHeap(), 0, write_buffer);
196  break;
197  case ENCODING_UTF8:
198  write_buffer_len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, NULL, 0, NULL, NULL);
199  write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len);
200  if (!write_buffer) return;
201  len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL);
202  WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL);
203  HeapFree(GetProcessHeap(), 0, write_buffer);
204  break;
205  case ENCODING_UTF16LE:
206  WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL);
207  break;
208  case ENCODING_UTF16BE:
210  WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL);
211  break;
212  default:
213  FIXME("encoding type %d not implemented\n", encoding);
214  }
215 }
216 
217 /***********************************************************************
218  * PROFILE_Save
219  *
220  * Save a profile tree to a file.
221  */
223 {
224  PROFILEKEY *key;
225  WCHAR *buffer, *p;
226 
228 
229  for ( ; section; section = section->next)
230  {
231  int len = 0;
232 
233  if (section->name[0]) len += strlenW(section->name) + 4;
234 
235  for (key = section->key; key; key = key->next)
236  {
237  len += strlenW(key->name) + 2;
238  if (key->value) len += strlenW(key->value) + 1;
239  }
240 
241  buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
242  if (!buffer) return;
243 
244  p = buffer;
245  if (section->name[0])
246  {
247  *p++ = '[';
248  strcpyW( p, section->name );
249  p += strlenW(p);
250  *p++ = ']';
251  *p++ = '\r';
252  *p++ = '\n';
253  }
254 
255  for (key = section->key; key; key = key->next)
256  {
257  strcpyW( p, key->name );
258  p += strlenW(p);
259  if (key->value)
260  {
261  *p++ = '=';
262  strcpyW( p, key->value );
263  p += strlenW(p);
264  }
265  *p++ = '\r';
266  *p++ = '\n';
267  }
270  }
271 }
272 
273 
274 /***********************************************************************
275  * PROFILE_Free
276  *
277  * Free a profile tree.
278  */
280 {
281  PROFILESECTION *next_section;
282  PROFILEKEY *key, *next_key;
283 
284  for ( ; section; section = next_section)
285  {
286  for (key = section->key; key; key = next_key)
287  {
288  next_key = key->next;
289  HeapFree( GetProcessHeap(), 0, key->value );
290  HeapFree( GetProcessHeap(), 0, key );
291  }
292  next_section = section->next;
294  }
295 }
296 
297 /* returns TRUE if a whitespace character, else FALSE */
298 static inline BOOL PROFILE_isspaceW(WCHAR c)
299 {
300  /* ^Z (DOS EOF) is a space too (found on CD-ROMs) */
301  return isspaceW(c) || c == 0x1a;
302 }
303 
304 static inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * len)
305 {
309  if (*len >= sizeof(bom_utf8) && !memcmp(buffer, bom_utf8, sizeof(bom_utf8)))
310  {
311  *len = sizeof(bom_utf8);
312  return ENCODING_UTF8;
313  }
316  {
317  *len = sizeof(WCHAR);
318  return ENCODING_UTF16LE;
319  }
321  {
322  *len = sizeof(WCHAR);
323  return ENCODING_UTF16BE;
324  }
325  *len = 0;
326  return ENCODING_ANSI;
327 }
328 
329 
330 /***********************************************************************
331  * PROFILE_Load
332  *
333  * Load a profile tree from a file.
334  */
336 {
337  void *buffer_base, *pBuffer;
338  WCHAR * szFile;
339  const WCHAR *szLineStart, *szLineEnd;
340  const WCHAR *szValueStart, *szEnd, *next_line;
341  int line = 0, len;
342  PROFILESECTION *section, *first_section;
343  PROFILESECTION **next_section;
344  PROFILEKEY *key, *prev_key, **next_key;
346 
347  TRACE("%p\n", hFile);
348 
350  if (dwFileSize == INVALID_FILE_SIZE || dwFileSize == 0)
351  return NULL;
352 
353  buffer_base = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
354  if (!buffer_base) return NULL;
355 
356  if (!ReadFile(hFile, buffer_base, dwFileSize, &dwFileSize, NULL))
357  {
358  HeapFree(GetProcessHeap(), 0, buffer_base);
359  WARN("Error %d reading file\n", GetLastError());
360  return NULL;
361  }
362  len = dwFileSize;
363  *pEncoding = PROFILE_DetectTextEncoding(buffer_base, &len);
364  /* len is set to the number of bytes in the character marker.
365  * we want to skip these bytes */
366  pBuffer = (char *)buffer_base + len;
367  dwFileSize -= len;
368  switch (*pEncoding)
369  {
370  case ENCODING_ANSI:
371  TRACE("ANSI encoding\n");
372 
374  szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
375  if (!szFile)
376  {
377  HeapFree(GetProcessHeap(), 0, buffer_base);
378  return NULL;
379  }
381  szEnd = szFile + len;
382  break;
383  case ENCODING_UTF8:
384  TRACE("UTF8 encoding\n");
385 
387  szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
388  if (!szFile)
389  {
390  HeapFree(GetProcessHeap(), 0, buffer_base);
391  return NULL;
392  }
394  szEnd = szFile + len;
395  break;
396  case ENCODING_UTF16LE:
397  TRACE("UTF16 Little Endian encoding\n");
398  szFile = pBuffer;
399  szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
400  break;
401  case ENCODING_UTF16BE:
402  TRACE("UTF16 Big Endian encoding\n");
403  szFile = pBuffer;
404  szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
405  PROFILE_ByteSwapShortBuffer(szFile, dwFileSize / sizeof(WCHAR));
406  break;
407  default:
408  FIXME("encoding type %d not implemented\n", *pEncoding);
409  HeapFree(GetProcessHeap(), 0, buffer_base);
410  return NULL;
411  }
412 
413  first_section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) );
414  if(first_section == NULL)
415  {
416  if (szFile != pBuffer)
417  HeapFree(GetProcessHeap(), 0, szFile);
418  HeapFree(GetProcessHeap(), 0, buffer_base);
419  return NULL;
420  }
421  first_section->name[0] = 0;
422  first_section->key = NULL;
423  first_section->next = NULL;
424  next_section = &first_section->next;
425  next_key = &first_section->key;
426  prev_key = NULL;
427  next_line = szFile;
428 
429  while (next_line < szEnd)
430  {
431  szLineStart = next_line;
432  next_line = memchrW(szLineStart, '\n', szEnd - szLineStart);
433  if (!next_line) next_line = memchrW(szLineStart, '\r', szEnd - szLineStart);
434  if (!next_line) next_line = szEnd;
435  else next_line++;
436  szLineEnd = next_line;
437 
438  line++;
439 
440  /* get rid of white space */
441  while (szLineStart < szLineEnd && PROFILE_isspaceW(*szLineStart)) szLineStart++;
442  while ((szLineEnd > szLineStart) && PROFILE_isspaceW(szLineEnd[-1])) szLineEnd--;
443 
444  if (szLineStart >= szLineEnd) continue;
445 
446  if (*szLineStart == '[') /* section start */
447  {
448  const WCHAR * szSectionEnd;
449  if (!(szSectionEnd = memrchrW( szLineStart, ']', szLineEnd - szLineStart )))
450  {
451  WARN("Invalid section header at line %d: %s\n",
452  line, debugstr_wn(szLineStart, (int)(szLineEnd - szLineStart)) );
453  }
454  else
455  {
456  szLineStart++;
457  len = (int)(szSectionEnd - szLineStart);
458  /* no need to allocate +1 for NULL terminating character as
459  * already included in structure */
460  if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) + len * sizeof(WCHAR) )))
461  break;
462  memcpy(section->name, szLineStart, len * sizeof(WCHAR));
463  section->name[len] = '\0';
464  section->key = NULL;
465  section->next = NULL;
466  *next_section = section;
467  next_section = &section->next;
468  next_key = &section->key;
469  prev_key = NULL;
470 
471  TRACE("New section: %s\n", debugstr_w(section->name));
472 
473  continue;
474  }
475  }
476 
477  /* get rid of white space after the name and before the start
478  * of the value */
479  len = szLineEnd - szLineStart;
480  if ((szValueStart = memchrW( szLineStart, '=', szLineEnd - szLineStart )) != NULL)
481  {
482  const WCHAR *szNameEnd = szValueStart;
483  while ((szNameEnd > szLineStart) && PROFILE_isspaceW(szNameEnd[-1])) szNameEnd--;
484  len = szNameEnd - szLineStart;
485  szValueStart++;
486  while (szValueStart < szLineEnd && PROFILE_isspaceW(*szValueStart)) szValueStart++;
487  }
488 
489  if (len || !prev_key || *prev_key->name)
490  {
491  /* no need to allocate +1 for NULL terminating character as
492  * already included in structure */
493  if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) + len * sizeof(WCHAR) ))) break;
494  memcpy(key->name, szLineStart, len * sizeof(WCHAR));
495  key->name[len] = '\0';
496  if (szValueStart)
497  {
498  len = (int)(szLineEnd - szValueStart);
499  key->value = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
500  memcpy(key->value, szValueStart, len * sizeof(WCHAR));
501  key->value[len] = '\0';
502  }
503  else key->value = NULL;
504 
505  key->next = NULL;
506  *next_key = key;
507  next_key = &key->next;
508  prev_key = key;
509 
510 #ifdef __REACTOS__
511  TRACE("New key: name=%s, value=%s\n",
512  debugstr_w(key->name),
513  key->value ? debugstr_w(key->value) : L"(none)");
514 #else
515  TRACE("New key: name=%s, value=%s\n",
516  debugstr_w(key->name), key->value ? debugstr_w(key->value) : "(none)");
517 #endif
518  }
519  }
520  if (szFile != pBuffer)
521  HeapFree(GetProcessHeap(), 0, szFile);
522  HeapFree(GetProcessHeap(), 0, buffer_base);
523  return first_section;
524 }
525 
526 
527 /***********************************************************************
528  * PROFILE_DeleteSection
529  *
530  * Delete a section from a profile tree.
531  */
533 {
534  while (*section)
535  {
536  if (!strcmpiW( (*section)->name, name ))
537  {
538  PROFILESECTION *to_del = *section;
539  *section = to_del->next;
540  to_del->next = NULL;
541  PROFILE_Free( to_del );
542  return TRUE;
543  }
544  section = &(*section)->next;
545  }
546  return FALSE;
547 }
548 
549 
550 /***********************************************************************
551  * PROFILE_DeleteKey
552  *
553  * Delete a key from a profile tree.
554  */
556  LPCWSTR section_name, LPCWSTR key_name )
557 {
558  while (*section)
559  {
560  if (!strcmpiW( (*section)->name, section_name ))
561  {
562  PROFILEKEY **key = &(*section)->key;
563  while (*key)
564  {
565  if (!strcmpiW( (*key)->name, key_name ))
566  {
567  PROFILEKEY *to_del = *key;
568  *key = to_del->next;
569  HeapFree( GetProcessHeap(), 0, to_del->value);
570  HeapFree( GetProcessHeap(), 0, to_del );
571  return TRUE;
572  }
573  key = &(*key)->next;
574  }
575  }
576  section = &(*section)->next;
577  }
578  return FALSE;
579 }
580 
581 
582 /***********************************************************************
583  * PROFILE_DeleteAllKeys
584  *
585  * Delete all keys from a profile tree.
586  */
587 static void PROFILE_DeleteAllKeys( LPCWSTR section_name)
588 {
589  PROFILESECTION **section= &CurProfile->section;
590  while (*section)
591  {
592  if (!strcmpiW( (*section)->name, section_name ))
593  {
594  PROFILEKEY **key = &(*section)->key;
595  while (*key)
596  {
597  PROFILEKEY *to_del = *key;
598  *key = to_del->next;
599  HeapFree( GetProcessHeap(), 0, to_del->value);
600  HeapFree( GetProcessHeap(), 0, to_del );
601  CurProfile->changed =TRUE;
602  }
603  }
604  section = &(*section)->next;
605  }
606 }
607 
608 
609 /***********************************************************************
610  * PROFILE_Find
611  *
612  * Find a key in a profile tree, optionally creating it.
613  */
615  LPCWSTR key_name, BOOL create, BOOL create_always )
616 {
617  LPCWSTR p;
618  int seclen = 0, keylen = 0;
619 
620  while (PROFILE_isspaceW(*section_name)) section_name++;
621  if (*section_name)
622  {
623  p = section_name + strlenW(section_name) - 1;
624  while ((p > section_name) && PROFILE_isspaceW(*p)) p--;
625  seclen = p - section_name + 1;
626  }
627 
628  while (PROFILE_isspaceW(*key_name)) key_name++;
629  if (*key_name)
630  {
631  p = key_name + strlenW(key_name) - 1;
632  while ((p > key_name) && PROFILE_isspaceW(*p)) p--;
633  keylen = p - key_name + 1;
634  }
635 
636  while (*section)
637  {
638  if (!strncmpiW((*section)->name, section_name, seclen) &&
639  ((*section)->name)[seclen] == '\0')
640  {
641  PROFILEKEY **key = &(*section)->key;
642 
643  while (*key)
644  {
645  /* If create_always is FALSE then we check if the keyname
646  * already exists. Otherwise we add it regardless of its
647  * existence, to allow keys to be added more than once in
648  * some cases.
649  */
650  if(!create_always)
651  {
652  if ( (!(strncmpiW( (*key)->name, key_name, keylen )))
653  && (((*key)->name)[keylen] == '\0') )
654  return *key;
655  }
656  key = &(*key)->next;
657  }
658  if (!create) return NULL;
659  if (!(*key = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) )))
660  return NULL;
661  strcpyW( (*key)->name, key_name );
662  (*key)->value = NULL;
663  (*key)->next = NULL;
664  return *key;
665  }
666  section = &(*section)->next;
667  }
668  if (!create) return NULL;
669  *section = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILESECTION) + strlenW(section_name) * sizeof(WCHAR) );
670  if(*section == NULL) return NULL;
671  strcpyW( (*section)->name, section_name );
672  (*section)->next = NULL;
673  if (!((*section)->key = HeapAlloc( GetProcessHeap(), 0,
674  sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) )))
675  {
677  return NULL;
678  }
679  strcpyW( (*section)->key->name, key_name );
680  (*section)->key->value = NULL;
681  (*section)->key->next = NULL;
682  return (*section)->key;
683 }
684 
685 
686 /***********************************************************************
687  * PROFILE_FlushFile
688  *
689  * Flush the current profile to disk if changed.
690  */
692 {
693  HANDLE hFile = NULL;
694  FILETIME LastWriteTime;
695 
696  if(!CurProfile)
697  {
698  WARN("No current profile!\n");
699  return FALSE;
700  }
701 
702  if (!CurProfile->changed) return TRUE;
703 
706 
708  {
709  WARN("could not save profile file %s (error was %d)\n", debugstr_w(CurProfile->filename), GetLastError());
710  return FALSE;
711  }
712 
713  TRACE("Saving %s\n", debugstr_w(CurProfile->filename));
714  PROFILE_Save( hFile, CurProfile->section, CurProfile->encoding );
715  if(GetFileTime(hFile, NULL, NULL, &LastWriteTime))
716  CurProfile->LastWriteTime=LastWriteTime;
717  CloseHandle( hFile );
718  CurProfile->changed = FALSE;
719  return TRUE;
720 }
721 
722 
723 /***********************************************************************
724  * PROFILE_ReleaseFile
725  *
726  * Flush the current profile to disk and remove it from the cache.
727  */
728 static void PROFILE_ReleaseFile(void)
729 {
731  PROFILE_Free( CurProfile->section );
732  HeapFree( GetProcessHeap(), 0, CurProfile->filename );
733  CurProfile->changed = FALSE;
734  CurProfile->section = NULL;
735  CurProfile->filename = NULL;
736  CurProfile->encoding = ENCODING_ANSI;
737  ZeroMemory(&CurProfile->LastWriteTime, sizeof(CurProfile->LastWriteTime));
738 }
739 
740 /***********************************************************************
741  *
742  * Compares a file time with the current time. If the file time is
743  * at least 2.1 seconds in the past, return true.
744  *
745  * Intended as cache safety measure: The time resolution on FAT is
746  * two seconds, so files that are not at least two seconds old might
747  * keep their time even on modification, so don't cache them.
748  */
750 {
751  FILETIME Now;
752  LONGLONG ftll, nowll;
754  ftll = ((LONGLONG)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
755  nowll = ((LONGLONG)Now.dwHighDateTime << 32) + Now.dwLowDateTime;
756  TRACE("%08x;%08x\n",(unsigned)ftll+21000000,(unsigned)nowll);
757  return ftll + 21000000 < nowll;
758 }
759 
760 /***********************************************************************
761  * PROFILE_Open
762  *
763  * Open a profile file, checking the cached file first.
764  */
765 static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access )
766 {
769  FILETIME LastWriteTime;
770  int i,j;
771  PROFILE *tempProfile;
772 
773  ZeroMemory(&LastWriteTime, sizeof(LastWriteTime));
774 
775  /* First time around */
776 
777  if(!CurProfile)
778  for(i=0;i<N_CACHED_PROFILES;i++)
779  {
780  MRUProfile[i]=HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILE) );
781  if(MRUProfile[i] == NULL) break;
786  ZeroMemory(&MRUProfile[i]->LastWriteTime, sizeof(FILETIME));
787  }
788 
789  if (!filename)
790  filename = wininiW;
791 
792 #ifdef __REACTOS__
794 #else
796 #endif
797  !strchrW(filename, '\\') && !strchrW(filename, '/'))
798  {
799  static const WCHAR wszSeparator[] = {'\\', 0};
800  WCHAR windirW[MAX_PATH];
801  GetWindowsDirectoryW( windirW, MAX_PATH );
802  strcpyW(buffer, windirW);
803  strcatW(buffer, wszSeparator);
805  }
806  else
807  {
808  LPWSTR dummy;
809  GetFullPathNameW(filename, sizeof(buffer)/sizeof(buffer[0]), buffer, &dummy);
810  }
811 
812  TRACE("path: %s\n", debugstr_w(buffer));
813 
814  hFile = CreateFileW(buffer, GENERIC_READ | (write_access ? GENERIC_WRITE : 0),
817 
819  {
820  WARN("Error %d opening file %s\n", GetLastError(), debugstr_w(buffer));
821  return FALSE;
822  }
823 
824  for(i=0;i<N_CACHED_PROFILES;i++)
825  {
827  {
828  TRACE("MRU Filename: %s, new filename: %s\n", debugstr_w(MRUProfile[i]->filename), debugstr_w(buffer));
829  if(i)
830  {
832  tempProfile=MRUProfile[i];
833  for(j=i;j>0;j--)
834  MRUProfile[j]=MRUProfile[j-1];
835  CurProfile=tempProfile;
836  }
837 
839  {
840  GetFileTime(hFile, NULL, NULL, &LastWriteTime);
841  if (!memcmp( &CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME) ) &&
842  is_not_current(&LastWriteTime))
843  TRACE("(%s): already opened (mru=%d)\n",
844  debugstr_w(buffer), i);
845  else
846  {
847  TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
848  debugstr_w(buffer), i);
849  PROFILE_Free(CurProfile->section);
850  CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding);
851  CurProfile->LastWriteTime = LastWriteTime;
852  }
854  return TRUE;
855  }
856  else TRACE("(%s): already opened, not yet created (mru=%d)\n",
857  debugstr_w(buffer), i);
858  }
859  }
860 
861  /* Flush the old current profile */
863 
864  /* Make the oldest profile the current one only in order to get rid of it */
865  if(i==N_CACHED_PROFILES)
866  {
867  tempProfile=MRUProfile[N_CACHED_PROFILES-1];
868  for(i=N_CACHED_PROFILES-1;i>0;i--)
869  MRUProfile[i]=MRUProfile[i-1];
870  CurProfile=tempProfile;
871  }
872  if(CurProfile->filename) PROFILE_ReleaseFile();
873 
874  /* OK, now that CurProfile is definitely free we assign it our new file */
875  CurProfile->filename = HeapAlloc( GetProcessHeap(), 0, (strlenW(buffer)+1) * sizeof(WCHAR) );
876  strcpyW( CurProfile->filename, buffer );
877 
879  {
880  CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding);
881  GetFileTime(hFile, NULL, NULL, &CurProfile->LastWriteTime);
883  }
884  else
885  {
886  /* Does not exist yet, we will create it in PROFILE_FlushFile */
887  WARN("profile file %s not found\n", debugstr_w(buffer) );
888  }
889  return TRUE;
890 }
891 
892 
893 /***********************************************************************
894  * PROFILE_GetSection
895  *
896  * Returns all keys of a section.
897  * If return_values is TRUE, also include the corresponding values.
898  */
900 #ifdef __REACTOS__
901  LPWSTR buffer, DWORD len, BOOL return_values )
902 #else
903  LPWSTR buffer, UINT len, BOOL return_values )
904 #endif
905 {
906  PROFILEKEY *key;
907 
908  if(!buffer) return 0;
909 
910  TRACE("%s,%p,%u\n", debugstr_w(section_name), buffer, len);
911 
912  while (section)
913  {
914  if (!strcmpiW( section->name, section_name ))
915  {
916  UINT oldlen = len;
917  for (key = section->key; key; key = key->next)
918  {
919  if (len <= 2) break;
920  if (!*key->name) continue; /* Skip empty lines */
921  if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
922  if (!return_values && !key->value) continue; /* Skip lines w.o. '=' */
923  PROFILE_CopyEntry( buffer, key->name, len - 1, 0 );
924  len -= strlenW(buffer) + 1;
925  buffer += strlenW(buffer) + 1;
926  if (len < 2)
927  break;
928  if (return_values && key->value) {
929  buffer[-1] = '=';
930  PROFILE_CopyEntry ( buffer, key->value, len - 1, 0 );
931  len -= strlenW(buffer) + 1;
932  buffer += strlenW(buffer) + 1;
933  }
934  }
935  *buffer = '\0';
936  if (len <= 1)
937  /*If either lpszSection or lpszKey is NULL and the supplied
938  destination buffer is too small to hold all the strings,
939  the last string is truncated and followed by two null characters.
940  In this case, the return value is equal to cchReturnBuffer
941  minus two. */
942  {
943  buffer[-1] = '\0';
944  return oldlen - 2;
945  }
946  return oldlen - len;
947  }
948  section = section->next;
949  }
950  buffer[0] = buffer[1] = '\0';
951  return 0;
952 }
953 
954 /* See GetPrivateProfileSectionNamesA for documentation */
955 #ifdef __REACTOS__
957 #else
959 #endif
960 {
961  LPWSTR buf;
962  UINT buflen,tmplen;
964 
965  TRACE("(%p, %d)\n", buffer, len);
966 
967  if (!buffer || !len)
968  return 0;
969  if (len==1) {
970  *buffer='\0';
971  return 0;
972  }
973 
974  buflen=len-1;
975  buf=buffer;
976  section = CurProfile->section;
977  while ((section!=NULL)) {
978  if (section->name[0]) {
979  tmplen = strlenW(section->name)+1;
980  if (tmplen >= buflen) {
981  if (buflen > 0) {
982  memcpy(buf, section->name, (buflen-1) * sizeof(WCHAR));
983  buf += buflen-1;
984  *buf++='\0';
985  }
986  *buf='\0';
987  return len-2;
988  }
989  memcpy(buf, section->name, tmplen * sizeof(WCHAR));
990  buf += tmplen;
991  buflen -= tmplen;
992  }
993  section = section->next;
994  }
995  *buf='\0';
996  return buf-buffer;
997 }
998 
999 
1000 /***********************************************************************
1001  * PROFILE_GetString
1002  *
1003  * Get a profile string.
1004  *
1005  * Tests with GetPrivateProfileString16, W95a,
1006  * with filled buffer ("****...") and section "set1" and key_name "1" valid:
1007  * section key_name def_val res buffer
1008  * "set1" "1" "x" 43 [data]
1009  * "set1" "1 " "x" 43 [data] (!)
1010  * "set1" " 1 "' "x" 43 [data] (!)
1011  * "set1" "" "x" 1 "x"
1012  * "set1" "" "x " 1 "x" (!)
1013  * "set1" "" " x " 3 " x" (!)
1014  * "set1" NULL "x" 6 "1\02\03\0\0"
1015  * "set1" "" "x" 1 "x"
1016  * NULL "1" "x" 0 "" (!)
1017  * "" "1" "x" 1 "x"
1018  * NULL NULL "" 0 ""
1019  *
1020  *
1021  */
1023 #ifdef __REACTOS__
1024  LPCWSTR def_val, LPWSTR buffer, DWORD len )
1025 #else
1026  LPCWSTR def_val, LPWSTR buffer, UINT len )
1027 #endif
1028 {
1029  PROFILEKEY *key = NULL;
1030  static const WCHAR empty_strW[] = { 0 };
1031 
1032  if(!buffer || !len) return 0;
1033 
1034  if (!def_val) def_val = empty_strW;
1035  if (key_name)
1036  {
1038  PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
1039  len, TRUE );
1040  TRACE("(%s,%s,%s): returning %s\n",
1042  debugstr_w(def_val), debugstr_w(buffer) );
1043  return strlenW( buffer );
1044  }
1045  /* no "else" here ! */
1046  if (section)
1047  {
1049  if (!buffer[0]) /* no luck -> def_val */
1050  {
1051  PROFILE_CopyEntry(buffer, def_val, len, TRUE);
1052  ret = strlenW(buffer);
1053  }
1054  return ret;
1055  }
1056  buffer[0] = '\0';
1057  return 0;
1058 }
1059 
1060 
1061 /***********************************************************************
1062  * PROFILE_SetString
1063  *
1064  * Set a profile string.
1065  */
1067  LPCWSTR value, BOOL create_always )
1068 {
1069  if (!key_name) /* Delete a whole section */
1070  {
1071  TRACE("(%s)\n", debugstr_w(section_name));
1072  CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
1073  section_name );
1074  return TRUE; /* Even if PROFILE_DeleteSection() has failed,
1075  this is not an error on application's level.*/
1076  }
1077  else if (!value) /* Delete a key */
1078  {
1079  TRACE("(%s,%s)\n", debugstr_w(section_name), debugstr_w(key_name) );
1080  CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
1081  section_name, key_name );
1082  return TRUE; /* same error handling as above */
1083  }
1084  else /* Set the key value */
1085  {
1086  PROFILEKEY *key = PROFILE_Find(&CurProfile->section, section_name,
1087  key_name, TRUE, create_always );
1088  TRACE("(%s,%s,%s):\n",
1089  debugstr_w(section_name), debugstr_w(key_name), debugstr_w(value) );
1090  if (!key) return FALSE;
1091 
1092  /* strip the leading spaces. We can safely strip \n\r and
1093  * friends too, they should not happen here anyway. */
1094  while (PROFILE_isspaceW(*value)) value++;
1095 
1096  if (key->value)
1097  {
1098  if (!strcmpW( key->value, value ))
1099  {
1100  TRACE(" no change needed\n" );
1101  return TRUE; /* No change needed */
1102  }
1103  TRACE(" replacing %s\n", debugstr_w(key->value) );
1104  HeapFree( GetProcessHeap(), 0, key->value );
1105  }
1106  else TRACE(" creating key\n" );
1107  key->value = HeapAlloc( GetProcessHeap(), 0, (strlenW(value)+1) * sizeof(WCHAR) );
1108  strcpyW( key->value, value );
1109  CurProfile->changed = TRUE;
1110  }
1111  return TRUE;
1112 }
1113 
1114 
1115 /********************* API functions **********************************/
1116 
1117 
1118 /***********************************************************************
1119  * GetProfileIntA (KERNEL32.@)
1120  */
1122 {
1123  return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
1124 }
1125 
1126 /***********************************************************************
1127  * GetProfileIntW (KERNEL32.@)
1128  */
1130 {
1131  return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1132 }
1133 
1134 /***********************************************************************
1135  * GetPrivateProfileStringW (KERNEL32.@)
1136  */
1137 #ifdef __REACTOS__
1139  LPCWSTR def_val, LPWSTR buffer,
1141 #else
1143  LPCWSTR def_val, LPWSTR buffer,
1145 #endif
1146 {
1147  int ret;
1148  LPWSTR defval_tmp = NULL;
1149 
1150  TRACE("%s,%s,%s,%p,%u,%s\n", debugstr_w(section), debugstr_w(entry),
1151  debugstr_w(def_val), buffer, len, debugstr_w(filename));
1152 
1153  /* strip any trailing ' ' of def_val. */
1154  if (def_val)
1155  {
1156  LPCWSTR p = def_val + strlenW(def_val) - 1;
1157 
1158  while (p > def_val && *p == ' ')
1159  p--;
1160 
1161  if (p >= def_val)
1162  {
1163  int vlen = (int)(p - def_val) + 1;
1164 
1165  defval_tmp = HeapAlloc(GetProcessHeap(), 0, (vlen + 1) * sizeof(WCHAR));
1166  memcpy(defval_tmp, def_val, vlen * sizeof(WCHAR));
1167  defval_tmp[vlen] = '\0';
1168  def_val = defval_tmp;
1169  }
1170  }
1171 
1173 
1174  if (PROFILE_Open( filename, FALSE )) {
1175  if (section == NULL)
1177  else
1178  /* PROFILE_GetString can handle the 'entry == NULL' case */
1179  ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1180  } else if (buffer && def_val) {
1181  lstrcpynW( buffer, def_val, len );
1182  ret = strlenW( buffer );
1183  }
1184  else
1185  ret = 0;
1186 
1188 
1189  HeapFree(GetProcessHeap(), 0, defval_tmp);
1190 
1191  TRACE("returning %s, %d\n", debugstr_w(buffer), ret);
1192 
1193  return ret;
1194 }
1195 
1196 /***********************************************************************
1197  * GetPrivateProfileStringA (KERNEL32.@)
1198  */
1199 #ifdef __REACTOS__
1201  LPCSTR def_val, LPSTR buffer,
1203 #else
1205  LPCSTR def_val, LPSTR buffer,
1206  UINT len, LPCSTR filename )
1207 #endif
1208 {
1209  UNICODE_STRING sectionW, entryW, def_valW, filenameW;
1210  LPWSTR bufferW;
1211  INT retW, ret = 0;
1212 
1213  bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)) : NULL;
1215  else sectionW.Buffer = NULL;
1217  else entryW.Buffer = NULL;
1218  if (def_val) RtlCreateUnicodeStringFromAsciiz(&def_valW, def_val);
1219  else def_valW.Buffer = NULL;
1221  else filenameW.Buffer = NULL;
1222 
1223  retW = GetPrivateProfileStringW( sectionW.Buffer, entryW.Buffer,
1224  def_valW.Buffer, bufferW, len,
1225  filenameW.Buffer);
1226  if (len && buffer)
1227  {
1228  if (retW)
1229  {
1230  ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW, buffer, len - 1, NULL, NULL);
1231  if (!ret)
1232  ret = len - 1;
1233  }
1234  buffer[ret] = 0;
1235  }
1236 
1237  RtlFreeUnicodeString(&sectionW);
1238  RtlFreeUnicodeString(&entryW);
1239  RtlFreeUnicodeString(&def_valW);
1241  HeapFree(GetProcessHeap(), 0, bufferW);
1242  return ret;
1243 }
1244 
1245 /***********************************************************************
1246  * GetProfileStringA (KERNEL32.@)
1247  */
1248 #ifdef __REACTOS__
1250  LPSTR buffer, DWORD len )
1251 #else
1253  LPSTR buffer, UINT len )
1254 #endif
1255 {
1256  return GetPrivateProfileStringA( section, entry, def_val,
1257  buffer, len, "win.ini" );
1258 }
1259 
1260 /***********************************************************************
1261  * GetProfileStringW (KERNEL32.@)
1262  */
1263 #ifdef __REACTOS__
1265  LPCWSTR def_val, LPWSTR buffer, DWORD len )
1266 #else
1268  LPCWSTR def_val, LPWSTR buffer, UINT len )
1269 #endif
1270 {
1271  return GetPrivateProfileStringW( section, entry, def_val,
1272  buffer, len, wininiW );
1273 }
1274 
1275 /***********************************************************************
1276  * WriteProfileStringA (KERNEL32.@)
1277  */
1279  LPCSTR string )
1280 {
1281  return WritePrivateProfileStringA( section, entry, string, "win.ini" );
1282 }
1283 
1284 /***********************************************************************
1285  * WriteProfileStringW (KERNEL32.@)
1286  */
1288  LPCWSTR string )
1289 {
1290  return WritePrivateProfileStringW( section, entry, string, wininiW );
1291 }
1292 
1293 
1294 /***********************************************************************
1295  * GetPrivateProfileIntW (KERNEL32.@)
1296  */
1298  INT def_val, LPCWSTR filename )
1299 {
1300  WCHAR buffer[30];
1301  UNICODE_STRING bufferW;
1302  ULONG result;
1303 
1305  buffer, sizeof(buffer)/sizeof(WCHAR),
1306  filename ) == 0)
1307  return def_val;
1308 
1309  /* FIXME: if entry can be found but it's empty, then Win16 is
1310  * supposed to return 0 instead of def_val ! Difficult/problematic
1311  * to implement (every other failure also returns zero buffer),
1312  * thus wait until testing framework avail for making sure nothing
1313  * else gets broken that way. */
1314  if (!buffer[0]) return (UINT)def_val;
1315 
1316  RtlInitUnicodeString( &bufferW, buffer );
1317  RtlUnicodeStringToInteger( &bufferW, 0, &result);
1318  return result;
1319 }
1320 
1321 /***********************************************************************
1322  * GetPrivateProfileIntA (KERNEL32.@)
1323  *
1324  * FIXME: rewrite using unicode
1325  */
1327  INT def_val, LPCSTR filename )
1328 {
1329  UNICODE_STRING entryW, filenameW, sectionW;
1330  UINT res;
1332  else entryW.Buffer = NULL;
1334  else filenameW.Buffer = NULL;
1336  else sectionW.Buffer = NULL;
1337  res = GetPrivateProfileIntW(sectionW.Buffer, entryW.Buffer, def_val,
1338  filenameW.Buffer);
1339  RtlFreeUnicodeString(&sectionW);
1341  RtlFreeUnicodeString(&entryW);
1342  return res;
1343 }
1344 
1345 /***********************************************************************
1346  * GetPrivateProfileSectionW (KERNEL32.@)
1347  */
1348 #ifdef __REACTOS__
1350 #else
1352 #endif
1354 {
1355  int ret = 0;
1356 
1357  if (!section || !buffer)
1358  {
1360  return 0;
1361  }
1362 
1363  TRACE("(%s, %p, %d, %s)\n", debugstr_w(section), buffer, len, debugstr_w(filename));
1364 
1366 
1367  if (PROFILE_Open( filename, FALSE ))
1369 
1371 
1372  return ret;
1373 }
1374 
1375 /***********************************************************************
1376  * GetPrivateProfileSectionA (KERNEL32.@)
1377  */
1378 #ifdef __REACTOS__
1380 #else
1382 #endif
1384 {
1385  UNICODE_STRING sectionW, filenameW;
1386  LPWSTR bufferW;
1387  INT retW, ret = 0;
1388 
1389  if (!section || !buffer)
1390  {
1392  return 0;
1393  }
1394 
1395  bufferW = HeapAlloc(GetProcessHeap(), 0, len * 2 * sizeof(WCHAR));
1398  else filenameW.Buffer = NULL;
1399 
1400  retW = GetPrivateProfileSectionW(sectionW.Buffer, bufferW, len * 2, filenameW.Buffer);
1401  if (retW)
1402  {
1403  if (retW == len * 2 - 2) retW++; /* overflow */
1404  ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW + 1, buffer, len, NULL, NULL);
1405  if (!ret || ret == len) /* overflow */
1406  {
1407  ret = len - 2;
1408  buffer[len-2] = 0;
1409  buffer[len-1] = 0;
1410  }
1411  else ret--;
1412  }
1413  else
1414  {
1415  buffer[0] = 0;
1416  buffer[1] = 0;
1417  }
1418 
1419  RtlFreeUnicodeString(&sectionW);
1421  HeapFree(GetProcessHeap(), 0, bufferW);
1422  return ret;
1423 }
1424 
1425 /***********************************************************************
1426  * GetProfileSectionA (KERNEL32.@)
1427  */
1428 #ifdef __REACTOS__
1430 #else
1432 #endif
1433 {
1434  return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
1435 }
1436 
1437 /***********************************************************************
1438  * GetProfileSectionW (KERNEL32.@)
1439  */
1440 #ifdef __REACTOS__
1442 #else
1444 #endif
1445 {
1447 }
1448 
1449 
1450 /***********************************************************************
1451  * WritePrivateProfileStringW (KERNEL32.@)
1452  */
1454  LPCWSTR string, LPCWSTR filename )
1455 {
1456  BOOL ret = FALSE;
1457 
1459 
1460  if (!section && !entry && !string) /* documented "file flush" case */
1461  {
1462  if (!filename || PROFILE_Open( filename, TRUE ))
1463  {
1464  if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */
1465  }
1466  }
1467  else if (PROFILE_Open( filename, TRUE ))
1468  {
1469  if (!section) {
1471  } else {
1472  ret = PROFILE_SetString( section, entry, string, FALSE);
1473  if (ret) ret = PROFILE_FlushFile();
1474  }
1475  }
1476 
1478  return ret;
1479 }
1480 
1481 /***********************************************************************
1482  * WritePrivateProfileStringA (KERNEL32.@)
1483  */
1485  LPCSTR string, LPCSTR filename )
1486 {
1487  UNICODE_STRING sectionW, entryW, stringW, filenameW;
1488  BOOL ret;
1489 
1491  else sectionW.Buffer = NULL;
1493  else entryW.Buffer = NULL;
1494  if (string) RtlCreateUnicodeStringFromAsciiz(&stringW, string);
1495  else stringW.Buffer = NULL;
1497  else filenameW.Buffer = NULL;
1498 
1499  ret = WritePrivateProfileStringW(sectionW.Buffer, entryW.Buffer,
1500  stringW.Buffer, filenameW.Buffer);
1501  RtlFreeUnicodeString(&sectionW);
1502  RtlFreeUnicodeString(&entryW);
1505  return ret;
1506 }
1507 
1508 /***********************************************************************
1509  * WritePrivateProfileSectionW (KERNEL32.@)
1510  */
1512  LPCWSTR string, LPCWSTR filename )
1513 {
1514  BOOL ret = FALSE;
1515  LPWSTR p;
1516 
1518 
1519  if (!section && !string)
1520  {
1521  if (!filename || PROFILE_Open( filename, TRUE ))
1522  {
1523  if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */
1524  }
1525  }
1526  else if (PROFILE_Open( filename, TRUE )) {
1527  if (!string) {/* delete the named section*/
1529  } else {
1531  ret = TRUE;
1532  while(*string && ret) {
1533  LPWSTR buf = HeapAlloc( GetProcessHeap(), 0, (strlenW(string)+1) * sizeof(WCHAR) );
1534  strcpyW( buf, string );
1535  if((p = strchrW( buf, '='))) {
1536  *p='\0';
1538  }
1539  HeapFree( GetProcessHeap(), 0, buf );
1540  string += strlenW(string)+1;
1541  }
1542  }
1543  if (ret) ret = PROFILE_FlushFile();
1544  }
1545 
1547  return ret;
1548 }
1549 
1550 /***********************************************************************
1551  * WritePrivateProfileSectionA (KERNEL32.@)
1552  */
1554  LPCSTR string, LPCSTR filename)
1555 
1556 {
1557  UNICODE_STRING sectionW, filenameW;
1558  LPWSTR stringW;
1559  BOOL ret;
1560 
1561  if (string)
1562  {
1563  INT lenA, lenW;
1564  LPCSTR p = string;
1565 
1566  while(*p) p += strlen(p) + 1;
1567  lenA = p - string + 1;
1568  lenW = MultiByteToWideChar(CP_ACP, 0, string, lenA, NULL, 0);
1569  if ((stringW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR))))
1570  MultiByteToWideChar(CP_ACP, 0, string, lenA, stringW, lenW);
1571  }
1572  else stringW = NULL;
1574  else sectionW.Buffer = NULL;
1576  else filenameW.Buffer = NULL;
1577 
1579 
1581  RtlFreeUnicodeString(&sectionW);
1583  return ret;
1584 }
1585 
1586 /***********************************************************************
1587  * WriteProfileSectionA (KERNEL32.@)
1588  */
1590 
1591 {
1592  return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
1593 }
1594 
1595 /***********************************************************************
1596  * WriteProfileSectionW (KERNEL32.@)
1597  */
1599 {
1600  return WritePrivateProfileSectionW(section, keys_n_values, wininiW);
1601 }
1602 
1603 
1604 /***********************************************************************
1605  * GetPrivateProfileSectionNamesW (KERNEL32.@)
1606  *
1607  * Returns the section names contained in the specified file.
1608  * FIXME: Where do we find this file when the path is relative?
1609  * The section names are returned as a list of strings with an extra
1610  * '\0' to mark the end of the list. Except for that the behavior
1611  * depends on the Windows version.
1612  *
1613  * Win95:
1614  * - if the buffer is 0 or 1 character long then it is as if it was of
1615  * infinite length.
1616  * - otherwise, if the buffer is too small only the section names that fit
1617  * are returned.
1618  * - note that this means if the buffer was too small to return even just
1619  * the first section name then a single '\0' will be returned.
1620  * - the return value is the number of characters written in the buffer,
1621  * except if the buffer was too small in which case len-2 is returned
1622  *
1623  * Win2000:
1624  * - if the buffer is 0, 1 or 2 characters long then it is filled with
1625  * '\0' and the return value is 0
1626  * - otherwise if the buffer is too small then the first section name that
1627  * does not fit is truncated so that the string list can be terminated
1628  * correctly (double '\0')
1629  * - the return value is the number of characters written in the buffer
1630  * except for the trailing '\0'. If the buffer is too small, then the
1631  * return value is len-2
1632  * - Win2000 has a bug that triggers when the section names and the
1633  * trailing '\0' fit exactly in the buffer. In that case the trailing
1634  * '\0' is missing.
1635  *
1636  * Wine implements the observed Win2000 behavior (except for the bug).
1637  *
1638  * Note that when the buffer is big enough then the return value may be any
1639  * value between 1 and len-1 (or len in Win95), including len-2.
1640  */
1642  LPCWSTR filename)
1643 {
1644  DWORD ret = 0;
1645 
1647 
1648  if (PROFILE_Open( filename, FALSE ))
1650 
1652 
1653  return ret;
1654 }
1655 
1656 
1657 /***********************************************************************
1658  * GetPrivateProfileSectionNamesA (KERNEL32.@)
1659  */
1661  LPCSTR filename)
1662 {
1664  LPWSTR bufferW;
1665  INT retW, ret = 0;
1666 
1667  bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)) : NULL;
1669  else filenameW.Buffer = NULL;
1670 
1671  retW = GetPrivateProfileSectionNamesW(bufferW, size, filenameW.Buffer);
1672  if (retW && size)
1673  {
1674  ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW+1, buffer, size-1, NULL, NULL);
1675  if (!ret)
1676  {
1677  ret = size-2;
1678  buffer[size-1] = 0;
1679  }
1680  else
1681  ret = ret-1;
1682  }
1683  else if(size)
1684  buffer[0] = '\0';
1685 
1687  HeapFree(GetProcessHeap(), 0, bufferW);
1688  return ret;
1689 }
1690 
1691 /***********************************************************************
1692  * GetPrivateProfileStructW (KERNEL32.@)
1693  *
1694  * Should match Win95's behaviour pretty much
1695  */
1698 {
1699  BOOL ret = FALSE;
1700 
1702 
1703  if (PROFILE_Open( filename, FALSE )) {
1704  PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE);
1705  if (k) {
1706  TRACE("value (at %p): %s\n", k->value, debugstr_w(k->value));
1707  if (((strlenW(k->value) - 2) / 2) == len)
1708  {
1709  LPWSTR end, p;
1710  BOOL valid = TRUE;
1711  WCHAR c;
1712  DWORD chksum = 0;
1713 
1714  end = k->value + strlenW(k->value); /* -> '\0' */
1715  /* check for invalid chars in ASCII coded hex string */
1716  for (p=k->value; p < end; p++)
1717  {
1718  if (!isxdigitW(*p))
1719  {
1720  WARN("invalid char '%x' in file %s->[%s]->%s !\n",
1722  valid = FALSE;
1723  break;
1724  }
1725  }
1726  if (valid)
1727  {
1728  BOOL highnibble = TRUE;
1729  BYTE b = 0, val;
1730  LPBYTE binbuf = buf;
1731 
1732  end -= 2; /* don't include checksum in output data */
1733  /* translate ASCII hex format into binary data */
1734  for (p=k->value; p < end; p++)
1735  {
1736  c = toupperW(*p);
1737  val = (c > '9') ?
1738  (c - 'A' + 10) : (c - '0');
1739 
1740  if (highnibble)
1741  b = val << 4;
1742  else
1743  {
1744  b += val;
1745  *binbuf++ = b; /* feed binary data into output */
1746  chksum += b; /* calculate checksum */
1747  }
1748  highnibble ^= 1; /* toggle */
1749  }
1750  /* retrieve stored checksum value */
1751  c = toupperW(*p++);
1752  b = ( (c > '9') ? (c - 'A' + 10) : (c - '0') ) << 4;
1753  c = toupperW(*p);
1754  b += (c > '9') ? (c - 'A' + 10) : (c - '0');
1755  if (b == (chksum & 0xff)) /* checksums match ? */
1756  ret = TRUE;
1757  }
1758  }
1759  }
1760  }
1762 
1763  return ret;
1764 }
1765 
1766 /***********************************************************************
1767  * GetPrivateProfileStructA (KERNEL32.@)
1768  */
1771 {
1772  UNICODE_STRING sectionW, keyW, filenameW;
1773  INT ret;
1774 
1776  else sectionW.Buffer = NULL;
1778  else keyW.Buffer = NULL;
1780  else filenameW.Buffer = NULL;
1781 
1782  ret = GetPrivateProfileStructW(sectionW.Buffer, keyW.Buffer, buffer, len,
1783  filenameW.Buffer);
1784  /* Do not translate binary data. */
1785 
1786  RtlFreeUnicodeString(&sectionW);
1789  return ret;
1790 }
1791 
1792 
1793 
1794 /***********************************************************************
1795  * WritePrivateProfileStructW (KERNEL32.@)
1796  */
1799 {
1800  BOOL ret = FALSE;
1801  LPBYTE binbuf;
1802  LPWSTR outstring, p;
1803  DWORD sum = 0;
1804 
1805  if (!section && !key && !buf) /* flush the cache */
1807 
1808  /* allocate string buffer for hex chars + checksum hex char + '\0' */
1809  outstring = HeapAlloc( GetProcessHeap(), 0, (bufsize*2 + 2 + 1) * sizeof(WCHAR) );
1810  p = outstring;
1811  for (binbuf = (LPBYTE)buf; binbuf < (LPBYTE)buf+bufsize; binbuf++) {
1812  *p++ = hex[*binbuf >> 4];
1813  *p++ = hex[*binbuf & 0xf];
1814  sum += *binbuf;
1815  }
1816  /* checksum is sum & 0xff */
1817  *p++ = hex[(sum & 0xf0) >> 4];
1818  *p++ = hex[sum & 0xf];
1819  *p++ = '\0';
1820 
1822 
1823  if (PROFILE_Open( filename, TRUE )) {
1824  ret = PROFILE_SetString( section, key, outstring, FALSE);
1825  if (ret) ret = PROFILE_FlushFile();
1826  }
1827 
1829 
1830  HeapFree( GetProcessHeap(), 0, outstring );
1831 
1832  return ret;
1833 }
1834 
1835 /***********************************************************************
1836  * WritePrivateProfileStructA (KERNEL32.@)
1837  */
1840 {
1841  UNICODE_STRING sectionW, keyW, filenameW;
1842  INT ret;
1843 
1845  else sectionW.Buffer = NULL;
1847  else keyW.Buffer = NULL;
1849  else filenameW.Buffer = NULL;
1850 
1851  /* Do not translate binary data. */
1852  ret = WritePrivateProfileStructW(sectionW.Buffer, keyW.Buffer, buf, bufsize,
1853  filenameW.Buffer);
1854 
1855  RtlFreeUnicodeString(&sectionW);
1858  return ret;
1859 }
1860 
1861 
1862 /***********************************************************************
1863  * OpenProfileUserMapping (KERNEL32.@)
1864  */
1866  FIXME("(), stub!\n");
1868  return FALSE;
1869 }
1870 
1871 /***********************************************************************
1872  * CloseProfileUserMapping (KERNEL32.@)
1873  */
1875  FIXME("(), stub!\n");
1877  return FALSE;
1878 }
#define N_CACHED_PROFILES
Definition: profile.c:86
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
FILETIME LastWriteTime
Definition: profile.c:81
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
struct tagPROFILEKEY PROFILEKEY
INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len, LPCWSTR filename)
Definition: profile.c:1142
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
BOOL WINAPI OpenProfileUserMapping(void)
Definition: profile.c:1865
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:101
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
WCHAR * name
Definition: path.c:44
DWORD WINAPI GetPrivateProfileSectionNamesA(LPSTR buffer, DWORD size, LPCSTR filename)
Definition: profile.c:1660
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
struct _PROFILE PROFILE
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3199
static void PROFILE_WriteLine(HANDLE hFile, WCHAR *szLine, int len, ENCODING encoding)
Definition: profile.c:179
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
BOOL WINAPI WriteProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string)
Definition: profile.c:1287
#define CP_ACP
Definition: compat.h:99
WINE_UNICODE_INLINE int isspaceW(WCHAR wc)
Definition: unicode.h:165
PROFILESECTION * section
Definition: profile.c:79
#define WARN(fmt,...)
Definition: debug.h:111
static INT PROFILE_GetString(LPCWSTR section, LPCWSTR key_name, LPCWSTR def_val, LPWSTR buffer, UINT len)
Definition: profile.c:1022
DWORD dwFileSize
Definition: more.c:36
BOOL WINAPI WritePrivateProfileStructW(LPCWSTR section, LPCWSTR key, LPVOID buf, UINT bufsize, LPCWSTR filename)
Definition: profile.c:1797
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
GLuint buffer
Definition: glext.h:5915
BOOL WINAPI GetPrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buffer, UINT len, LPCSTR filename)
Definition: profile.c:1769
WCHAR name[1]
Definition: profile.c:72
static void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding)
Definition: profile.c:157
WCHAR * filename
Definition: profile.c:80
GLuint GLuint end
Definition: gl.h:1545
#define INVALID_FILE_SIZE
Definition: winbase.h:529
static void PROFILE_CopyEntry(LPWSTR buffer, LPCWSTR value, int len, BOOL strip_quote)
Definition: profile.c:131
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
Definition: parser.c:55
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
char * LPSTR
Definition: xmlstorage.h:182
const char * filename
Definition: ioapi.h:135
static const char hex[16]
Definition: profile.c:123
#define lstrlenW
Definition: compat.h:407
int32_t INT
Definition: typedefs.h:56
static const WCHAR stringW[]
Definition: engine.c:36
#define FILE_SHARE_READ
Definition: compat.h:125
static IMAGE_SECTION_HEADER section
Definition: loader.c:152
#define IS_TEXT_UNICODE_SIGNATURE
Definition: winnt_old.h:925
struct tagPROFILEKEY * next
Definition: profile.c:64
const WCHAR * name
Definition: parser.c:57
#define lstrcpynW
Definition: compat.h:397
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2351
INT WINAPI GetProfileSectionW(LPCWSTR section, LPWSTR buffer, DWORD len)
Definition: profile.c:1443
INT WINAPI GetPrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len, LPCSTR filename)
Definition: profile.c:1204
static PROFILESECTION * PROFILE_Load(HANDLE hFile, ENCODING *pEncoding)
Definition: profile.c:335
UINT WINAPI GetPrivateProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val, LPCWSTR filename)
Definition: profile.c:1297
static const WCHAR filenameW[]
Definition: amstream.c:41
BOOL WINAPI GetPrivateProfileStructW(LPCWSTR section, LPCWSTR key, LPVOID buf, UINT len, LPCWSTR filename)
Definition: profile.c:1696
DWORD dwHighDateTime
Definition: mapidefs.h:66
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void PROFILE_ReleaseFile(void)
Definition: profile.c:728
static void PROFILE_Free(PROFILESECTION *section)
Definition: profile.c:279
ENCODING encoding
Definition: profile.c:82
unsigned char * LPBYTE
Definition: typedefs.h:52
NTSYSAPI BOOLEAN NTAPI RtlIsTextUnicode(_In_ CONST VOID *Buffer, _In_ INT Size, _Inout_opt_ INT *Flags)
WCHAR name[1]
Definition: profile.c:65
#define CP_UTF8
Definition: nls.h:20
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
WINE_DEFAULT_DEBUG_CHANNEL(hnetcfg)
ENCODING
Definition: profile.c:53
#define GENERIC_WRITE
Definition: nt_native.h:90
#define debugstr_w
Definition: kernel32.h:32
BOOL WINAPI WritePrivateProfileSectionA(LPCSTR section, LPCSTR string, LPCSTR filename)
Definition: profile.c:1553
#define FIXME(fmt,...)
Definition: debug.h:110
#define quote
Definition: macro.lex.yy.c:531
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
static CRITICAL_SECTION PROFILE_CritSect
Definition: profile.c:112
WCHAR * value
Definition: path.c:46
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
static const WCHAR szLine[]
Definition: dialog.c:141
Definition: parser.c:48
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
static ENCODING PROFILE_DetectTextEncoding(const void *buffer, int *len)
Definition: profile.c:304
INT WINAPI GetProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len)
Definition: profile.c:1252
const char * LPCSTR
Definition: xmlstorage.h:183
DWORD WINAPI GetPrivateProfileSectionNamesW(LPWSTR buffer, DWORD size, LPCWSTR filename)
Definition: profile.c:1641
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
#define OPEN_EXISTING
Definition: compat.h:426
#define b
Definition: ke_i.h:79
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:240
static BOOL PROFILE_SetString(LPCWSTR section_name, LPCWSTR key_name, LPCWSTR value, BOOL create_always)
Definition: profile.c:1066
WINE_UNICODE_INLINE WCHAR toupperW(WCHAR ch)
Definition: unicode.h:141
#define IS_TEXT_UNICODE_REVERSE_SIGNATURE
Definition: winnt_old.h:926
int64_t LONGLONG
Definition: typedefs.h:66
static void PROFILE_Save(HANDLE hFile, const PROFILESECTION *section, ENCODING encoding)
Definition: profile.c:222
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
BOOL WINAPI WriteProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string)
Definition: profile.c:1278
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: profile.c:113
__wchar_t WCHAR
Definition: xmlstorage.h:180
static PROFILEKEY * PROFILE_Find(PROFILESECTION **section, LPCWSTR section_name, LPCWSTR key_name, BOOL create, BOOL create_always)
Definition: profile.c:614
static const WCHAR keyW[]
Definition: tokenize.c:60
#define IS_TEXT_UNICODE_ODD_LENGTH
Definition: winnt_old.h:928
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
#define SetLastError(x)
Definition: compat.h:409
static const char bom_utf8[]
Definition: profile.c:51
static BOOL PROFILE_isspaceW(WCHAR c)
Definition: profile.c:298
GLbitfield flags
Definition: glext.h:7161
WCHAR * value
Definition: profile.c:63
WINE_UNICODE_INLINE int isxdigitW(WCHAR wc)
Definition: unicode.h:175
static const WCHAR emptystringW[]
Definition: profile.c:96
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
HKEY key
Definition: reg.c:42
struct tm * Now
Definition: output.c:19
BOOL WINAPI WriteProfileSectionW(LPCWSTR section, LPCWSTR keys_n_values)
Definition: profile.c:1598
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
INT WINAPI GetProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len)
Definition: profile.c:1267
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
struct tagPROFILEKEY * key
Definition: profile.c:70
#define GENERIC_READ
Definition: compat.h:124
static BOOL PROFILE_DeleteSection(PROFILESECTION **section, LPCWSTR name)
Definition: profile.c:532
LIST_ENTRY ProcessLocksList
Definition: winbase.h:848
_In_ HANDLE hFile
Definition: mswsock.h:90
#define debugstr_wn
Definition: kernel32.h:33
static INT PROFILE_GetSection(PROFILESECTION *section, LPCWSTR section_name, LPWSTR buffer, UINT len, BOOL return_values)
Definition: profile.c:899
BOOL WINAPI WritePrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string, LPCWSTR filename)
Definition: profile.c:1453
ed encoding
Definition: write.c:2839
char string[160]
Definition: util.h:11
WINE_UNICODE_INLINE WCHAR * memrchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:302
BOOL WINAPI WritePrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buf, UINT bufsize, LPCSTR filename)
Definition: profile.c:1838
#define strcmpiW(s1, s2)
Definition: unicode.h:39
#define CurProfile
Definition: profile.c:91
struct tagPROFILESECTION * next
Definition: profile.c:71
static void PROFILE_DeleteAllKeys(LPCWSTR section_name)
Definition: profile.c:587
ENCODING
Definition: more.c:155
#define CREATE_ALWAYS
Definition: disk.h:72
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
BOOL WINAPI CloseProfileUserMapping(void)
Definition: profile.c:1874
unsigned short USHORT
Definition: pedump.c:61
static BOOL PROFILE_FlushFile(void)
Definition: profile.c:691
static u32_t chksum(void *dataptr, u16_t len)
Definition: inet6.c:55
unsigned char dummy
Definition: maze.c:118
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
unsigned int UINT
Definition: ndis.h:50
UINT WINAPI GetProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val)
Definition: profile.c:1129
static BOOL is_not_current(FILETIME *ft)
Definition: profile.c:749
#define MultiByteToWideChar
Definition: compat.h:100
#define CreateFileW
Definition: compat.h:400
Definition: name.c:36
BOOL WINAPI WritePrivateProfileSectionW(LPCWSTR section, LPCWSTR string, LPCWSTR filename)
Definition: profile.c:1511
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
GLuint res
Definition: glext.h:9613
#define c
Definition: ke_i.h:80
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
static const WCHAR wininiW[]
Definition: profile.c:97
unsigned int ULONG
Definition: retypes.h:1
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define profile
Definition: kernel32.h:12
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
WINE_UNICODE_INLINE WCHAR * memchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:295
INT WINAPI GetPrivateProfileSectionW(LPCWSTR section, LPWSTR buffer, DWORD len, LPCWSTR filename)
Definition: profile.c:1351
BOOL WINAPI DECLSPEC_HOTPATCH WritePrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string, LPCSTR filename)
Definition: profile.c:1484
INT WINAPI GetProfileSectionA(LPCSTR section, LPSTR buffer, DWORD len)
Definition: profile.c:1431
static BOOL PROFILE_Open(LPCWSTR filename, BOOL write_access)
Definition: profile.c:765
UINT WINAPI GetProfileIntA(LPCSTR section, LPCSTR entry, INT def_val)
Definition: profile.c:1121
static INT PROFILE_GetSectionNames(LPWSTR buffer, UINT len)
Definition: profile.c:958
UINT WINAPI GetPrivateProfileIntA(LPCSTR section, LPCSTR entry, INT def_val, LPCSTR filename)
Definition: profile.c:1326
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
BOOL changed
Definition: profile.c:78
GLuint64EXT * result
Definition: glext.h:11304
static const struct access_res create[16]
Definition: package.c:7720
static PROFILE * MRUProfile[N_CACHED_PROFILES]
Definition: profile.c:89
BOOL WINAPI WriteProfileSectionA(LPCSTR section, LPCSTR keys_n_values)
Definition: profile.c:1589
int k
Definition: mpi.c:3369
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1046
struct tagPROFILESECTION PROFILESECTION
#define HeapFree(x, y, z)
Definition: compat.h:394
static BOOL PROFILE_DeleteKey(PROFILESECTION **section, LPCWSTR section_name, LPCWSTR key_name)
Definition: profile.c:555
DWORD dwLowDateTime
Definition: mapidefs.h:65
#define IS_ENTRY_COMMENT(str)
Definition: profile.c:94
Definition: path.c:42
INT WINAPI GetPrivateProfileSectionA(LPCSTR section, LPSTR buffer, DWORD len, LPCSTR filename)
Definition: profile.c:1381
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static void PROFILE_ByteSwapShortBuffer(WCHAR *buffer, int len)
Definition: profile.c:148
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)