Fix subclassing to support nested messages.
[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 "winreg.h"
39 #include "winternl.h"
40 #include "wine/winbase16.h"
41 #include "wine/server.h"
42 #include "kernel_private.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(file);
47
48
49 /***********************************************************************
50  *           GetProfileInt   (KERNEL.57)
51  */
52 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
53 {
54     return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
55 }
56
57
58 /***********************************************************************
59  *           GetProfileString   (KERNEL.58)
60  */
61 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
62                                  LPSTR buffer, UINT16 len )
63 {
64     return GetPrivateProfileString16( section, entry, def_val,
65                                       buffer, len, "win.ini" );
66 }
67
68
69 /***********************************************************************
70  *           WriteProfileString   (KERNEL.59)
71  */
72 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
73                                     LPCSTR string )
74 {
75     return WritePrivateProfileString16( section, entry, string, "win.ini" );
76 }
77
78
79 /***********************************************************************
80  *           _lclose   (KERNEL.81)
81  */
82 HFILE16 WINAPI _lclose16( HFILE16 hFile )
83 {
84     if ((hFile >= DOS_TABLE_SIZE) || !dos_handles[hFile])
85     {
86         SetLastError( ERROR_INVALID_HANDLE );
87         return HFILE_ERROR16;
88     }
89     TRACE("%d (handle32=%p)\n", hFile, dos_handles[hFile] );
90     CloseHandle( dos_handles[hFile] );
91     dos_handles[hFile] = 0;
92     return 0;
93 }
94
95 /***********************************************************************
96  *           _lcreat   (KERNEL.83)
97  */
98 HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
99 {
100     return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) );
101 }
102
103 /***********************************************************************
104  *           _llseek   (KERNEL.84)
105  *
106  * FIXME:
107  *   Seeking before the start of the file should be allowed for _llseek16,
108  *   but cause subsequent I/O operations to fail (cf. interrupt list)
109  *
110  */
111 LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
112 {
113     return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin );
114 }
115
116
117 /***********************************************************************
118  *           _lopen   (KERNEL.85)
119  */
120 HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
121 {
122     return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) );
123 }
124
125
126 /***********************************************************************
127  *           _lread16   (KERNEL.82)
128  */
129 UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
130 {
131     return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
132 }
133
134
135 /***********************************************************************
136  *           _lwrite   (KERNEL.86)
137  */
138 UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
139 {
140     return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
141 }
142
143 /***********************************************************************
144  *           _hread (KERNEL.349)
145  */
146 LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
147 {
148     LONG maxlen;
149
150     TRACE("%d %08lx %ld\n", hFile, (DWORD)buffer, count );
151
152     /* Some programs pass a count larger than the allocated buffer */
153     maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
154     if (count > maxlen) count = maxlen;
155     return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
156 }
157
158
159 /***********************************************************************
160  *           _lread (KERNEL.82)
161  */
162 UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
163 {
164     return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
165 }
166
167
168 /***********************************************************************
169  *           GetTempFileName   (KERNEL.97)
170  */
171 UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
172                                  LPSTR buffer )
173 {
174     char temppath[MAX_PATH];
175     char *prefix16 = NULL;
176     UINT16 ret;
177
178     if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
179     {
180         GetCurrentDirectoryA(sizeof(temppath), temppath); 
181         drive |= temppath[0];
182     }
183
184     if (drive & TF_FORCEDRIVE)
185     {
186         char    d[3];
187
188         d[0] = drive & ~TF_FORCEDRIVE;
189         d[1] = ':';
190         d[2] = '\0';
191         if (GetDriveTypeA(d) == DRIVE_NO_ROOT_DIR)
192         {
193             drive &= ~TF_FORCEDRIVE;
194             WARN("invalid drive %d specified\n", drive );
195         }
196     }
197
198     if (drive & TF_FORCEDRIVE)
199         sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
200     else
201         GetTempPathA( MAX_PATH, temppath );
202
203     if (prefix)
204     {
205         prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2);
206         *prefix16 = '~';
207         strcpy(prefix16 + 1, prefix);
208     }
209
210     ret = GetTempFileNameA( temppath, prefix16, unique, buffer );
211
212     if (prefix16) HeapFree(GetProcessHeap(), 0, prefix16);
213     return ret;
214 }
215
216
217 /***********************************************************************
218  *           GetPrivateProfileInt   (KERNEL.127)
219  */
220 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
221                                       INT16 def_val, LPCSTR filename )
222 {
223     /* we used to have some elaborate return value limitation (<= -32768 etc.)
224      * here, but Win98SE doesn't care about this at all, so I deleted it.
225      * AFAIR versions prior to Win9x had these limits, though. */
226     return (INT16)GetPrivateProfileIntA(section,entry,def_val,filename);
227 }
228
229
230 /***********************************************************************
231  *           WritePrivateProfileString   (KERNEL.129)
232  */
233 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
234                                            LPCSTR string, LPCSTR filename )
235 {
236     return WritePrivateProfileStringA(section,entry,string,filename);
237 }
238
239
240 /***********************************************************************
241  *           GetWindowsDirectory   (KERNEL.134)
242  */
243 UINT16 WINAPI GetWindowsDirectory16( LPSTR path, UINT16 count )
244 {
245     return GetWindowsDirectoryA( path, count );
246 }
247
248
249 /***********************************************************************
250  *           GetSystemDirectory   (KERNEL.135)
251  */
252 UINT16 WINAPI GetSystemDirectory16( LPSTR path, UINT16 count )
253 {
254     return GetSystemDirectoryA( path, count );
255 }
256
257
258 /***********************************************************************
259  *           GetDriveType   (KERNEL.136)
260  * This function returns the type of a drive in Win16.
261  * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
262  * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
263  * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
264  * do any pseudo-clever changes.
265  */
266 UINT16 WINAPI GetDriveType16( UINT16 drive ) /* [in] number (NOT letter) of drive */
267 {
268     UINT type;
269     WCHAR root[3];
270
271     root[0] = 'A' + drive;
272     root[1] = ':';
273     root[2] = 0;
274     type = GetDriveTypeW( root );
275     if (type == DRIVE_CDROM) type = DRIVE_REMOTE;
276     return type;
277 }
278
279
280 /***********************************************************************
281  *           GetProfileSectionNames   (KERNEL.142)
282  */
283 WORD WINAPI GetProfileSectionNames16(LPSTR buffer, WORD size)
284
285 {
286     return GetPrivateProfileSectionNamesA(buffer,size,"win.ini");
287 }
288
289
290 /***********************************************************************
291  *           GetPrivateProfileSectionNames   (KERNEL.143)
292  */
293 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
294                                              LPCSTR filename )
295 {
296     return GetPrivateProfileSectionNamesA(buffer,size,filename);
297 }
298
299
300 /***********************************************************************
301  *           CreateDirectory   (KERNEL.144)
302  */
303 BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
304 {
305     return CreateDirectoryA( path, NULL );
306 }
307
308
309 /***********************************************************************
310  *           RemoveDirectory   (KERNEL.145)
311  */
312 BOOL16 WINAPI RemoveDirectory16( LPCSTR path )
313 {
314     return RemoveDirectoryA( path );
315 }
316
317
318 /***********************************************************************
319  *           DeleteFile   (KERNEL.146)
320  */
321 BOOL16 WINAPI DeleteFile16( LPCSTR path )
322 {
323     return DeleteFileA( path );
324 }
325
326
327 /***********************************************************************
328  *           SetHandleCount   (KERNEL.199)
329  */
330 UINT16 WINAPI SetHandleCount16( UINT16 count )
331 {
332     return SetHandleCount( count );
333 }
334
335
336 /***********************************************************************
337  *           _hread16   (KERNEL.349)
338  */
339 LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
340 {
341     return _lread( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
342 }
343
344
345 /***********************************************************************
346  *           _hwrite   (KERNEL.350)
347  */
348 LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
349 {
350     return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
351 }
352
353
354 /***********************************************************************
355  *           WritePrivateProfileStruct (KERNEL.406)
356  */
357 BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
358                                            LPVOID buf, UINT16 bufsize, LPCSTR filename)
359 {
360     return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
361 }
362
363
364 /***********************************************************************
365  *           GetPrivateProfileStruct (KERNEL.407)
366  */
367 BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
368                                         LPVOID buf, UINT16 len, LPCSTR filename)
369 {
370     return GetPrivateProfileStructA( section, key, buf, len, filename );
371 }
372
373
374 /***********************************************************************
375  *           SetCurrentDirectory   (KERNEL.412)
376  */
377 BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
378 {
379     return SetCurrentDirectoryA( dir );
380 }
381
382
383 /*************************************************************************
384  *           FindFirstFile   (KERNEL.413)
385  */
386 HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data )
387 {
388     HGLOBAL16 h16;
389     HANDLE handle, *ptr;
390
391     if (!(h16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(handle) ))) return INVALID_HANDLE_VALUE16;
392     ptr = GlobalLock16( h16 );
393     *ptr = handle = FindFirstFileA( path, data );
394     GlobalUnlock16( h16 );
395
396     if (handle == INVALID_HANDLE_VALUE)
397     {
398         GlobalFree16( h16 );
399         h16 = INVALID_HANDLE_VALUE16;
400     }
401     return h16;
402 }
403
404
405 /*************************************************************************
406  *           FindNextFile   (KERNEL.414)
407  */
408 BOOL16 WINAPI FindNextFile16( HANDLE16 handle, WIN32_FIND_DATAA *data )
409 {
410     HANDLE *ptr;
411     BOOL ret = FALSE;
412
413     if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
414     {
415         SetLastError( ERROR_INVALID_HANDLE );
416         return ret;
417     }
418     ret = FindNextFileA( *ptr, data );
419     GlobalUnlock16( handle );
420     return ret;
421 }
422
423
424 /*************************************************************************
425  *           FindClose   (KERNEL.415)
426  */
427 BOOL16 WINAPI FindClose16( HANDLE16 handle )
428 {
429     HANDLE *ptr;
430
431     if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
432     {
433         SetLastError( ERROR_INVALID_HANDLE );
434         return FALSE;
435     }
436     FindClose( *ptr );
437     GlobalUnlock16( handle );
438     GlobalFree16( handle );
439     return TRUE;
440 }
441
442
443 /***********************************************************************
444  *           WritePrivateProfileSection   (KERNEL.416)
445  */
446 BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
447                                             LPCSTR string, LPCSTR filename )
448 {
449     return WritePrivateProfileSectionA( section, string, filename );
450 }
451
452
453 /***********************************************************************
454  *           WriteProfileSection   (KERNEL.417)
455  */
456 BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
457 {
458     return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
459 }
460
461
462 /***********************************************************************
463  *           GetPrivateProfileSection   (KERNEL.418)
464  */
465 INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
466                                          UINT16 len, LPCSTR filename )
467 {
468     return GetPrivateProfileSectionA( section, buffer, len, filename );
469 }
470
471
472 /***********************************************************************
473  *           GetProfileSection   (KERNEL.419)
474  */
475 INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
476 {
477     return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
478 }
479
480
481 /**************************************************************************
482  *           GetFileAttributes   (KERNEL.420)
483  */
484 DWORD WINAPI GetFileAttributes16( LPCSTR name )
485 {
486     return GetFileAttributesA( name );
487 }
488
489
490 /**************************************************************************
491  *              SetFileAttributes       (KERNEL.421)
492  */
493 BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes )
494 {
495     return SetFileAttributesA( lpFileName, attributes );
496 }
497
498
499 /***********************************************************************
500  *           GetDiskFreeSpace   (KERNEL.422)
501  */
502 BOOL16 WINAPI GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors,
503                                   LPDWORD sector_bytes, LPDWORD free_clusters,
504                                   LPDWORD total_clusters )
505 {
506     return GetDiskFreeSpaceA( root, cluster_sectors, sector_bytes,
507                                 free_clusters, total_clusters );
508 }