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
;