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 * GetTempDrive (KERNEL.92)
352 * A closer look at krnl386.exe shows what the SDK doesn't mention:
356 * AH: ':' - yes, some kernel code even does stosw with
360 UINT WINAPI
GetTempDrive( BYTE ignored
)
365 if (GetTempPathW( 8, buffer
)) ret
= (BYTE
)toupperW(buffer
[0]);
367 return MAKELONG( ret
| (':' << 8), 1 );
371 /***********************************************************************
372 * GetTempFileName (KERNEL.97)
374 UINT16 WINAPI
GetTempFileName16( BYTE drive
, LPCSTR prefix
, UINT16 unique
,
377 char temppath
[MAX_PATH
];
378 char *prefix16
= NULL
;
381 if (!(drive
& ~TF_FORCEDRIVE
)) /* drive 0 means current default drive */
383 GetCurrentDirectoryA(sizeof(temppath
), temppath
);
384 drive
|= temppath
[0];
387 if (drive
& TF_FORCEDRIVE
)
391 d
[0] = drive
& ~TF_FORCEDRIVE
;
394 if (GetDriveTypeA(d
) == DRIVE_NO_ROOT_DIR
)
396 drive
&= ~TF_FORCEDRIVE
;
397 WARN("invalid drive %d specified\n", drive
);
401 if (drive
& TF_FORCEDRIVE
)
402 sprintf(temppath
,"%c:", drive
& ~TF_FORCEDRIVE
);
404 GetTempPathA( MAX_PATH
, temppath
);
408 prefix16
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + 2);
410 strcpy(prefix16
+ 1, prefix
);
413 ret
= GetTempFileNameA( temppath
, prefix16
, unique
, buffer
);
415 if (prefix16
) HeapFree(GetProcessHeap(), 0, prefix16
);
420 /***********************************************************************
421 * GetPrivateProfileInt (KERNEL.127)
423 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
424 INT16 def_val
, LPCSTR filename
)
426 /* we used to have some elaborate return value limitation (<= -32768 etc.)
427 * here, but Win98SE doesn't care about this at all, so I deleted it.
428 * AFAIR versions prior to Win9x had these limits, though. */
429 return (INT16
)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
433 /***********************************************************************
434 * WritePrivateProfileString (KERNEL.129)
436 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
437 LPCSTR string
, LPCSTR filename
)
439 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
443 /***********************************************************************
444 * GetWindowsDirectory (KERNEL.134)
446 UINT16 WINAPI
GetWindowsDirectory16( LPSTR path
, UINT16 count
)
448 return GetWindowsDirectoryA( path
, count
);
452 /***********************************************************************
453 * GetSystemDirectory (KERNEL.135)
455 UINT16 WINAPI
GetSystemDirectory16( LPSTR path
, UINT16 count
)
457 return GetSystemDirectoryA( path
, count
);
461 /***********************************************************************
462 * GetDriveType (KERNEL.136)
463 * This function returns the type of a drive in Win16.
464 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
465 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
466 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
467 * do any pseudo-clever changes.
469 UINT16 WINAPI
GetDriveType16( UINT16 drive
) /* [in] number (NOT letter) of drive */
474 root
[0] = 'A' + drive
;
477 type
= GetDriveTypeW( root
);
478 if (type
== DRIVE_CDROM
) type
= DRIVE_REMOTE
;
483 /***********************************************************************
484 * GetProfileSectionNames (KERNEL.142)
486 WORD WINAPI
GetProfileSectionNames16(LPSTR buffer
, WORD size
)
489 return GetPrivateProfileSectionNamesA(buffer
,size
,"win.ini");
493 /***********************************************************************
494 * GetPrivateProfileSectionNames (KERNEL.143)
496 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
499 return GetPrivateProfileSectionNamesA(buffer
,size
,filename
);
503 /***********************************************************************
504 * CreateDirectory (KERNEL.144)
506 BOOL16 WINAPI
CreateDirectory16( LPCSTR path
, LPVOID dummy
)
508 return CreateDirectoryA( path
, NULL
);
512 /***********************************************************************
513 * RemoveDirectory (KERNEL.145)
515 BOOL16 WINAPI
RemoveDirectory16( LPCSTR path
)
517 return RemoveDirectoryA( path
);
521 /***********************************************************************
522 * DeleteFile (KERNEL.146)
524 BOOL16 WINAPI
DeleteFile16( LPCSTR path
)
526 return DeleteFileA( path
);
530 /***********************************************************************
531 * SetHandleCount (KERNEL.199)
533 UINT16 WINAPI
SetHandleCount16( UINT16 count
)
535 return SetHandleCount( count
);
539 /***********************************************************************
540 * _hread16 (KERNEL.349)
542 LONG WINAPI
_hread16( HFILE16 hFile
, LPVOID buffer
, LONG count
)
544 return _lread( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
548 /***********************************************************************
549 * _hwrite (KERNEL.350)
551 LONG WINAPI
_hwrite16( HFILE16 hFile
, LPCSTR buffer
, LONG count
)
553 return _hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
557 /***********************************************************************
558 * WritePrivateProfileStruct (KERNEL.406)
560 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
561 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
563 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
567 /***********************************************************************
568 * GetPrivateProfileStruct (KERNEL.407)
570 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
571 LPVOID buf
, UINT16 len
, LPCSTR filename
)
573 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
577 /***********************************************************************
578 * SetCurrentDirectory (KERNEL.412)
580 BOOL16 WINAPI
SetCurrentDirectory16( LPCSTR dir
)
582 return SetCurrentDirectoryA( dir
);
586 /*************************************************************************
587 * FindFirstFile (KERNEL.413)
589 HANDLE16 WINAPI
FindFirstFile16( LPCSTR path
, WIN32_FIND_DATAA
*data
)
594 if (!(h16
= GlobalAlloc16( GMEM_MOVEABLE
, sizeof(handle
) ))) return INVALID_HANDLE_VALUE16
;
595 ptr
= GlobalLock16( h16
);
596 *ptr
= handle
= FindFirstFileA( path
, data
);
597 GlobalUnlock16( h16
);
599 if (handle
== INVALID_HANDLE_VALUE
)
602 h16
= INVALID_HANDLE_VALUE16
;
608 /*************************************************************************
609 * FindNextFile (KERNEL.414)
611 BOOL16 WINAPI
FindNextFile16( HANDLE16 handle
, WIN32_FIND_DATAA
*data
)
616 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
618 SetLastError( ERROR_INVALID_HANDLE
);
621 ret
= FindNextFileA( *ptr
, data
);
622 GlobalUnlock16( handle
);
627 /*************************************************************************
628 * FindClose (KERNEL.415)
630 BOOL16 WINAPI
FindClose16( HANDLE16 handle
)
634 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
636 SetLastError( ERROR_INVALID_HANDLE
);
640 GlobalUnlock16( handle
);
641 GlobalFree16( handle
);
646 /***********************************************************************
647 * WritePrivateProfileSection (KERNEL.416)
649 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
650 LPCSTR string
, LPCSTR filename
)
652 return WritePrivateProfileSectionA( section
, string
, filename
);
656 /***********************************************************************
657 * WriteProfileSection (KERNEL.417)
659 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
661 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
665 /***********************************************************************
666 * GetPrivateProfileSection (KERNEL.418)
668 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
669 UINT16 len
, LPCSTR filename
)
671 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
675 /***********************************************************************
676 * GetProfileSection (KERNEL.419)
678 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
680 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
684 /**************************************************************************
685 * GetFileAttributes (KERNEL.420)
687 DWORD WINAPI
GetFileAttributes16( LPCSTR name
)
689 return GetFileAttributesA( name
);
693 /**************************************************************************
694 * SetFileAttributes (KERNEL.421)
696 BOOL16 WINAPI
SetFileAttributes16( LPCSTR lpFileName
, DWORD attributes
)
698 return SetFileAttributesA( lpFileName
, attributes
);
702 /***********************************************************************
703 * GetDiskFreeSpace (KERNEL.422)
705 BOOL16 WINAPI
GetDiskFreeSpace16( LPCSTR root
, LPDWORD cluster_sectors
,
706 LPDWORD sector_bytes
, LPDWORD free_clusters
,
707 LPDWORD total_clusters
)
709 return GetDiskFreeSpaceA( root
, cluster_sectors
, sector_bytes
,
710 free_clusters
, total_clusters
);