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
39 #include "wine/winbase16.h"
40 #include "wine/server.h"
41 #include "kernel_private.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(file
);
48 /***********************************************************************
49 * GetProfileInt (KERNEL.57)
51 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
53 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
57 /***********************************************************************
58 * GetProfileString (KERNEL.58)
60 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
61 LPSTR buffer
, UINT16 len
)
63 return GetPrivateProfileString16( section
, entry
, def_val
,
64 buffer
, len
, "win.ini" );
68 /***********************************************************************
69 * WriteProfileString (KERNEL.59)
71 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
74 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
78 /* get the search path for the current module; helper for OpenFile16 */
79 static char *get_search_path(void)
82 char *ret
, *p
, module
[OFS_MAXPATHNAME
];
85 if (GetCurrentTask() && GetModuleFileName16( GetCurrentTask(), module
, sizeof(module
) ))
87 if (!(p
= strrchr( module
, '\\' ))) p
= module
;
91 len
= (2 + /* search order: first current dir */
92 GetSystemDirectoryA( NULL
, 0 ) + 1 + /* then system dir */
93 GetWindowsDirectoryA( NULL
, 0 ) + 1 + /* then windows dir */
94 strlen( module
) + 1 + /* then module path */
95 GetEnvironmentVariableA( "PATH", NULL
, 0 ) + 1); /* then look in PATH */
96 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, len
))) return NULL
;
99 GetSystemDirectoryA( p
, ret
+ len
- p
);
102 GetWindowsDirectoryA( p
, ret
+ len
- p
);
111 GetEnvironmentVariableA( "PATH", p
, ret
+ len
- p
);
115 /***********************************************************************
116 * OpenFile (KERNEL.74)
117 * OpenFileEx (KERNEL.360)
119 HFILE16 WINAPI
OpenFile16( LPCSTR name
, OFSTRUCT
*ofs
, UINT16 mode
)
124 WORD filedatetime
[2];
125 const char *p
, *filename
;
127 if (!ofs
) return HFILE_ERROR
;
129 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",debugstr_a(name
),
130 ((mode
& 0x3 )==OF_READ
)?"OF_READ":
131 ((mode
& 0x3 )==OF_WRITE
)?"OF_WRITE":
132 ((mode
& 0x3 )==OF_READWRITE
)?"OF_READWRITE":"unknown",
133 ((mode
& 0x70 )==OF_SHARE_COMPAT
)?"OF_SHARE_COMPAT":
134 ((mode
& 0x70 )==OF_SHARE_DENY_NONE
)?"OF_SHARE_DENY_NONE":
135 ((mode
& 0x70 )==OF_SHARE_DENY_READ
)?"OF_SHARE_DENY_READ":
136 ((mode
& 0x70 )==OF_SHARE_DENY_WRITE
)?"OF_SHARE_DENY_WRITE":
137 ((mode
& 0x70 )==OF_SHARE_EXCLUSIVE
)?"OF_SHARE_EXCLUSIVE":"unknown",
138 ((mode
& OF_PARSE
)==OF_PARSE
)?"OF_PARSE ":"",
139 ((mode
& OF_DELETE
)==OF_DELETE
)?"OF_DELETE ":"",
140 ((mode
& OF_VERIFY
)==OF_VERIFY
)?"OF_VERIFY ":"",
141 ((mode
& OF_SEARCH
)==OF_SEARCH
)?"OF_SEARCH ":"",
142 ((mode
& OF_CANCEL
)==OF_CANCEL
)?"OF_CANCEL ":"",
143 ((mode
& OF_CREATE
)==OF_CREATE
)?"OF_CREATE ":"",
144 ((mode
& OF_PROMPT
)==OF_PROMPT
)?"OF_PROMPT ":"",
145 ((mode
& OF_EXIST
)==OF_EXIST
)?"OF_EXIST ":"",
146 ((mode
& OF_REOPEN
)==OF_REOPEN
)?"OF_REOPEN ":""
151 OpenFile( name
, ofs
, mode
);
155 if (mode
& OF_CREATE
)
157 handle
= (HANDLE
)OpenFile( name
, ofs
, mode
);
158 if (handle
== (HANDLE
)HFILE_ERROR
) goto error
;
162 ofs
->cBytes
= sizeof(OFSTRUCT
);
164 if (mode
& OF_REOPEN
) name
= ofs
->szPathName
;
166 if (!name
) return HFILE_ERROR
;
168 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
169 Are there any cases where getting the path here is wrong?
170 Uwe Bonnes 1997 Apr 2 */
171 if (!GetFullPathNameA( name
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
)) goto error
;
173 /* If OF_SEARCH is set, ignore the given path */
176 if ((mode
& OF_SEARCH
) && !(mode
& OF_REOPEN
))
178 /* First try the file name as is */
179 if (GetFileAttributesA( filename
) != INVALID_FILE_ATTRIBUTES
) filename
= NULL
;
182 /* Now remove the path */
183 if (filename
[0] && (filename
[1] == ':')) filename
+= 2;
184 if ((p
= strrchr( filename
, '\\' ))) filename
= p
+ 1;
185 if ((p
= strrchr( filename
, '/' ))) filename
= p
+ 1;
188 SetLastError( ERROR_FILE_NOT_FOUND
);
194 /* Now look for the file */
199 char *path
= get_search_path();
201 if (!path
) goto error
;
202 found
= SearchPathA( path
, filename
, NULL
, sizeof(ofs
->szPathName
),
203 ofs
->szPathName
, NULL
);
204 HeapFree( GetProcessHeap(), 0, path
);
205 if (!found
) goto error
;
208 TRACE("found %s\n", debugstr_a(ofs
->szPathName
) );
210 if (mode
& OF_DELETE
)
212 if (!DeleteFileA( ofs
->szPathName
)) goto error
;
213 TRACE("(%s): OF_DELETE return = OK\n", name
);
217 handle
= (HANDLE
)_lopen( ofs
->szPathName
, mode
);
218 if (handle
== INVALID_HANDLE_VALUE
) goto error
;
220 GetFileTime( handle
, NULL
, NULL
, &filetime
);
221 FileTimeToDosDateTime( &filetime
, &filedatetime
[0], &filedatetime
[1] );
222 if ((mode
& OF_VERIFY
) && (mode
& OF_REOPEN
))
224 if (ofs
->Reserved1
!= filedatetime
[0] || ofs
->Reserved2
!= filedatetime
[1] )
226 CloseHandle( handle
);
227 WARN("(%s): OF_VERIFY failed\n", name
);
228 /* FIXME: what error here? */
229 SetLastError( ERROR_FILE_NOT_FOUND
);
233 ofs
->Reserved1
= filedatetime
[0];
234 ofs
->Reserved2
= filedatetime
[1];
237 TRACE("(%s): OK, return = %p\n", name
, handle
);
238 hFileRet
= Win32HandleToDosFileHandle( handle
);
239 if (hFileRet
== HFILE_ERROR16
) goto error
;
240 if (mode
& OF_EXIST
) _lclose16( hFileRet
); /* Return the handle, but close it first */
243 error
: /* We get here if there was an error opening the file */
244 ofs
->nErrCode
= GetLastError();
245 WARN("(%s): return = HFILE_ERROR error= %d\n", name
,ofs
->nErrCode
);
246 return HFILE_ERROR16
;
250 /***********************************************************************
251 * _lclose (KERNEL.81)
253 HFILE16 WINAPI
_lclose16( HFILE16 hFile
)
255 if ((hFile
>= DOS_TABLE_SIZE
) || !dos_handles
[hFile
])
257 SetLastError( ERROR_INVALID_HANDLE
);
258 return HFILE_ERROR16
;
260 TRACE("%d (handle32=%p)\n", hFile
, dos_handles
[hFile
] );
261 CloseHandle( dos_handles
[hFile
] );
262 dos_handles
[hFile
] = 0;
266 /***********************************************************************
267 * _lcreat (KERNEL.83)
269 HFILE16 WINAPI
_lcreat16( LPCSTR path
, INT16 attr
)
271 return Win32HandleToDosFileHandle( (HANDLE
)_lcreat( path
, attr
) );
274 /***********************************************************************
275 * _llseek (KERNEL.84)
278 * Seeking before the start of the file should be allowed for _llseek16,
279 * but cause subsequent I/O operations to fail (cf. interrupt list)
282 LONG WINAPI
_llseek16( HFILE16 hFile
, LONG lOffset
, INT16 nOrigin
)
284 return SetFilePointer( DosFileHandleToWin32Handle(hFile
), lOffset
, NULL
, nOrigin
);
288 /***********************************************************************
291 HFILE16 WINAPI
_lopen16( LPCSTR path
, INT16 mode
)
293 return Win32HandleToDosFileHandle( (HANDLE
)_lopen( path
, mode
) );
297 /***********************************************************************
298 * _lread16 (KERNEL.82)
300 UINT16 WINAPI
_lread16( HFILE16 hFile
, LPVOID buffer
, UINT16 count
)
302 return (UINT16
)_lread((HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
306 /***********************************************************************
307 * _lwrite (KERNEL.86)
309 UINT16 WINAPI
_lwrite16( HFILE16 hFile
, LPCSTR buffer
, UINT16 count
)
311 return (UINT16
)_hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, (LONG
)count
);
314 /***********************************************************************
315 * _hread (KERNEL.349)
317 LONG WINAPI
WIN16_hread( HFILE16 hFile
, SEGPTR buffer
, LONG count
)
321 TRACE("%d %08lx %ld\n", hFile
, (DWORD
)buffer
, count
);
323 /* Some programs pass a count larger than the allocated buffer */
324 maxlen
= GetSelectorLimit16( SELECTOROF(buffer
) ) - OFFSETOF(buffer
) + 1;
325 if (count
> maxlen
) count
= maxlen
;
326 return _lread((HFILE
)DosFileHandleToWin32Handle(hFile
), MapSL(buffer
), count
);
330 /***********************************************************************
333 UINT16 WINAPI
WIN16_lread( HFILE16 hFile
, SEGPTR buffer
, UINT16 count
)
335 return (UINT16
)WIN16_hread( hFile
, buffer
, (LONG
)count
);
339 /***********************************************************************
340 * GetTempDrive (KERNEL.92)
341 * A closer look at krnl386.exe shows what the SDK doesn't mention:
345 * AH: ':' - yes, some kernel code even does stosw with
349 UINT WINAPI
GetTempDrive( BYTE ignored
)
354 if (GetTempPathW( 8, buffer
)) ret
= (BYTE
)toupperW(buffer
[0]);
356 return MAKELONG( ret
| (':' << 8), 1 );
360 /***********************************************************************
361 * GetTempFileName (KERNEL.97)
363 UINT16 WINAPI
GetTempFileName16( BYTE drive
, LPCSTR prefix
, UINT16 unique
,
366 char temppath
[MAX_PATH
];
367 char *prefix16
= NULL
;
370 if (!(drive
& ~TF_FORCEDRIVE
)) /* drive 0 means current default drive */
372 GetCurrentDirectoryA(sizeof(temppath
), temppath
);
373 drive
|= temppath
[0];
376 if (drive
& TF_FORCEDRIVE
)
380 d
[0] = drive
& ~TF_FORCEDRIVE
;
383 if (GetDriveTypeA(d
) == DRIVE_NO_ROOT_DIR
)
385 drive
&= ~TF_FORCEDRIVE
;
386 WARN("invalid drive %d specified\n", drive
);
390 if (drive
& TF_FORCEDRIVE
)
391 sprintf(temppath
,"%c:", drive
& ~TF_FORCEDRIVE
);
393 GetTempPathA( MAX_PATH
, temppath
);
397 prefix16
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + 2);
399 strcpy(prefix16
+ 1, prefix
);
402 ret
= GetTempFileNameA( temppath
, prefix16
, unique
, buffer
);
404 HeapFree(GetProcessHeap(), 0, prefix16
);
409 /***********************************************************************
410 * GetPrivateProfileInt (KERNEL.127)
412 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
413 INT16 def_val
, LPCSTR filename
)
415 /* we used to have some elaborate return value limitation (<= -32768 etc.)
416 * here, but Win98SE doesn't care about this at all, so I deleted it.
417 * AFAIR versions prior to Win9x had these limits, though. */
418 return (INT16
)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
422 /***********************************************************************
423 * WritePrivateProfileString (KERNEL.129)
425 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
426 LPCSTR string
, LPCSTR filename
)
428 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
432 /***********************************************************************
433 * GetWindowsDirectory (KERNEL.134)
435 UINT16 WINAPI
GetWindowsDirectory16( LPSTR path
, UINT16 count
)
437 return GetWindowsDirectoryA( path
, count
);
441 /***********************************************************************
442 * GetSystemDirectory (KERNEL.135)
444 UINT16 WINAPI
GetSystemDirectory16( LPSTR path
, UINT16 count
)
446 return GetSystemDirectoryA( path
, count
);
450 /***********************************************************************
451 * GetDriveType (KERNEL.136)
452 * This function returns the type of a drive in Win16.
453 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
454 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
455 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
456 * do any pseudo-clever changes.
458 UINT16 WINAPI
GetDriveType16( UINT16 drive
) /* [in] number (NOT letter) of drive */
463 root
[0] = 'A' + drive
;
466 type
= GetDriveTypeW( root
);
467 if (type
== DRIVE_CDROM
) type
= DRIVE_REMOTE
;
468 else if (type
== DRIVE_NO_ROOT_DIR
) type
= DRIVE_UNKNOWN
;
473 /***********************************************************************
474 * GetProfileSectionNames (KERNEL.142)
476 WORD WINAPI
GetProfileSectionNames16(LPSTR buffer
, WORD size
)
479 return GetPrivateProfileSectionNamesA(buffer
,size
,"win.ini");
483 /***********************************************************************
484 * GetPrivateProfileSectionNames (KERNEL.143)
486 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
489 return GetPrivateProfileSectionNamesA(buffer
,size
,filename
);
493 /***********************************************************************
494 * CreateDirectory (KERNEL.144)
496 BOOL16 WINAPI
CreateDirectory16( LPCSTR path
, LPVOID dummy
)
498 return CreateDirectoryA( path
, NULL
);
502 /***********************************************************************
503 * RemoveDirectory (KERNEL.145)
505 BOOL16 WINAPI
RemoveDirectory16( LPCSTR path
)
507 return RemoveDirectoryA( path
);
511 /***********************************************************************
512 * DeleteFile (KERNEL.146)
514 BOOL16 WINAPI
DeleteFile16( LPCSTR path
)
516 return DeleteFileA( path
);
520 /***********************************************************************
521 * SetHandleCount (KERNEL.199)
523 UINT16 WINAPI
SetHandleCount16( UINT16 count
)
525 return SetHandleCount( count
);
529 /***********************************************************************
530 * _hread16 (KERNEL.349)
532 LONG WINAPI
_hread16( HFILE16 hFile
, LPVOID buffer
, LONG count
)
534 return _lread( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
538 /***********************************************************************
539 * _hwrite (KERNEL.350)
541 LONG WINAPI
_hwrite16( HFILE16 hFile
, LPCSTR buffer
, LONG count
)
543 return _hwrite( (HFILE
)DosFileHandleToWin32Handle(hFile
), buffer
, count
);
547 /***********************************************************************
548 * WritePrivateProfileStruct (KERNEL.406)
550 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
551 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
553 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
557 /***********************************************************************
558 * GetPrivateProfileStruct (KERNEL.407)
560 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
561 LPVOID buf
, UINT16 len
, LPCSTR filename
)
563 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
567 /***********************************************************************
568 * GetCurrentDirectory (KERNEL.411)
570 UINT16 WINAPI
GetCurrentDirectory16( UINT16 buflen
, LPSTR buf
)
572 return GetCurrentDirectoryA( buflen
, buf
);
576 /***********************************************************************
577 * SetCurrentDirectory (KERNEL.412)
579 BOOL16 WINAPI
SetCurrentDirectory16( LPCSTR dir
)
581 char fulldir
[MAX_PATH
];
583 if (!GetFullPathNameA( dir
, MAX_PATH
, fulldir
, NULL
)) return FALSE
;
585 if (!SetCurrentDirectoryA( dir
)) return FALSE
;
587 if (fulldir
[0] && fulldir
[1] == ':')
589 TDB
*pTask
= GlobalLock16( GetCurrentTask() );
590 char env_var
[4] = "=A:";
592 env_var
[1] = fulldir
[0];
593 SetEnvironmentVariableA( env_var
, fulldir
);
595 /* update the directory in the TDB */
598 pTask
->curdrive
= 0x80 | (fulldir
[0] - 'A');
599 GetShortPathNameA( fulldir
+ 2, pTask
->curdir
, sizeof(pTask
->curdir
) );
606 /*************************************************************************
607 * FindFirstFile (KERNEL.413)
609 HANDLE16 WINAPI
FindFirstFile16( LPCSTR path
, WIN32_FIND_DATAA
*data
)
614 if (!(h16
= GlobalAlloc16( GMEM_MOVEABLE
, sizeof(handle
) ))) return INVALID_HANDLE_VALUE16
;
615 ptr
= GlobalLock16( h16
);
616 *ptr
= handle
= FindFirstFileA( path
, data
);
617 GlobalUnlock16( h16
);
619 if (handle
== INVALID_HANDLE_VALUE
)
622 h16
= INVALID_HANDLE_VALUE16
;
628 /*************************************************************************
629 * FindNextFile (KERNEL.414)
631 BOOL16 WINAPI
FindNextFile16( HANDLE16 handle
, WIN32_FIND_DATAA
*data
)
636 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
638 SetLastError( ERROR_INVALID_HANDLE
);
641 ret
= FindNextFileA( *ptr
, data
);
642 GlobalUnlock16( handle
);
647 /*************************************************************************
648 * FindClose (KERNEL.415)
650 BOOL16 WINAPI
FindClose16( HANDLE16 handle
)
654 if ((handle
== INVALID_HANDLE_VALUE16
) || !(ptr
= GlobalLock16( handle
)))
656 SetLastError( ERROR_INVALID_HANDLE
);
660 GlobalUnlock16( handle
);
661 GlobalFree16( handle
);
666 /***********************************************************************
667 * WritePrivateProfileSection (KERNEL.416)
669 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
670 LPCSTR string
, LPCSTR filename
)
672 return WritePrivateProfileSectionA( section
, string
, filename
);
676 /***********************************************************************
677 * WriteProfileSection (KERNEL.417)
679 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
681 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
685 /***********************************************************************
686 * GetPrivateProfileSection (KERNEL.418)
688 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
689 UINT16 len
, LPCSTR filename
)
691 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
695 /***********************************************************************
696 * GetProfileSection (KERNEL.419)
698 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
700 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
704 /**************************************************************************
705 * GetFileAttributes (KERNEL.420)
707 DWORD WINAPI
GetFileAttributes16( LPCSTR name
)
709 return GetFileAttributesA( name
);
713 /**************************************************************************
714 * SetFileAttributes (KERNEL.421)
716 BOOL16 WINAPI
SetFileAttributes16( LPCSTR lpFileName
, DWORD attributes
)
718 return SetFileAttributesA( lpFileName
, attributes
);
722 /***********************************************************************
723 * GetDiskFreeSpace (KERNEL.422)
725 BOOL16 WINAPI
GetDiskFreeSpace16( LPCSTR root
, LPDWORD cluster_sectors
,
726 LPDWORD sector_bytes
, LPDWORD free_clusters
,
727 LPDWORD total_clusters
)
729 return GetDiskFreeSpaceA( root
, cluster_sectors
, sector_bytes
,
730 free_clusters
, total_clusters
);