ReactOS 0.4.15-dev-5666-gc548b97
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
51static const char bom_utf8[] = {0xEF,0xBB,0xBF};
52
53typedef enum
54{
60
61typedef struct tagPROFILEKEY
62{
67
68typedef struct tagPROFILESECTION
69{
74
75
76typedef 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
96static const WCHAR emptystringW[] = {0};
97static 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};
108static 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};
119static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
120
121#endif /* __REACTOS__ */
122
123static 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
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 */
148static 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{
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;
290 HeapFree( GetProcessHeap(), 0, key );
291 }
292 next_section = section->next;
294 }
295}
296
297/* returns TRUE if a whitespace character, else FALSE */
299{
300 /* ^Z (DOS EOF) is a space too (found on CD-ROMs) */
301 return isspaceW(c) || c == 0x1a;
302}
303
304static 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
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);
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",
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 */
587static 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
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;
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 */
728static 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{
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 */
765static 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)
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 {
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--)
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",
845 else
846 {
847 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
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",
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 */
866 {
867 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
868 for(i=N_CACHED_PROFILES-1;i>0;i--)
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{
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,
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__
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;
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 */
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 */
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 )) {
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
1783 filenameW.Buffer);
1784 /* Do not translate binary data. */
1785
1786 RtlFreeUnicodeString(&sectionW);
1787 RtlFreeUnicodeString(&keyW);
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. */
1853 filenameW.Buffer);
1854
1855 RtlFreeUnicodeString(&sectionW);
1856 RtlFreeUnicodeString(&keyW);
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 DECLSPEC_HOTPATCH
Definition: _mingw.h:243
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR quote[]
Definition: reg.c:40
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:896
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
DWORD WINAPI GetPrivateProfileSectionNamesW(LPWSTR buffer, DWORD size, LPCWSTR filename)
Definition: profile.c:1641
static void PROFILE_DeleteAllKeys(LPCWSTR section_name)
Definition: profile.c:587
BOOL WINAPI WriteProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string)
Definition: profile.c:1278
static INT PROFILE_GetSection(PROFILESECTION *section, LPCWSTR section_name, LPWSTR buffer, UINT len, BOOL return_values)
Definition: profile.c:899
static INT PROFILE_GetString(LPCWSTR section, LPCWSTR key_name, LPCWSTR def_val, LPWSTR buffer, UINT len)
Definition: profile.c:1022
UINT WINAPI GetPrivateProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val, LPCWSTR filename)
Definition: profile.c:1297
#define CurProfile
Definition: profile.c:91
UINT WINAPI GetProfileIntA(LPCSTR section, LPCSTR entry, INT def_val)
Definition: profile.c:1121
BOOL WINAPI WriteProfileSectionA(LPCSTR section, LPCSTR keys_n_values)
Definition: profile.c:1589
static BOOL PROFILE_Open(LPCWSTR filename, BOOL write_access)
Definition: profile.c:765
static BOOL PROFILE_DeleteSection(PROFILESECTION **section, LPCWSTR name)
Definition: profile.c:532
BOOL WINAPI WriteProfileSectionW(LPCWSTR section, LPCWSTR keys_n_values)
Definition: profile.c:1598
static PROFILESECTION * PROFILE_Load(HANDLE hFile, ENCODING *pEncoding)
Definition: profile.c:335
static void PROFILE_ByteSwapShortBuffer(WCHAR *buffer, int len)
Definition: profile.c:148
INT WINAPI GetPrivateProfileSectionA(LPCSTR section, LPSTR buffer, DWORD len, LPCSTR filename)
Definition: profile.c:1381
BOOL WINAPI WritePrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buf, UINT bufsize, LPCSTR filename)
Definition: profile.c:1838
BOOL WINAPI WritePrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string, LPCWSTR filename)
Definition: profile.c:1453
static BOOL PROFILE_FlushFile(void)
Definition: profile.c:691
static BOOL is_not_current(FILETIME *ft)
Definition: profile.c:749
#define N_CACHED_PROFILES
Definition: profile.c:86
BOOL WINAPI OpenProfileUserMapping(void)
Definition: profile.c:1865
static void PROFILE_Save(HANDLE hFile, const PROFILESECTION *section, ENCODING encoding)
Definition: profile.c:222
struct tagPROFILEKEY PROFILEKEY
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: profile.c:113
static BOOL PROFILE_SetString(LPCWSTR section_name, LPCWSTR key_name, LPCWSTR value, BOOL create_always)
Definition: profile.c:1066
static const WCHAR emptystringW[]
Definition: profile.c:96
struct tagPROFILESECTION PROFILESECTION
BOOL WINAPI WritePrivateProfileSectionA(LPCSTR section, LPCSTR string, LPCSTR filename)
Definition: profile.c:1553
static ENCODING PROFILE_DetectTextEncoding(const void *buffer, int *len)
Definition: profile.c:304
INT WINAPI GetProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len)
Definition: profile.c:1267
INT WINAPI GetPrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len, LPCSTR filename)
Definition: profile.c:1204
ENCODING
Definition: profile.c:54
@ ENCODING_UTF16BE
Definition: profile.c:58
@ ENCODING_UTF8
Definition: profile.c:56
@ ENCODING_UTF16LE
Definition: profile.c:57
@ ENCODING_ANSI
Definition: profile.c:55
DWORD WINAPI GetPrivateProfileSectionNamesA(LPSTR buffer, DWORD size, LPCSTR filename)
Definition: profile.c:1660
static const char bom_utf8[]
Definition: profile.c:51
static CRITICAL_SECTION PROFILE_CritSect
Definition: profile.c:112
INT WINAPI GetProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len)
Definition: profile.c:1252
BOOL WINAPI WritePrivateProfileStructW(LPCWSTR section, LPCWSTR key, LPVOID buf, UINT bufsize, LPCWSTR filename)
Definition: profile.c:1797
static void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding)
Definition: profile.c:157
static void PROFILE_ReleaseFile(void)
Definition: profile.c:728
INT WINAPI GetProfileSectionA(LPCSTR section, LPSTR buffer, DWORD len)
Definition: profile.c:1431
#define IS_ENTRY_COMMENT(str)
Definition: profile.c:94
static void PROFILE_WriteLine(HANDLE hFile, WCHAR *szLine, int len, ENCODING encoding)
Definition: profile.c:179
static PROFILE * MRUProfile[N_CACHED_PROFILES]
Definition: profile.c:89
static const WCHAR wininiW[]
Definition: profile.c:97
UINT WINAPI GetPrivateProfileIntA(LPCSTR section, LPCSTR entry, INT def_val, LPCSTR filename)
Definition: profile.c:1326
BOOL WINAPI CloseProfileUserMapping(void)
Definition: profile.c:1874
static void PROFILE_CopyEntry(LPWSTR buffer, LPCWSTR value, int len, BOOL strip_quote)
Definition: profile.c:131
INT WINAPI GetPrivateProfileSectionW(LPCWSTR section, LPWSTR buffer, DWORD len, LPCWSTR filename)
Definition: profile.c:1351
static BOOL PROFILE_DeleteKey(PROFILESECTION **section, LPCWSTR section_name, LPCWSTR key_name)
Definition: profile.c:555
INT WINAPI GetProfileSectionW(LPCWSTR section, LPWSTR buffer, DWORD len)
Definition: profile.c:1443
static void PROFILE_Free(PROFILESECTION *section)
Definition: profile.c:279
static INT PROFILE_GetSectionNames(LPWSTR buffer, UINT len)
Definition: profile.c:958
BOOL WINAPI WritePrivateProfileSectionW(LPCWSTR section, LPCWSTR string, LPCWSTR filename)
Definition: profile.c:1511
INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len, LPCWSTR filename)
Definition: profile.c:1142
static BOOL PROFILE_isspaceW(WCHAR c)
Definition: profile.c:298
BOOL WINAPI GetPrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buffer, UINT len, LPCSTR filename)
Definition: profile.c:1769
static PROFILEKEY * PROFILE_Find(PROFILESECTION **section, LPCWSTR section_name, LPCWSTR key_name, BOOL create, BOOL create_always)
Definition: profile.c:614
BOOL WINAPI DECLSPEC_HOTPATCH WritePrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string, LPCSTR filename)
Definition: profile.c:1484
BOOL WINAPI GetPrivateProfileStructW(LPCWSTR section, LPCWSTR key, LPVOID buf, UINT len, LPCWSTR filename)
Definition: profile.c:1696
UINT WINAPI GetProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val)
Definition: profile.c:1129
static const char hex[16]
Definition: profile.c:123
BOOL WINAPI WriteProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string)
Definition: profile.c:1287
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static const WCHAR stringW[]
Definition: engine.c:38
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOLEAN valid
GLuint GLuint end
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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
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
WINE_UNICODE_INLINE WCHAR * memrchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:302
WINE_UNICODE_INLINE WCHAR * memchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:295
@ RELATIVE_PATH
Definition: winternl.h:1113
static u32_t chksum(void *dataptr, u16_t len)
Definition: inet6.c:55
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define profile
Definition: kernel32.h:12
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
unsigned int ULONG
Definition: retypes.h:1
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
char string[160]
Definition: util.h:11
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static const WCHAR filenameW[]
Definition: amstream.c:41
static const struct access_res create[16]
Definition: package.c:7644
ENCODING
Definition: more.c:492
DWORD dwFileSize
Definition: more.c:40
int k
Definition: mpi.c:3369
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI BOOLEAN NTAPI RtlIsTextUnicode(_In_ CONST VOID *Buffer, _In_ INT Size, _Inout_opt_ INT *Flags)
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
@ RtlPathTypeRelative
Definition: rtltypes.h:476
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define GENERIC_WRITE
Definition: nt_native.h:90
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
PVOID pBuffer
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define toupperW(n)
Definition: unicode.h:45
#define strcmpW(s1, s2)
Definition: unicode.h:38
#define strchrW(s, c)
Definition: unicode.h:34
#define strcmpiW(s1, s2)
Definition: unicode.h:39
#define strlenW(s)
Definition: unicode.h:28
#define strcatW(d, s)
Definition: unicode.h:30
#define isxdigitW(n)
Definition: unicode.h:51
#define isspaceW(n)
Definition: unicode.h:52
#define strcpyW(d, s)
Definition: unicode.h:29
#define CP_UTF8
Definition: nls.h:20
struct tm * Now
Definition: output.c:19
#define TRACE(s)
Definition: solgame.cpp:4
ENCODING encoding
Definition: profile.c:82
WCHAR * filename
Definition: profile.c:80
FILETIME LastWriteTime
Definition: profile.c:81
BOOL changed
Definition: profile.c:78
PROFILESECTION * section
Definition: profile.c:79
LIST_ENTRY ProcessLocksList
Definition: winbase.h:883
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
struct define * next
Definition: compiler.c:65
Definition: copy.c:22
WCHAR * value
Definition: path.c:45
WCHAR * name
Definition: path.c:43
Definition: parser.c:49
Definition: name.c:39
Definition: parser.c:56
const WCHAR * name
Definition: parser.c:57
WCHAR * value
Definition: profile.c:63
struct tagPROFILEKEY * next
Definition: profile.c:64
WCHAR name[1]
Definition: profile.c:65
WCHAR name[1]
Definition: profile.c:72
struct tagPROFILESECTION * next
Definition: profile.c:71
struct tagPROFILEKEY * key
Definition: profile.c:70
#define DWORD_PTR
Definition: treelist.c:76
unsigned char * LPBYTE
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
int32_t INT
Definition: typedefs.h:58
Definition: pdh_main.c:94
int ret
#define ZeroMemory
Definition: winbase.h:1670
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
#define INVALID_FILE_SIZE
Definition: winbase.h:548
#define WINAPI
Definition: msvc.h:6
#define IS_TEXT_UNICODE_ODD_LENGTH
Definition: winnt_old.h:929
#define IS_TEXT_UNICODE_REVERSE_SIGNATURE
Definition: winnt_old.h:927
#define IS_TEXT_UNICODE_SIGNATURE
Definition: winnt_old.h:926
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3197
static char * encoding
Definition: xmllint.c:155
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193