Release 960623
[wine/multimedia.git] / win32 / file.c
blob5e5ad28bd1a00955ebd39e122c962a8258497aa3
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis, Sven Verdoolaege, and Cameron Heide
5 */
7 #include <errno.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/mman.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <time.h>
16 #include "windows.h"
17 #include "winbase.h"
18 #include "winerror.h"
19 #include "kernel32.h"
20 #include "handle32.h"
21 #include "dos_fs.h"
22 #include "stddebug.h"
23 #define DEBUG_WIN32
24 #include "debug.h"
27 extern FILE_OBJECT *hstdin;
28 extern FILE_OBJECT *hstdout;
29 extern FILE_OBJECT *hstderr;
31 static void UnixTimeToFileTime(time_t unix_time, FILETIME *filetime);
32 static int TranslateCreationFlags(DWORD create_flags);
33 static int TranslateAccessFlags(DWORD access_flags);
34 #ifndef MAP_ANON
35 #define MAP_ANON 0
36 #endif
38 /***********************************************************************
39 * OpenFileMappingA (KERNEL32.397)
42 HANDLE32 OpenFileMapping(DWORD access, BOOL inherit,const char *fname)
44 return 0;
46 /***********************************************************************
47 * CreateFileMappingA (KERNEL32.46)
50 int TranslateProtectionFlags(DWORD);
51 HANDLE32 CreateFileMapping(HANDLE32 h,SECURITY_ATTRIBUTES *ats,
52 DWORD pot, DWORD sh, DWORD hlow, const char * lpName )
54 FILE_OBJECT *file_obj;
55 FILEMAP_OBJECT *filemap_obj;
56 int fd;
58 if (sh)
60 SetLastError(ErrnoToLastError(errno));
61 return INVALID_HANDLE_VALUE;
63 fd = open(lpName, O_CREAT, 0666);
64 if(fd == -1)
66 SetLastError(ErrnoToLastError(errno));
67 return INVALID_HANDLE_VALUE;
69 file_obj = (FILE_OBJECT *)
70 CreateKernelObject(sizeof(FILE_OBJECT));
71 if(file_obj == NULL)
73 SetLastError(ERROR_UNKNOWN);
74 return 0;
76 filemap_obj = (FILEMAP_OBJECT *)
77 CreateKernelObject(sizeof(FILEMAP_OBJECT));
78 if(filemap_obj == NULL)
80 ReleaseKernelObject(file_obj);
81 SetLastError(ERROR_UNKNOWN);
82 return 0;
84 file_obj->common.magic = KERNEL_OBJECT_FILE;
85 file_obj->fd = fd;
86 file_obj->type = FILE_TYPE_DISK;
87 filemap_obj->common.magic = KERNEL_OBJECT_FILEMAP;
88 filemap_obj->file_obj = file_obj;
89 filemap_obj->prot = TranslateProtectionFlags(pot);
90 filemap_obj->size = hlow;
91 return (HANDLE32)filemap_obj;;
94 /***********************************************************************
95 * MapViewOfFileEx (KERNEL32.386)
98 void *MapViewOfFileEx(HANDLE32 handle, DWORD access, DWORD offhi,
99 DWORD offlo, DWORD size, DWORD st)
101 if (!size) size = ((FILEMAP_OBJECT *)handle)->size;
102 return mmap ((caddr_t)st, size, ((FILEMAP_OBJECT *)handle)->prot,
103 MAP_ANON|MAP_PRIVATE,
104 ((FILEMAP_OBJECT *)handle)->file_obj->fd,
105 offlo);
108 /***********************************************************************
109 * GetFileInformationByHandle (KERNEL32.219)
112 DWORD GetFileInformationByHandle(FILE_OBJECT *hFile,
113 BY_HANDLE_FILE_INFORMATION *lpfi)
115 struct stat file_stat;
116 int rc;
118 if(ValidateKernelObject((HANDLE32)hFile) != 0)
120 SetLastError(ERROR_INVALID_HANDLE);
121 return 0;
123 if(hFile->common.magic != KERNEL_OBJECT_FILE)
125 SetLastError(ERROR_INVALID_HANDLE);
126 return 0;
129 rc = fstat(hFile->fd, &file_stat);
130 if(rc == -1)
132 SetLastError(ErrnoToLastError(errno));
133 return 0;
136 /* Translate the file attributes.
138 lpfi->dwFileAttributes = 0;
139 if(file_stat.st_mode & S_IFREG)
140 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
141 if(file_stat.st_mode & S_IFDIR)
142 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
143 if((file_stat.st_mode & S_IWRITE) == 0)
144 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
146 /* Translate the file times. Use the last modification time
147 * for both the creation time and write time.
149 UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftCreationTime));
150 UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftLastWriteTime));
151 UnixTimeToFileTime(file_stat.st_atime, &(lpfi->ftLastAccessTime));
153 lpfi->nFileSizeLow = file_stat.st_size;
154 lpfi->nNumberOfLinks = file_stat.st_nlink;
155 lpfi->nFileIndexLow = file_stat.st_ino;
157 /* Zero out currently unused fields.
159 lpfi->dwVolumeSerialNumber = 0;
160 lpfi->nFileSizeHigh = 0;
161 lpfi->nFileIndexHigh = 0;
163 return 1;
167 static void UnixTimeToFileTime(time_t unix_time, FILETIME *filetime)
169 /* This isn't anywhere close to being correct, but should
170 * work for now.
172 filetime->dwLowDateTime = (unix_time & 0x0000FFFF) << 16;
173 filetime->dwHighDateTime = (unix_time & 0xFFFF0000) >> 16;
177 /***********************************************************************
178 * GetFileType (KERNEL32.222)
180 * GetFileType currently only supports stdin, stdout, and stderr, which
181 * are considered to be of type FILE_TYPE_CHAR.
183 DWORD GetFileType(FILE_OBJECT *hFile)
185 if(ValidateKernelObject((HANDLE32)hFile) != 0)
187 SetLastError(ERROR_UNKNOWN);
188 return FILE_TYPE_UNKNOWN;
190 if(hFile->common.magic != KERNEL_OBJECT_FILE)
192 SetLastError(ERROR_UNKNOWN);
193 return FILE_TYPE_UNKNOWN;
196 return hFile->type;
199 /***********************************************************************
200 * GetStdHandle (KERNEL32.276)
202 HANDLE32 GetStdHandle(DWORD nStdHandle)
204 HANDLE32 rc;
206 switch(nStdHandle)
208 case STD_INPUT_HANDLE:
209 rc = (HANDLE32)hstdin;
210 break;
212 case STD_OUTPUT_HANDLE:
213 rc = (HANDLE32)hstdout;
214 break;
216 case STD_ERROR_HANDLE:
217 rc = (HANDLE32)hstderr;
218 break;
220 default:
221 rc = INVALID_HANDLE_VALUE;
222 SetLastError(ERROR_INVALID_HANDLE);
223 break;
226 return rc;
229 /***********************************************************************
230 * SetFilePointer (KERNEL32.492)
232 * Luckily enough, this function maps almost directly into an lseek
233 * call, the exception being the use of 64-bit offsets.
235 DWORD SetFilePointer(FILE_OBJECT *hFile, LONG distance, LONG *highword,
236 DWORD method)
238 int rc;
240 if(ValidateKernelObject((HANDLE32)hFile) != 0)
242 SetLastError(ERROR_INVALID_HANDLE);
243 return ((DWORD)0xFFFFFFFF);
245 if(hFile->common.magic != KERNEL_OBJECT_FILE)
247 SetLastError(ERROR_INVALID_HANDLE);
248 return ((DWORD)0xFFFFFFFF);
251 if(highword != NULL)
253 if(*highword != 0)
255 dprintf_win32(stddeb, "SetFilePointer: 64-bit offsets not yet supported.\n");
256 return -1;
260 rc = lseek(hFile->fd, distance, method);
261 if(rc == -1)
262 SetLastError(ErrnoToLastError(errno));
263 return rc;
266 /***********************************************************************
267 * WriteFile (KERNEL32.578)
269 BOOL WriteFile(FILE_OBJECT *hFile, LPVOID lpBuffer, DWORD numberOfBytesToWrite,
270 LPDWORD numberOfBytesWritten, LPOVERLAPPED lpOverlapped)
272 int written;
274 if(ValidateKernelObject((HANDLE32)hFile) != 0)
276 SetLastError(ERROR_INVALID_HANDLE);
277 return 0;
279 if(hFile->common.magic != KERNEL_OBJECT_FILE)
281 SetLastError(ERROR_INVALID_HANDLE);
282 return 0;
285 written = write(hFile->fd, lpBuffer, numberOfBytesToWrite);
286 if(numberOfBytesWritten)
287 *numberOfBytesWritten = written;
289 return 1;
292 /***********************************************************************
293 * ReadFile (KERNEL32.428)
295 BOOL ReadFile(FILE_OBJECT *hFile, LPVOID lpBuffer, DWORD numtoread,
296 LPDWORD numread, LPOVERLAPPED lpOverlapped)
298 int actual_read;
300 if(ValidateKernelObject((HANDLE32)hFile) != 0)
302 SetLastError(ERROR_INVALID_HANDLE);
303 return 0;
305 if(hFile->common.magic != KERNEL_OBJECT_FILE)
307 SetLastError(ERROR_INVALID_HANDLE);
308 return 0;
311 actual_read = read(hFile->fd, lpBuffer, numtoread);
312 if(actual_read == -1)
314 SetLastError(ErrnoToLastError(errno));
315 return 0;
317 if(numread)
318 *numread = actual_read;
320 return 1;
323 /*************************************************************************
324 * CreateFile (KERNEL32.45)
326 * Doesn't support character devices, pipes, template files, or a
327 * lot of the 'attributes' flags yet.
329 HANDLE32 CreateFileA(LPSTR filename, DWORD access, DWORD sharing,
330 LPSECURITY_ATTRIBUTES security, DWORD creation,
331 DWORD attributes, HANDLE32 template)
333 int access_flags, create_flags;
334 int fd;
335 FILE_OBJECT *file_obj;
336 int type;
338 /* Translate the various flags to Unix-style.
340 access_flags = TranslateAccessFlags(access);
341 create_flags = TranslateCreationFlags(creation);
343 if(template)
344 dprintf_win32(stddeb, "CreateFile: template handles not supported.\n");
346 /* If the name starts with '\\?' or '\\.', ignore the first 3 chars.
348 if(!strncmp(filename, "\\\\?", 3) || !strncmp(filename, "\\\\.", 3))
349 filename += 3;
351 /* If the name still starts with '\\', it's a UNC name.
353 if(!strncmp(filename, "\\\\", 2))
355 dprintf_win32(stddeb, "CreateFile: UNC names not supported.\n");
356 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
357 return INVALID_HANDLE_VALUE;
360 /* If the name is either CONIN$ or CONOUT$, give them stdin
361 * or stdout, respectively.
363 if(!strcmp(filename, "CONIN$"))
365 type = FILE_TYPE_CHAR;
366 fd = 0;
368 else if(!strcmp(filename, "CONOUT$"))
370 type = FILE_TYPE_CHAR;
371 fd = 1;
373 else
375 const char *unixName = DOSFS_GetUnixFileName( filename, FALSE );
376 type = FILE_TYPE_DISK;
378 /* Try to open the file.
380 if (!unixName ||
381 ((fd = open(unixName, access_flags | create_flags, 0666)) == -1))
383 SetLastError(ErrnoToLastError(errno));
384 return INVALID_HANDLE_VALUE;
388 /* We seem to have succeeded, so allocate a kernel object
389 * and set it up.
391 file_obj = (FILE_OBJECT *)CreateKernelObject(sizeof(FILE_OBJECT));
392 if(file_obj == NULL)
394 SetLastError(ERROR_INVALID_HANDLE);
395 return INVALID_HANDLE_VALUE;
397 file_obj->common.magic = KERNEL_OBJECT_FILE;
398 file_obj->fd = fd;
399 file_obj->type = type;
400 file_obj->misc_flags = attributes;
401 file_obj->access_flags = access_flags;
402 file_obj->create_flags = create_flags;
404 return (HANDLE32)file_obj;
407 /*************************************************************************
408 * W32_SetHandleCount (KERNEL32.??)
411 UINT W32_SetHandleCount(UINT cHandles)
413 return SetHandleCount(cHandles);
416 int CloseFileHandle(FILE_OBJECT *hFile)
418 /* If it's one of the 3 standard handles, don't really
419 * close it.
421 if(hFile->fd > 2)
422 close(hFile->fd);
424 return 1;
427 static int TranslateAccessFlags(DWORD access_flags)
429 int rc = 0;
431 switch(access_flags)
433 case GENERIC_READ:
434 rc = O_RDONLY;
435 break;
437 case GENERIC_WRITE:
438 rc = O_WRONLY;
439 break;
441 case (GENERIC_READ | GENERIC_WRITE):
442 rc = O_RDWR;
443 break;
446 return rc;
449 static int TranslateCreationFlags(DWORD create_flags)
451 int rc = 0;
453 switch(create_flags)
455 case CREATE_NEW:
456 rc = O_CREAT | O_EXCL;
457 break;
459 case CREATE_ALWAYS:
460 rc = O_CREAT | O_TRUNC;
461 break;
463 case OPEN_EXISTING:
464 rc = 0;
465 break;
467 case OPEN_ALWAYS:
468 rc = O_CREAT;
469 break;
471 case TRUNCATE_EXISTING:
472 rc = O_TRUNC;
473 break;
476 return rc;
479 /**************************************************************************
480 * GetFileAttributes
482 DWORD GetFileAttributesA(LPCSTR lpFileName)
484 struct stat buf;
485 DWORD res=0;
486 char *fn;
488 dprintf_win32(stddeb,"GetFileAttributesA(%s)\n",lpFileName);
489 fn=DOSFS_GetUnixFileName(lpFileName,FALSE);
490 /* fn points to a static buffer, don't free it */
491 if(stat(fn,&buf)==-1) {
492 SetLastError(ErrnoToLastError(errno));
493 return 0xFFFFFFFF;
495 if(buf.st_mode & S_IFREG)
496 res |= FILE_ATTRIBUTE_NORMAL;
497 if(buf.st_mode & S_IFDIR)
498 res |= FILE_ATTRIBUTE_DIRECTORY;
499 if((buf.st_mode & S_IWRITE) == 0)
500 res |= FILE_ATTRIBUTE_READONLY;
501 return res;