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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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
39 #include "wine/winbase16.h"
40 #include "kernel_private.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(file
);
47 /***********************************************************************
48 * GetProfileInt (KERNEL.57)
50 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
52 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
56 /***********************************************************************
57 * GetProfileString (KERNEL.58)
59 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
60 LPSTR buffer
, UINT16 len
)
62 return GetPrivateProfileString16( section
, entry
, def_val
,
63 buffer
, len
, "win.ini" );
67 /***********************************************************************
68 * WriteProfileString (KERNEL.59)
70 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
73 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
77 /* get the search path for the current module; helper for OpenFile16 */
78 static char *get_search_path(void)
81 char *ret
, *p
, module
[OFS_MAXPATHNAME
];
84 if (GetCurrentTask() && GetModuleFileName16( GetCurrentTask(), module
, sizeof(module
) ))
86 if (!(p
= strrchr( module
, '\\' ))) p
= module
;
90 len
= (2 + /* search order: first current dir */
91 GetSystemDirectoryA( NULL
, 0 ) + 1 + /* then system dir */
92 GetWindowsDirectoryA( NULL
, 0 ) + 1 + /* then windows dir */
93 strlen( module
) + 1 + /* then module path */
94 GetEnvironmentVariableA( "PATH", NULL
, 0 ) + 1); /* then look in PATH */
95 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, len
))) return NULL
;
98 GetSystemDirectoryA( p
, ret
+ len
- p
);
101 GetWindowsDirectoryA( p
, ret
+ len
- p
);
110 GetEnvironmentVariableA( "PATH", p
, ret
+ len
- p
);
114 /***********************************************************************
115 * OpenFile (KERNEL.74)
116 * OpenFileEx (KERNEL.360)
118 HFILE16 WINAPI
OpenFile16( LPCSTR name
, OFSTRUCT
*ofs
, UINT16 mode
)
123 WORD filedatetime
[2];
124 const char *p
, *filename
;
126 if (!ofs
) return HFILE_ERROR
;
128 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",debugstr_a(name
),
129 ((mode
& 0x3 )==OF_READ
)?"OF_READ":
130 ((mode
& 0x3 )==OF_WRITE
)?"OF_WRITE":
131 ((mode
& 0x3 )==OF_READWRITE
)?"OF_READWRITE":"unknown",
132 ((mode
& 0x70 )==OF_SHARE_COMPAT
)?"OF_SHARE_COMPAT":
133 ((mode
& 0x70 )==OF_SHARE_DENY_NONE
)?"OF_SHARE_DENY_NONE":
134 ((mode
& 0x70 )==OF_SHARE_DENY_READ
)?"OF_SHARE_DENY_READ":
135 ((mode
& 0x70 )==OF_SHARE_DENY_WRITE
)?"OF_SHARE_DENY_WRITE":
136 ((mode
& 0x70 )==OF_SHARE_EXCLUSIVE
)?"OF_SHARE_EXCLUSIVE":"unknown",
137 ((mode
& OF_PARSE
)==OF_PARSE
)?"OF_PARSE ":"",
138 ((mode
& OF_DELETE
)==OF_DELETE
)?"OF_DELETE ":"",
139 ((mode
& OF_VERIFY
)==OF_VERIFY
)?"OF_VERIFY ":"",
140 ((mode
& OF_SEARCH
)==OF_SEARCH
)?"OF_SEARCH ":"",
141 ((mode
& OF_CANCEL
)==OF_CANCEL
)?"OF_CANCEL ":"",
142 ((mode
& OF_CREATE
)==OF_CREATE
)?"OF_CREATE ":"",
143 ((mode
& OF_PROMPT
)==OF_PROMPT
)?"OF_PROMPT ":"",
144 ((mode
& OF_EXIST
)==OF_EXIST
)?"OF_EXIST ":"",
145 ((mode
& OF_REOPEN
)==OF_REOPEN
)?"OF_REOPEN ":""
150 OpenFile( name
, ofs
, mode
);
154 if (mode
& OF_CREATE
)
156 handle
= (HANDLE
)OpenFile( name
, ofs
, mode
);
157 if (handle
== (HANDLE
)HFILE_ERROR
) goto error
;
161 ofs
->cBytes
= sizeof(OFSTRUCT
);
163 if (mode
& OF_REOPEN
) name
= ofs
->szPathName
;
165 if (!name
) return HFILE_ERROR
;
167 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
168 Are there any cases where getting the path here is wrong?
169 Uwe Bonnes 1997 Apr 2 */
170 if (!GetFullPathNameA( name
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
)) goto error
;
172 /* If OF_SEARCH is set, ignore the given path */
175 if ((mode
& OF_SEARCH
) && !(mode
& OF_REOPEN
))
177 /* First try the file name as is */
178 if (GetFileAttributesA( filename
) != INVALID_FILE_ATTRIBUTES
) filename
= NULL
;
181 /* Now remove the path */
182 if (filename
[0] && (filename
[1] == ':')) filename
+= 2;
183 if ((p
= strrchr( filename
, '\\' ))) filename
= p
+ 1;
184 if ((p
= strrchr( filename
, '/' ))) filename
= p
+ 1;
187 SetLastError( ERROR_FILE_NOT_FOUND
);
193 /* Now look for the file */
198 char *path
= get_search_path();
200 if (!path
) goto error
;
201 found
= SearchPathA( path
, filename
, NULL
, sizeof(ofs
->szPathName
),
202 ofs
->szPathName
, NULL
);
203 HeapFree( GetProcessHeap(), 0, path
);
204 if (!found
) goto error
;
207 TRACE("found %s\n", debugstr_a(ofs
->szPathName
) );
209 if (mode
& OF_DELETE
)
211 if (!DeleteFileA( ofs
->szPathName
)) goto error
;
212 TRACE("(%s): OF_DELETE return = OK\n", name
);
216 handle
= (HANDLE
)_lopen( ofs
->szPathName
, mode
);
217 if (handle
== INVALID_HANDLE_VALUE
) goto error
;
219 GetFileTime( handle
, NULL
, NULL
, &filetime
);
220 FileTimeToDosDateTime( &filetime
, &filedatetime
[0], &filedatetime
[1] );
221 if ((mode
& OF_VERIFY
) && (mode
& OF_REOPEN
))
223 if (ofs
->Reserved1
!= filedatetime
[0] || ofs
->Reserved2
!= filedatetime
[1] )
225 CloseHandle( handle
);
226 WARN("(%s): OF_VERIFY failed\n", name
);
227 /* FIXME: what error here? */
228 SetLastError( ERROR_FILE_NOT_FOUND
);
232 ofs
->Reserved1
= filedatetime
[0];
233 ofs
->Reserved2
= filedatetime
[1];
236 TRACE("(%s): OK, return = %p\n", name
, handle
);
237 hFileRet
= Win32HandleToDosFileHandle( handle
);
238 if (hFileRet
== HFILE_ERROR16
) goto error
;
239 if (mode
& OF_EXIST
) _lclose16( hFileRet
); /* Return the handle, but close it first */
242 error
: /* We get here if there was an error opening the file */
243 ofs
->nErrCode
= GetLastError();
244 WARN("(%s): return = HFILE_ERROR error= %d\n", name
,ofs
->nErrCode
);
245 return HFILE_ERROR16
;
249 /***********************************************************************
250 * _lclose (KERNEL.81)
252 HFILE16 WINAPI
_lclose16( HFILE16 hFile
)
254 if ((hFile
>= DOS_TABLE_SIZE
) || !dos_handles
[hFile
])
256 SetLastError( ERROR_INVALID_HANDLE
);
257 return HFILE_ERROR16
;
259 TRACE("%d (handle32=%p)\n", hFile
, dos_handles
[hFile
] );
260 CloseHandle( dos_handles
[hFile
] );
261 dos_handles
[hFile
] = 0;
265 /***********************************************************************
266 * _lcreat (KERNEL.83)
268 HFILE16 WINAPI
_lcreat16( LPCSTR path
, INT16 attr
)
270 return Win32HandleToDosFileHandle( (HANDLE
)_lcreat( path
, attr
) );
273 /***********************************************************************
274 * _llseek (KERNEL.84)
277 * Seeking before the start of the file should be allowed for _llseek16,
278 * but cause subsequent I/O operations to fail (cf. interrupt list)
281 LONG WINAPI
_llseek16( HFILE16 hFile
, LONG lOffset
, INT16 nOrigin
)
283 return SetFilePointer( DosFileHandleToWin32Handle(hFile
), lOffset
, NULL
, nOrigin
);
287 /***********************************************************************
290 HFILE16 WINAPI
_lopen16( LPCSTR path
, INT16 mode
)
292 return Win32HandleToDosFileHandle( (HANDLE
)_lopen( path
, mode
) );
296 /***********************************************************************
297 * _lread16 (KERNEL.82)
299 UINT16 WINAPI
_lread16( HFILE16 hFile
, LPVOID buffer
, UINT16 count
)
301 return (UINT16
)_lread((HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
305 /***********************************************************************
306 * _lwrite (KERNEL.86)
308 UINT16 WINAPI
_lwrite16( HFILE16 hFile
, LPCSTR buffer
, UINT16 count
)
310 return (UINT16
)_hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
313 /***********************************************************************
314 * _hread (KERNEL.349)
316 LONG WINAPI
WIN16_hread( HFILE16 hFile
, SEGPTR buffer
, LONG count
)
320 TRACE("%d %08x %d\n", hFile
, (DWORD
)buffer
, count
);
322 /* Some programs pass a count larger than the allocated buffer */
323 maxlen
= GetSelectorLimit16( SELECTOROF(buffer
) ) - OFFSETOF(buffer
) + 1;
324 if (count
> maxlen
) count
= maxlen
;
325 return _lread((HFILE
)DosFileHandleToWin32Handle(hFile
), MapSL(buffer
), count
);
329 /***********************************************************************
332 UINT16 WINAPI
WIN16_lread( HFILE16 hFile
, SEGPTR buffer
, UINT16 count
)
334 return (UINT16
)WIN16_hread( hFile
, buffer
, (LONG
)count
);
338 /***********************************************************************
339 * GetTempDrive (KERNEL.92)
340 * A closer look at krnl386.exe shows what the SDK doesn't mention:
344 * AH: ':' - yes, some kernel code even does stosw with
348 UINT WINAPI
GetTempDrive( BYTE ignored
)
353 if (GetTempPathW( 8, buffer
)) ret
= (BYTE
)toupperW(buffer
[0]);
355 return MAKELONG( ret
| (':' << 8), 1 );
359 /***********************************************************************
360 * GetTempFileName (KERNEL.97)
362 UINT16 WINAPI
GetTempFileName16( BYTE drive
, LPCSTR prefix
, UINT16 unique
,
365 char temppath
[MAX_PATH
];
366 char *prefix16
= NULL
;
369 if (!(drive
& ~TF_FORCEDRIVE
)) /* drive 0 means current default drive */
371 GetCurrentDirectoryA(sizeof(temppath
), temppath
);
372 drive
|= temppath
[0];
375 if (drive
& TF_FORCEDRIVE
)
379 d
[0] = drive
& ~TF_FORCEDRIVE
;
382 if (GetDriveTypeA(d
) == DRIVE_NO_ROOT_DIR
)
384 drive
&= ~TF_FORCEDRIVE
;
385 WARN("invalid drive %d specified\n", drive
);
389 if (drive
& TF_FORCEDRIVE
)
390 sprintf(temppath
,"%c:", drive
& ~TF_FORCEDRIVE
);
392 GetTempPathA( MAX_PATH
, temppath
);
396 prefix16
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + 2);
398 strcpy(prefix16
+ 1, prefix
);
401 ret
= GetTempFileNameA( temppath
, prefix16
, unique
, buffer
);
403 HeapFree(GetProcessHeap(), 0, prefix16
);
408 /***********************************************************************
409 * GetPrivateProfileInt (KERNEL.127)
411 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
412 INT16 def_val
, LPCSTR filename
)
414 /* we used to have some elaborate return value limitation (<= -32768 etc.)
415 * here, but Win98SE doesn't care about this at all, so I deleted it.
416 * AFAIR versions prior to Win9x had these limits, though. */
417 return (INT16
)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
421 /***********************************************************************
422 * WritePrivateProfileString (KERNEL.129)
424 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
425 LPCSTR string
, LPCSTR filename
)
427 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
431 /***********************************************************************
432 * GetWindowsDirectory (KERNEL.134)
434 UINT16 WINAPI
GetWindowsDirectory16( LPSTR path
, UINT16 count
)
436 return GetWindowsDirectoryA( path
, count
);
440 /***********************************************************************
441 * GetSystemDirectory (KERNEL.135)
443 UINT16 WINAPI
GetSystemDirectory16( LPSTR path
, UINT16 count
)
445 return GetSystemDirectoryA( path
, count
);
449 /***********************************************************************
450 * GetDriveType (KERNEL.136)
451 * Get the type of a drive in Win16.
454 * The type of the Drive. For a list see GetDriveTypeW from kernel32.
457 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
458 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
459 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
460 * do any pseudo-clever changes.
462 UINT16 WINAPI
GetDriveType16( UINT16 drive
) /* [in] number (NOT letter) of drive */
467 root
[0] = 'A' + drive
;
470 type
= GetDriveTypeW( root
);
471 if (type
== DRIVE_CDROM
) type
= DRIVE_REMOTE
;
472 else if (type
== DRIVE_NO_ROOT_DIR
) type
= DRIVE_UNKNOWN
;
477 /***********************************************************************
478 * GetProfileSectionNames (KERNEL.142)
480 WORD WINAPI
GetProfileSectionNames16(LPSTR buffer
, WORD size
)
483 return GetPrivateProfileSectionNamesA(buffer
,size
,"win.ini");
487 /***********************************************************************
488 * GetPrivateProfileSectionNames (KERNEL.143)
490 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
493 return GetPrivateProfileSectionNamesA(buffer
,size
,filename
);
497 /***********************************************************************
498 * CreateDirectory (KERNEL.144)
500 BOOL16 WINAPI
CreateDirectory16( LPCSTR path
, LPVOID dummy
)
502 return CreateDirectoryA( path
, NULL
);
506 /***********************************************************************
507 * RemoveDirectory (KERNEL.145)
509 BOOL16 WINAPI
RemoveDirectory16( LPCSTR path
)
511 return RemoveDirectoryA( path
);
515 /***********************************************************************
516 * DeleteFile (KERNEL.146)
518 BOOL16 WINAPI
DeleteFile16( LPCSTR path
)
520 return DeleteFileA( path
);
524 /***********************************************************************
525 * SetHandleCount (KERNEL.199)
527 UINT16 WINAPI
SetHandleCount16( UINT16 count
)
529 return SetHandleCount( count
);
533 /***********************************************************************
534 * _hread16 (KERNEL.349)
536 LONG WINAPI
_hread16( HFILE16 hFile
, LPVOID buffer
, LONG count
)
538 return _lread( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
542 /***********************************************************************
543 * _hwrite (KERNEL.350)
545 LONG WINAPI
_hwrite16( HFILE16 hFile
, LPCSTR buffer
, LONG count
)
547 return _hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
551 /***********************************************************************
552 * WritePrivateProfileStruct (KERNEL.406)
554 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
555 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
557 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
561 /***********************************************************************
562 * GetPrivateProfileStruct (KERNEL.407)
564 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
565 LPVOID buf
, UINT16 len
, LPCSTR filename
)
567 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
571 /***********************************************************************
572 * GetCurrentDirectory (KERNEL.411)
574 UINT16 WINAPI
GetCurrentDirectory16( UINT16 buflen
, LPSTR buf
)
576 return GetCurrentDirectoryA( buflen
, buf
);
580 /***********************************************************************
581 * SetCurrentDirectory (KERNEL.412)
583 BOOL16 WINAPI
SetCurrentDirectory16( LPCSTR dir
)
585 char fulldir
[MAX_PATH
];
587 if (!GetFullPathNameA( dir
, MAX_PATH
, fulldir
, NULL
)) return FALSE
;
589 if (!SetCurrentDirectoryA( dir
)) return FALSE
;
591 if (fulldir
[0] && fulldir
[1] == ':')
593 TDB
*pTask
= GlobalLock16( GetCurrentTask() );
594 char env_var
[4] = "=A:";
596 env_var
[1] = fulldir
[0];
597 SetEnvironmentVariableA( env_var
, fulldir
);
599 /* update the directory in the TDB */
602 pTask
->curdrive
= 0x80 | (fulldir
[0] - 'A');
603 GetShortPathNameA( fulldir
+ 2, pTask
->curdir
, sizeof(pTask
->curdir
) );
610 /*************************************************************************
611 * FindFirstFile (KERNEL.413)
613 HANDLE16 WINAPI
FindFirstFile16( LPCSTR path
, WIN32_FIND_DATAA
*data
)
618 if (!(h16
= GlobalAlloc16( GMEM_MOVEABLE
, sizeof(handle
) ))) return INVALID_HANDLE_VALUE16
;
619 ptr
= GlobalLock16( h16
);
620 *ptr
= handle
= FindFirstFileA( path
, data
);
621 GlobalUnlock16( h16
);
623 if (handle
== INVALID_HANDLE_VALUE
)
626 h16
= INVALID_HANDLE_VALUE16
;
632 /*************************************************************************
633 * FindNextFile (KERNEL.414)
635 BOOL16 WINAPI
FindNextFile16( HANDLE16 handle
, WIN32_FIND_DATAA
*data
)
640 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
642 SetLastError( ERROR_INVALID_HANDLE
);
645 ret
= FindNextFileA( *ptr
, data
);
646 GlobalUnlock16( handle
);
651 /*************************************************************************
652 * FindClose (KERNEL.415)
654 BOOL16 WINAPI
FindClose16( HANDLE16 handle
)
658 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
660 SetLastError( ERROR_INVALID_HANDLE
);
664 GlobalUnlock16( handle
);
665 GlobalFree16( handle
);
670 /***********************************************************************
671 * WritePrivateProfileSection (KERNEL.416)
673 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
674 LPCSTR string
, LPCSTR filename
)
676 return WritePrivateProfileSectionA( section
, string
, filename
);
680 /***********************************************************************
681 * WriteProfileSection (KERNEL.417)
683 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
685 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
689 /***********************************************************************
690 * GetPrivateProfileSection (KERNEL.418)
692 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
693 UINT16 len
, LPCSTR filename
)
695 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
699 /***********************************************************************
700 * GetProfileSection (KERNEL.419)
702 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
704 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
708 /**************************************************************************
709 * GetFileAttributes (KERNEL.420)
711 DWORD WINAPI
GetFileAttributes16( LPCSTR name
)
713 return GetFileAttributesA( name
);
717 /**************************************************************************
718 * SetFileAttributes (KERNEL.421)
720 BOOL16 WINAPI
SetFileAttributes16( LPCSTR lpFileName
, DWORD attributes
)
722 return SetFileAttributesA( lpFileName
, attributes
);
726 /***********************************************************************
727 * GetDiskFreeSpace (KERNEL.422)
729 BOOL16 WINAPI
GetDiskFreeSpace16( LPCSTR root
, LPDWORD cluster_sectors
,
730 LPDWORD sector_bytes
, LPDWORD free_clusters
,
731 LPDWORD total_clusters
)
733 return GetDiskFreeSpaceA( root
, cluster_sectors
, sector_bytes
,
734 free_clusters
, total_clusters
);
737 /***********************************************************************
738 * FileCDR (KERNEL.130)
740 FARPROC16 WINAPI
FileCDR16(FARPROC16 x
)
742 FIXME("(%p): stub\n", x
);
743 return (FARPROC16
)TRUE
;