A NULL module handle means 'main exe' in GetProcAddress too.
[wine] / dlls / kernel / file16.c
1 /*
2  * File handling functions
3  *
4  * Copyright 1993 John Burton
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * TODO:
22  *    Fix the CopyFileEx methods to implement the "extended" functionality.
23  *    Right now, they simply call the CopyFile method.
24  */
25
26 #include "config.h"
27 #include "wine/port.h"
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <assert.h>
32
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
35 #include "winerror.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winternl.h"
39 #include "wine/winbase16.h"
40 #include "wine/server.h"
41 #include "kernel_private.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(file);
46
47
48 /***********************************************************************
49  *           GetProfileInt   (KERNEL.57)
50  */
51 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
52 {
53     return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
54 }
55
56
57 /***********************************************************************
58  *           GetProfileString   (KERNEL.58)
59  */
60 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
61                                  LPSTR buffer, UINT16 len )
62 {
63     return GetPrivateProfileString16( section, entry, def_val,
64                                       buffer, len, "win.ini" );
65 }
66
67
68 /***********************************************************************
69  *           WriteProfileString   (KERNEL.59)
70  */
71 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
72                                     LPCSTR string )
73 {
74     return WritePrivateProfileString16( section, entry, string, "win.ini" );
75 }
76
77
78 /* get the search path for the current module; helper for OpenFile16 */
79 static char *get_search_path(void)
80 {
81     UINT len;
82     char *ret, *p, module[OFS_MAXPATHNAME];
83
84     module[0] = 0;
85     if (GetCurrentTask() && GetModuleFileName16( GetCurrentTask(), module, sizeof(module) ))
86     {
87         if (!(p = strrchr( module, '\\' ))) p = module;
88         *p = 0;
89     }
90
91     len = (2 +                                              /* search order: first current dir */
92            GetSystemDirectoryA( NULL, 0 ) + 1 +             /* then system dir */
93            GetWindowsDirectoryA( NULL, 0 ) + 1 +            /* then windows dir */
94            strlen( module ) + 1 +                           /* then module path */
95            GetEnvironmentVariableA( "PATH", NULL, 0 ) + 1); /* then look in PATH */
96     if (!(ret = HeapAlloc( GetProcessHeap(), 0, len ))) return NULL;
97     strcpy( ret, ".;" );
98     p = ret + 2;
99     GetSystemDirectoryA( p, ret + len - p );
100     p += strlen( p );
101     *p++ = ';';
102     GetWindowsDirectoryA( p, ret + len - p );
103     p += strlen( p );
104     *p++ = ';';
105     if (module[0])
106     {
107         strcpy( p, module );
108         p += strlen( p );
109         *p++ = ';';
110     }
111     GetEnvironmentVariableA( "PATH", p, ret + len - p );
112     return ret;
113 }
114
115 /***********************************************************************
116  *           OpenFile   (KERNEL.74)
117  *           OpenFileEx (KERNEL.360)
118  */
119 HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
120 {
121     HFILE hFileRet;
122     HANDLE handle;
123     FILETIME filetime;
124     WORD filedatetime[2];
125     const char *p, *filename;
126
127     if (!ofs) return HFILE_ERROR;
128
129     TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",debugstr_a(name),
130           ((mode & 0x3 )==OF_READ)?"OF_READ":
131           ((mode & 0x3 )==OF_WRITE)?"OF_WRITE":
132           ((mode & 0x3 )==OF_READWRITE)?"OF_READWRITE":"unknown",
133           ((mode & 0x70 )==OF_SHARE_COMPAT)?"OF_SHARE_COMPAT":
134           ((mode & 0x70 )==OF_SHARE_DENY_NONE)?"OF_SHARE_DENY_NONE":
135           ((mode & 0x70 )==OF_SHARE_DENY_READ)?"OF_SHARE_DENY_READ":
136           ((mode & 0x70 )==OF_SHARE_DENY_WRITE)?"OF_SHARE_DENY_WRITE":
137           ((mode & 0x70 )==OF_SHARE_EXCLUSIVE)?"OF_SHARE_EXCLUSIVE":"unknown",
138           ((mode & OF_PARSE )==OF_PARSE)?"OF_PARSE ":"",
139           ((mode & OF_DELETE )==OF_DELETE)?"OF_DELETE ":"",
140           ((mode & OF_VERIFY )==OF_VERIFY)?"OF_VERIFY ":"",
141           ((mode & OF_SEARCH )==OF_SEARCH)?"OF_SEARCH ":"",
142           ((mode & OF_CANCEL )==OF_CANCEL)?"OF_CANCEL ":"",
143           ((mode & OF_CREATE )==OF_CREATE)?"OF_CREATE ":"",
144           ((mode & OF_PROMPT )==OF_PROMPT)?"OF_PROMPT ":"",
145           ((mode & OF_EXIST )==OF_EXIST)?"OF_EXIST ":"",
146           ((mode & OF_REOPEN )==OF_REOPEN)?"OF_REOPEN ":""
147         );
148
149     if (mode & OF_PARSE)
150     {
151         OpenFile( name, ofs, mode );
152         return 0;
153     }
154
155     if (mode & OF_CREATE)
156     {
157         handle = (HANDLE)OpenFile( name, ofs, mode );
158         if (handle == (HANDLE)HFILE_ERROR) goto error;
159     }
160     else
161     {
162         ofs->cBytes = sizeof(OFSTRUCT);
163         ofs->nErrCode = 0;
164         if (mode & OF_REOPEN) name = ofs->szPathName;
165
166         if (!name) return HFILE_ERROR;
167
168         /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
169            Are there any cases where getting the path here is wrong?
170            Uwe Bonnes 1997 Apr 2 */
171         if (!GetFullPathNameA( name, sizeof(ofs->szPathName), ofs->szPathName, NULL )) goto error;
172
173         /* If OF_SEARCH is set, ignore the given path */
174
175         filename = name;
176         if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
177         {
178             /* First try the file name as is */
179             if (GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES) filename = NULL;
180             else
181             {
182                 /* Now remove the path */
183                 if (filename[0] && (filename[1] == ':')) filename += 2;
184                 if ((p = strrchr( filename, '\\' ))) filename = p + 1;
185                 if ((p = strrchr( filename, '/' ))) filename = p + 1;
186                 if (!filename[0])
187                 {
188                     SetLastError( ERROR_FILE_NOT_FOUND );
189                     goto error;
190                 }
191             }
192         }
193
194         /* Now look for the file */
195
196         if (filename)
197         {
198             BOOL found;
199             char *path = get_search_path();
200
201             if (!path) goto error;
202             found = SearchPathA( path, filename, NULL, sizeof(ofs->szPathName),
203                                  ofs->szPathName, NULL );
204             HeapFree( GetProcessHeap(), 0, path );
205             if (!found) goto error;
206         }
207
208         TRACE("found %s\n", debugstr_a(ofs->szPathName) );
209
210         if (mode & OF_DELETE)
211         {
212             if (!DeleteFileA( ofs->szPathName )) goto error;
213             TRACE("(%s): OF_DELETE return = OK\n", name);
214             return 1;
215         }
216
217         handle = (HANDLE)_lopen( ofs->szPathName, mode );
218         if (handle == INVALID_HANDLE_VALUE) goto error;
219
220         GetFileTime( handle, NULL, NULL, &filetime );
221         FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
222         if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
223         {
224             if (ofs->Reserved1 != filedatetime[0] || ofs->Reserved2 != filedatetime[1] )
225             {
226                 CloseHandle( handle );
227                 WARN("(%s): OF_VERIFY failed\n", name );
228                 /* FIXME: what error here? */
229                 SetLastError( ERROR_FILE_NOT_FOUND );
230                 goto error;
231             }
232         }
233         ofs->Reserved1 = filedatetime[0];
234         ofs->Reserved2 = filedatetime[1];
235     }
236
237     TRACE("(%s): OK, return = %p\n", name, handle );
238     hFileRet = Win32HandleToDosFileHandle( handle );
239     if (hFileRet == HFILE_ERROR16) goto error;
240     if (mode & OF_EXIST) _lclose16( hFileRet ); /* Return the handle, but close it first */
241     return hFileRet;
242
243 error:  /* We get here if there was an error opening the file */
244     ofs->nErrCode = GetLastError();
245     WARN("(%s): return = HFILE_ERROR error= %d\n", name,ofs->nErrCode );
246     return HFILE_ERROR16;
247 }
248
249
250 /***********************************************************************
251  *           _lclose   (KERNEL.81)
252  */
253 HFILE16 WINAPI _lclose16( HFILE16 hFile )
254 {
255     if ((hFile >= DOS_TABLE_SIZE) || !dos_handles[hFile])
256     {
257         SetLastError( ERROR_INVALID_HANDLE );
258         return HFILE_ERROR16;
259     }
260     TRACE("%d (handle32=%p)\n", hFile, dos_handles[hFile] );
261     CloseHandle( dos_handles[hFile] );
262     dos_handles[hFile] = 0;
263     return 0;
264 }
265
266 /***********************************************************************
267  *           _lcreat   (KERNEL.83)
268  */
269 HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
270 {
271     return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) );
272 }
273
274 /***********************************************************************
275  *           _llseek   (KERNEL.84)
276  *
277  * FIXME:
278  *   Seeking before the start of the file should be allowed for _llseek16,
279  *   but cause subsequent I/O operations to fail (cf. interrupt list)
280  *
281  */
282 LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
283 {
284     return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin );
285 }
286
287
288 /***********************************************************************
289  *           _lopen   (KERNEL.85)
290  */
291 HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
292 {
293     return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) );
294 }
295
296
297 /***********************************************************************
298  *           _lread16   (KERNEL.82)
299  */
300 UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
301 {
302     return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
303 }
304
305
306 /***********************************************************************
307  *           _lwrite   (KERNEL.86)
308  */
309 UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
310 {
311     return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
312 }
313
314 /***********************************************************************
315  *           _hread (KERNEL.349)
316  */
317 LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
318 {
319     LONG maxlen;
320
321     TRACE("%d %08lx %ld\n", hFile, (DWORD)buffer, count );
322
323     /* Some programs pass a count larger than the allocated buffer */
324     maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
325     if (count > maxlen) count = maxlen;
326     return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
327 }
328
329
330 /***********************************************************************
331  *           _lread (KERNEL.82)
332  */
333 UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
334 {
335     return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
336 }
337
338
339 /***********************************************************************
340  *           GetTempDrive   (KERNEL.92)
341  * A closer look at krnl386.exe shows what the SDK doesn't mention:
342  *
343  * returns:
344  *   AL: driveletter
345  *   AH: ':'            - yes, some kernel code even does stosw with
346  *                            the returned AX.
347  *   DX: 1 for success
348  */
349 UINT WINAPI GetTempDrive( BYTE ignored )
350 {
351     WCHAR buffer[8];
352     BYTE ret;
353
354     if (GetTempPathW( 8, buffer )) ret = (BYTE)toupperW(buffer[0]);
355     else ret = 'C';
356     return MAKELONG( ret | (':' << 8), 1 );
357 }
358
359
360 /***********************************************************************
361  *           GetTempFileName   (KERNEL.97)
362  */
363 UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
364                                  LPSTR buffer )
365 {
366     char temppath[MAX_PATH];
367     char *prefix16 = NULL;
368     UINT16 ret;
369
370     if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
371     {
372         GetCurrentDirectoryA(sizeof(temppath), temppath); 
373         drive |= temppath[0];
374     }
375
376     if (drive & TF_FORCEDRIVE)
377     {
378         char    d[3];
379
380         d[0] = drive & ~TF_FORCEDRIVE;
381         d[1] = ':';
382         d[2] = '\0';
383         if (GetDriveTypeA(d) == DRIVE_NO_ROOT_DIR)
384         {
385             drive &= ~TF_FORCEDRIVE;
386             WARN("invalid drive %d specified\n", drive );
387         }
388     }
389
390     if (drive & TF_FORCEDRIVE)
391         sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
392     else
393         GetTempPathA( MAX_PATH, temppath );
394
395     if (prefix)
396     {
397         prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2);
398         *prefix16 = '~';
399         strcpy(prefix16 + 1, prefix);
400     }
401
402     ret = GetTempFileNameA( temppath, prefix16, unique, buffer );
403
404     HeapFree(GetProcessHeap(), 0, prefix16);
405     return ret;
406 }
407
408
409 /***********************************************************************
410  *           GetPrivateProfileInt   (KERNEL.127)
411  */
412 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
413                                       INT16 def_val, LPCSTR filename )
414 {
415     /* we used to have some elaborate return value limitation (<= -32768 etc.)
416      * here, but Win98SE doesn't care about this at all, so I deleted it.
417      * AFAIR versions prior to Win9x had these limits, though. */
418     return (INT16)GetPrivateProfileIntA(section,entry,def_val,filename);
419 }
420
421
422 /***********************************************************************
423  *           WritePrivateProfileString   (KERNEL.129)
424  */
425 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
426                                            LPCSTR string, LPCSTR filename )
427 {
428     return WritePrivateProfileStringA(section,entry,string,filename);
429 }
430
431
432 /***********************************************************************
433  *           GetWindowsDirectory   (KERNEL.134)
434  */
435 UINT16 WINAPI GetWindowsDirectory16( LPSTR path, UINT16 count )
436 {
437     return GetWindowsDirectoryA( path, count );
438 }
439
440
441 /***********************************************************************
442  *           GetSystemDirectory   (KERNEL.135)
443  */
444 UINT16 WINAPI GetSystemDirectory16( LPSTR path, UINT16 count )
445 {
446     return GetSystemDirectoryA( path, count );
447 }
448
449
450 /***********************************************************************
451  *           GetDriveType   (KERNEL.136)
452  * This function returns the type of a drive in Win16.
453  * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
454  * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
455  * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
456  * do any pseudo-clever changes.
457  */
458 UINT16 WINAPI GetDriveType16( UINT16 drive ) /* [in] number (NOT letter) of drive */
459 {
460     UINT type;
461     WCHAR root[3];
462
463     root[0] = 'A' + drive;
464     root[1] = ':';
465     root[2] = 0;
466     type = GetDriveTypeW( root );
467     if (type == DRIVE_CDROM) type = DRIVE_REMOTE;
468     else if (type == DRIVE_NO_ROOT_DIR) type = DRIVE_UNKNOWN;
469     return type;
470 }
471
472
473 /***********************************************************************
474  *           GetProfileSectionNames   (KERNEL.142)
475  */
476 WORD WINAPI GetProfileSectionNames16(LPSTR buffer, WORD size)
477
478 {
479     return GetPrivateProfileSectionNamesA(buffer,size,"win.ini");
480 }
481
482
483 /***********************************************************************
484  *           GetPrivateProfileSectionNames   (KERNEL.143)
485  */
486 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
487                                              LPCSTR filename )
488 {
489     return GetPrivateProfileSectionNamesA(buffer,size,filename);
490 }
491
492
493 /***********************************************************************
494  *           CreateDirectory   (KERNEL.144)
495  */
496 BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
497 {
498     return CreateDirectoryA( path, NULL );
499 }
500
501
502 /***********************************************************************
503  *           RemoveDirectory   (KERNEL.145)
504  */
505 BOOL16 WINAPI RemoveDirectory16( LPCSTR path )
506 {
507     return RemoveDirectoryA( path );
508 }
509
510
511 /***********************************************************************
512  *           DeleteFile   (KERNEL.146)
513  */
514 BOOL16 WINAPI DeleteFile16( LPCSTR path )
515 {
516     return DeleteFileA( path );
517 }
518
519
520 /***********************************************************************
521  *           SetHandleCount   (KERNEL.199)
522  */
523 UINT16 WINAPI SetHandleCount16( UINT16 count )
524 {
525     return SetHandleCount( count );
526 }
527
528
529 /***********************************************************************
530  *           _hread16   (KERNEL.349)
531  */
532 LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
533 {
534     return _lread( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
535 }
536
537
538 /***********************************************************************
539  *           _hwrite   (KERNEL.350)
540  */
541 LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
542 {
543     return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
544 }
545
546
547 /***********************************************************************
548  *           WritePrivateProfileStruct (KERNEL.406)
549  */
550 BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
551                                            LPVOID buf, UINT16 bufsize, LPCSTR filename)
552 {
553     return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
554 }
555
556
557 /***********************************************************************
558  *           GetPrivateProfileStruct (KERNEL.407)
559  */
560 BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
561                                         LPVOID buf, UINT16 len, LPCSTR filename)
562 {
563     return GetPrivateProfileStructA( section, key, buf, len, filename );
564 }
565
566
567 /***********************************************************************
568  *           GetCurrentDirectory   (KERNEL.411)
569  */
570 UINT16 WINAPI GetCurrentDirectory16( UINT16 buflen, LPSTR buf )
571 {
572     return GetCurrentDirectoryA( buflen, buf );
573 }
574
575
576 /***********************************************************************
577  *           SetCurrentDirectory   (KERNEL.412)
578  */
579 BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
580 {
581     char fulldir[MAX_PATH];
582
583     if (!GetFullPathNameA( dir, MAX_PATH, fulldir, NULL )) return FALSE;
584
585     if (!SetCurrentDirectoryA( dir )) return FALSE;
586
587     if (fulldir[0] && fulldir[1] == ':')
588     {
589         TDB *pTask = GlobalLock16( GetCurrentTask() );
590         char env_var[4] = "=A:";
591
592         env_var[1] = fulldir[0];
593         SetEnvironmentVariableA( env_var, fulldir );
594
595         /* update the directory in the TDB */
596         if (pTask)
597         {
598             pTask->curdrive = 0x80 | (fulldir[0] - 'A');
599             GetShortPathNameA( fulldir + 2, pTask->curdir, sizeof(pTask->curdir) );
600         }
601     }
602     return TRUE;
603 }
604
605
606 /*************************************************************************
607  *           FindFirstFile   (KERNEL.413)
608  */
609 HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data )
610 {
611     HGLOBAL16 h16;
612     HANDLE handle, *ptr;
613
614     if (!(h16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(handle) ))) return INVALID_HANDLE_VALUE16;
615     ptr = GlobalLock16( h16 );
616     *ptr = handle = FindFirstFileA( path, data );
617     GlobalUnlock16( h16 );
618
619     if (handle == INVALID_HANDLE_VALUE)
620     {
621         GlobalFree16( h16 );
622         h16 = INVALID_HANDLE_VALUE16;
623     }
624     return h16;
625 }
626
627
628 /*************************************************************************
629  *           FindNextFile   (KERNEL.414)
630  */
631 BOOL16 WINAPI FindNextFile16( HANDLE16 handle, WIN32_FIND_DATAA *data )
632 {
633     HANDLE *ptr;
634     BOOL ret = FALSE;
635
636     if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
637     {
638         SetLastError( ERROR_INVALID_HANDLE );
639         return ret;
640     }
641     ret = FindNextFileA( *ptr, data );
642     GlobalUnlock16( handle );
643     return ret;
644 }
645
646
647 /*************************************************************************
648  *           FindClose   (KERNEL.415)
649  */
650 BOOL16 WINAPI FindClose16( HANDLE16 handle )
651 {
652     HANDLE *ptr;
653
654     if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
655     {
656         SetLastError( ERROR_INVALID_HANDLE );
657         return FALSE;
658     }
659     FindClose( *ptr );
660     GlobalUnlock16( handle );
661     GlobalFree16( handle );
662     return TRUE;
663 }
664
665
666 /***********************************************************************
667  *           WritePrivateProfileSection   (KERNEL.416)
668  */
669 BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
670                                             LPCSTR string, LPCSTR filename )
671 {
672     return WritePrivateProfileSectionA( section, string, filename );
673 }
674
675
676 /***********************************************************************
677  *           WriteProfileSection   (KERNEL.417)
678  */
679 BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
680 {
681     return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
682 }
683
684
685 /***********************************************************************
686  *           GetPrivateProfileSection   (KERNEL.418)
687  */
688 INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
689                                          UINT16 len, LPCSTR filename )
690 {
691     return GetPrivateProfileSectionA( section, buffer, len, filename );
692 }
693
694
695 /***********************************************************************
696  *           GetProfileSection   (KERNEL.419)
697  */
698 INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
699 {
700     return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
701 }
702
703
704 /**************************************************************************
705  *           GetFileAttributes   (KERNEL.420)
706  */
707 DWORD WINAPI GetFileAttributes16( LPCSTR name )
708 {
709     return GetFileAttributesA( name );
710 }
711
712
713 /**************************************************************************
714  *              SetFileAttributes       (KERNEL.421)
715  */
716 BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes )
717 {
718     return SetFileAttributesA( lpFileName, attributes );
719 }
720
721
722 /***********************************************************************
723  *           GetDiskFreeSpace   (KERNEL.422)
724  */
725 BOOL16 WINAPI GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors,
726                                   LPDWORD sector_bytes, LPDWORD free_clusters,
727                                   LPDWORD total_clusters )
728 {
729     return GetDiskFreeSpaceA( root, cluster_sectors, sector_bytes,
730                                 free_clusters, total_clusters );
731 }