2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis, Sven Verdoolaege, and Cameron Heide
10 #include <sys/types.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);
38 /***********************************************************************
39 * OpenFileMappingA (KERNEL32.397)
42 HANDLE32 OpenFileMapping(DWORD access, BOOL inherit,const char *fname)
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;
60 SetLastError(ErrnoToLastError(errno));
61 return INVALID_HANDLE_VALUE;
63 fd = open(lpName, O_CREAT, 0666);
66 SetLastError(ErrnoToLastError(errno));
67 return INVALID_HANDLE_VALUE;
69 file_obj = (FILE_OBJECT *)
70 CreateKernelObject(sizeof(FILE_OBJECT));
73 SetLastError(ERROR_UNKNOWN);
76 filemap_obj = (FILEMAP_OBJECT *)
77 CreateKernelObject(sizeof(FILEMAP_OBJECT));
78 if(filemap_obj == NULL)
80 ReleaseKernelObject(file_obj);
81 SetLastError(ERROR_UNKNOWN);
84 file_obj->common.magic = KERNEL_OBJECT_FILE;
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,
108 /***********************************************************************
109 * GetFileInformationByHandle (KERNEL32.219)
112 DWORD GetFileInformationByHandle(FILE_OBJECT *hFile,
113 BY_HANDLE_FILE_INFORMATION *lpfi)
115 struct stat file_stat;
118 if(ValidateKernelObject((HANDLE32)hFile) != 0)
120 SetLastError(ERROR_INVALID_HANDLE);
123 if(hFile->common.magic != KERNEL_OBJECT_FILE)
125 SetLastError(ERROR_INVALID_HANDLE);
129 rc = fstat(hFile->fd, &file_stat);
132 SetLastError(ErrnoToLastError(errno));
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;
167 static void UnixTimeToFileTime(time_t unix_time, FILETIME *filetime)
169 /* This isn't anywhere close to being correct, but should
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;
199 /***********************************************************************
200 * GetStdHandle (KERNEL32.276)
202 HANDLE32 GetStdHandle(DWORD nStdHandle)
208 case STD_INPUT_HANDLE:
209 rc = (HANDLE32)hstdin;
212 case STD_OUTPUT_HANDLE:
213 rc = (HANDLE32)hstdout;
216 case STD_ERROR_HANDLE:
217 rc = (HANDLE32)hstderr;
221 rc = INVALID_HANDLE_VALUE;
222 SetLastError(ERROR_INVALID_HANDLE);
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,
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);
255 dprintf_win32(stddeb, "SetFilePointer: 64-bit offsets not yet supported.\n");
260 rc = lseek(hFile->fd, distance, method);
262 SetLastError(ErrnoToLastError(errno));
266 /***********************************************************************
267 * WriteFile (KERNEL32.578)
269 BOOL WriteFile(FILE_OBJECT *hFile, LPVOID lpBuffer, DWORD numberOfBytesToWrite,
270 LPDWORD numberOfBytesWritten, LPOVERLAPPED lpOverlapped)
274 if(ValidateKernelObject((HANDLE32)hFile) != 0)
276 SetLastError(ERROR_INVALID_HANDLE);
279 if(hFile->common.magic != KERNEL_OBJECT_FILE)
281 SetLastError(ERROR_INVALID_HANDLE);
285 written = write(hFile->fd, lpBuffer, numberOfBytesToWrite);
286 if(numberOfBytesWritten)
287 *numberOfBytesWritten = written;
292 /***********************************************************************
293 * ReadFile (KERNEL32.428)
295 BOOL ReadFile(FILE_OBJECT *hFile, LPVOID lpBuffer, DWORD numtoread,
296 LPDWORD numread, LPOVERLAPPED lpOverlapped)
300 if(ValidateKernelObject((HANDLE32)hFile) != 0)
302 SetLastError(ERROR_INVALID_HANDLE);
305 if(hFile->common.magic != KERNEL_OBJECT_FILE)
307 SetLastError(ERROR_INVALID_HANDLE);
311 actual_read = read(hFile->fd, lpBuffer, numtoread);
312 if(actual_read == -1)
314 SetLastError(ErrnoToLastError(errno));
318 *numread = actual_read;
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;
335 FILE_OBJECT *file_obj;
338 /* Translate the various flags to Unix-style.
340 access_flags = TranslateAccessFlags(access);
341 create_flags = TranslateCreationFlags(creation);
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))
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;
368 else if(!strcmp(filename, "CONOUT$"))
370 type = FILE_TYPE_CHAR;
375 const char *unixName = DOSFS_GetUnixFileName( filename, FALSE );
376 type = FILE_TYPE_DISK;
378 /* Try to open the file.
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
391 file_obj = (FILE_OBJECT *)CreateKernelObject(sizeof(FILE_OBJECT));
394 SetLastError(ERROR_INVALID_HANDLE);
395 return INVALID_HANDLE_VALUE;
397 file_obj->common.magic = KERNEL_OBJECT_FILE;
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
427 static int TranslateAccessFlags(DWORD access_flags)
441 case (GENERIC_READ | GENERIC_WRITE):
449 static int TranslateCreationFlags(DWORD create_flags)
456 rc = O_CREAT | O_EXCL;
460 rc = O_CREAT | O_TRUNC;
471 case TRUNCATE_EXISTING:
479 /**************************************************************************
482 DWORD GetFileAttributesA(LPCSTR lpFileName)
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));
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;