Release 961222
[wine/multimedia.git] / win32 / file.c
blob7b9ec586f4905b0ff256bfffbe19c226d8917200
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 "heap.h"
21 #include "handle32.h"
22 #include "dos_fs.h"
23 #include "xmalloc.h"
24 #include "stddebug.h"
25 #define DEBUG_WIN32
26 #include "debug.h"
29 static int TranslateCreationFlags(DWORD create_flags);
30 static int TranslateAccessFlags(DWORD access_flags);
31 int TranslateProtectionFlags(DWORD);
32 #ifndef MAP_ANON
33 #define MAP_ANON 0
34 #endif
36 /***********************************************************************
37 * OpenFileMappingA (KERNEL32.397)
38 * FIXME: stub
41 HANDLE32 OpenFileMapping(DWORD access, BOOL inherit,const char *fname)
43 return 0;
47 /***********************************************************************
48 * CreateFileMapping32A (KERNEL32.46)
50 HANDLE32 CreateFileMapping32A(HANDLE32 h,LPSECURITY_ATTRIBUTES ats,
51 DWORD pot, DWORD sh, DWORD hlow, LPCSTR lpName )
53 FILEMAP_OBJECT *filemap_obj;
55 dprintf_win32(stddeb,"CreateFileMapping32A(%08x,%p,%ld,%ld,%ld,%s)\n",
56 h,ats,pot,sh,hlow,lpName
58 if (sh) {
59 SetLastError(ErrnoToLastError(errno));
60 return INVALID_HANDLE_VALUE;
62 filemap_obj=(FILEMAP_OBJECT *)CreateKernelObject(sizeof(FILEMAP_OBJECT));
63 if(filemap_obj == NULL) {
64 SetLastError(ERROR_UNKNOWN);
65 return 0;
67 if (h==INVALID_HANDLE_VALUE)
68 h=_lcreat(lpName,1);/*FIXME*/
70 filemap_obj->common.magic = KERNEL_OBJECT_FILEMAP;
71 filemap_obj->hfile = h;
72 filemap_obj->prot = TranslateProtectionFlags(pot);
73 filemap_obj->size = hlow;
74 return (HANDLE32)filemap_obj;;
77 /***********************************************************************
78 * CreateFileMapping32W (KERNEL32.47)
81 HANDLE32 CreateFileMapping32W(HANDLE32 h,LPSECURITY_ATTRIBUTES ats,
82 DWORD pot, DWORD sh, DWORD hlow, LPCWSTR lpName)
84 LPSTR aname = HEAP_strdupWtoA( GetProcessHeap(), 0, lpName );
85 HANDLE32 res = CreateFileMapping32A(h,ats,pot,sh,hlow,aname);
86 HeapFree( GetProcessHeap(), 0, aname );
87 return res;
91 /***********************************************************************
92 * MapViewOfFile (KERNEL32.385)
94 LPVOID MapViewOfFile(HANDLE32 handle, DWORD access, DWORD offhi,
95 DWORD offlo, DWORD size)
97 return MapViewOfFileEx(handle,access,offhi,offlo,size,0);
100 /***********************************************************************
101 * MapViewOfFileEx (KERNEL32.386)
104 LPVOID MapViewOfFileEx(HANDLE32 handle, DWORD access, DWORD offhi,
105 DWORD offlo, DWORD size, DWORD st)
107 FILEMAP_OBJECT *fmap = (FILEMAP_OBJECT*)handle;
109 if (!size) size = fmap->size;
110 if (!size) size = 1;
111 return mmap ((caddr_t)st, size, fmap->prot,
112 MAP_ANON|MAP_PRIVATE,
113 FILE_GetUnixHandle(fmap->hfile),
114 offlo);
117 /***********************************************************************
118 * UnmapViewOfFile (KERNEL32.385)
120 BOOL32 UnmapViewOfFile(LPVOID address) {
121 munmap(address,/*hmm*/1); /* FIXME: size? */
122 return TRUE;
127 /***********************************************************************
128 * GetFileInformationByHandle (KERNEL32.219)
130 DWORD GetFileInformationByHandle(HFILE hFile,BY_HANDLE_FILE_INFORMATION *lpfi)
132 struct stat file_stat;
133 int rc;
134 int unixfd = FILE_GetUnixHandle(hFile);
136 if (unixfd==-1)
137 return 0;
138 rc = fstat(unixfd,&file_stat);
139 if(rc == -1) {
140 SetLastError(ErrnoToLastError(errno));
141 return 0;
144 /* Translate the file attributes.
146 lpfi->dwFileAttributes = 0;
147 if(file_stat.st_mode & S_IFREG)
148 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
149 if(file_stat.st_mode & S_IFDIR)
150 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
151 if((file_stat.st_mode & S_IWRITE) == 0)
152 lpfi->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
154 /* Translate the file times. Use the last modification time
155 * for both the creation time and write time.
157 DOSFS_UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftCreationTime));
158 DOSFS_UnixTimeToFileTime(file_stat.st_mtime, &(lpfi->ftLastWriteTime));
159 DOSFS_UnixTimeToFileTime(file_stat.st_atime, &(lpfi->ftLastAccessTime));
161 lpfi->nFileSizeLow = file_stat.st_size;
162 lpfi->nNumberOfLinks = file_stat.st_nlink;
163 lpfi->nFileIndexLow = file_stat.st_ino;
165 /* Zero out currently unused fields.
167 lpfi->dwVolumeSerialNumber = 0;
168 lpfi->nFileSizeHigh = 0;
169 lpfi->nFileIndexHigh = 0;
171 return 1;
174 /***********************************************************************
175 * GetFileSize (KERNEL32.220)
177 DWORD GetFileSize(HFILE hf,LPDWORD filesizehigh) {
178 BY_HANDLE_FILE_INFORMATION fi;
179 DWORD res = GetFileInformationByHandle(hf,&fi);
181 if (!res)
182 return 0; /* FIXME: correct ? */
183 if (filesizehigh)
184 *filesizehigh = fi.nFileSizeHigh;
185 return fi.nFileSizeLow;
188 /***********************************************************************
189 * GetStdHandle (KERNEL32.276)
190 * FIXME: We should probably allocate filehandles for stdin/stdout/stderr
191 * at task creation (with HFILE-handle 0,1,2 respectively) and
192 * return them here. Or at least look, if we created them already.
194 HFILE GetStdHandle(DWORD nStdHandle)
196 HFILE hfile;
197 int unixfd;
199 switch(nStdHandle)
201 case STD_INPUT_HANDLE:
202 unixfd = 0;
203 break;
205 case STD_OUTPUT_HANDLE:
206 unixfd = 1;
207 break;
209 case STD_ERROR_HANDLE:
210 unixfd = 2;
211 break;
212 default:
213 SetLastError(ERROR_INVALID_HANDLE);
214 return HFILE_ERROR;
216 hfile = FILE_DupUnixHandle(unixfd);
217 if (hfile == HFILE_ERROR)
218 return HFILE_ERROR;
219 FILE_SetFileType( hfile, FILE_TYPE_CHAR );
220 return hfile;
224 /***********************************************************************
225 * SetFilePointer (KERNEL32.492)
227 * Luckily enough, this function maps almost directly into an lseek
228 * call, the exception being the use of 64-bit offsets.
230 DWORD SetFilePointer(HFILE hFile, LONG distance, LONG *highword,
231 DWORD method)
233 LONG rc;
234 if(highword != NULL)
236 if(*highword != 0)
238 dprintf_file(stddeb, "SetFilePointer: 64-bit offsets not yet supported.\n");
239 return -1;
243 rc = _llseek(hFile, distance, method);
244 if(rc == -1)
245 SetLastError(ErrnoToLastError(errno));
246 return rc;
249 /***********************************************************************
250 * WriteFile (KERNEL32.578)
252 BOOL32 WriteFile(HFILE hFile, LPVOID lpBuffer, DWORD numberOfBytesToWrite,
253 LPDWORD numberOfBytesWritten, LPOVERLAPPED lpOverlapped)
255 LONG res;
257 res = _lwrite32(hFile,lpBuffer,numberOfBytesToWrite);
258 if (res==-1) {
259 SetLastError(ErrnoToLastError(errno));
260 return FALSE;
262 if(numberOfBytesWritten)
263 *numberOfBytesWritten = res;
264 return TRUE;
267 /***********************************************************************
268 * ReadFile (KERNEL32.428)
270 BOOL32 ReadFile(HFILE hFile, LPVOID lpBuffer, DWORD numtoread,
271 LPDWORD numread, LPOVERLAPPED lpOverlapped)
273 int actual_read;
275 actual_read = _lread32(hFile,lpBuffer,numtoread);
276 if(actual_read == -1) {
277 SetLastError(ErrnoToLastError(errno));
278 return FALSE;
280 if(numread)
281 *numread = actual_read;
283 return TRUE;
287 /*************************************************************************
288 * CreateFile32A (KERNEL32.45)
290 * Doesn't support character devices, pipes, template files, or a
291 * lot of the 'attributes' flags yet.
293 HFILE CreateFile32A(LPCSTR filename, DWORD access, DWORD sharing,
294 LPSECURITY_ATTRIBUTES security, DWORD creation,
295 DWORD attributes, HANDLE32 template)
297 int access_flags, create_flags;
299 /* Translate the various flags to Unix-style.
301 access_flags = TranslateAccessFlags(access);
302 create_flags = TranslateCreationFlags(creation);
304 if(template)
305 dprintf_file(stddeb, "CreateFile: template handles not supported.\n");
307 /* If the name starts with '\\?' or '\\.', ignore the first 3 chars.
309 if(!strncmp(filename, "\\\\?", 3) || !strncmp(filename, "\\\\.", 3))
310 filename += 3;
312 /* If the name still starts with '\\', it's a UNC name.
314 if(!strncmp(filename, "\\\\", 2))
316 dprintf_file(stddeb, "CreateFile: UNC names not supported.\n");
317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
318 return HFILE_ERROR;
321 /* If the name is either CONIN$ or CONOUT$, give them stdin
322 * or stdout, respectively.
324 if(!strcmp(filename, "CONIN$")) return GetStdHandle( STD_INPUT_HANDLE );
325 if(!strcmp(filename, "CONOUT$")) return GetStdHandle( STD_OUTPUT_HANDLE );
327 return FILE_Open( filename, access_flags | create_flags );
331 /*************************************************************************
332 * CreateFile32W (KERNEL32.48)
334 HFILE CreateFile32W(LPCWSTR filename, DWORD access, DWORD sharing,
335 LPSECURITY_ATTRIBUTES security, DWORD creation,
336 DWORD attributes, HANDLE32 template)
338 LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
339 HFILE res = CreateFile32A( afn, access, sharing, security, creation,
340 attributes, template );
341 HeapFree( GetProcessHeap(), 0, afn );
342 return res;
345 /*************************************************************************
346 * SetHandleCount32 (KERNEL32.494)
348 UINT32 SetHandleCount32( UINT32 cHandles )
350 return SetHandleCount16(cHandles);
354 int CloseFileHandle(HFILE hFile)
356 if (!_lclose(hFile))
357 return TRUE;
358 return FALSE;
361 static int TranslateAccessFlags(DWORD access_flags)
363 int rc = 0;
365 switch(access_flags)
367 case GENERIC_READ:
368 rc = O_RDONLY;
369 break;
371 case GENERIC_WRITE:
372 rc = O_WRONLY;
373 break;
375 case (GENERIC_READ | GENERIC_WRITE):
376 rc = O_RDWR;
377 break;
380 return rc;
383 static int TranslateCreationFlags(DWORD create_flags)
385 int rc = 0;
387 switch(create_flags)
389 case CREATE_NEW:
390 rc = O_CREAT | O_EXCL;
391 break;
393 case CREATE_ALWAYS:
394 rc = O_CREAT | O_TRUNC;
395 break;
397 case OPEN_EXISTING:
398 rc = 0;
399 break;
401 case OPEN_ALWAYS:
402 rc = O_CREAT;
403 break;
405 case TRUNCATE_EXISTING:
406 rc = O_TRUNC;
407 break;
410 return rc;
414 /**************************************************************************
415 * GetFileAttributes32A (KERNEL32.217)
417 DWORD GetFileAttributes32A(LPCSTR lpFileName)
419 struct stat buf;
420 DWORD res=0;
421 char *fn;
423 dprintf_file(stddeb,"GetFileAttributesA(%s)\n",lpFileName);
424 fn=(LPSTR)DOSFS_GetUnixFileName(lpFileName,FALSE);
425 /* fn points to a static buffer, don't free it */
426 if(stat(fn,&buf)==-1) {
427 SetLastError(ErrnoToLastError(errno));
428 return 0xFFFFFFFF;
430 if(buf.st_mode & S_IFREG)
431 res |= FILE_ATTRIBUTE_NORMAL;
432 if(buf.st_mode & S_IFDIR)
433 res |= FILE_ATTRIBUTE_DIRECTORY;
434 if((buf.st_mode & S_IWRITE) == 0)
435 res |= FILE_ATTRIBUTE_READONLY;
436 return res;
439 /**************************************************************************
440 * GetFileAttributes32W (KERNEL32.218)
442 DWORD GetFileAttributes32W(LPCWSTR lpFileName)
444 LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
445 DWORD res = GetFileAttributes32A( afn );
446 HeapFree( GetProcessHeap(), 0, afn );
447 return res;
451 /**************************************************************************
452 * SetFileAttributes32A (KERNEL32.490)
454 BOOL32 SetFileAttributes32A(LPCSTR lpFileName, DWORD attributes)
456 struct stat buf;
457 LPSTR fn=(LPSTR)DOSFS_GetUnixFileName(lpFileName,FALSE);
459 dprintf_file(stddeb,"SetFileAttributes(%s,%lx)\n",lpFileName,attributes);
460 if(stat(fn,&buf)==-1) {
461 SetLastError(ErrnoToLastError(errno));
462 return FALSE;
464 if (attributes & FILE_ATTRIBUTE_READONLY) {
465 buf.st_mode &= ~0222; /* octal!, clear write permission bits */
466 attributes &= ~FILE_ATTRIBUTE_READONLY;
468 attributes &= ~(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
469 if (attributes)
470 fprintf(stdnimp,"SetFileAttributesA(%s):%lx attribute(s) not implemented.\n",lpFileName,attributes);
471 if (-1==chmod(fn,buf.st_mode)) {
472 SetLastError(ErrnoToLastError(errno));
473 return FALSE;
475 return TRUE;
478 /**************************************************************************
479 * SetFileAttributes32W (KERNEL32.491)
481 BOOL32 SetFileAttributes32W(LPCWSTR lpFileName, DWORD attributes)
483 LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
484 BOOL32 res = SetFileAttributes32A( afn, attributes );
485 HeapFree( GetProcessHeap(), 0, afn );
486 return res;
489 /**************************************************************************
490 * SetEndOfFile (KERNEL32.483)
492 BOOL32 SetEndOfFile(HFILE hFile)
494 int unixfd = FILE_GetUnixHandle(hFile);
496 dprintf_file(stddeb,"SetEndOfFile(%lx)\n",(LONG)hFile);
497 if (!unixfd)
498 return 0;
499 if (-1==ftruncate(unixfd,lseek(unixfd,0,SEEK_CUR))) {
500 SetLastError(ErrnoToLastError(errno));
501 return FALSE;
503 return TRUE;
507 /**************************************************************************
508 * MoveFileA (KERNEL32.387)
510 BOOL32 MoveFile32A(LPCSTR fn1,LPCSTR fn2)
512 LPSTR ufn1;
513 LPSTR ufn2;
515 dprintf_file(stddeb,"MoveFileA(%s,%s)\n",fn1,fn2);
516 ufn1 = (LPSTR)DOSFS_GetUnixFileName(fn1,FALSE);
517 if (!ufn1) {
518 SetLastError(ErrnoToLastError(ENOENT));
519 return FALSE;
521 ufn1 = xstrdup(ufn1);
522 ufn2 = (LPSTR)DOSFS_GetUnixFileName(fn2,FALSE);
523 if (!ufn2) {
524 SetLastError(ErrnoToLastError(ENOENT));
525 return FALSE;
527 ufn2 = xstrdup(ufn2);
528 if (-1==rename(ufn1,ufn2)) {
529 SetLastError(ErrnoToLastError(errno));
530 free(ufn1);
531 free(ufn2);
532 return FALSE;
534 free(ufn1);
535 free(ufn2);
536 return TRUE;
539 /**************************************************************************
540 * MoveFileW (KERNEL32.390)
542 BOOL32 MoveFile32W(LPCWSTR fn1,LPCWSTR fn2)
544 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
545 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
546 BOOL32 res = MoveFile32A( afn1, afn2 );
547 HeapFree( GetProcessHeap(), 0, afn1 );
548 HeapFree( GetProcessHeap(), 0, afn2 );
549 return res;
552 VOID SetFileApisToOEM()
554 fprintf(stdnimp,"SetFileApisToOEM(),stub!\n");
557 VOID SetFileApisToANSI()
559 fprintf(stdnimp,"SetFileApisToANSI(),stub!\n");
562 BOOL32 AreFileApisANSI()
564 fprintf(stdnimp,"AreFileApisANSI(),stub!\n");
565 return TRUE;
569 BOOL32 CopyFile32A(LPCSTR sourcefn,LPCSTR destfn,BOOL32 failifexists)
571 OFSTRUCT of;
572 HFILE hf1,hf2;
573 char buffer[2048];
574 int lastread,curlen;
576 fprintf(stddeb,"CopyFile: %s -> %s\n",sourcefn,destfn);
577 hf1 = OpenFile(sourcefn,&of,OF_READ);
578 if (hf1==HFILE_ERROR)
579 return TRUE;
580 if (failifexists) {
581 hf2 = OpenFile(sourcefn,&of,OF_WRITE);
582 if (hf2 != HFILE_ERROR)
583 return FALSE;
584 _lclose(hf2);
586 hf2 = OpenFile(sourcefn,&of,OF_WRITE);
587 if (hf2 == HFILE_ERROR)
588 return FALSE;
589 curlen = 0;
590 while ((lastread=_lread16(hf1,buffer,sizeof(buffer)))>0) {
591 curlen=0;
592 while (curlen<lastread) {
593 int res = _lwrite16(hf2,buffer+curlen,lastread-curlen);
594 if (res<=0) break;
595 curlen+=res;
598 _lclose(hf1);
599 _lclose(hf2);
600 return curlen > 0;
603 BOOL32
604 LockFile(
605 HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
606 DWORD nNumberOfBytesToLockLow,DWORD nNumberOfBytesToLockHigh )
608 fprintf(stdnimp,"LockFile(%d,0x%08lx%08lx,0x%08lx%08lx),stub!\n",
609 hFile,dwFileOffsetHigh,dwFileOffsetLow,
610 nNumberOfBytesToLockHigh,nNumberOfBytesToLockLow
612 return TRUE;
615 BOOL32
616 UnlockFile(
617 HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
618 DWORD nNumberOfBytesToUnlockLow,DWORD nNumberOfBytesToUnlockHigh )
620 fprintf(stdnimp,"UnlockFile(%d,0x%08lx%08lx,0x%08lx%08lx),stub!\n",
621 hFile,dwFileOffsetHigh,dwFileOffsetLow,
622 nNumberOfBytesToUnlockHigh,nNumberOfBytesToUnlockLow
624 return TRUE;