2 * File handling functions
4 * Copyright 1993 John Burton
5 * Copyright 1996 Alexandre Julliard
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.
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.
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
22 * Fix the CopyFileEx methods to implement the "extended" functionality.
23 * Right now, they simply call the CopyFile method.
27 #include "wine/port.h"
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
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"
46 WINE_DEFAULT_DEBUG_CHANNEL(file
);
49 /***********************************************************************
50 * GetProfileInt (KERNEL.57)
52 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
54 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
58 /***********************************************************************
59 * GetProfileString (KERNEL.58)
61 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
62 LPSTR buffer
, UINT16 len
)
64 return GetPrivateProfileString16( section
, entry
, def_val
,
65 buffer
, len
, "win.ini" );
69 /***********************************************************************
70 * WriteProfileString (KERNEL.59)
72 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
75 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
79 /* get the search path for the current module; helper for OpenFile16 */
80 static char *get_search_path(void)
83 char *ret
, *p
, module
[OFS_MAXPATHNAME
];
86 if (GetCurrentTask() && GetModuleFileName16( GetCurrentTask(), module
, sizeof(module
) ))
88 if (!(p
= strrchr( module
, '\\' ))) p
= module
;
92 len
= (2 + /* search order: first current dir */
93 GetSystemDirectoryA( NULL
, 0 ) + 1 + /* then system dir */
94 GetWindowsDirectoryA( NULL
, 0 ) + 1 + /* then windows dir */
95 strlen( module
) + 1 + /* then module path */
96 GetEnvironmentVariableA( "PATH", NULL
, 0 ) + 1); /* then look in PATH */
97 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, len
))) return NULL
;
100 GetSystemDirectoryA( p
, ret
+ len
- p
);
103 GetWindowsDirectoryA( p
, ret
+ len
- p
);
112 GetEnvironmentVariableA( "PATH", p
, ret
+ len
- p
);
116 /***********************************************************************
117 * OpenFile (KERNEL.74)
118 * OpenFileEx (KERNEL.360)
120 HFILE16 WINAPI
OpenFile16( LPCSTR name
, OFSTRUCT
*ofs
, UINT16 mode
)
125 WORD filedatetime
[2];
128 if (!ofs
) return HFILE_ERROR
;
130 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",debugstr_a(name
),
131 ((mode
& 0x3 )==OF_READ
)?"OF_READ":
132 ((mode
& 0x3 )==OF_WRITE
)?"OF_WRITE":
133 ((mode
& 0x3 )==OF_READWRITE
)?"OF_READWRITE":"unknown",
134 ((mode
& 0x70 )==OF_SHARE_COMPAT
)?"OF_SHARE_COMPAT":
135 ((mode
& 0x70 )==OF_SHARE_DENY_NONE
)?"OF_SHARE_DENY_NONE":
136 ((mode
& 0x70 )==OF_SHARE_DENY_READ
)?"OF_SHARE_DENY_READ":
137 ((mode
& 0x70 )==OF_SHARE_DENY_WRITE
)?"OF_SHARE_DENY_WRITE":
138 ((mode
& 0x70 )==OF_SHARE_EXCLUSIVE
)?"OF_SHARE_EXCLUSIVE":"unknown",
139 ((mode
& OF_PARSE
)==OF_PARSE
)?"OF_PARSE ":"",
140 ((mode
& OF_DELETE
)==OF_DELETE
)?"OF_DELETE ":"",
141 ((mode
& OF_VERIFY
)==OF_VERIFY
)?"OF_VERIFY ":"",
142 ((mode
& OF_SEARCH
)==OF_SEARCH
)?"OF_SEARCH ":"",
143 ((mode
& OF_CANCEL
)==OF_CANCEL
)?"OF_CANCEL ":"",
144 ((mode
& OF_CREATE
)==OF_CREATE
)?"OF_CREATE ":"",
145 ((mode
& OF_PROMPT
)==OF_PROMPT
)?"OF_PROMPT ":"",
146 ((mode
& OF_EXIST
)==OF_EXIST
)?"OF_EXIST ":"",
147 ((mode
& OF_REOPEN
)==OF_REOPEN
)?"OF_REOPEN ":""
150 ofs
->cBytes
= sizeof(OFSTRUCT
);
152 if (mode
& OF_REOPEN
) name
= ofs
->szPathName
;
154 if (!name
) return HFILE_ERROR
;
156 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
157 Are there any cases where getting the path here is wrong?
158 Uwe Bonnes 1997 Apr 2 */
159 if (!GetFullPathNameA( name
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
)) goto error
;
161 /* OF_PARSE simply fills the structure */
165 ofs
->fFixedDisk
= (GetDriveType16( ofs
->szPathName
[0]-'A' ) != DRIVE_REMOVABLE
);
166 TRACE("(%s): OF_PARSE, res = '%s'\n", name
, ofs
->szPathName
);
170 /* OF_CREATE is completely different from all other options, so
173 if (mode
& OF_CREATE
)
175 DWORD access
, sharing
;
176 FILE_ConvertOFMode( mode
, &access
, &sharing
);
177 if ((handle
= CreateFileA( ofs
->szPathName
, GENERIC_READ
| GENERIC_WRITE
,
178 sharing
, NULL
, CREATE_ALWAYS
,
179 FILE_ATTRIBUTE_NORMAL
, 0 ))== INVALID_HANDLE_VALUE
)
184 /* If OF_SEARCH is set, ignore the given path */
186 filename
= ofs
->szPathName
;
187 if ((mode
& OF_SEARCH
) && !(mode
& OF_REOPEN
))
189 /* First try the file name as is */
190 if (GetFileAttributesA( filename
) != INVALID_FILE_ATTRIBUTES
) filename
= NULL
;
193 /* Now remove the path */
194 if (filename
[0] && (filename
[1] == ':')) filename
+= 2;
195 if ((p
= strrchr( filename
, '\\' ))) filename
= p
+ 1;
196 if ((p
= strrchr( filename
, '/' ))) filename
= p
+ 1;
199 SetLastError( ERROR_FILE_NOT_FOUND
);
205 /* Now look for the file */
210 char *path
= get_search_path();
212 if (!path
) goto error
;
213 found
= SearchPathA( path
, filename
, NULL
, sizeof(ofs
->szPathName
),
214 ofs
->szPathName
, NULL
);
215 HeapFree( GetProcessHeap(), 0, path
);
216 if (!found
) goto error
;
219 TRACE("found %s\n", debugstr_a(ofs
->szPathName
) );
221 if (mode
& OF_DELETE
)
223 if (!DeleteFileA( ofs
->szPathName
)) goto error
;
224 TRACE("(%s): OF_DELETE return = OK\n", name
);
228 handle
= (HANDLE
)_lopen( ofs
->szPathName
, mode
);
229 if (handle
== INVALID_HANDLE_VALUE
) goto error
;
231 GetFileTime( handle
, NULL
, NULL
, &filetime
);
232 FileTimeToDosDateTime( &filetime
, &filedatetime
[0], &filedatetime
[1] );
233 if ((mode
& OF_VERIFY
) && (mode
& OF_REOPEN
))
235 if (ofs
->Reserved1
!= filedatetime
[0] || ofs
->Reserved2
!= filedatetime
[1] )
237 CloseHandle( handle
);
238 WARN("(%s): OF_VERIFY failed\n", name
);
239 /* FIXME: what error here? */
240 SetLastError( ERROR_FILE_NOT_FOUND
);
244 ofs
->Reserved1
= filedatetime
[0];
245 ofs
->Reserved2
= filedatetime
[1];
248 TRACE("(%s): OK, return = %p\n", name
, handle
);
249 hFileRet
= Win32HandleToDosFileHandle( handle
);
250 if (hFileRet
== HFILE_ERROR16
) goto error
;
251 if (mode
& OF_EXIST
) _lclose16( hFileRet
); /* Return the handle, but close it first */
254 error
: /* We get here if there was an error opening the file */
255 ofs
->nErrCode
= GetLastError();
256 WARN("(%s): return = HFILE_ERROR error= %d\n", name
,ofs
->nErrCode
);
257 return HFILE_ERROR16
;
261 /***********************************************************************
262 * _lclose (KERNEL.81)
264 HFILE16 WINAPI
_lclose16( HFILE16 hFile
)
266 if ((hFile
>= DOS_TABLE_SIZE
) || !dos_handles
[hFile
])
268 SetLastError( ERROR_INVALID_HANDLE
);
269 return HFILE_ERROR16
;
271 TRACE("%d (handle32=%p)\n", hFile
, dos_handles
[hFile
] );
272 CloseHandle( dos_handles
[hFile
] );
273 dos_handles
[hFile
] = 0;
277 /***********************************************************************
278 * _lcreat (KERNEL.83)
280 HFILE16 WINAPI
_lcreat16( LPCSTR path
, INT16 attr
)
282 return Win32HandleToDosFileHandle( (HANDLE
)_lcreat( path
, attr
) );
285 /***********************************************************************
286 * _llseek (KERNEL.84)
289 * Seeking before the start of the file should be allowed for _llseek16,
290 * but cause subsequent I/O operations to fail (cf. interrupt list)
293 LONG WINAPI
_llseek16( HFILE16 hFile
, LONG lOffset
, INT16 nOrigin
)
295 return SetFilePointer( DosFileHandleToWin32Handle(hFile
), lOffset
, NULL
, nOrigin
);
299 /***********************************************************************
302 HFILE16 WINAPI
_lopen16( LPCSTR path
, INT16 mode
)
304 return Win32HandleToDosFileHandle( (HANDLE
)_lopen( path
, mode
) );
308 /***********************************************************************
309 * _lread16 (KERNEL.82)
311 UINT16 WINAPI
_lread16( HFILE16 hFile
, LPVOID buffer
, UINT16 count
)
313 return (UINT16
)_lread((HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
317 /***********************************************************************
318 * _lwrite (KERNEL.86)
320 UINT16 WINAPI
_lwrite16( HFILE16 hFile
, LPCSTR buffer
, UINT16 count
)
322 return (UINT16
)_hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
325 /***********************************************************************
326 * _hread (KERNEL.349)
328 LONG WINAPI
WIN16_hread( HFILE16 hFile
, SEGPTR buffer
, LONG count
)
332 TRACE("%d %08lx %ld\n", hFile
, (DWORD
)buffer
, count
);
334 /* Some programs pass a count larger than the allocated buffer */
335 maxlen
= GetSelectorLimit16( SELECTOROF(buffer
) ) - OFFSETOF(buffer
) + 1;
336 if (count
> maxlen
) count
= maxlen
;
337 return _lread((HFILE
)DosFileHandleToWin32Handle(hFile
), MapSL(buffer
), count
);
341 /***********************************************************************
344 UINT16 WINAPI
WIN16_lread( HFILE16 hFile
, SEGPTR buffer
, UINT16 count
)
346 return (UINT16
)WIN16_hread( hFile
, buffer
, (LONG
)count
);
350 /***********************************************************************
351 * GetTempFileName (KERNEL.97)
353 UINT16 WINAPI
GetTempFileName16( BYTE drive
, LPCSTR prefix
, UINT16 unique
,
356 char temppath
[MAX_PATH
];
357 char *prefix16
= NULL
;
360 if (!(drive
& ~TF_FORCEDRIVE
)) /* drive 0 means current default drive */
362 GetCurrentDirectoryA(sizeof(temppath
), temppath
);
363 drive
|= temppath
[0];
366 if (drive
& TF_FORCEDRIVE
)
370 d
[0] = drive
& ~TF_FORCEDRIVE
;
373 if (GetDriveTypeA(d
) == DRIVE_NO_ROOT_DIR
)
375 drive
&= ~TF_FORCEDRIVE
;
376 WARN("invalid drive %d specified\n", drive
);
380 if (drive
& TF_FORCEDRIVE
)
381 sprintf(temppath
,"%c:", drive
& ~TF_FORCEDRIVE
);
383 GetTempPathA( MAX_PATH
, temppath
);
387 prefix16
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + 2);
389 strcpy(prefix16
+ 1, prefix
);
392 ret
= GetTempFileNameA( temppath
, prefix16
, unique
, buffer
);
394 if (prefix16
) HeapFree(GetProcessHeap(), 0, prefix16
);
399 /***********************************************************************
400 * GetPrivateProfileInt (KERNEL.127)
402 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
403 INT16 def_val
, LPCSTR filename
)
405 /* we used to have some elaborate return value limitation (<= -32768 etc.)
406 * here, but Win98SE doesn't care about this at all, so I deleted it.
407 * AFAIR versions prior to Win9x had these limits, though. */
408 return (INT16
)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
412 /***********************************************************************
413 * WritePrivateProfileString (KERNEL.129)
415 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
416 LPCSTR string
, LPCSTR filename
)
418 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
422 /***********************************************************************
423 * GetWindowsDirectory (KERNEL.134)
425 UINT16 WINAPI
GetWindowsDirectory16( LPSTR path
, UINT16 count
)
427 return GetWindowsDirectoryA( path
, count
);
431 /***********************************************************************
432 * GetSystemDirectory (KERNEL.135)
434 UINT16 WINAPI
GetSystemDirectory16( LPSTR path
, UINT16 count
)
436 return GetSystemDirectoryA( path
, count
);
440 /***********************************************************************
441 * GetDriveType (KERNEL.136)
442 * This function returns the type of a drive in Win16.
443 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
444 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
445 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
446 * do any pseudo-clever changes.
448 UINT16 WINAPI
GetDriveType16( UINT16 drive
) /* [in] number (NOT letter) of drive */
453 root
[0] = 'A' + drive
;
456 type
= GetDriveTypeW( root
);
457 if (type
== DRIVE_CDROM
) type
= DRIVE_REMOTE
;
462 /***********************************************************************
463 * GetProfileSectionNames (KERNEL.142)
465 WORD WINAPI
GetProfileSectionNames16(LPSTR buffer
, WORD size
)
468 return GetPrivateProfileSectionNamesA(buffer
,size
,"win.ini");
472 /***********************************************************************
473 * GetPrivateProfileSectionNames (KERNEL.143)
475 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
478 return GetPrivateProfileSectionNamesA(buffer
,size
,filename
);
482 /***********************************************************************
483 * CreateDirectory (KERNEL.144)
485 BOOL16 WINAPI
CreateDirectory16( LPCSTR path
, LPVOID dummy
)
487 return CreateDirectoryA( path
, NULL
);
491 /***********************************************************************
492 * RemoveDirectory (KERNEL.145)
494 BOOL16 WINAPI
RemoveDirectory16( LPCSTR path
)
496 return RemoveDirectoryA( path
);
500 /***********************************************************************
501 * DeleteFile (KERNEL.146)
503 BOOL16 WINAPI
DeleteFile16( LPCSTR path
)
505 return DeleteFileA( path
);
509 /***********************************************************************
510 * SetHandleCount (KERNEL.199)
512 UINT16 WINAPI
SetHandleCount16( UINT16 count
)
514 return SetHandleCount( count
);
518 /***********************************************************************
519 * _hread16 (KERNEL.349)
521 LONG WINAPI
_hread16( HFILE16 hFile
, LPVOID buffer
, LONG count
)
523 return _lread( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
527 /***********************************************************************
528 * _hwrite (KERNEL.350)
530 LONG WINAPI
_hwrite16( HFILE16 hFile
, LPCSTR buffer
, LONG count
)
532 return _hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
536 /***********************************************************************
537 * WritePrivateProfileStruct (KERNEL.406)
539 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
540 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
542 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
546 /***********************************************************************
547 * GetPrivateProfileStruct (KERNEL.407)
549 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
550 LPVOID buf
, UINT16 len
, LPCSTR filename
)
552 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
556 /***********************************************************************
557 * SetCurrentDirectory (KERNEL.412)
559 BOOL16 WINAPI
SetCurrentDirectory16( LPCSTR dir
)
561 return SetCurrentDirectoryA( dir
);
565 /*************************************************************************
566 * FindFirstFile (KERNEL.413)
568 HANDLE16 WINAPI
FindFirstFile16( LPCSTR path
, WIN32_FIND_DATAA
*data
)
573 if (!(h16
= GlobalAlloc16( GMEM_MOVEABLE
, sizeof(handle
) ))) return INVALID_HANDLE_VALUE16
;
574 ptr
= GlobalLock16( h16
);
575 *ptr
= handle
= FindFirstFileA( path
, data
);
576 GlobalUnlock16( h16
);
578 if (handle
== INVALID_HANDLE_VALUE
)
581 h16
= INVALID_HANDLE_VALUE16
;
587 /*************************************************************************
588 * FindNextFile (KERNEL.414)
590 BOOL16 WINAPI
FindNextFile16( HANDLE16 handle
, WIN32_FIND_DATAA
*data
)
595 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
597 SetLastError( ERROR_INVALID_HANDLE
);
600 ret
= FindNextFileA( *ptr
, data
);
601 GlobalUnlock16( handle
);
606 /*************************************************************************
607 * FindClose (KERNEL.415)
609 BOOL16 WINAPI
FindClose16( HANDLE16 handle
)
613 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
615 SetLastError( ERROR_INVALID_HANDLE
);
619 GlobalUnlock16( handle
);
620 GlobalFree16( handle
);
625 /***********************************************************************
626 * WritePrivateProfileSection (KERNEL.416)
628 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
629 LPCSTR string
, LPCSTR filename
)
631 return WritePrivateProfileSectionA( section
, string
, filename
);
635 /***********************************************************************
636 * WriteProfileSection (KERNEL.417)
638 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
640 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
644 /***********************************************************************
645 * GetPrivateProfileSection (KERNEL.418)
647 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
648 UINT16 len
, LPCSTR filename
)
650 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
654 /***********************************************************************
655 * GetProfileSection (KERNEL.419)
657 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
659 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
663 /**************************************************************************
664 * GetFileAttributes (KERNEL.420)
666 DWORD WINAPI
GetFileAttributes16( LPCSTR name
)
668 return GetFileAttributesA( name
);
672 /**************************************************************************
673 * SetFileAttributes (KERNEL.421)
675 BOOL16 WINAPI
SetFileAttributes16( LPCSTR lpFileName
, DWORD attributes
)
677 return SetFileAttributesA( lpFileName
, attributes
);
681 /***********************************************************************
682 * GetDiskFreeSpace (KERNEL.422)
684 BOOL16 WINAPI
GetDiskFreeSpace16( LPCSTR root
, LPDWORD cluster_sectors
,
685 LPDWORD sector_bytes
, LPDWORD free_clusters
,
686 LPDWORD total_clusters
)
688 return GetDiskFreeSpaceA( root
, cluster_sectors
, sector_bytes
,
689 free_clusters
, total_clusters
);