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];
126 const char *p
, *filename
;
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 ":""
152 OpenFile( name
, ofs
, mode
);
156 if (mode
& OF_CREATE
)
158 handle
= (HANDLE
)OpenFile( name
, ofs
, mode
);
159 if (handle
== (HANDLE
)HFILE_ERROR
) goto error
;
163 ofs
->cBytes
= sizeof(OFSTRUCT
);
165 if (mode
& OF_REOPEN
) name
= ofs
->szPathName
;
167 if (!name
) return HFILE_ERROR
;
169 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
170 Are there any cases where getting the path here is wrong?
171 Uwe Bonnes 1997 Apr 2 */
172 if (!GetFullPathNameA( name
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
)) goto error
;
174 /* If OF_SEARCH is set, ignore the given path */
177 if ((mode
& OF_SEARCH
) && !(mode
& OF_REOPEN
))
179 /* First try the file name as is */
180 if (GetFileAttributesA( filename
) != INVALID_FILE_ATTRIBUTES
) filename
= NULL
;
183 /* Now remove the path */
184 if (filename
[0] && (filename
[1] == ':')) filename
+= 2;
185 if ((p
= strrchr( filename
, '\\' ))) filename
= p
+ 1;
186 if ((p
= strrchr( filename
, '/' ))) filename
= p
+ 1;
189 SetLastError( ERROR_FILE_NOT_FOUND
);
195 /* Now look for the file */
200 char *path
= get_search_path();
202 if (!path
) goto error
;
203 found
= SearchPathA( path
, filename
, NULL
, sizeof(ofs
->szPathName
),
204 ofs
->szPathName
, NULL
);
205 HeapFree( GetProcessHeap(), 0, path
);
206 if (!found
) goto error
;
209 TRACE("found %s\n", debugstr_a(ofs
->szPathName
) );
211 if (mode
& OF_DELETE
)
213 if (!DeleteFileA( ofs
->szPathName
)) goto error
;
214 TRACE("(%s): OF_DELETE return = OK\n", name
);
218 handle
= (HANDLE
)_lopen( ofs
->szPathName
, mode
);
219 if (handle
== INVALID_HANDLE_VALUE
) goto error
;
221 GetFileTime( handle
, NULL
, NULL
, &filetime
);
222 FileTimeToDosDateTime( &filetime
, &filedatetime
[0], &filedatetime
[1] );
223 if ((mode
& OF_VERIFY
) && (mode
& OF_REOPEN
))
225 if (ofs
->Reserved1
!= filedatetime
[0] || ofs
->Reserved2
!= filedatetime
[1] )
227 CloseHandle( handle
);
228 WARN("(%s): OF_VERIFY failed\n", name
);
229 /* FIXME: what error here? */
230 SetLastError( ERROR_FILE_NOT_FOUND
);
234 ofs
->Reserved1
= filedatetime
[0];
235 ofs
->Reserved2
= filedatetime
[1];
238 TRACE("(%s): OK, return = %p\n", name
, handle
);
239 hFileRet
= Win32HandleToDosFileHandle( handle
);
240 if (hFileRet
== HFILE_ERROR16
) goto error
;
241 if (mode
& OF_EXIST
) _lclose16( hFileRet
); /* Return the handle, but close it first */
244 error
: /* We get here if there was an error opening the file */
245 ofs
->nErrCode
= GetLastError();
246 WARN("(%s): return = HFILE_ERROR error= %d\n", name
,ofs
->nErrCode
);
247 return HFILE_ERROR16
;
251 /***********************************************************************
252 * _lclose (KERNEL.81)
254 HFILE16 WINAPI
_lclose16( HFILE16 hFile
)
256 if ((hFile
>= DOS_TABLE_SIZE
) || !dos_handles
[hFile
])
258 SetLastError( ERROR_INVALID_HANDLE
);
259 return HFILE_ERROR16
;
261 TRACE("%d (handle32=%p)\n", hFile
, dos_handles
[hFile
] );
262 CloseHandle( dos_handles
[hFile
] );
263 dos_handles
[hFile
] = 0;
267 /***********************************************************************
268 * _lcreat (KERNEL.83)
270 HFILE16 WINAPI
_lcreat16( LPCSTR path
, INT16 attr
)
272 return Win32HandleToDosFileHandle( (HANDLE
)_lcreat( path
, attr
) );
275 /***********************************************************************
276 * _llseek (KERNEL.84)
279 * Seeking before the start of the file should be allowed for _llseek16,
280 * but cause subsequent I/O operations to fail (cf. interrupt list)
283 LONG WINAPI
_llseek16( HFILE16 hFile
, LONG lOffset
, INT16 nOrigin
)
285 return SetFilePointer( DosFileHandleToWin32Handle(hFile
), lOffset
, NULL
, nOrigin
);
289 /***********************************************************************
292 HFILE16 WINAPI
_lopen16( LPCSTR path
, INT16 mode
)
294 return Win32HandleToDosFileHandle( (HANDLE
)_lopen( path
, mode
) );
298 /***********************************************************************
299 * _lread16 (KERNEL.82)
301 UINT16 WINAPI
_lread16( HFILE16 hFile
, LPVOID buffer
, UINT16 count
)
303 return (UINT16
)_lread((HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
307 /***********************************************************************
308 * _lwrite (KERNEL.86)
310 UINT16 WINAPI
_lwrite16( HFILE16 hFile
, LPCSTR buffer
, UINT16 count
)
312 return (UINT16
)_hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
315 /***********************************************************************
316 * _hread (KERNEL.349)
318 LONG WINAPI
WIN16_hread( HFILE16 hFile
, SEGPTR buffer
, LONG count
)
322 TRACE("%d %08lx %ld\n", hFile
, (DWORD
)buffer
, count
);
324 /* Some programs pass a count larger than the allocated buffer */
325 maxlen
= GetSelectorLimit16( SELECTOROF(buffer
) ) - OFFSETOF(buffer
) + 1;
326 if (count
> maxlen
) count
= maxlen
;
327 return _lread((HFILE
)DosFileHandleToWin32Handle(hFile
), MapSL(buffer
), count
);
331 /***********************************************************************
334 UINT16 WINAPI
WIN16_lread( HFILE16 hFile
, SEGPTR buffer
, UINT16 count
)
336 return (UINT16
)WIN16_hread( hFile
, buffer
, (LONG
)count
);
340 /***********************************************************************
341 * GetTempDrive (KERNEL.92)
342 * A closer look at krnl386.exe shows what the SDK doesn't mention:
346 * AH: ':' - yes, some kernel code even does stosw with
350 UINT WINAPI
GetTempDrive( BYTE ignored
)
355 if (GetTempPathW( 8, buffer
)) ret
= (BYTE
)toupperW(buffer
[0]);
357 return MAKELONG( ret
| (':' << 8), 1 );
361 /***********************************************************************
362 * GetTempFileName (KERNEL.97)
364 UINT16 WINAPI
GetTempFileName16( BYTE drive
, LPCSTR prefix
, UINT16 unique
,
367 char temppath
[MAX_PATH
];
368 char *prefix16
= NULL
;
371 if (!(drive
& ~TF_FORCEDRIVE
)) /* drive 0 means current default drive */
373 GetCurrentDirectoryA(sizeof(temppath
), temppath
);
374 drive
|= temppath
[0];
377 if (drive
& TF_FORCEDRIVE
)
381 d
[0] = drive
& ~TF_FORCEDRIVE
;
384 if (GetDriveTypeA(d
) == DRIVE_NO_ROOT_DIR
)
386 drive
&= ~TF_FORCEDRIVE
;
387 WARN("invalid drive %d specified\n", drive
);
391 if (drive
& TF_FORCEDRIVE
)
392 sprintf(temppath
,"%c:", drive
& ~TF_FORCEDRIVE
);
394 GetTempPathA( MAX_PATH
, temppath
);
398 prefix16
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + 2);
400 strcpy(prefix16
+ 1, prefix
);
403 ret
= GetTempFileNameA( temppath
, prefix16
, unique
, buffer
);
405 if (prefix16
) HeapFree(GetProcessHeap(), 0, prefix16
);
410 /***********************************************************************
411 * GetPrivateProfileInt (KERNEL.127)
413 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
414 INT16 def_val
, LPCSTR filename
)
416 /* we used to have some elaborate return value limitation (<= -32768 etc.)
417 * here, but Win98SE doesn't care about this at all, so I deleted it.
418 * AFAIR versions prior to Win9x had these limits, though. */
419 return (INT16
)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
423 /***********************************************************************
424 * WritePrivateProfileString (KERNEL.129)
426 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
427 LPCSTR string
, LPCSTR filename
)
429 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
433 /***********************************************************************
434 * GetWindowsDirectory (KERNEL.134)
436 UINT16 WINAPI
GetWindowsDirectory16( LPSTR path
, UINT16 count
)
438 return GetWindowsDirectoryA( path
, count
);
442 /***********************************************************************
443 * GetSystemDirectory (KERNEL.135)
445 UINT16 WINAPI
GetSystemDirectory16( LPSTR path
, UINT16 count
)
447 return GetSystemDirectoryA( path
, count
);
451 /***********************************************************************
452 * GetDriveType (KERNEL.136)
453 * This function returns the type of a drive in Win16.
454 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
455 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
456 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
457 * do any pseudo-clever changes.
459 UINT16 WINAPI
GetDriveType16( UINT16 drive
) /* [in] number (NOT letter) of drive */
464 root
[0] = 'A' + drive
;
467 type
= GetDriveTypeW( root
);
468 if (type
== DRIVE_CDROM
) type
= DRIVE_REMOTE
;
469 else if (type
== DRIVE_NO_ROOT_DIR
) type
= DRIVE_UNKNOWN
;
474 /***********************************************************************
475 * GetProfileSectionNames (KERNEL.142)
477 WORD WINAPI
GetProfileSectionNames16(LPSTR buffer
, WORD size
)
480 return GetPrivateProfileSectionNamesA(buffer
,size
,"win.ini");
484 /***********************************************************************
485 * GetPrivateProfileSectionNames (KERNEL.143)
487 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
490 return GetPrivateProfileSectionNamesA(buffer
,size
,filename
);
494 /***********************************************************************
495 * CreateDirectory (KERNEL.144)
497 BOOL16 WINAPI
CreateDirectory16( LPCSTR path
, LPVOID dummy
)
499 return CreateDirectoryA( path
, NULL
);
503 /***********************************************************************
504 * RemoveDirectory (KERNEL.145)
506 BOOL16 WINAPI
RemoveDirectory16( LPCSTR path
)
508 return RemoveDirectoryA( path
);
512 /***********************************************************************
513 * DeleteFile (KERNEL.146)
515 BOOL16 WINAPI
DeleteFile16( LPCSTR path
)
517 return DeleteFileA( path
);
521 /***********************************************************************
522 * SetHandleCount (KERNEL.199)
524 UINT16 WINAPI
SetHandleCount16( UINT16 count
)
526 return SetHandleCount( count
);
530 /***********************************************************************
531 * _hread16 (KERNEL.349)
533 LONG WINAPI
_hread16( HFILE16 hFile
, LPVOID buffer
, LONG count
)
535 return _lread( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
539 /***********************************************************************
540 * _hwrite (KERNEL.350)
542 LONG WINAPI
_hwrite16( HFILE16 hFile
, LPCSTR buffer
, LONG count
)
544 return _hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
548 /***********************************************************************
549 * WritePrivateProfileStruct (KERNEL.406)
551 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
552 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
554 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
558 /***********************************************************************
559 * GetPrivateProfileStruct (KERNEL.407)
561 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
562 LPVOID buf
, UINT16 len
, LPCSTR filename
)
564 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
568 /***********************************************************************
569 * GetCurrentDirectory (KERNEL.411)
571 UINT16 WINAPI
GetCurrentDirectory16( UINT16 buflen
, LPSTR buf
)
573 return GetCurrentDirectoryA( buflen
, buf
);
577 /***********************************************************************
578 * SetCurrentDirectory (KERNEL.412)
580 BOOL16 WINAPI
SetCurrentDirectory16( LPCSTR dir
)
582 char fulldir
[MAX_PATH
];
584 if (!GetFullPathNameA( dir
, MAX_PATH
, fulldir
, NULL
)) return FALSE
;
586 if (!SetCurrentDirectoryA( dir
)) return FALSE
;
588 if (fulldir
[0] && fulldir
[1] == ':')
590 TDB
*pTask
= GlobalLock16( GetCurrentTask() );
591 char env_var
[4] = "=A:";
593 env_var
[1] = fulldir
[0];
594 SetEnvironmentVariableA( env_var
, fulldir
);
596 /* update the directory in the TDB */
599 pTask
->curdrive
= 0x80 | (fulldir
[0] - 'A');
600 GetShortPathNameA( fulldir
+ 2, pTask
->curdir
, sizeof(pTask
->curdir
) );
607 /*************************************************************************
608 * FindFirstFile (KERNEL.413)
610 HANDLE16 WINAPI
FindFirstFile16( LPCSTR path
, WIN32_FIND_DATAA
*data
)
615 if (!(h16
= GlobalAlloc16( GMEM_MOVEABLE
, sizeof(handle
) ))) return INVALID_HANDLE_VALUE16
;
616 ptr
= GlobalLock16( h16
);
617 *ptr
= handle
= FindFirstFileA( path
, data
);
618 GlobalUnlock16( h16
);
620 if (handle
== INVALID_HANDLE_VALUE
)
623 h16
= INVALID_HANDLE_VALUE16
;
629 /*************************************************************************
630 * FindNextFile (KERNEL.414)
632 BOOL16 WINAPI
FindNextFile16( HANDLE16 handle
, WIN32_FIND_DATAA
*data
)
637 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
639 SetLastError( ERROR_INVALID_HANDLE
);
642 ret
= FindNextFileA( *ptr
, data
);
643 GlobalUnlock16( handle
);
648 /*************************************************************************
649 * FindClose (KERNEL.415)
651 BOOL16 WINAPI
FindClose16( HANDLE16 handle
)
655 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
657 SetLastError( ERROR_INVALID_HANDLE
);
661 GlobalUnlock16( handle
);
662 GlobalFree16( handle
);
667 /***********************************************************************
668 * WritePrivateProfileSection (KERNEL.416)
670 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
671 LPCSTR string
, LPCSTR filename
)
673 return WritePrivateProfileSectionA( section
, string
, filename
);
677 /***********************************************************************
678 * WriteProfileSection (KERNEL.417)
680 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
682 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
686 /***********************************************************************
687 * GetPrivateProfileSection (KERNEL.418)
689 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
690 UINT16 len
, LPCSTR filename
)
692 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
696 /***********************************************************************
697 * GetProfileSection (KERNEL.419)
699 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
701 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
705 /**************************************************************************
706 * GetFileAttributes (KERNEL.420)
708 DWORD WINAPI
GetFileAttributes16( LPCSTR name
)
710 return GetFileAttributesA( name
);
714 /**************************************************************************
715 * SetFileAttributes (KERNEL.421)
717 BOOL16 WINAPI
SetFileAttributes16( LPCSTR lpFileName
, DWORD attributes
)
719 return SetFileAttributesA( lpFileName
, attributes
);
723 /***********************************************************************
724 * GetDiskFreeSpace (KERNEL.422)
726 BOOL16 WINAPI
GetDiskFreeSpace16( LPCSTR root
, LPDWORD cluster_sectors
,
727 LPDWORD sector_bytes
, LPDWORD free_clusters
,
728 LPDWORD total_clusters
)
730 return GetDiskFreeSpaceA( root
, cluster_sectors
, sector_bytes
,
731 free_clusters
, total_clusters
);