Release 960928
[wine/multimedia.git] / win32 / file.c
blob150322bcc574e7cc1f090b616ceeeb36be40442a
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 "file.h"
20 #include "handle32.h"
21 #include "string32.h"
22 #include "dos_fs.h"
23 #include "xmalloc.h"
24 #include "stddebug.h"
25 #define DEBUG_WIN32
26 #include "debug.h"
29 static void UnixTimeToFileTime(time_t unix_time, FILETIME *filetime);
30 static int TranslateCreationFlags(DWORD create_flags);
31 static int TranslateAccessFlags(DWORD access_flags);
32 int TranslateProtectionFlags(DWORD);
33 #ifndef MAP_ANON
34 #define MAP_ANON 0
35 #endif
37 /***********************************************************************
38 * OpenFileMappingA (KERNEL32.397)
39 * FIXME: stub
42 HANDLE32 OpenFileMapping(DWORD access, BOOL inherit,const char *fname)
44 return 0;
48 /***********************************************************************
49 * CreateFileMapping32A (KERNEL32.46)
51 HANDLE32 CreateFileMapping32A(HANDLE32 h,LPSECURITY_ATTRIBUTES ats,
52 DWORD pot, DWORD sh, DWORD hlow, LPCSTR lpName )
54 HFILE hfile;
55 FILEMAP_OBJECT *filemap_obj;
57 if (sh) {
58 SetLastError(ErrnoToLastError(errno));
59 return INVALID_HANDLE_VALUE;
61 hfile = _lcreat(lpName,1);
62 if(hfile == HFILE_ERROR) {
63 SetLastError(ErrnoToLastError(errno));
64 return INVALID_HANDLE_VALUE;
66 filemap_obj=(FILEMAP_OBJECT *)CreateKernelObject(sizeof(FILEMAP_OBJECT));
67 if(filemap_obj == NULL) {
68 _lclose(hfile);
69 SetLastError(ERROR_UNKNOWN);
70 return 0;
73 filemap_obj->common.magic = KERNEL_OBJECT_FILEMAP;
74 filemap_obj->hfile = hfile;
75 filemap_obj->prot = TranslateProtectionFlags(pot);
76 filemap_obj->size = hlow;
77 return (HANDLE32)filemap_obj;;
80 /***********************************************************************
81 * CreateFileMapping32W (KERNEL32.47)
84 HANDLE32 CreateFileMapping32W(HANDLE32 h,LPSECURITY_ATTRIBUTES ats,
85 DWORD pot, DWORD sh, DWORD hlow, LPCWSTR lpName)
87 HANDLE32 res;
88 LPSTR aname = STRING32_DupUniToAnsi(lpName);
90 res = CreateFileMapping32A(h,ats,pot,sh,hlow,aname);
91 free(aname);
92 return res;
96 /***********************************************************************
97 * MapViewOfFileEx (KERNEL32.386)
100 LPVOID MapViewOfFileEx(HANDLE32 handle, DWORD access, DWORD offhi,
101 DWORD offlo, DWORD size, DWORD st)
103 if (!size) size = ((FILEMAP_OBJECT *)handle)->size;
104 return mmap ((caddr_t)st, size, ((FILEMAP_OBJECT *)handle)->prot,
105 MAP_ANON|MAP_PRIVATE,
106 FILE_GetUnixHandle(((FILEMAP_OBJECT *)handle)->hfile),
107 offlo);
111 /***********************************************************************
112 * GetFileInformationByHandle (KERNEL32.219)
114 DWORD GetFileInformationByHandle(HFILE hFile,BY_HANDLE_FILE_INFORMATION *lpfi)
116 struct stat file_stat;
117 int rc;
118 int unixfd = FILE_GetUnixHandle(hFile);
120 if (unixfd==-1)
121 return 0;
122 rc = fstat(unixfd,&file_stat);
123 if(rc == -1) {
124 SetLastError(ErrnoToLastError(errno));
125 return 0;
128 /* Translate the file attributes.
130 lpfi->dwFileAttributes = 0;
131 if(file_stat.st_mode & S_IFREG)
132 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
133 if(file_stat.st_mode & S_IFDIR)
134 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
135 if((file_stat.st_mode & S_IWRITE) == 0)
136 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
138 /* Translate the file times. Use the last modification time
139 * for both the creation time and write time.
141 UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftCreationTime));
142 UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftLastWriteTime));
143 UnixTimeToFileTime(file_stat.st_atime, &(lpfi->ftLastAccessTime));
145 lpfi->nFileSizeLow = file_stat.st_size;
146 lpfi->nNumberOfLinks = file_stat.st_nlink;
147 lpfi->nFileIndexLow = file_stat.st_ino;
149 /* Zero out currently unused fields.
151 lpfi->dwVolumeSerialNumber = 0;
152 lpfi->nFileSizeHigh = 0;
153 lpfi->nFileIndexHigh = 0;
155 return 1;
158 static void UnixTimeToFileTime(time_t unix_time, FILETIME *filetime)
160 /* This isn't anywhere close to being correct, but should
161 * work for now.
163 filetime->dwLowDateTime = (unix_time & 0x0000FFFF) << 16;
164 filetime->dwHighDateTime = (unix_time & 0xFFFF0000) >> 16;
167 time_t FileTimeToUnixTime(FILETIME *filetime)
169 /* reverse of UnixTimeToFileTime */
170 return (filetime->dwLowDateTime>>16)+(filetime->dwHighDateTime<<16);
173 /***********************************************************************
174 * GetStdHandle (KERNEL32.276)
175 * FIXME: We should probably allocate filehandles for stdin/stdout/stderr
176 * at task creation (with HFILE-handle 0,1,2 respectively) and
177 * return them here. Or at least look, if we created them already.
179 HFILE GetStdHandle(DWORD nStdHandle)
181 HFILE hfile;
182 int unixfd;
184 switch(nStdHandle)
186 case STD_INPUT_HANDLE:
187 unixfd = 0;
188 break;
190 case STD_OUTPUT_HANDLE:
191 unixfd = 1;
192 break;
194 case STD_ERROR_HANDLE:
195 unixfd = 2;
196 break;
197 default:
198 SetLastError(ERROR_INVALID_HANDLE);
199 return HFILE_ERROR;
201 hfile = FILE_DupUnixHandle(unixfd);
202 if (hfile == HFILE_ERROR)
203 return HFILE_ERROR;
204 FILE_SetFileType( hfile, FILE_TYPE_CHAR );
205 return hfile;
209 /***********************************************************************
210 * SetFilePointer (KERNEL32.492)
212 * Luckily enough, this function maps almost directly into an lseek
213 * call, the exception being the use of 64-bit offsets.
215 DWORD SetFilePointer(HFILE hFile, LONG distance, LONG *highword,
216 DWORD method)
218 LONG rc;
219 if(highword != NULL)
221 if(*highword != 0)
223 dprintf_file(stddeb, "SetFilePointer: 64-bit offsets not yet supported.\n");
224 return -1;
228 rc = _llseek(hFile, distance, method);
229 if(rc == -1)
230 SetLastError(ErrnoToLastError(errno));
231 return rc;
234 /***********************************************************************
235 * WriteFile (KERNEL32.578)
237 BOOL32 WriteFile(HFILE hFile, LPVOID lpBuffer, DWORD numberOfBytesToWrite,
238 LPDWORD numberOfBytesWritten, LPOVERLAPPED lpOverlapped)
240 LONG res;
242 res = _lwrite32(hFile,lpBuffer,numberOfBytesToWrite);
243 if (res==-1) {
244 SetLastError(ErrnoToLastError(errno));
245 return FALSE;
247 if(numberOfBytesWritten)
248 *numberOfBytesWritten = res;
249 return TRUE;
252 /***********************************************************************
253 * ReadFile (KERNEL32.428)
255 BOOL32 ReadFile(HFILE hFile, LPVOID lpBuffer, DWORD numtoread,
256 LPDWORD numread, LPOVERLAPPED lpOverlapped)
258 int actual_read;
260 actual_read = _lread32(hFile,lpBuffer,numtoread);
261 if(actual_read == -1) {
262 SetLastError(ErrnoToLastError(errno));
263 return FALSE;
265 if(numread)
266 *numread = actual_read;
268 return TRUE;
272 /*************************************************************************
273 * CreateFile32A (KERNEL32.45)
275 * Doesn't support character devices, pipes, template files, or a
276 * lot of the 'attributes' flags yet.
278 HFILE CreateFile32A(LPCSTR filename, DWORD access, DWORD sharing,
279 LPSECURITY_ATTRIBUTES security, DWORD creation,
280 DWORD attributes, HANDLE32 template)
282 int access_flags, create_flags;
284 /* Translate the various flags to Unix-style.
286 access_flags = TranslateAccessFlags(access);
287 create_flags = TranslateCreationFlags(creation);
289 if(template)
290 dprintf_file(stddeb, "CreateFile: template handles not supported.\n");
292 /* If the name starts with '\\?' or '\\.', ignore the first 3 chars.
294 if(!strncmp(filename, "\\\\?", 3) || !strncmp(filename, "\\\\.", 3))
295 filename += 3;
297 /* If the name still starts with '\\', it's a UNC name.
299 if(!strncmp(filename, "\\\\", 2))
301 dprintf_file(stddeb, "CreateFile: UNC names not supported.\n");
302 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
303 return HFILE_ERROR;
306 /* If the name is either CONIN$ or CONOUT$, give them stdin
307 * or stdout, respectively.
309 if(!strcmp(filename, "CONIN$")) return GetStdHandle( STD_INPUT_HANDLE );
310 if(!strcmp(filename, "CONOUT$")) return GetStdHandle( STD_OUTPUT_HANDLE );
312 return FILE_Open( filename, access_flags | create_flags );
316 /*************************************************************************
317 * CreateFile32W (KERNEL32.48)
319 HFILE CreateFile32W(LPCWSTR filename, DWORD access, DWORD sharing,
320 LPSECURITY_ATTRIBUTES security, DWORD creation,
321 DWORD attributes, HANDLE32 template)
323 HFILE res;
324 LPSTR afn = STRING32_DupUniToAnsi(filename);
326 res = CreateFile32A(afn,access,sharing,security,creation,attributes,template);
327 free(afn);
328 return res;
331 /*************************************************************************
332 * SetHandleCount32 (KERNEL32.494)
334 UINT32 SetHandleCount32( UINT32 cHandles )
336 return SetHandleCount16(cHandles);
340 int CloseFileHandle(HFILE hFile)
342 if (!_lclose(hFile))
343 return TRUE;
344 return FALSE;
347 static int TranslateAccessFlags(DWORD access_flags)
349 int rc = 0;
351 switch(access_flags)
353 case GENERIC_READ:
354 rc = O_RDONLY;
355 break;
357 case GENERIC_WRITE:
358 rc = O_WRONLY;
359 break;
361 case (GENERIC_READ | GENERIC_WRITE):
362 rc = O_RDWR;
363 break;
366 return rc;
369 static int TranslateCreationFlags(DWORD create_flags)
371 int rc = 0;
373 switch(create_flags)
375 case CREATE_NEW:
376 rc = O_CREAT | O_EXCL;
377 break;
379 case CREATE_ALWAYS:
380 rc = O_CREAT | O_TRUNC;
381 break;
383 case OPEN_EXISTING:
384 rc = 0;
385 break;
387 case OPEN_ALWAYS:
388 rc = O_CREAT;
389 break;
391 case TRUNCATE_EXISTING:
392 rc = O_TRUNC;
393 break;
396 return rc;
400 /**************************************************************************
401 * GetFileAttributes32A (KERNEL32.217)
403 DWORD GetFileAttributes32A(LPCSTR lpFileName)
405 struct stat buf;
406 DWORD res=0;
407 char *fn;
409 dprintf_file(stddeb,"GetFileAttributesA(%s)\n",lpFileName);
410 fn=(LPSTR)DOSFS_GetUnixFileName(lpFileName,FALSE);
411 /* fn points to a static buffer, don't free it */
412 if(stat(fn,&buf)==-1) {
413 SetLastError(ErrnoToLastError(errno));
414 return 0xFFFFFFFF;
416 if(buf.st_mode & S_IFREG)
417 res |= FILE_ATTRIBUTE_NORMAL;
418 if(buf.st_mode & S_IFDIR)
419 res |= FILE_ATTRIBUTE_DIRECTORY;
420 if((buf.st_mode & S_IWRITE) == 0)
421 res |= FILE_ATTRIBUTE_READONLY;
422 return res;
425 /**************************************************************************
426 * GetFileAttributes32W (KERNEL32.218)
428 DWORD GetFileAttributes32W(LPCWSTR lpFileName)
430 LPSTR afn = STRING32_DupUniToAnsi(lpFileName);
431 DWORD res;
433 res = GetFileAttributes32A(afn);
434 free(afn);
435 return res;
439 /**************************************************************************
440 * SetFileAttributes32A (KERNEL32.490)
442 BOOL32 SetFileAttributes32A(LPCSTR lpFileName, DWORD attributes)
444 struct stat buf;
445 LPSTR fn=(LPSTR)DOSFS_GetUnixFileName(lpFileName,FALSE);
447 dprintf_file(stddeb,"SetFileAttributes(%s,%lx)\n",lpFileName,attributes);
448 if(stat(fn,&buf)==-1) {
449 SetLastError(ErrnoToLastError(errno));
450 return FALSE;
452 if (attributes & FILE_ATTRIBUTE_READONLY) {
453 buf.st_mode &= ~0222; /* octal!, clear write permission bits */
454 attributes &= ~FILE_ATTRIBUTE_READONLY;
456 attributes &= ~(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
457 if (attributes)
458 fprintf(stdnimp,"SetFileAttributesA(%s):%lx attribute(s) not implemented.\n",lpFileName,attributes);
459 if (-1==chmod(fn,buf.st_mode)) {
460 SetLastError(ErrnoToLastError(errno));
461 return FALSE;
463 return TRUE;
466 /**************************************************************************
467 * SetFileAttributes32W (KERNEL32.491)
469 BOOL32 SetFileAttributes32W(LPCWSTR lpFileName, DWORD attributes)
471 LPSTR afn = STRING32_DupUniToAnsi(lpFileName);
472 BOOL32 res;
474 res = SetFileAttributes32A(afn,attributes);
475 free(afn);
476 return res;
479 /**************************************************************************
480 * SetEndOfFile (KERNEL32.483)
482 BOOL32 SetEndOfFile(HFILE hFile)
484 int unixfd = FILE_GetUnixHandle(hFile);
486 dprintf_file(stddeb,"SetEndOfFile(%lx)\n",(LONG)hFile);
487 if (!unixfd)
488 return 0;
489 if (-1==ftruncate(unixfd,lseek(unixfd,0,SEEK_CUR))) {
490 SetLastError(ErrnoToLastError(errno));
491 return FALSE;
493 return TRUE;
497 /**************************************************************************
498 * MoveFileA (KERNEL32.387)
500 BOOL32 MoveFile32A(LPCSTR fn1,LPCSTR fn2)
502 LPSTR ufn1;
503 LPSTR ufn2;
505 dprintf_file(stddeb,"MoveFileA(%s,%s)\n",fn1,fn2);
506 ufn1 = (LPSTR)DOSFS_GetUnixFileName(fn1,FALSE);
507 if (!ufn1) {
508 SetLastError(ErrnoToLastError(ENOENT));
509 return FALSE;
511 ufn1 = xstrdup(ufn1);
512 ufn2 = (LPSTR)DOSFS_GetUnixFileName(fn2,FALSE);
513 if (!ufn2) {
514 SetLastError(ErrnoToLastError(ENOENT));
515 return FALSE;
517 ufn2 = xstrdup(ufn2);
518 if (-1==rename(ufn1,ufn2)) {
519 SetLastError(ErrnoToLastError(errno));
520 free(ufn1);
521 free(ufn2);
522 return FALSE;
524 free(ufn1);
525 free(ufn2);
526 return TRUE;
529 /**************************************************************************
530 * MoveFileW (KERNEL32.390)
532 BOOL32 MoveFile32W(LPCWSTR fn1,LPCWSTR fn2)
534 LPSTR afn1 = STRING32_DupUniToAnsi(fn1);
535 LPSTR afn2 = STRING32_DupUniToAnsi(fn2);
536 BOOL32 res;
538 res = MoveFile32A(afn1,afn2);
539 free(afn1);
540 free(afn2);
541 return res;