2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis, Sven Verdoolaege, and Cameron Heide
10 #include <sys/types.h>
26 extern FILE_OBJECT
*hstdin
;
27 extern FILE_OBJECT
*hstdout
;
28 extern FILE_OBJECT
*hstderr
;
30 static void UnixTimeToFileTime(time_t unix_time
, FILETIME
*filetime
);
31 static int TranslateCreationFlags(DWORD create_flags
);
32 static int TranslateAccessFlags(DWORD access_flags
);
37 /***********************************************************************
38 * OpenFileMappingA (KERNEL32.397)
41 HANDLE32
OpenFileMapping(DWORD access
, BOOL inherit
,const char *fname
)
45 /***********************************************************************
46 * CreateFileMappingA (KERNEL32.46)
49 int TranslateProtectionFlags(DWORD
);
50 HANDLE32
CreateFileMapping(HANDLE32 h
,SECURITY_ATTRIBUTES
*ats
,
51 DWORD pot
, DWORD sh
, DWORD hlow
, const char * lpName
)
53 FILE_OBJECT
*file_obj
;
54 FILEMAP_OBJECT
*filemap_obj
;
59 SetLastError(ErrnoToLastError(errno
));
60 return INVALID_HANDLE_VALUE
;
62 fd
= open(lpName
, O_CREAT
, 0666);
65 SetLastError(ErrnoToLastError(errno
));
66 return INVALID_HANDLE_VALUE
;
68 file_obj
= (FILE_OBJECT
*)
69 CreateKernelObject(sizeof(FILE_OBJECT
));
72 SetLastError(ERROR_UNKNOWN
);
75 filemap_obj
= (FILEMAP_OBJECT
*)
76 CreateKernelObject(sizeof(FILEMAP_OBJECT
));
77 if(filemap_obj
== NULL
)
79 ReleaseKernelObject(file_obj
);
80 SetLastError(ERROR_UNKNOWN
);
83 file_obj
->common
.magic
= KERNEL_OBJECT_FILE
;
85 file_obj
->type
= FILE_TYPE_DISK
;
86 filemap_obj
->common
.magic
= KERNEL_OBJECT_FILEMAP
;
87 filemap_obj
->file_obj
= file_obj
;
88 filemap_obj
->prot
= TranslateProtectionFlags(pot
);
89 filemap_obj
->size
= hlow
;
90 return (HANDLE32
)filemap_obj
;;
93 /***********************************************************************
94 * MapViewOfFileEx (KERNEL32.386)
97 void *MapViewOfFileEx(HANDLE32 handle
, DWORD access
, DWORD offhi
,
98 DWORD offlo
, DWORD size
, DWORD st
)
100 if (!size
) size
= ((FILEMAP_OBJECT
*)handle
)->size
;
101 return mmap ((caddr_t
)st
, size
, ((FILEMAP_OBJECT
*)handle
)->prot
,
102 MAP_ANON
|MAP_PRIVATE
,
103 ((FILEMAP_OBJECT
*)handle
)->file_obj
->fd
,
107 /***********************************************************************
108 * GetFileInformationByHandle (KERNEL32.219)
111 DWORD
GetFileInformationByHandle(FILE_OBJECT
*hFile
,
112 BY_HANDLE_FILE_INFORMATION
*lpfi
)
114 struct stat file_stat
;
117 if(ValidateKernelObject((HANDLE32
)hFile
) != 0)
119 SetLastError(ERROR_INVALID_HANDLE
);
122 if(hFile
->common
.magic
!= KERNEL_OBJECT_FILE
)
124 SetLastError(ERROR_INVALID_HANDLE
);
128 rc
= fstat(hFile
->fd
, &file_stat
);
131 SetLastError(ErrnoToLastError(errno
));
135 /* Translate the file attributes.
137 lpfi
->dwFileAttributes
= 0;
138 if(file_stat
.st_mode
& S_IFREG
)
139 lpfi
->dwFileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
140 if(file_stat
.st_mode
& S_IFDIR
)
141 lpfi
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
142 if((file_stat
.st_mode
& S_IWRITE
) == 0)
143 lpfi
->dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
145 /* Translate the file times. Use the last modification time
146 * for both the creation time and write time.
148 UnixTimeToFileTime(file_stat
.st_mtime
, &(lpfi
->ftCreationTime
));
149 UnixTimeToFileTime(file_stat
.st_mtime
, &(lpfi
->ftLastWriteTime
));
150 UnixTimeToFileTime(file_stat
.st_atime
, &(lpfi
->ftLastAccessTime
));
152 lpfi
->nFileSizeLow
= file_stat
.st_size
;
153 lpfi
->nNumberOfLinks
= file_stat
.st_nlink
;
154 lpfi
->nFileIndexLow
= file_stat
.st_ino
;
156 /* Zero out currently unused fields.
158 lpfi
->dwVolumeSerialNumber
= 0;
159 lpfi
->nFileSizeHigh
= 0;
160 lpfi
->nFileIndexHigh
= 0;
166 static void UnixTimeToFileTime(time_t unix_time
, FILETIME
*filetime
)
168 /* This isn't anywhere close to being correct, but should
171 filetime
->dwLowDateTime
= (unix_time
& 0x0000FFFF) << 16;
172 filetime
->dwHighDateTime
= (unix_time
& 0xFFFF0000) >> 16;
176 /***********************************************************************
177 * GetFileType (KERNEL32.222)
179 * GetFileType currently only supports stdin, stdout, and stderr, which
180 * are considered to be of type FILE_TYPE_CHAR.
182 DWORD
GetFileType(FILE_OBJECT
*hFile
)
184 if(ValidateKernelObject((HANDLE32
)hFile
) != 0)
186 SetLastError(ERROR_UNKNOWN
);
187 return FILE_TYPE_UNKNOWN
;
189 if(hFile
->common
.magic
!= KERNEL_OBJECT_FILE
)
191 SetLastError(ERROR_UNKNOWN
);
192 return FILE_TYPE_UNKNOWN
;
198 /***********************************************************************
199 * GetStdHandle (KERNEL32.276)
201 HANDLE32
GetStdHandle(DWORD nStdHandle
)
207 case STD_INPUT_HANDLE
:
208 rc
= (HANDLE32
)hstdin
;
211 case STD_OUTPUT_HANDLE
:
212 rc
= (HANDLE32
)hstdout
;
215 case STD_ERROR_HANDLE
:
216 rc
= (HANDLE32
)hstderr
;
220 rc
= INVALID_HANDLE_VALUE
;
221 SetLastError(ERROR_INVALID_HANDLE
);
228 /***********************************************************************
229 * SetFilePointer (KERNEL32.492)
231 * Luckily enough, this function maps almost directly into an lseek
232 * call, the exception being the use of 64-bit offsets.
234 DWORD
SetFilePointer(FILE_OBJECT
*hFile
, LONG distance
, LONG
*highword
,
239 if(ValidateKernelObject((HANDLE32
)hFile
) != 0)
241 SetLastError(ERROR_INVALID_HANDLE
);
242 return ((DWORD
)0xFFFFFFFF);
244 if(hFile
->common
.magic
!= KERNEL_OBJECT_FILE
)
246 SetLastError(ERROR_INVALID_HANDLE
);
247 return ((DWORD
)0xFFFFFFFF);
254 dprintf_win32(stddeb
, "SetFilePointer: 64-bit offsets not yet supported.\n");
259 rc
= lseek(hFile
->fd
, distance
, method
);
261 SetLastError(ErrnoToLastError(errno
));
265 /***********************************************************************
266 * WriteFile (KERNEL32.578)
268 BOOL
WriteFile(FILE_OBJECT
*hFile
, LPVOID lpBuffer
, DWORD numberOfBytesToWrite
,
269 LPDWORD numberOfBytesWritten
, LPOVERLAPPED lpOverlapped
)
273 if(ValidateKernelObject((HANDLE32
)hFile
) != 0)
275 SetLastError(ERROR_INVALID_HANDLE
);
278 if(hFile
->common
.magic
!= KERNEL_OBJECT_FILE
)
280 SetLastError(ERROR_INVALID_HANDLE
);
284 written
= write(hFile
->fd
, lpBuffer
, numberOfBytesToWrite
);
285 if(numberOfBytesWritten
)
286 *numberOfBytesWritten
= written
;
291 /***********************************************************************
292 * ReadFile (KERNEL32.428)
294 BOOL
ReadFile(FILE_OBJECT
*hFile
, LPVOID lpBuffer
, DWORD numtoread
,
295 LPDWORD numread
, LPOVERLAPPED lpOverlapped
)
299 if(ValidateKernelObject((HANDLE32
)hFile
) != 0)
301 SetLastError(ERROR_INVALID_HANDLE
);
304 if(hFile
->common
.magic
!= KERNEL_OBJECT_FILE
)
306 SetLastError(ERROR_INVALID_HANDLE
);
310 actual_read
= read(hFile
->fd
, lpBuffer
, numtoread
);
311 if(actual_read
== -1)
313 SetLastError(ErrnoToLastError(errno
));
317 *numread
= actual_read
;
322 /*************************************************************************
323 * CreateFile (KERNEL32.45)
325 * Doesn't support character devices, pipes, template files, or a
326 * lot of the 'attributes' flags yet.
328 HANDLE32
CreateFileA(LPSTR filename
, DWORD access
, DWORD sharing
,
329 LPSECURITY_ATTRIBUTES security
, DWORD creation
,
330 DWORD attributes
, HANDLE32
template)
332 int access_flags
, create_flags
;
334 FILE_OBJECT
*file_obj
;
337 /* Translate the various flags to Unix-style.
339 access_flags
= TranslateAccessFlags(access
);
340 create_flags
= TranslateCreationFlags(creation
);
343 dprintf_win32(stddeb
, "CreateFile: template handles not supported.\n");
345 /* If the name starts with '\\?' or '\\.', ignore the first 3 chars.
347 if(!strncmp(filename
, "\\\\?", 3) || !strncmp(filename
, "\\\\.", 3))
350 /* If the name still starts with '\\', it's a UNC name.
352 if(!strncmp(filename
, "\\\\", 2))
354 dprintf_win32(stddeb
, "CreateFile: UNC names not supported.\n");
355 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
356 return INVALID_HANDLE_VALUE
;
359 /* If the name is either CONIN$ or CONOUT$, give them stdin
360 * or stdout, respectively.
362 if(!strcmp(filename
, "CONIN$"))
364 type
= FILE_TYPE_CHAR
;
367 else if(!strcmp(filename
, "CONOUT$"))
369 type
= FILE_TYPE_CHAR
;
374 const char *unixName
= DOSFS_GetUnixFileName( filename
, FALSE
);
375 type
= FILE_TYPE_DISK
;
377 /* Try to open the file.
380 ((fd
= open(unixName
, access_flags
| create_flags
, 0666)) == -1))
382 SetLastError(ErrnoToLastError(errno
));
383 return INVALID_HANDLE_VALUE
;
387 /* We seem to have succeeded, so allocate a kernel object
390 file_obj
= (FILE_OBJECT
*)CreateKernelObject(sizeof(FILE_OBJECT
));
393 SetLastError(ERROR_INVALID_HANDLE
);
394 return INVALID_HANDLE_VALUE
;
396 file_obj
->common
.magic
= KERNEL_OBJECT_FILE
;
398 file_obj
->type
= type
;
399 file_obj
->misc_flags
= attributes
;
400 file_obj
->access_flags
= access_flags
;
401 file_obj
->create_flags
= create_flags
;
403 return (HANDLE32
)file_obj
;
406 /*************************************************************************
407 * W32_SetHandleCount (KERNEL32.??)
410 UINT
W32_SetHandleCount(UINT cHandles
)
412 return SetHandleCount(cHandles
);
415 int CloseFileHandle(FILE_OBJECT
*hFile
)
417 /* If it's one of the 3 standard handles, don't really
426 static int TranslateAccessFlags(DWORD access_flags
)
440 case (GENERIC_READ
| GENERIC_WRITE
):
448 static int TranslateCreationFlags(DWORD create_flags
)
455 rc
= O_CREAT
| O_EXCL
;
459 rc
= O_CREAT
| O_TRUNC
;
470 case TRUNCATE_EXISTING
:
478 /**************************************************************************
481 DWORD
GetFileAttributesA(LPCSTR lpFileName
)
485 if(stat(lpFileName
,&buf
)==-1)
487 SetLastError(ErrnoToLastError(errno
));
490 if(buf
.st_mode
& S_IFREG
)
491 res
|= FILE_ATTRIBUTE_NORMAL
;
492 if(buf
.st_mode
& S_IFDIR
)
493 res
|= FILE_ATTRIBUTE_DIRECTORY
;
494 if((buf
.st_mode
& S_IWRITE
) == 0)
495 res
|= FILE_ATTRIBUTE_READONLY
;