blob: e3e4eeb26128f83a88d2c8e913f20aec9b833fff [file] [log] [blame]
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001/*
2 * File handling functions
3 *
4 * Copyright 1993 John Burton
5 * Copyright 1996 Alexandre Julliard
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00006 *
7 * TODO:
Andreas Mohr20cd9352000-09-12 23:40:40 +00008 * Fix the CopyFileEx methods to implement the "extended" functionality.
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00009 * Right now, they simply call the CopyFile method.
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000010 */
11
Howard Abrams13277481999-07-10 13:16:29 +000012#include "config.h"
13
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000014#include <assert.h>
Alexandre Julliardd90840e1996-06-11 16:02:08 +000015#include <ctype.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000016#include <errno.h>
17#include <fcntl.h>
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +000018#include <stdlib.h>
Alexandre Julliard383da682000-02-10 22:15:21 +000019#include <stdio.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000020#include <string.h>
Howard Abrams13277481999-07-10 13:16:29 +000021#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000022#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000023#endif
Alexandre Julliard01d63461997-01-20 19:43:45 +000024#include <sys/types.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000025#include <sys/stat.h>
Howard Abrams13277481999-07-10 13:16:29 +000026#ifdef HAVE_SYS_MMAN_H
Alexandre Julliard21979011997-03-05 08:22:35 +000027#include <sys/mman.h>
Howard Abrams13277481999-07-10 13:16:29 +000028#endif
Marcus Meissner7d123bf1998-12-11 09:13:29 +000029#include <sys/time.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000030#include <time.h>
31#include <unistd.h>
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +000032#include <utime.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000033
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000034#include "winerror.h"
Marcus Meissner317af321999-02-17 13:51:06 +000035#include "windef.h"
36#include "winbase.h"
37#include "wine/winbase16.h"
Alexandre Julliard27bb3112000-11-29 17:48:06 +000038#include "wine/port.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000039#include "drive.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000040#include "file.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000041#include "heap.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000042#include "msdos.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000043#include "task.h"
Marcus Meissner6b5a8111999-01-30 13:06:00 +000044#include "wincon.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000045#include "debugtools.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000046
Alexandre Julliard338e7571998-12-27 15:28:54 +000047#include "server.h"
48
Alexandre Julliard383da682000-02-10 22:15:21 +000049DEFAULT_DEBUG_CHANNEL(file);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000050
Alexandre Julliard21979011997-03-05 08:22:35 +000051#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
52#define MAP_ANON MAP_ANONYMOUS
53#endif
Alexandre Julliard0c126c71996-02-18 18:44:41 +000054
Alexandre Julliard8da12c41999-01-17 16:55:11 +000055/* Size of per-process table of DOS handles */
56#define DOS_TABLE_SIZE 256
Alexandre Julliard0c126c71996-02-18 18:44:41 +000057
Alexandre Julliard231674d2000-08-09 22:30:18 +000058static HANDLE dos_handles[DOS_TABLE_SIZE];
59
Alexandre Julliarda11d7b11998-03-01 20:05:02 +000060
Alexandre Julliard0c126c71996-02-18 18:44:41 +000061/***********************************************************************
Alexandre Julliard05625391999-01-03 11:55:56 +000062 * FILE_ConvertOFMode
Uwe Bonnese6b5e381998-10-18 14:48:31 +000063 *
Alexandre Julliard05625391999-01-03 11:55:56 +000064 * Convert OF_* mode into flags for CreateFile.
Uwe Bonnese6b5e381998-10-18 14:48:31 +000065 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000066static void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing )
Uwe Bonnese6b5e381998-10-18 14:48:31 +000067{
Alexandre Julliard05625391999-01-03 11:55:56 +000068 switch(mode & 0x03)
69 {
70 case OF_READ: *access = GENERIC_READ; break;
71 case OF_WRITE: *access = GENERIC_WRITE; break;
72 case OF_READWRITE: *access = GENERIC_READ | GENERIC_WRITE; break;
73 default: *access = 0; break;
74 }
75 switch(mode & 0x70)
76 {
77 case OF_SHARE_EXCLUSIVE: *sharing = 0; break;
78 case OF_SHARE_DENY_WRITE: *sharing = FILE_SHARE_READ; break;
79 case OF_SHARE_DENY_READ: *sharing = FILE_SHARE_WRITE; break;
80 case OF_SHARE_DENY_NONE:
81 case OF_SHARE_COMPAT:
82 default: *sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break;
83 }
Uwe Bonnese6b5e381998-10-18 14:48:31 +000084}
85
Uwe Bonnese6b5e381998-10-18 14:48:31 +000086
87/***********************************************************************
Aric Stewarte4d09322000-12-03 03:14:29 +000088 * FILE_strcasecmp
Uwe Bonnese6b5e381998-10-18 14:48:31 +000089 *
Aric Stewarte4d09322000-12-03 03:14:29 +000090 * locale-independent case conversion for file I/O
Uwe Bonnese6b5e381998-10-18 14:48:31 +000091 */
Aric Stewarte4d09322000-12-03 03:14:29 +000092int FILE_strcasecmp( const char *str1, const char *str2 )
Uwe Bonnese6b5e381998-10-18 14:48:31 +000093{
Aric Stewarte4d09322000-12-03 03:14:29 +000094 for (;;)
Uwe Bonnese6b5e381998-10-18 14:48:31 +000095 {
Aric Stewarte4d09322000-12-03 03:14:29 +000096 int ret = FILE_toupper(*str1) - FILE_toupper(*str2);
97 if (ret || !*str1) return ret;
98 str1++;
99 str2++;
Uwe Bonnese6b5e381998-10-18 14:48:31 +0000100 }
Uwe Bonnese6b5e381998-10-18 14:48:31 +0000101}
Aric Stewarte4d09322000-12-03 03:14:29 +0000102
103
104/***********************************************************************
105 * FILE_strncasecmp
106 *
107 * locale-independent case conversion for file I/O
108 */
109int FILE_strncasecmp( const char *str1, const char *str2, int len )
110{
111 int ret = 0;
112 for ( ; len > 0; len--, str1++, str2++)
113 if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
114 return ret;
115}
Uwe Bonnese6b5e381998-10-18 14:48:31 +0000116
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000117
118/***********************************************************************
119 * FILE_SetDosError
120 *
121 * Set the DOS error code from errno.
122 */
123void FILE_SetDosError(void)
124{
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000125 int save_errno = errno; /* errno gets overwritten by printf */
126
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000127 TRACE("errno = %d %s\n", errno, strerror(errno));
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000128 switch (save_errno)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000129 {
130 case EAGAIN:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000131 SetLastError( ERROR_SHARING_VIOLATION );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000132 break;
133 case EBADF:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000134 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000135 break;
136 case ENOSPC:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000137 SetLastError( ERROR_HANDLE_DISK_FULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000138 break;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000139 case EACCES:
140 case EPERM:
141 case EROFS:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000142 SetLastError( ERROR_ACCESS_DENIED );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000143 break;
144 case EBUSY:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000145 SetLastError( ERROR_LOCK_VIOLATION );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000146 break;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000147 case ENOENT:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000148 SetLastError( ERROR_FILE_NOT_FOUND );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000149 break;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000150 case EISDIR:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000151 SetLastError( ERROR_CANNOT_MAKE );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000152 break;
153 case ENFILE:
154 case EMFILE:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000155 SetLastError( ERROR_NO_MORE_FILES );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000156 break;
157 case EEXIST:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000158 SetLastError( ERROR_FILE_EXISTS );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000159 break;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000160 case EINVAL:
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000161 case ESPIPE:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000162 SetLastError( ERROR_SEEK );
Alexandre Julliarde658d821997-11-30 17:45:40 +0000163 break;
164 case ENOTEMPTY:
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000165 SetLastError( ERROR_DIR_NOT_EMPTY );
Alexandre Julliarde658d821997-11-30 17:45:40 +0000166 break;
Alexandre Julliard045d81f2000-05-01 16:20:23 +0000167 case ENOEXEC:
168 SetLastError( ERROR_BAD_FORMAT );
169 break;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000170 default:
Dimitrie O. Paun864dc592000-11-10 23:31:06 +0000171 WARN( "unknown file error: %s", strerror(save_errno) );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000172 SetLastError( ERROR_GEN_FAILURE );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000173 break;
174 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000175 errno = save_errno;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000176}
177
178
179/***********************************************************************
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000180 * FILE_DupUnixHandle
181 *
182 * Duplicate a Unix handle into a task handle.
183 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000184HFILE FILE_DupUnixHandle( int fd, DWORD access )
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000185{
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000186 struct alloc_file_handle_request *req = get_req_buffer();
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000187 req->access = access;
Alexandre Julliard8a971bf2000-04-04 19:57:23 +0000188 server_call_fd( REQ_ALLOC_FILE_HANDLE, fd, NULL );
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000189 return req->handle;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000190}
191
192
193/***********************************************************************
Alexandre Julliard92643002000-08-31 01:59:51 +0000194 * FILE_GetUnixHandle
195 *
196 * Retrieve the Unix handle corresponding to a file handle.
197 */
198int FILE_GetUnixHandle( HANDLE handle, DWORD access )
199{
200 int unix_handle = -1;
201 if (access == GENERIC_READ)
202 {
203 struct get_read_fd_request *req = get_req_buffer();
204 req->handle = handle;
205 server_call_fd( REQ_GET_READ_FD, -1, &unix_handle );
206 }
207 else if (access == GENERIC_WRITE)
208 {
209 struct get_write_fd_request *req = get_req_buffer();
210 req->handle = handle;
211 server_call_fd( REQ_GET_WRITE_FD, -1, &unix_handle );
212 }
213 else ERR( "bad access %08lx\n", access );
214 return unix_handle;
215}
216
217
Alexandre Julliard83f52d12000-09-26 22:20:14 +0000218/*************************************************************************
219 * FILE_OpenConsole
220 *
221 * Open a handle to the current process console.
222 */
223static HANDLE FILE_OpenConsole( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
224{
225 int ret = -1;
226
227 SERVER_START_REQ
228 {
229 struct open_console_request *req = server_alloc_req( sizeof(*req), 0 );
230
231 req->output = output;
232 req->access = access;
233 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
234 SetLastError(0);
235 if (!server_call( REQ_OPEN_CONSOLE )) ret = req->handle;
236 }
237 SERVER_END_REQ;
238 return ret;
239}
240
241
Alexandre Julliard92643002000-08-31 01:59:51 +0000242/***********************************************************************
Alexandre Julliard05625391999-01-03 11:55:56 +0000243 * FILE_CreateFile
244 *
245 * Implementation of CreateFile. Takes a Unix path name.
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000246 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000247HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000248 LPSECURITY_ATTRIBUTES sa, DWORD creation,
249 DWORD attributes, HANDLE template, BOOL fail_read_only )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000250{
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000251 DWORD err;
Alexandre Julliard92643002000-08-31 01:59:51 +0000252 HANDLE ret;
253 size_t len = strlen(filename);
254
255 if (len > REQUEST_MAX_VAR_SIZE)
256 {
257 FIXME("filename '%s' too long\n", filename );
258 SetLastError( ERROR_INVALID_PARAMETER );
259 return -1;
260 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000261
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000262 restart:
Alexandre Julliard92643002000-08-31 01:59:51 +0000263 SERVER_START_REQ
264 {
265 struct create_file_request *req = server_alloc_req( sizeof(*req), len );
266 req->access = access;
267 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
268 req->sharing = sharing;
269 req->create = creation;
270 req->attrs = attributes;
271 memcpy( server_data_ptr(req), filename, len );
272 SetLastError(0);
273 err = server_call( REQ_CREATE_FILE );
274 ret = req->handle;
275 }
276 SERVER_END_REQ;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000277
Alexandre Julliard05625391999-01-03 11:55:56 +0000278 /* If write access failed, retry without GENERIC_WRITE */
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000279
Alexandre Julliard92643002000-08-31 01:59:51 +0000280 if ((ret == -1) && !fail_read_only && (access & GENERIC_WRITE))
Alexandre Julliard05625391999-01-03 11:55:56 +0000281 {
Andreas Mohraf7e1ae2000-04-13 15:58:30 +0000282 if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000283 {
Matthew Cline8bfd8252000-02-18 19:05:11 +0000284 TRACE("Write access failed for file '%s', trying without "
Andreas Mohr2caee712000-07-16 15:44:22 +0000285 "write access\n", filename);
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000286 access &= ~GENERIC_WRITE;
287 goto restart;
288 }
Matthew Cline8bfd8252000-02-18 19:05:11 +0000289 }
290
Alexandre Julliard92643002000-08-31 01:59:51 +0000291 if (ret == -1)
Andreas Mohr2caee712000-07-16 15:44:22 +0000292 WARN("Unable to create file '%s' (GLE %ld)\n", filename,
Matthew Cline8bfd8252000-02-18 19:05:11 +0000293 GetLastError());
294
Alexandre Julliard92643002000-08-31 01:59:51 +0000295 return ret;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000296}
297
298
299/***********************************************************************
300 * FILE_CreateDevice
301 *
302 * Same as FILE_CreateFile but for a device
303 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000304HFILE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000305{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000306 HFILE ret;
307 SERVER_START_REQ
308 {
309 struct create_device_request *req = server_alloc_req( sizeof(*req), 0 );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000310
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000311 req->access = access;
312 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
313 req->id = client_id;
314 SetLastError(0);
315 server_call( REQ_CREATE_DEVICE );
316 ret = req->handle;
317 }
318 SERVER_END_REQ;
319 return ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000320}
321
322
Alexandre Julliard05625391999-01-03 11:55:56 +0000323/*************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000324 * CreateFileA [KERNEL32.45] Creates or opens a file or other object
Uwe Bonnesa370ab41998-10-24 09:16:44 +0000325 *
Alexandre Julliard05625391999-01-03 11:55:56 +0000326 * Creates or opens an object, and returns a handle that can be used to
327 * access that object.
Uwe Bonnesa370ab41998-10-24 09:16:44 +0000328 *
Alexandre Julliard05625391999-01-03 11:55:56 +0000329 * PARAMS
330 *
331 * filename [I] pointer to filename to be accessed
332 * access [I] access mode requested
333 * sharing [I] share mode
334 * sa [I] pointer to security attributes
335 * creation [I] how to create the file
336 * attributes [I] attributes for newly created file
337 * template [I] handle to file with extended attributes to copy
338 *
339 * RETURNS
340 * Success: Open handle to specified file
341 * Failure: INVALID_HANDLE_VALUE
342 *
343 * NOTES
344 * Should call SetLastError() on failure.
345 *
346 * BUGS
347 *
348 * Doesn't support character devices, pipes, template files, or a
349 * lot of the 'attributes' flags yet.
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000350 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000351HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
Alexandre Julliard05625391999-01-03 11:55:56 +0000352 LPSECURITY_ATTRIBUTES sa, DWORD creation,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000353 DWORD attributes, HANDLE template )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000354{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000355 DOS_FULL_NAME full_name;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000356
Alexandre Julliard05625391999-01-03 11:55:56 +0000357 if (!filename)
358 {
359 SetLastError( ERROR_INVALID_PARAMETER );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000360 return HFILE_ERROR;
Alexandre Julliard05625391999-01-03 11:55:56 +0000361 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000362 TRACE("%s %s%s%s%s%s%s%s\n",filename,
Uwe Bonnese4f46dc1999-06-06 17:08:13 +0000363 ((access & GENERIC_READ)==GENERIC_READ)?"GENERIC_READ ":"",
364 ((access & GENERIC_WRITE)==GENERIC_WRITE)?"GENERIC_WRITE ":"",
365 (!access)?"QUERY_ACCESS ":"",
366 ((sharing & FILE_SHARE_READ)==FILE_SHARE_READ)?"FILE_SHARE_READ ":"",
367 ((sharing & FILE_SHARE_WRITE)==FILE_SHARE_WRITE)?"FILE_SHARE_WRITE ":"",
368 ((sharing & FILE_SHARE_DELETE)==FILE_SHARE_DELETE)?"FILE_SHARE_DELETE ":"",
369 (creation ==CREATE_NEW)?"CREATE_NEW":
370 (creation ==CREATE_ALWAYS)?"CREATE_ALWAYS ":
371 (creation ==OPEN_EXISTING)?"OPEN_EXISTING ":
372 (creation ==OPEN_ALWAYS)?"OPEN_ALWAYS ":
373 (creation ==TRUNCATE_EXISTING)?"TRUNCATE_EXISTING ":"");
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000374
Alexandre Julliard05625391999-01-03 11:55:56 +0000375 /* If the name starts with '\\?\', ignore the first 4 chars. */
376 if (!strncmp(filename, "\\\\?\\", 4))
377 {
378 filename += 4;
379 if (!strncmp(filename, "UNC\\", 4))
380 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000381 FIXME("UNC name (%s) not supported.\n", filename );
Alexandre Julliard05625391999-01-03 11:55:56 +0000382 SetLastError( ERROR_PATH_NOT_FOUND );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000383 return HFILE_ERROR;
Alexandre Julliard05625391999-01-03 11:55:56 +0000384 }
385 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000386
Marcus Meissnerdd7523d2000-01-23 02:18:27 +0000387 if (!strncmp(filename, "\\\\.\\", 4)) {
388 if (!DOSFS_GetDevice( filename ))
389 return DEVICE_Open( filename+4, access, sa );
390 else
391 filename+=4; /* fall into DOSFS_Device case below */
392 }
Alexandre Julliard05625391999-01-03 11:55:56 +0000393
394 /* If the name still starts with '\\', it's a UNC name. */
395 if (!strncmp(filename, "\\\\", 2))
396 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000397 FIXME("UNC name (%s) not supported.\n", filename );
Alexandre Julliard05625391999-01-03 11:55:56 +0000398 SetLastError( ERROR_PATH_NOT_FOUND );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000399 return HFILE_ERROR;
Alexandre Julliard05625391999-01-03 11:55:56 +0000400 }
401
Francois Boisvert567bcf11999-09-20 18:31:21 +0000402 /* If the name contains a DOS wild card (* or ?), do no create a file */
403 if(strchr(filename,'*') || strchr(filename,'?'))
404 return HFILE_ERROR;
405
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000406 /* Open a console for CONIN$ or CONOUT$ */
Alexandre Julliard83f52d12000-09-26 22:20:14 +0000407 if (!strcasecmp(filename, "CONIN$")) return FILE_OpenConsole( FALSE, access, sa );
408 if (!strcasecmp(filename, "CONOUT$")) return FILE_OpenConsole( TRUE, access, sa );
Alexandre Julliard05625391999-01-03 11:55:56 +0000409
410 if (DOSFS_GetDevice( filename ))
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000411 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000412 HFILE ret;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000413
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000414 TRACE("opening device '%s'\n", filename );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000415
Alexandre Julliarda3960291999-02-26 11:11:13 +0000416 if (HFILE_ERROR!=(ret=DOSFS_OpenDevice( filename, access )))
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000417 return ret;
418
419 /* Do not silence this please. It is a critical error. -MM */
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000420 ERR("Couldn't open device '%s'!\n",filename);
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000421 SetLastError( ERROR_FILE_NOT_FOUND );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000422 return HFILE_ERROR;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000423 }
Alexandre Julliard05625391999-01-03 11:55:56 +0000424
425 /* check for filename, don't check for last entry if creating */
426 if (!DOSFS_GetFullName( filename,
Matthew Cline8bfd8252000-02-18 19:05:11 +0000427 (creation == OPEN_EXISTING) ||
428 (creation == TRUNCATE_EXISTING),
429 &full_name )) {
430 WARN("Unable to get full filename from '%s' (GLE %ld)\n",
431 filename, GetLastError());
Alexandre Julliarda3960291999-02-26 11:11:13 +0000432 return HFILE_ERROR;
Matthew Cline8bfd8252000-02-18 19:05:11 +0000433 }
Alexandre Julliard05625391999-01-03 11:55:56 +0000434
435 return FILE_CreateFile( full_name.long_name, access, sharing,
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000436 sa, creation, attributes, template,
437 DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000438}
439
440
Alexandre Julliard05625391999-01-03 11:55:56 +0000441
442/*************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000443 * CreateFileW (KERNEL32.48)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000444 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000445HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
Alexandre Julliard05625391999-01-03 11:55:56 +0000446 LPSECURITY_ATTRIBUTES sa, DWORD creation,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000447 DWORD attributes, HANDLE template)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000448{
Alexandre Julliard05625391999-01-03 11:55:56 +0000449 LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
Jim Aston031f4fa1999-10-23 19:00:02 +0000450 HANDLE res = CreateFileA( afn, access, sharing, sa, creation, attributes, template );
Alexandre Julliard05625391999-01-03 11:55:56 +0000451 HeapFree( GetProcessHeap(), 0, afn );
452 return res;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000453}
454
455
456/***********************************************************************
457 * FILE_FillInfo
458 *
459 * Fill a file information from a struct stat.
460 */
461static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
462{
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000463 if (S_ISDIR(st->st_mode))
Alexandre Julliard84c70f51997-05-09 08:40:27 +0000464 info->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
465 else
466 info->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
Alexandre Julliard01d63461997-01-20 19:43:45 +0000467 if (!(st->st_mode & S_IWUSR))
468 info->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000469
Alexandre Julliarde101f6d2000-08-14 14:42:41 +0000470 RtlSecondsSince1970ToTime( st->st_mtime, &info->ftCreationTime );
471 RtlSecondsSince1970ToTime( st->st_mtime, &info->ftLastWriteTime );
472 RtlSecondsSince1970ToTime( st->st_atime, &info->ftLastAccessTime );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000473
474 info->dwVolumeSerialNumber = 0; /* FIXME */
475 info->nFileSizeHigh = 0;
476 info->nFileSizeLow = S_ISDIR(st->st_mode) ? 0 : st->st_size;
477 info->nNumberOfLinks = st->st_nlink;
478 info->nFileIndexHigh = 0;
479 info->nFileIndexLow = st->st_ino;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000480}
481
482
483/***********************************************************************
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000484 * FILE_Stat
485 *
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000486 * Stat a Unix path name. Return TRUE if OK.
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000487 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000488BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000489{
490 struct stat st;
491
Andreas Mohr220312e2000-10-19 20:38:38 +0000492 if (lstat( unixName, &st ) == -1)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000493 {
494 FILE_SetDosError();
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000495 return FALSE;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000496 }
Andreas Mohr220312e2000-10-19 20:38:38 +0000497 if (!S_ISLNK(st.st_mode)) FILE_FillInfo( &st, info );
498 else
499 {
500 /* do a "real" stat to find out
501 about the type of the symlink destination */
502 if (stat( unixName, &st ) == -1)
503 {
504 FILE_SetDosError();
505 return FALSE;
506 }
507 FILE_FillInfo( &st, info );
508 info->dwFileAttributes |= FILE_ATTRIBUTE_SYMLINK;
509 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000510 return TRUE;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000511}
512
513
514/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000515 * GetFileInformationByHandle (KERNEL32.219)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000516 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000517DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000518 BY_HANDLE_FILE_INFORMATION *info )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000519{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000520 DWORD ret;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000521 if (!info) return 0;
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000522
523 SERVER_START_REQ
524 {
525 struct get_file_info_request *req = server_alloc_req( sizeof(*req), 0 );
526 req->handle = hFile;
527 if ((ret = !server_call( REQ_GET_FILE_INFO )))
528 {
529 RtlSecondsSince1970ToTime( req->write_time, &info->ftCreationTime );
530 RtlSecondsSince1970ToTime( req->write_time, &info->ftLastWriteTime );
531 RtlSecondsSince1970ToTime( req->access_time, &info->ftLastAccessTime );
532 info->dwFileAttributes = req->attr;
533 info->dwVolumeSerialNumber = req->serial;
534 info->nFileSizeHigh = req->size_high;
535 info->nFileSizeLow = req->size_low;
536 info->nNumberOfLinks = req->links;
537 info->nFileIndexHigh = req->index_high;
538 info->nFileIndexLow = req->index_low;
539 }
540 }
541 SERVER_END_REQ;
542 return ret;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000543}
544
545
546/**************************************************************************
547 * GetFileAttributes16 (KERNEL.420)
548 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000549DWORD WINAPI GetFileAttributes16( LPCSTR name )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000550{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000551 return GetFileAttributesA( name );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000552}
553
554
555/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000556 * GetFileAttributesA (KERNEL32.217)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000557 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000558DWORD WINAPI GetFileAttributesA( LPCSTR name )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000559{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000560 DOS_FULL_NAME full_name;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000561 BY_HANDLE_FILE_INFORMATION info;
562
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000563 if (name == NULL || *name=='\0') return -1;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000564
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000565 if (!DOSFS_GetFullName( name, TRUE, &full_name )) return -1;
566 if (!FILE_Stat( full_name.long_name, &info )) return -1;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000567 return info.dwFileAttributes;
568}
569
570
571/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000572 * GetFileAttributesW (KERNEL32.218)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000573 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000574DWORD WINAPI GetFileAttributesW( LPCWSTR name )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000575{
576 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000577 DWORD res = GetFileAttributesA( nameA );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000578 HeapFree( GetProcessHeap(), 0, nameA );
579 return res;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000580}
581
582
583/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000584 * GetFileSize (KERNEL32.220)
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000585 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000586DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD filesizehigh )
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000587{
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000588 BY_HANDLE_FILE_INFORMATION info;
589 if (!GetFileInformationByHandle( hFile, &info )) return 0;
590 if (filesizehigh) *filesizehigh = info.nFileSizeHigh;
591 return info.nFileSizeLow;
592}
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000593
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000594
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000595/***********************************************************************
596 * GetFileTime (KERNEL32.221)
597 */
Jim Aston031f4fa1999-10-23 19:00:02 +0000598BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000599 FILETIME *lpLastAccessTime,
600 FILETIME *lpLastWriteTime )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000601{
602 BY_HANDLE_FILE_INFORMATION info;
603 if (!GetFileInformationByHandle( hFile, &info )) return FALSE;
604 if (lpCreationTime) *lpCreationTime = info.ftCreationTime;
605 if (lpLastAccessTime) *lpLastAccessTime = info.ftLastAccessTime;
606 if (lpLastWriteTime) *lpLastWriteTime = info.ftLastWriteTime;
607 return TRUE;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000608}
609
Alexandre Julliard349a9531997-02-02 19:01:52 +0000610/***********************************************************************
611 * CompareFileTime (KERNEL32.28)
612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000613INT WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
Alexandre Julliard349a9531997-02-02 19:01:52 +0000614{
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000615 if (!x || !y) return -1;
616
Alexandre Julliard349a9531997-02-02 19:01:52 +0000617 if (x->dwHighDateTime > y->dwHighDateTime)
618 return 1;
619 if (x->dwHighDateTime < y->dwHighDateTime)
620 return -1;
621 if (x->dwLowDateTime > y->dwLowDateTime)
622 return 1;
623 if (x->dwLowDateTime < y->dwLowDateTime)
624 return -1;
625 return 0;
626}
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000627
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000628/***********************************************************************
Gerard Patelc465e191999-10-24 20:48:54 +0000629 * FILE_GetTempFileName : utility for GetTempFileName
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000630 */
Gerard Patelc465e191999-10-24 20:48:54 +0000631static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
632 LPSTR buffer, BOOL isWin16 )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000633{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000634 static UINT unique_temp;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000635 DOS_FULL_NAME full_name;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000636 int i;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000637 LPSTR p;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000638 UINT num;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000639
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000640 if ( !path || !prefix || !buffer ) return 0;
641
Uwe Bonnes2e525891998-11-01 15:04:52 +0000642 if (!unique_temp) unique_temp = time(NULL) & 0xffff;
643 num = unique ? (unique & 0xffff) : (unique_temp++ & 0xffff);
644
Alexandre Julliardca22b331996-07-12 19:02:39 +0000645 strcpy( buffer, path );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000646 p = buffer + strlen(buffer);
Alexandre Julliard02e90081998-01-04 17:49:09 +0000647
648 /* add a \, if there isn't one and path is more than just the drive letter ... */
649 if ( !((strlen(buffer) == 2) && (buffer[1] == ':'))
650 && ((p == buffer) || (p[-1] != '\\'))) *p++ = '\\';
651
Gerard Patelc465e191999-10-24 20:48:54 +0000652 if (isWin16) *p++ = '~';
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000653 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
654 sprintf( p, "%04x.tmp", num );
655
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000656 /* Now try to create it */
657
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000658 if (!unique)
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000659 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000660 do
661 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000662 HFILE handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
Alexandre Julliard05625391999-01-03 11:55:56 +0000663 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000664 if (handle != INVALID_HANDLE_VALUE)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000665 { /* We created it */
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000666 TRACE("created %s\n",
Alexandre Julliard21979011997-03-05 08:22:35 +0000667 buffer);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000668 CloseHandle( handle );
669 break;
670 }
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000671 if (GetLastError() != ERROR_FILE_EXISTS)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000672 break; /* No need to go on */
673 num++;
674 sprintf( p, "%04x.tmp", num );
675 } while (num != (unique & 0xffff));
676 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000677
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000678 /* Get the full path name */
679
680 if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
681 {
Alexandre Julliard01d63461997-01-20 19:43:45 +0000682 /* Check if we have write access in the directory */
683 if ((p = strrchr( full_name.long_name, '/' ))) *p = '\0';
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000684 if (access( full_name.long_name, W_OK ) == -1)
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000685 WARN("returns '%s', which doesn't seem to be writeable.\n",
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000686 buffer);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000687 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000688 TRACE("returning %s\n", buffer );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000689 return unique ? unique : num;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000690}
691
692
693/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000694 * GetTempFileNameA (KERNEL32.290)
Gerard Patelc465e191999-10-24 20:48:54 +0000695 */
696UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique,
697 LPSTR buffer)
698{
699 return FILE_GetTempFileName(path, prefix, unique, buffer, FALSE);
700}
701
702/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000703 * GetTempFileNameW (KERNEL32.291)
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000704 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000705UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000706 LPWSTR buffer )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000707{
708 LPSTR patha,prefixa;
709 char buffera[144];
Alexandre Julliarda3960291999-02-26 11:11:13 +0000710 UINT ret;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000711
712 if (!path) return 0;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000713 patha = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
714 prefixa = HEAP_strdupWtoA( GetProcessHeap(), 0, prefix );
Gerard Patelc465e191999-10-24 20:48:54 +0000715 ret = FILE_GetTempFileName( patha, prefixa, unique, buffera, FALSE );
Alexandre Julliard24a62ab2000-11-28 22:40:56 +0000716 MultiByteToWideChar( CP_ACP, 0, buffera, -1, buffer, MAX_PATH );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000717 HeapFree( GetProcessHeap(), 0, patha );
718 HeapFree( GetProcessHeap(), 0, prefixa );
Alexandre Julliardca22b331996-07-12 19:02:39 +0000719 return ret;
720}
721
722
723/***********************************************************************
Gerard Patelc465e191999-10-24 20:48:54 +0000724 * GetTempFileName16 (KERNEL.97)
725 */
726UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
727 LPSTR buffer )
728{
729 char temppath[144];
730
731 if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
732 drive |= DRIVE_GetCurrentDrive() + 'A';
733
734 if ((drive & TF_FORCEDRIVE) &&
735 !DRIVE_IsValid( toupper(drive & ~TF_FORCEDRIVE) - 'A' ))
736 {
737 drive &= ~TF_FORCEDRIVE;
738 WARN("invalid drive %d specified\n", drive );
739 }
740
741 if (drive & TF_FORCEDRIVE)
742 sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
743 else
744 GetTempPathA( 132, temppath );
745 return (UINT16)FILE_GetTempFileName( temppath, prefix, unique, buffer, TRUE );
746}
747
748/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000749 * FILE_DoOpenFile
750 *
751 * Implementation of OpenFile16() and OpenFile32().
Alexandre Julliardca22b331996-07-12 19:02:39 +0000752 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000753static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
754 BOOL win32 )
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000755{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000756 HFILE hFileRet;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000757 FILETIME filetime;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000758 WORD filedatetime[2];
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000759 DOS_FULL_NAME full_name;
Alexandre Julliard05625391999-01-03 11:55:56 +0000760 DWORD access, sharing;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000761 char *p;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000762
Alexandre Julliarda3960291999-02-26 11:11:13 +0000763 if (!ofs) return HFILE_ERROR;
Uwe Bonnese4f46dc1999-06-06 17:08:13 +0000764
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000765 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",name,
Uwe Bonnese4f46dc1999-06-06 17:08:13 +0000766 ((mode & 0x3 )==OF_READ)?"OF_READ":
767 ((mode & 0x3 )==OF_WRITE)?"OF_WRITE":
768 ((mode & 0x3 )==OF_READWRITE)?"OF_READWRITE":"unknown",
769 ((mode & 0x70 )==OF_SHARE_COMPAT)?"OF_SHARE_COMPAT":
770 ((mode & 0x70 )==OF_SHARE_DENY_NONE)?"OF_SHARE_DENY_NONE":
771 ((mode & 0x70 )==OF_SHARE_DENY_READ)?"OF_SHARE_DENY_READ":
772 ((mode & 0x70 )==OF_SHARE_DENY_WRITE)?"OF_SHARE_DENY_WRITE":
773 ((mode & 0x70 )==OF_SHARE_EXCLUSIVE)?"OF_SHARE_EXCLUSIVE":"unknown",
774 ((mode & OF_PARSE )==OF_PARSE)?"OF_PARSE ":"",
775 ((mode & OF_DELETE )==OF_DELETE)?"OF_DELETE ":"",
776 ((mode & OF_VERIFY )==OF_VERIFY)?"OF_VERIFY ":"",
777 ((mode & OF_SEARCH )==OF_SEARCH)?"OF_SEARCH ":"",
778 ((mode & OF_CANCEL )==OF_CANCEL)?"OF_CANCEL ":"",
779 ((mode & OF_CREATE )==OF_CREATE)?"OF_CREATE ":"",
780 ((mode & OF_PROMPT )==OF_PROMPT)?"OF_PROMPT ":"",
781 ((mode & OF_EXIST )==OF_EXIST)?"OF_EXIST ":"",
782 ((mode & OF_REOPEN )==OF_REOPEN)?"OF_REOPEN ":""
783 );
784
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000785
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000786 ofs->cBytes = sizeof(OFSTRUCT);
787 ofs->nErrCode = 0;
788 if (mode & OF_REOPEN) name = ofs->szPathName;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000789
790 if (!name) {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000791 ERR("called with `name' set to NULL ! Please debug.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +0000792 return HFILE_ERROR;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000793 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000794
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000795 TRACE("%s %04x\n", name, mode );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000796
Alexandre Julliard889f7421997-04-15 17:19:52 +0000797 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
798 Are there any cases where getting the path here is wrong?
799 Uwe Bonnes 1997 Apr 2 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000800 if (!GetFullPathNameA( name, sizeof(ofs->szPathName),
Alexandre Julliard889f7421997-04-15 17:19:52 +0000801 ofs->szPathName, NULL )) goto error;
Alexandre Julliard05625391999-01-03 11:55:56 +0000802 FILE_ConvertOFMode( mode, &access, &sharing );
Alexandre Julliard889f7421997-04-15 17:19:52 +0000803
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000804 /* OF_PARSE simply fills the structure */
805
806 if (mode & OF_PARSE)
807 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000808 ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' )
809 != DRIVE_REMOVABLE);
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000810 TRACE("(%s): OF_PARSE, res = '%s'\n",
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000811 name, ofs->szPathName );
812 return 0;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000813 }
814
815 /* OF_CREATE is completely different from all other options, so
816 handle it first */
817
818 if (mode & OF_CREATE)
819 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000820 if ((hFileRet = CreateFileA( name, GENERIC_READ | GENERIC_WRITE,
Alexandre Julliard638f1691999-01-17 16:32:32 +0000821 sharing, NULL, CREATE_ALWAYS,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000822 FILE_ATTRIBUTE_NORMAL, -1 ))== INVALID_HANDLE_VALUE)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000823 goto error;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000824 goto success;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000825 }
826
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000827 /* If OF_SEARCH is set, ignore the given path */
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000828
829 if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
830 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000831 /* First try the file name as is */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000832 if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000833 /* Now remove the path */
834 if (name[0] && (name[1] == ':')) name += 2;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000835 if ((p = strrchr( name, '\\' ))) name = p + 1;
836 if ((p = strrchr( name, '/' ))) name = p + 1;
837 if (!name[0]) goto not_found;
838 }
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000839
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000840 /* Now look for the file */
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000841
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000842 if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000843
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000844found:
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000845 TRACE("found %s = %s\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000846 full_name.long_name, full_name.short_name );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000847 lstrcpynA( ofs->szPathName, full_name.short_name,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000848 sizeof(ofs->szPathName) );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000849
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000850 if (mode & OF_SHARE_EXCLUSIVE)
Uwe Bonnese6b5e381998-10-18 14:48:31 +0000851 /* Some InstallShield version uses OF_SHARE_EXCLUSIVE
852 on the file <tempdir>/_ins0432._mp to determine how
853 far installation has proceeded.
854 _ins0432._mp is an executable and while running the
855 application expects the open with OF_SHARE_ to fail*/
856 /* Probable FIXME:
857 As our loader closes the files after loading the executable,
858 we can't find the running executable with FILE_InUse.
859 Perhaps the loader should keep the file open.
860 Recheck against how Win handles that case */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000861 {
862 char *last = strrchr(full_name.long_name,'/');
863 if (!last)
864 last = full_name.long_name - 1;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000865 if (GetModuleHandle16(last+1))
866 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000867 TRACE("Denying shared open for %s\n",full_name.long_name);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000868 return HFILE_ERROR;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000869 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000870 }
871
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000872 if (mode & OF_DELETE)
873 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000874 if (unlink( full_name.long_name ) == -1) goto not_found;
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000875 TRACE("(%s): OF_DELETE return = OK\n", name);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000876 return 1;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000877 }
878
Alexandre Julliard05625391999-01-03 11:55:56 +0000879 hFileRet = FILE_CreateFile( full_name.long_name, access, sharing,
Alexandre Julliardfbace6e2000-04-04 20:35:45 +0000880 NULL, OPEN_EXISTING, 0, -1,
881 DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000882 if (hFileRet == HFILE_ERROR) goto not_found;
Uwe Bonnese6b5e381998-10-18 14:48:31 +0000883
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000884 GetFileTime( hFileRet, NULL, NULL, &filetime );
885 FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000886 if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000887 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000888 if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) ))
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000889 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000890 CloseHandle( hFileRet );
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000891 WARN("(%s): OF_VERIFY failed\n", name );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000892 /* FIXME: what error here? */
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000893 SetLastError( ERROR_FILE_NOT_FOUND );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000894 goto error;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000895 }
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000896 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000897 memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000898
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000899success: /* We get here if the open was successful */
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000900 TRACE("(%s): OK, return = %d\n", name, hFileRet );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000901 if (win32)
902 {
903 if (mode & OF_EXIST) /* Return the handle, but close it first */
904 CloseHandle( hFileRet );
905 }
906 else
907 {
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000908 hFileRet = Win32HandleToDosFileHandle( hFileRet );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000909 if (hFileRet == HFILE_ERROR16) goto error;
910 if (mode & OF_EXIST) /* Return the handle, but close it first */
911 _lclose16( hFileRet );
912 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000913 return hFileRet;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000914
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000915not_found: /* We get here if the file does not exist */
Andreas Mohr20cd9352000-09-12 23:40:40 +0000916 WARN("'%s' not found or sharing violation\n", name );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000917 SetLastError( ERROR_FILE_NOT_FOUND );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000918 /* fall through */
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000919
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000920error: /* We get here if there was an error opening the file */
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000921 ofs->nErrCode = GetLastError();
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000922 WARN("(%s): return = HFILE_ERROR error= %d\n",
Alexandre Julliard889f7421997-04-15 17:19:52 +0000923 name,ofs->nErrCode );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000924 return HFILE_ERROR;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000925}
926
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000927
928/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000929 * OpenFile16 (KERNEL.74)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000930 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000931HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000932{
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000933 return FILE_DoOpenFile( name, ofs, mode, FALSE );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000934}
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000935
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000936
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000937/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000938 * OpenFile (KERNEL32.396)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000939 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000940HFILE WINAPI OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000941{
942 return FILE_DoOpenFile( name, ofs, mode, TRUE );
943}
944
945
946/***********************************************************************
Marcus Meissnerb12e72d1999-01-23 14:01:08 +0000947 * FILE_InitProcessDosHandles
948 *
949 * Allocates the default DOS handles for a process. Called either by
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000950 * Win32HandleToDosFileHandle below or by the DOSVM stuff.
Marcus Meissnerb12e72d1999-01-23 14:01:08 +0000951 */
Alexandre Julliard231674d2000-08-09 22:30:18 +0000952static void FILE_InitProcessDosHandles( void )
953{
954 dos_handles[0] = GetStdHandle(STD_INPUT_HANDLE);
955 dos_handles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
956 dos_handles[2] = GetStdHandle(STD_ERROR_HANDLE);
957 dos_handles[3] = GetStdHandle(STD_ERROR_HANDLE);
958 dos_handles[4] = GetStdHandle(STD_ERROR_HANDLE);
Marcus Meissnerb12e72d1999-01-23 14:01:08 +0000959}
960
961/***********************************************************************
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000962 * Win32HandleToDosFileHandle (KERNEL32.21)
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000963 *
964 * Allocate a DOS handle for a Win32 handle. The Win32 handle is no
965 * longer valid after this function (even on failure).
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000966 *
967 * Note: this is not exactly right, since on Win95 the Win32 handles
968 * are on top of DOS handles and we do it the other way
969 * around. Should be good enough though.
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000970 */
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000971HFILE WINAPI Win32HandleToDosFileHandle( HANDLE handle )
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000972{
973 int i;
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000974
Alexandre Julliarda3960291999-02-26 11:11:13 +0000975 if (!handle || (handle == INVALID_HANDLE_VALUE))
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000976 return HFILE_ERROR;
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000977
Alexandre Julliard231674d2000-08-09 22:30:18 +0000978 for (i = 5; i < DOS_TABLE_SIZE; i++)
979 if (!dos_handles[i])
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000980 {
Alexandre Julliard231674d2000-08-09 22:30:18 +0000981 dos_handles[i] = handle;
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000982 TRACE("Got %d for h32 %d\n", i, handle );
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000983 return (HFILE)i;
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000984 }
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000985 CloseHandle( handle );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +0000986 SetLastError( ERROR_TOO_MANY_OPEN_FILES );
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000987 return HFILE_ERROR;
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000988}
989
990
991/***********************************************************************
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000992 * DosFileHandleToWin32Handle (KERNEL32.20)
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000993 *
994 * Return the Win32 handle for a DOS handle.
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000995 *
996 * Note: this is not exactly right, since on Win95 the Win32 handles
997 * are on top of DOS handles and we do it the other way
998 * around. Should be good enough though.
Alexandre Julliard8da12c41999-01-17 16:55:11 +0000999 */
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001000HANDLE WINAPI DosFileHandleToWin32Handle( HFILE handle )
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001001{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001002 HFILE16 hfile = (HFILE16)handle;
Alexandre Julliard231674d2000-08-09 22:30:18 +00001003 if (hfile < 5 && !dos_handles[hfile]) FILE_InitProcessDosHandles();
1004 if ((hfile >= DOS_TABLE_SIZE) || !dos_handles[hfile])
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001005 {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001006 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001007 return INVALID_HANDLE_VALUE;
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001008 }
Alexandre Julliard231674d2000-08-09 22:30:18 +00001009 return dos_handles[hfile];
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001010}
1011
1012
1013/***********************************************************************
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001014 * DisposeLZ32Handle (KERNEL32.22)
1015 *
1016 * Note: this is not entirely correct, we should only close the
1017 * 32-bit handle and not the 16-bit one, but we cannot do
1018 * this because of the way our DOS handles are implemented.
1019 * It shouldn't break anything though.
1020 */
1021void WINAPI DisposeLZ32Handle( HANDLE handle )
1022{
1023 int i;
1024
1025 if (!handle || (handle == INVALID_HANDLE_VALUE)) return;
1026
1027 for (i = 5; i < DOS_TABLE_SIZE; i++)
1028 if (dos_handles[i] == handle)
1029 {
1030 dos_handles[i] = 0;
1031 CloseHandle( handle );
1032 break;
1033 }
1034}
1035
1036
1037/***********************************************************************
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001038 * FILE_Dup2
1039 *
1040 * dup2() function for DOS handles.
1041 */
1042HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 )
1043{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001044 HANDLE new_handle;
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001045
Alexandre Julliard231674d2000-08-09 22:30:18 +00001046 if (hFile1 < 5 && !dos_handles[hFile1]) FILE_InitProcessDosHandles();
1047
1048 if ((hFile1 >= DOS_TABLE_SIZE) || (hFile2 >= DOS_TABLE_SIZE) || !dos_handles[hFile1])
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001049 {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001050 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001051 return HFILE_ERROR16;
1052 }
1053 if (hFile2 < 5)
1054 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001055 FIXME("stdio handle closed, need proper conversion\n" );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001056 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001057 return HFILE_ERROR16;
1058 }
Alexandre Julliard231674d2000-08-09 22:30:18 +00001059 if (!DuplicateHandle( GetCurrentProcess(), dos_handles[hFile1],
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001060 GetCurrentProcess(), &new_handle,
1061 0, FALSE, DUPLICATE_SAME_ACCESS ))
1062 return HFILE_ERROR16;
Alexandre Julliard231674d2000-08-09 22:30:18 +00001063 if (dos_handles[hFile2]) CloseHandle( dos_handles[hFile2] );
1064 dos_handles[hFile2] = new_handle;
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001065 return hFile2;
1066}
1067
1068
1069/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001070 * _lclose16 (KERNEL.81)
1071 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001072HFILE16 WINAPI _lclose16( HFILE16 hFile )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001073{
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001074 if (hFile < 5)
1075 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001076 FIXME("stdio handle closed, need proper conversion\n" );
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001077 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001078 return HFILE_ERROR16;
1079 }
Alexandre Julliard231674d2000-08-09 22:30:18 +00001080 if ((hFile >= DOS_TABLE_SIZE) || !dos_handles[hFile])
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001081 {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001082 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001083 return HFILE_ERROR16;
1084 }
Alexandre Julliard231674d2000-08-09 22:30:18 +00001085 TRACE("%d (handle32=%d)\n", hFile, dos_handles[hFile] );
1086 CloseHandle( dos_handles[hFile] );
1087 dos_handles[hFile] = 0;
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001088 return 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001089}
1090
1091
1092/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001093 * _lclose (KERNEL32.592)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001094 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001095HFILE WINAPI _lclose( HFILE hFile )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001096{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001097 TRACE("handle %d\n", hFile );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001098 return CloseHandle( hFile ) ? 0 : HFILE_ERROR;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001099}
1100
Moshe Vainer0ea089b1999-11-10 19:51:01 +00001101/***********************************************************************
1102 * GetOverlappedResult (KERNEL32.360)
1103 */
1104BOOL WINAPI GetOverlappedResult(HANDLE hFile,LPOVERLAPPED lpOverlapped,
1105 LPDWORD lpNumberOfBytesTransferred,
1106 BOOL bWait)
1107{
Andreas Mohr2caee712000-07-16 15:44:22 +00001108 /* Since all i/o is currently synchronous,
Moshe Vainer0ea089b1999-11-10 19:51:01 +00001109 * return true, assuming ReadFile/WriteFile
1110 * have completed the operation */
1111 FIXME("NO Asynch I/O, assuming Read/Write succeeded\n" );
1112 return TRUE;
1113}
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001114
1115/***********************************************************************
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001116 * ReadFile (KERNEL32.428)
1117 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001118BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001119 LPDWORD bytesRead, LPOVERLAPPED overlapped )
1120{
Alexandre Julliard55443871998-12-31 15:52:06 +00001121 int unix_handle, result;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001122
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001123 TRACE("%d %p %ld\n", hFile, buffer, bytesToRead );
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001124
1125 if (bytesRead) *bytesRead = 0; /* Do this before anything else */
1126 if (!bytesToRead) return TRUE;
1127
Peter Gantenf6c43881999-12-11 23:08:00 +00001128 if ( overlapped ) {
1129 SetLastError ( ERROR_INVALID_PARAMETER );
1130 return FALSE;
1131 }
1132
Alexandre Julliard92643002000-08-31 01:59:51 +00001133 unix_handle = FILE_GetUnixHandle( hFile, GENERIC_READ );
Alexandre Julliard55443871998-12-31 15:52:06 +00001134 if (unix_handle == -1) return FALSE;
1135 while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001136 {
Alexandre Julliard55443871998-12-31 15:52:06 +00001137 if ((errno == EAGAIN) || (errno == EINTR)) continue;
Alexandre Julliard982a2232000-12-13 20:20:09 +00001138 if ((errno == EFAULT) && !IsBadWritePtr( buffer, bytesToRead )) continue;
Alexandre Julliard55443871998-12-31 15:52:06 +00001139 FILE_SetDosError();
1140 break;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001141 }
Alexandre Julliard55443871998-12-31 15:52:06 +00001142 close( unix_handle );
1143 if (result == -1) return FALSE;
1144 if (bytesRead) *bytesRead = result;
1145 return TRUE;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001146}
1147
1148
1149/***********************************************************************
1150 * WriteFile (KERNEL32.578)
1151 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001152BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001153 LPDWORD bytesWritten, LPOVERLAPPED overlapped )
1154{
Alexandre Julliard55443871998-12-31 15:52:06 +00001155 int unix_handle, result;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001156
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001157 TRACE("%d %p %ld\n", hFile, buffer, bytesToWrite );
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001158
1159 if (bytesWritten) *bytesWritten = 0; /* Do this before anything else */
1160 if (!bytesToWrite) return TRUE;
1161
Peter Gantenf6c43881999-12-11 23:08:00 +00001162 if ( overlapped ) {
1163 SetLastError ( ERROR_INVALID_PARAMETER );
1164 return FALSE;
1165 }
1166
Alexandre Julliard92643002000-08-31 01:59:51 +00001167 unix_handle = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
Alexandre Julliard55443871998-12-31 15:52:06 +00001168 if (unix_handle == -1) return FALSE;
1169 while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001170 {
Alexandre Julliard55443871998-12-31 15:52:06 +00001171 if ((errno == EAGAIN) || (errno == EINTR)) continue;
Alexandre Julliard982a2232000-12-13 20:20:09 +00001172 if ((errno == EFAULT) && !IsBadReadPtr( buffer, bytesToWrite )) continue;
Gerard Patel8f3c0a31999-06-27 15:26:37 +00001173 if (errno == ENOSPC)
1174 SetLastError( ERROR_DISK_FULL );
1175 else
Alexandre Julliard55443871998-12-31 15:52:06 +00001176 FILE_SetDosError();
1177 break;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001178 }
Alexandre Julliard55443871998-12-31 15:52:06 +00001179 close( unix_handle );
1180 if (result == -1) return FALSE;
1181 if (bytesWritten) *bytesWritten = result;
1182 return TRUE;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001183}
1184
1185
1186/***********************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001187 * WIN16_hread
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001188 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001189LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001190{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001191 LONG maxlen;
1192
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001193 TRACE("%d %08lx %ld\n",
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001194 hFile, (DWORD)buffer, count );
1195
1196 /* Some programs pass a count larger than the allocated buffer */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001197 maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001198 if (count > maxlen) count = maxlen;
Alexandre Julliard982a2232000-12-13 20:20:09 +00001199 return _lread(DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001200}
1201
1202
1203/***********************************************************************
1204 * WIN16_lread
1205 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001206UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001207{
1208 return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
1209}
1210
1211
1212/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001213 * _lread (KERNEL32.596)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001214 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001215UINT WINAPI _lread( HFILE handle, LPVOID buffer, UINT count )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001216{
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001217 DWORD result;
1218 if (!ReadFile( handle, buffer, count, &result, NULL )) return -1;
1219 return result;
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001220}
1221
1222
1223/***********************************************************************
1224 * _lread16 (KERNEL.82)
1225 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001226UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001227{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001228 return (UINT16)_lread(DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001229}
1230
1231
1232/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001233 * _lcreat16 (KERNEL.83)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001234 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001235HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001236{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001237 return Win32HandleToDosFileHandle( _lcreat( path, attr ) );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001238}
1239
1240
1241/***********************************************************************
Alexandre Julliardd5240f11999-04-03 13:54:51 +00001242 * _lcreat (KERNEL32.593)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001243 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001244HFILE WINAPI _lcreat( LPCSTR path, INT attr )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001245{
Alexandre Julliardd5240f11999-04-03 13:54:51 +00001246 /* Mask off all flags not explicitly allowed by the doc */
1247 attr &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001248 TRACE("%s %02x\n", path, attr );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001249 return CreateFileA( path, GENERIC_READ | GENERIC_WRITE,
Alexandre Julliardd5240f11999-04-03 13:54:51 +00001250 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1251 CREATE_ALWAYS, attr, -1 );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001252}
1253
1254
1255/***********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001256 * SetFilePointer (KERNEL32.492)
1257 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001258DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001259 DWORD method )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001260{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001261 DWORD ret = 0xffffffff;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001262
Hidenori Takeshima66791af2000-07-31 23:26:50 +00001263 if (highword &&
1264 ((distance >= 0 && *highword != 0) || (distance < 0 && *highword != -1)))
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001265 {
Hidenori Takeshima66791af2000-07-31 23:26:50 +00001266 FIXME("64-bit offsets not supported yet\n"
1267 "SetFilePointer(%08x,%08lx,%08lx,%08lx)\n",
1268 hFile,distance,*highword,method);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001269 SetLastError( ERROR_INVALID_PARAMETER );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001270 return ret;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001271 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001272 TRACE("handle %d offset %ld origin %ld\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001273 hFile, distance, method );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001274
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001275 SERVER_START_REQ
1276 {
1277 struct set_file_pointer_request *req = server_alloc_req( sizeof(*req), 0 );
1278 req->handle = hFile;
1279 req->low = distance;
1280 req->high = highword ? *highword : (distance >= 0) ? 0 : -1;
1281 /* FIXME: assumes 1:1 mapping between Windows and Unix seek constants */
1282 req->whence = method;
1283 SetLastError( 0 );
1284 if (!server_call( REQ_SET_FILE_POINTER ))
1285 {
1286 ret = req->new_low;
1287 if (highword) *highword = req->new_high;
1288 }
1289 }
1290 SERVER_END_REQ;
1291 return ret;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001292}
1293
1294
1295/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001296 * _llseek16 (KERNEL.84)
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001297 *
1298 * FIXME:
1299 * Seeking before the start of the file should be allowed for _llseek16,
1300 * but cause subsequent I/O operations to fail (cf. interrupt list)
1301 *
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001302 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001303LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001304{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001305 return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001306}
1307
1308
1309/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001310 * _llseek (KERNEL32.594)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001311 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001312LONG WINAPI _llseek( HFILE hFile, LONG lOffset, INT nOrigin )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001313{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001314 return SetFilePointer( hFile, lOffset, NULL, nOrigin );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001315}
1316
1317
1318/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001319 * _lopen16 (KERNEL.85)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001320 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001321HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001322{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001323 return Win32HandleToDosFileHandle( _lopen( path, mode ) );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001324}
1325
1326
1327/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001328 * _lopen (KERNEL32.595)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001329 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001330HFILE WINAPI _lopen( LPCSTR path, INT mode )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001331{
Alexandre Julliard05625391999-01-03 11:55:56 +00001332 DWORD access, sharing;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001333
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001334 TRACE("('%s',%04x)\n", path, mode );
Alexandre Julliard05625391999-01-03 11:55:56 +00001335 FILE_ConvertOFMode( mode, &access, &sharing );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001336 return CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, -1 );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001337}
1338
1339
1340/***********************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001341 * _lwrite16 (KERNEL.86)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001342 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001343UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001344{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001345 return (UINT16)_hwrite( DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001346}
1347
1348/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001349 * _lwrite (KERNEL32.761)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001350 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001351UINT WINAPI _lwrite( HFILE hFile, LPCSTR buffer, UINT count )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001352{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001353 return (UINT)_hwrite( hFile, buffer, (LONG)count );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001354}
1355
1356
1357/***********************************************************************
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001358 * _hread16 (KERNEL.349)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001359 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001360LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001361{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001362 return _lread( DosFileHandleToWin32Handle(hFile), buffer, count );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001363}
1364
1365
1366/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001367 * _hread (KERNEL32.590)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001368 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001369LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001370{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001371 return _lread( hFile, buffer, count );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001372}
1373
1374
1375/***********************************************************************
1376 * _hwrite16 (KERNEL.350)
1377 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001378LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001379{
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001380 return _hwrite( DosFileHandleToWin32Handle(hFile), buffer, count );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001381}
1382
1383
1384/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001385 * _hwrite (KERNEL32.591)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001386 *
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001387 * experimentation yields that _lwrite:
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001388 * o truncates the file at the current position with
1389 * a 0 len write
1390 * o returns 0 on a 0 length write
1391 * o works with console handles
1392 *
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001393 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001394LONG WINAPI _hwrite( HFILE handle, LPCSTR buffer, LONG count )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001395{
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001396 DWORD result;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001397
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001398 TRACE("%d %p %ld\n", handle, buffer, count );
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001399
1400 if (!count)
1401 {
1402 /* Expand or truncate at current position */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001403 if (!SetEndOfFile( handle )) return HFILE_ERROR;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001404 return 0;
1405 }
1406 if (!WriteFile( handle, buffer, count, &result, NULL ))
Alexandre Julliarda3960291999-02-26 11:11:13 +00001407 return HFILE_ERROR;
Alexandre Julliardfbe63ad1998-12-30 12:10:06 +00001408 return result;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001409}
1410
1411
1412/***********************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001413 * SetHandleCount16 (KERNEL.199)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001414 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001415UINT16 WINAPI SetHandleCount16( UINT16 count )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001416{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001417 HGLOBAL16 hPDB = GetCurrentPDB16();
1418 PDB16 *pdb = (PDB16 *)GlobalLock16( hPDB );
Alexandre Julliard982a2232000-12-13 20:20:09 +00001419 BYTE *files = MapSL( pdb->fileHandlesPtr );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001420
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001421 TRACE("(%d)\n", count );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001422
1423 if (count < 20) count = 20; /* No point in going below 20 */
1424 else if (count > 254) count = 254;
1425
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001426 if (count == 20)
1427 {
1428 if (pdb->nbFiles > 20)
1429 {
1430 memcpy( pdb->fileHandles, files, 20 );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001431 GlobalFree16( pdb->hFileHandles );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001432 pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433 GlobalHandleToSel16( hPDB ) );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001434 pdb->hFileHandles = 0;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001435 pdb->nbFiles = 20;
1436 }
1437 }
1438 else /* More than 20, need a new file handles table */
1439 {
1440 BYTE *newfiles;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00001441 HGLOBAL16 newhandle = GlobalAlloc16( GMEM_MOVEABLE, count );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001442 if (!newhandle)
1443 {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001444 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001445 return pdb->nbFiles;
1446 }
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001447 newfiles = (BYTE *)GlobalLock16( newhandle );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001448
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001449 if (count > pdb->nbFiles)
1450 {
1451 memcpy( newfiles, files, pdb->nbFiles );
1452 memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
1453 }
1454 else memcpy( newfiles, files, count );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001455 if (pdb->nbFiles > 20) GlobalFree16( pdb->hFileHandles );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001456 pdb->fileHandlesPtr = WIN16_GlobalLock16( newhandle );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001457 pdb->hFileHandles = newhandle;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001458 pdb->nbFiles = count;
1459 }
1460 return pdb->nbFiles;
1461}
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001462
1463
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001464/*************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001465 * SetHandleCount (KERNEL32.494)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001466 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001467UINT WINAPI SetHandleCount( UINT count )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001468{
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001469 return min( 256, count );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001470}
1471
1472
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001473/***********************************************************************
1474 * FlushFileBuffers (KERNEL32.133)
1475 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001476BOOL WINAPI FlushFileBuffers( HANDLE hFile )
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001477{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001478 BOOL ret;
1479 SERVER_START_REQ
1480 {
1481 struct flush_file_request *req = server_alloc_req( sizeof(*req), 0 );
1482 req->handle = hFile;
1483 ret = !server_call( REQ_FLUSH_FILE );
1484 }
1485 SERVER_END_REQ;
1486 return ret;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001487}
1488
1489
1490/**************************************************************************
1491 * SetEndOfFile (KERNEL32.483)
1492 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001493BOOL WINAPI SetEndOfFile( HANDLE hFile )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001494{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001495 BOOL ret;
1496 SERVER_START_REQ
1497 {
1498 struct truncate_file_request *req = server_alloc_req( sizeof(*req), 0 );
1499 req->handle = hFile;
1500 ret = !server_call( REQ_TRUNCATE_FILE );
1501 }
1502 SERVER_END_REQ;
1503 return ret;
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001504}
1505
1506
1507/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001508 * DeleteFile16 (KERNEL.146)
1509 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001510BOOL16 WINAPI DeleteFile16( LPCSTR path )
Alexandre Julliard3051b641996-07-05 17:14:13 +00001511{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001512 return DeleteFileA( path );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001513}
1514
1515
1516/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001517 * DeleteFileA (KERNEL32.71)
Alexandre Julliard3051b641996-07-05 17:14:13 +00001518 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001519BOOL WINAPI DeleteFileA( LPCSTR path )
Alexandre Julliard3051b641996-07-05 17:14:13 +00001520{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001521 DOS_FULL_NAME full_name;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001522
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001523 TRACE("'%s'\n", path );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001524
Alexandre Julliard638f1691999-01-17 16:32:32 +00001525 if (!*path)
1526 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001527 ERR("Empty path passed\n");
Alexandre Julliard638f1691999-01-17 16:32:32 +00001528 return FALSE;
1529 }
Alexandre Julliard829fe321998-07-26 14:27:39 +00001530 if (DOSFS_GetDevice( path ))
Alexandre Julliard3051b641996-07-05 17:14:13 +00001531 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001532 WARN("cannot remove DOS device '%s'!\n", path);
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001533 SetLastError( ERROR_FILE_NOT_FOUND );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001534 return FALSE;
1535 }
1536
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001537 if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
1538 if (unlink( full_name.long_name ) == -1)
Alexandre Julliard3051b641996-07-05 17:14:13 +00001539 {
1540 FILE_SetDosError();
1541 return FALSE;
1542 }
1543 return TRUE;
1544}
1545
1546
1547/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001548 * DeleteFileW (KERNEL32.72)
Alexandre Julliard3051b641996-07-05 17:14:13 +00001549 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001550BOOL WINAPI DeleteFileW( LPCWSTR path )
Alexandre Julliard3051b641996-07-05 17:14:13 +00001551{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001552 LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001553 BOOL ret = DeleteFileA( xpath );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001554 HeapFree( GetProcessHeap(), 0, xpath );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001555 return ret;
1556}
1557
1558
1559/***********************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001560 * GetFileType (KERNEL32.222)
1561 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001562DWORD WINAPI GetFileType( HANDLE hFile )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001563{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001564 DWORD ret = FILE_TYPE_UNKNOWN;
1565 SERVER_START_REQ
1566 {
1567 struct get_file_info_request *req = server_alloc_req( sizeof(*req), 0 );
1568 req->handle = hFile;
1569 if (!server_call( REQ_GET_FILE_INFO )) ret = req->type;
1570 }
1571 SERVER_END_REQ;
1572 return ret;
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001573}
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001574
1575
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001576/**************************************************************************
Alexandre Julliard86a75531999-11-21 02:11:48 +00001577 * MoveFileExA (KERNEL32.???)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001578 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001579BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001580{
1581 DOS_FULL_NAME full_name1, full_name2;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001582
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001583 TRACE("(%s,%s,%04lx)\n", fn1, fn2, flag);
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001584
1585 if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
Alexandre Julliard86a75531999-11-21 02:11:48 +00001586
1587 if (fn2) /* !fn2 means delete fn1 */
1588 {
1589 if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))
1590 {
1591 /* target exists, check if we may overwrite */
1592 if (!(flag & MOVEFILE_REPLACE_EXISTING))
1593 {
1594 /* FIXME: Use right error code */
1595 SetLastError( ERROR_ACCESS_DENIED );
1596 return FALSE;
1597 }
1598 }
1599 else if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
1600
1601 /* Source name and target path are valid */
1602
1603 if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
1604 {
1605 /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
1606 Perhaps we should queue these command and execute it
1607 when exiting... What about using on_exit(2)
1608 */
1609 FIXME("Please move existing file '%s' to file '%s' when Wine has finished\n",
1610 full_name1.long_name, full_name2.long_name);
1611 return TRUE;
1612 }
1613
1614 if (full_name1.drive != full_name2.drive)
1615 {
1616 /* use copy, if allowed */
1617 if (!(flag & MOVEFILE_COPY_ALLOWED))
1618 {
1619 /* FIXME: Use right error code */
1620 SetLastError( ERROR_FILE_EXISTS );
1621 return FALSE;
1622 }
1623 return CopyFileA( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) );
1624 }
1625 if (rename( full_name1.long_name, full_name2.long_name ) == -1)
1626 {
1627 FILE_SetDosError();
1628 return FALSE;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001629 }
Alexandre Julliard86a75531999-11-21 02:11:48 +00001630 return TRUE;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001631 }
1632 else /* fn2 == NULL means delete source */
Alexandre Julliard86a75531999-11-21 02:11:48 +00001633 {
1634 if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
1635 {
1636 if (flag & MOVEFILE_COPY_ALLOWED) {
1637 WARN("Illegal flag\n");
1638 SetLastError( ERROR_GEN_FAILURE );
1639 return FALSE;
1640 }
1641 /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
1642 Perhaps we should queue these command and execute it
1643 when exiting... What about using on_exit(2)
1644 */
1645 FIXME("Please delete file '%s' when Wine has finished\n",
1646 full_name1.long_name);
1647 return TRUE;
1648 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001649
Alexandre Julliard86a75531999-11-21 02:11:48 +00001650 if (unlink( full_name1.long_name ) == -1)
1651 {
1652 FILE_SetDosError();
1653 return FALSE;
1654 }
1655 return TRUE; /* successfully deleted */
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001656 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001657}
1658
1659/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001660 * MoveFileExW (KERNEL32.???)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001661 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001662BOOL WINAPI MoveFileExW( LPCWSTR fn1, LPCWSTR fn2, DWORD flag )
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001663{
1664 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
1665 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001666 BOOL res = MoveFileExA( afn1, afn2, flag );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001667 HeapFree( GetProcessHeap(), 0, afn1 );
1668 HeapFree( GetProcessHeap(), 0, afn2 );
1669 return res;
1670}
1671
1672
1673/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001674 * MoveFileA (KERNEL32.387)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001675 *
1676 * Move file or directory
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001677 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001678BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001679{
1680 DOS_FULL_NAME full_name1, full_name2;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001681 struct stat fstat;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001682
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001683 TRACE("(%s,%s)\n", fn1, fn2 );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001684
1685 if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
Marcus Meissner242d23e2000-08-21 03:18:32 +00001686 if (DOSFS_GetFullName( fn2, TRUE, &full_name2 )) {
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001687 /* The new name must not already exist */
Marcus Meissner242d23e2000-08-21 03:18:32 +00001688 SetLastError(ERROR_ALREADY_EXISTS);
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001689 return FALSE;
Marcus Meissner242d23e2000-08-21 03:18:32 +00001690 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001691 if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001692
1693 if (full_name1.drive == full_name2.drive) /* move */
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001694 if (rename( full_name1.long_name, full_name2.long_name ) == -1)
1695 {
1696 FILE_SetDosError();
1697 return FALSE;
1698 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001699 else return TRUE;
1700 else /*copy */ {
1701 if (stat( full_name1.long_name, &fstat ))
1702 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001703 WARN("Invalid source file %s\n",
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001704 full_name1.long_name);
1705 FILE_SetDosError();
1706 return FALSE;
1707 }
1708 if (S_ISDIR(fstat.st_mode)) {
1709 /* No Move for directories across file systems */
1710 /* FIXME: Use right error code */
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00001711 SetLastError( ERROR_GEN_FAILURE );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001712 return FALSE;
1713 }
1714 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001715 return CopyFileA(fn1, fn2, TRUE); /*fail, if exist */
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001716 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001717}
1718
1719
1720/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001721 * MoveFileW (KERNEL32.390)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001722 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001723BOOL WINAPI MoveFileW( LPCWSTR fn1, LPCWSTR fn2 )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001724{
1725 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
1726 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001727 BOOL res = MoveFileA( afn1, afn2 );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001728 HeapFree( GetProcessHeap(), 0, afn1 );
1729 HeapFree( GetProcessHeap(), 0, afn2 );
1730 return res;
1731}
1732
1733
1734/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001735 * CopyFileA (KERNEL32.36)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001736 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001737BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001738{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001739 HFILE h1, h2;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001740 BY_HANDLE_FILE_INFORMATION info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001741 UINT count;
1742 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001743 int mode;
1744 char buffer[2048];
1745
Alexandre Julliarda3960291999-02-26 11:11:13 +00001746 if ((h1 = _lopen( source, OF_READ )) == HFILE_ERROR) return FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001747 if (!GetFileInformationByHandle( h1, &info ))
1748 {
1749 CloseHandle( h1 );
1750 return FALSE;
1751 }
1752 mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001753 if ((h2 = CreateFileA( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
Alexandre Julliard05625391999-01-03 11:55:56 +00001754 fail_if_exists ? CREATE_NEW : CREATE_ALWAYS,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001755 info.dwFileAttributes, h1 )) == HFILE_ERROR)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001756 {
1757 CloseHandle( h1 );
1758 return FALSE;
1759 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001760 while ((count = _lread( h1, buffer, sizeof(buffer) )) > 0)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001761 {
1762 char *p = buffer;
1763 while (count > 0)
1764 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001765 INT res = _lwrite( h2, p, count );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001766 if (res <= 0) goto done;
1767 p += res;
1768 count -= res;
1769 }
1770 }
1771 ret = TRUE;
1772done:
1773 CloseHandle( h1 );
1774 CloseHandle( h2 );
1775 return ret;
1776}
1777
1778
1779/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001780 * CopyFileW (KERNEL32.37)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001781 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001782BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001783{
1784 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
1785 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001786 BOOL ret = CopyFileA( sourceA, destA, fail_if_exists );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001787 HeapFree( GetProcessHeap(), 0, sourceA );
1788 HeapFree( GetProcessHeap(), 0, destA );
1789 return ret;
1790}
1791
1792
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001793/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001794 * CopyFileExA (KERNEL32.858)
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001795 *
1796 * This implementation ignores most of the extra parameters passed-in into
1797 * the "ex" version of the method and calls the CopyFile method.
1798 * It will have to be fixed eventually.
1799 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001800BOOL WINAPI CopyFileExA(LPCSTR sourceFilename,
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001801 LPCSTR destFilename,
1802 LPPROGRESS_ROUTINE progressRoutine,
1803 LPVOID appData,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001804 LPBOOL cancelFlagPointer,
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001805 DWORD copyFlags)
1806{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001807 BOOL failIfExists = FALSE;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001808
1809 /*
1810 * Interpret the only flag that CopyFile can interpret.
1811 */
1812 if ( (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0)
1813 {
1814 failIfExists = TRUE;
1815 }
1816
Alexandre Julliarda3960291999-02-26 11:11:13 +00001817 return CopyFileA(sourceFilename, destFilename, failIfExists);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001818}
1819
1820/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001821 * CopyFileExW (KERNEL32.859)
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001822 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001823BOOL WINAPI CopyFileExW(LPCWSTR sourceFilename,
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001824 LPCWSTR destFilename,
1825 LPPROGRESS_ROUTINE progressRoutine,
1826 LPVOID appData,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001827 LPBOOL cancelFlagPointer,
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001828 DWORD copyFlags)
1829{
1830 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, sourceFilename );
1831 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, destFilename );
1832
Alexandre Julliarda3960291999-02-26 11:11:13 +00001833 BOOL ret = CopyFileExA(sourceA,
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001834 destA,
1835 progressRoutine,
1836 appData,
1837 cancelFlagPointer,
1838 copyFlags);
1839
1840 HeapFree( GetProcessHeap(), 0, sourceA );
1841 HeapFree( GetProcessHeap(), 0, destA );
1842
1843 return ret;
1844}
1845
1846
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001847/***********************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001848 * SetFileTime (KERNEL32.650)
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001849 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001850BOOL WINAPI SetFileTime( HANDLE hFile,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001851 const FILETIME *lpCreationTime,
1852 const FILETIME *lpLastAccessTime,
1853 const FILETIME *lpLastWriteTime )
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001854{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001855 BOOL ret;
1856 SERVER_START_REQ
1857 {
1858 struct set_file_time_request *req = server_alloc_req( sizeof(*req), 0 );
1859 req->handle = hFile;
1860 if (lpLastAccessTime)
Alexandre Julliard27952ef2000-10-13 20:26:03 +00001861 RtlTimeToSecondsSince1970( lpLastAccessTime, (DWORD *)&req->access_time );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001862 else
1863 req->access_time = 0; /* FIXME */
1864 if (lpLastWriteTime)
Alexandre Julliard27952ef2000-10-13 20:26:03 +00001865 RtlTimeToSecondsSince1970( lpLastWriteTime, (DWORD *)&req->write_time );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001866 else
1867 req->write_time = 0; /* FIXME */
1868 ret = !server_call( REQ_SET_FILE_TIME );
1869 }
1870 SERVER_END_REQ;
1871 return ret;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001872}
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001873
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001874
1875/**************************************************************************
1876 * LockFile (KERNEL32.511)
1877 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001878BOOL WINAPI LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001879 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
1880{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001881 BOOL ret;
1882 SERVER_START_REQ
1883 {
1884 struct lock_file_request *req = server_alloc_req( sizeof(*req), 0 );
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001885
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001886 req->handle = hFile;
1887 req->offset_low = dwFileOffsetLow;
1888 req->offset_high = dwFileOffsetHigh;
1889 req->count_low = nNumberOfBytesToLockLow;
1890 req->count_high = nNumberOfBytesToLockHigh;
1891 ret = !server_call( REQ_LOCK_FILE );
1892 }
1893 SERVER_END_REQ;
1894 return ret;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001895}
1896
James Jurane8df90b1999-06-05 08:57:37 +00001897/**************************************************************************
1898 * LockFileEx [KERNEL32.512]
1899 *
1900 * Locks a byte range within an open file for shared or exclusive access.
1901 *
1902 * RETURNS
1903 * success: TRUE
1904 * failure: FALSE
1905 * NOTES
1906 *
1907 * Per Microsoft docs, the third parameter (reserved) must be set to 0.
1908 */
1909BOOL WINAPI LockFileEx( HANDLE hFile, DWORD flags, DWORD reserved,
1910 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1911 LPOVERLAPPED pOverlapped )
1912{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001913 FIXME("hFile=%d,flags=%ld,reserved=%ld,lowbytes=%ld,highbytes=%ld,overlapped=%p: stub.\n",
James Jurane8df90b1999-06-05 08:57:37 +00001914 hFile, flags, reserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh,
1915 pOverlapped);
1916 if (reserved == 0)
1917 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1918 else
1919 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001920 ERR("reserved == %ld: Supposed to be 0??\n", reserved);
James Jurane8df90b1999-06-05 08:57:37 +00001921 SetLastError(ERROR_INVALID_PARAMETER);
1922 }
1923
1924 return FALSE;
1925}
1926
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001927
1928/**************************************************************************
1929 * UnlockFile (KERNEL32.703)
1930 */
Jim Aston031f4fa1999-10-23 19:00:02 +00001931BOOL WINAPI UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001932 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
1933{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001934 BOOL ret;
1935 SERVER_START_REQ
1936 {
1937 struct unlock_file_request *req = server_alloc_req( sizeof(*req), 0 );
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001938
Alexandre Julliard9c2370b2000-08-30 00:00:48 +00001939 req->handle = hFile;
1940 req->offset_low = dwFileOffsetLow;
1941 req->offset_high = dwFileOffsetHigh;
1942 req->count_low = nNumberOfBytesToUnlockLow;
1943 req->count_high = nNumberOfBytesToUnlockHigh;
1944 ret = !server_call( REQ_UNLOCK_FILE );
1945 }
1946 SERVER_END_REQ;
1947 return ret;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001948}
1949
1950
Andreas Mohre00114c1999-07-03 11:56:07 +00001951/**************************************************************************
1952 * UnlockFileEx (KERNEL32.705)
1953 */
1954BOOL WINAPI UnlockFileEx(
1955 HFILE hFile,
1956 DWORD dwReserved,
1957 DWORD nNumberOfBytesToUnlockLow,
1958 DWORD nNumberOfBytesToUnlockHigh,
1959 LPOVERLAPPED lpOverlapped
1960)
1961{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001962 FIXME("hFile=%d,reserved=%ld,lowbytes=%ld,highbytes=%ld,overlapped=%p: stub.\n",
Andreas Mohre00114c1999-07-03 11:56:07 +00001963 hFile, dwReserved, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh,
1964 lpOverlapped);
1965 if (dwReserved == 0)
1966 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1967 else
1968 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001969 ERR("reserved == %ld: Supposed to be 0??\n", dwReserved);
Andreas Mohre00114c1999-07-03 11:56:07 +00001970 SetLastError(ERROR_INVALID_PARAMETER);
1971 }
1972
1973 return FALSE;
1974}
1975
1976
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001977#if 0
1978
1979struct DOS_FILE_LOCK {
1980 struct DOS_FILE_LOCK * next;
1981 DWORD base;
1982 DWORD len;
1983 DWORD processId;
1984 FILE_OBJECT * dos_file;
1985/* char * unix_name;*/
1986};
1987
1988typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
1989
1990static DOS_FILE_LOCK *locks = NULL;
1991static void DOS_RemoveFileLocks(FILE_OBJECT *file);
1992
1993
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001994/* Locks need to be mirrored because unix file locking is based
1995 * on the pid. Inside of wine there can be multiple WINE processes
1996 * that share the same unix pid.
1997 * Read's and writes should check these locks also - not sure
1998 * how critical that is at this point (FIXME).
1999 */
2000
Alexandre Julliarda3960291999-02-26 11:11:13 +00002001static BOOL DOS_AddLock(FILE_OBJECT *file, struct flock *f)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002002{
2003 DOS_FILE_LOCK *curr;
2004 DWORD processId;
2005
2006 processId = GetCurrentProcessId();
2007
2008 /* check if lock overlaps a current lock for the same file */
Alexandre Julliard62a8b431999-01-19 17:48:23 +00002009#if 0
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002010 for (curr = locks; curr; curr = curr->next) {
2011 if (strcmp(curr->unix_name, file->unix_name) == 0) {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002012 if ((f->l_start == curr->base) && (f->l_len == curr->len))
2013 return TRUE;/* region is identic */
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002014 if ((f->l_start < (curr->base + curr->len)) &&
2015 ((f->l_start + f->l_len) > curr->base)) {
2016 /* region overlaps */
2017 return FALSE;
2018 }
2019 }
2020 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +00002021#endif
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002022
Alexandre Julliard90476d62000-02-16 22:47:24 +00002023 curr = HeapAlloc( GetProcessHeap(), 0, sizeof(DOS_FILE_LOCK) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002024 curr->processId = GetCurrentProcessId();
2025 curr->base = f->l_start;
2026 curr->len = f->l_len;
Alexandre Julliard90476d62000-02-16 22:47:24 +00002027/* curr->unix_name = HEAP_strdupA( GetProcessHeap(), 0, file->unix_name);*/
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002028 curr->next = locks;
2029 curr->dos_file = file;
2030 locks = curr;
2031 return TRUE;
2032}
2033
2034static void DOS_RemoveFileLocks(FILE_OBJECT *file)
2035{
2036 DWORD processId;
2037 DOS_FILE_LOCK **curr;
2038 DOS_FILE_LOCK *rem;
2039
2040 processId = GetCurrentProcessId();
2041 curr = &locks;
2042 while (*curr) {
2043 if ((*curr)->dos_file == file) {
2044 rem = *curr;
2045 *curr = (*curr)->next;
Alexandre Julliard90476d62000-02-16 22:47:24 +00002046/* HeapFree( GetProcessHeap(), 0, rem->unix_name );*/
2047 HeapFree( GetProcessHeap(), 0, rem );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002048 }
2049 else
2050 curr = &(*curr)->next;
2051 }
2052}
2053
Alexandre Julliarda3960291999-02-26 11:11:13 +00002054static BOOL DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002055{
2056 DWORD processId;
2057 DOS_FILE_LOCK **curr;
2058 DOS_FILE_LOCK *rem;
2059
2060 processId = GetCurrentProcessId();
2061 for (curr = &locks; *curr; curr = &(*curr)->next) {
2062 if ((*curr)->processId == processId &&
2063 (*curr)->dos_file == file &&
2064 (*curr)->base == f->l_start &&
2065 (*curr)->len == f->l_len) {
2066 /* this is the same lock */
2067 rem = *curr;
2068 *curr = (*curr)->next;
Alexandre Julliard90476d62000-02-16 22:47:24 +00002069/* HeapFree( GetProcessHeap(), 0, rem->unix_name );*/
2070 HeapFree( GetProcessHeap(), 0, rem );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002071 return TRUE;
2072 }
2073 }
2074 /* no matching lock found */
2075 return FALSE;
2076}
2077
2078
2079/**************************************************************************
2080 * LockFile (KERNEL32.511)
2081 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002082BOOL WINAPI LockFile(
2083 HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002084 DWORD nNumberOfBytesToLockLow,DWORD nNumberOfBytesToLockHigh )
2085{
2086 struct flock f;
2087 FILE_OBJECT *file;
2088
Alexandre Julliard359f497e1999-07-04 16:02:24 +00002089 TRACE("handle %d offsetlow=%ld offsethigh=%ld nbyteslow=%ld nbyteshigh=%ld\n",
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002090 hFile, dwFileOffsetLow, dwFileOffsetHigh,
2091 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
2092
2093 if (dwFileOffsetHigh || nNumberOfBytesToLockHigh) {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00002094 FIXME("Unimplemented bytes > 32bits\n");
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002095 return FALSE;
2096 }
2097
2098 f.l_start = dwFileOffsetLow;
2099 f.l_len = nNumberOfBytesToLockLow;
2100 f.l_whence = SEEK_SET;
2101 f.l_pid = 0;
2102 f.l_type = F_WRLCK;
2103
Alexandre Julliard338e7571998-12-27 15:28:54 +00002104 if (!(file = FILE_GetFile(hFile,0,NULL))) return FALSE;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002105
2106 /* shadow locks internally */
2107 if (!DOS_AddLock(file, &f)) {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00002108 SetLastError( ERROR_LOCK_VIOLATION );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002109 return FALSE;
2110 }
2111
2112 /* FIXME: Unix locking commented out for now, doesn't work with Excel */
2113#ifdef USE_UNIX_LOCKS
2114 if (fcntl(file->unix_handle, F_SETLK, &f) == -1) {
2115 if (errno == EACCES || errno == EAGAIN) {
Alexandre Julliard4ff2a271999-01-31 15:23:45 +00002116 SetLastError( ERROR_LOCK_VIOLATION );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002117 }
2118 else {
2119 FILE_SetDosError();
2120 }
2121 /* remove our internal copy of the lock */
2122 DOS_RemoveLock(file, &f);
2123 return FALSE;
2124 }
2125#endif
2126 return TRUE;
2127}
2128
2129
2130/**************************************************************************
2131 * UnlockFile (KERNEL32.703)
2132 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002133BOOL WINAPI UnlockFile(
2134 HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002135 DWORD nNumberOfBytesToUnlockLow,DWORD nNumberOfBytesToUnlockHigh )
2136{
2137 FILE_OBJECT *file;
2138 struct flock f;
2139
Alexandre Julliard359f497e1999-07-04 16:02:24 +00002140 TRACE("handle %d offsetlow=%ld offsethigh=%ld nbyteslow=%ld nbyteshigh=%ld\n",
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002141 hFile, dwFileOffsetLow, dwFileOffsetHigh,
2142 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
2143
2144 if (dwFileOffsetHigh || nNumberOfBytesToUnlockHigh) {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00002145 WARN("Unimplemented bytes > 32bits\n");
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002146 return FALSE;
2147 }
2148
2149 f.l_start = dwFileOffsetLow;
2150 f.l_len = nNumberOfBytesToUnlockLow;
2151 f.l_whence = SEEK_SET;
2152 f.l_pid = 0;
2153 f.l_type = F_UNLCK;
2154
Alexandre Julliard338e7571998-12-27 15:28:54 +00002155 if (!(file = FILE_GetFile(hFile,0,NULL))) return FALSE;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002156
2157 DOS_RemoveLock(file, &f); /* ok if fails - may be another wine */
2158
2159 /* FIXME: Unix locking commented out for now, doesn't work with Excel */
2160#ifdef USE_UNIX_LOCKS
2161 if (fcntl(file->unix_handle, F_SETLK, &f) == -1) {
2162 FILE_SetDosError();
2163 return FALSE;
2164 }
2165#endif
2166 return TRUE;
2167}
Alexandre Julliard62a8b431999-01-19 17:48:23 +00002168#endif
Alexandre Julliardd37eb361997-07-20 16:23:21 +00002169
Alexandre Julliarda845b881998-06-01 10:44:35 +00002170/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00002171 * GetFileAttributesExA [KERNEL32.874]
Alexandre Julliarda845b881998-06-01 10:44:35 +00002172 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002173BOOL WINAPI GetFileAttributesExA(
Alexandre Julliarda845b881998-06-01 10:44:35 +00002174 LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
2175 LPVOID lpFileInformation)
2176{
2177 DOS_FULL_NAME full_name;
2178 BY_HANDLE_FILE_INFORMATION info;
2179
2180 if (lpFileName == NULL) return FALSE;
2181 if (lpFileInformation == NULL) return FALSE;
2182
2183 if (fInfoLevelId == GetFileExInfoStandard) {
2184 LPWIN32_FILE_ATTRIBUTE_DATA lpFad =
2185 (LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
2186 if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name )) return FALSE;
2187 if (!FILE_Stat( full_name.long_name, &info )) return FALSE;
2188
2189 lpFad->dwFileAttributes = info.dwFileAttributes;
2190 lpFad->ftCreationTime = info.ftCreationTime;
2191 lpFad->ftLastAccessTime = info.ftLastAccessTime;
2192 lpFad->ftLastWriteTime = info.ftLastWriteTime;
2193 lpFad->nFileSizeHigh = info.nFileSizeHigh;
2194 lpFad->nFileSizeLow = info.nFileSizeLow;
2195 }
2196 else {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00002197 FIXME("invalid info level %d!\n", fInfoLevelId);
Alexandre Julliarda845b881998-06-01 10:44:35 +00002198 return FALSE;
2199 }
2200
2201 return TRUE;
2202}
2203
2204
2205/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00002206 * GetFileAttributesExW [KERNEL32.875]
Alexandre Julliarda845b881998-06-01 10:44:35 +00002207 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002208BOOL WINAPI GetFileAttributesExW(
Alexandre Julliarda845b881998-06-01 10:44:35 +00002209 LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
2210 LPVOID lpFileInformation)
2211{
2212 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002213 BOOL res =
2214 GetFileAttributesExA( nameA, fInfoLevelId, lpFileInformation);
Alexandre Julliarda845b881998-06-01 10:44:35 +00002215 HeapFree( GetProcessHeap(), 0, nameA );
2216 return res;
2217}