Merge pull request #4433 from kumpera/android-fixes
[mono.git] / mono / metadata / w32file-win32.c
1 /*
2  * w32file-win32.c: Windows File IO internal calls.
3  *
4  * Copyright 2016 Microsoft
5  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
6  */
7 #include <config.h>
8 #include <glib.h>
9
10 #include <winsock2.h>
11 #include <windows.h>
12 #include "mono/metadata/w32file-win32-internals.h"
13
14 void
15 mono_w32file_init (void)
16 {
17 }
18
19 void
20 mono_w32file_cleanup (void)
21 {
22 }
23
24 gunichar2
25 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
26 {
27         return (gunichar2) ':'; /* colon */
28 }
29
30 gunichar2
31 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
32 {
33         return (gunichar2) '\\';        /* backslash */
34 }
35
36 gunichar2
37 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
38 {
39         return (gunichar2) '/'; /* forward slash */
40 }
41
42 gunichar2
43 ves_icall_System_IO_MonoIO_get_PathSeparator ()
44 {
45         return (gunichar2) ';'; /* semicolon */
46 }
47
48 void ves_icall_System_IO_MonoIO_DumpHandles (void)
49 {
50         return;
51 }
52
53 gpointer
54 mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
55 {
56         gpointer res;
57         MONO_ENTER_GC_SAFE;
58         res = CreateFile (name, fileaccess, sharemode, NULL, createmode, attrs, NULL);
59         MONO_EXIT_GC_SAFE;
60         return res;
61 }
62
63 gboolean
64 mono_w32file_close (gpointer handle)
65 {
66         gboolean res;
67         MONO_ENTER_GC_SAFE;
68         res = CloseHandle (handle);
69         MONO_EXIT_GC_SAFE;
70         return res;
71 }
72
73 gboolean
74 mono_w32file_delete (const gunichar2 *name)
75 {
76         gboolean res;
77         MONO_ENTER_GC_SAFE;
78         res = DeleteFile (name);
79         MONO_EXIT_GC_SAFE;
80         return res;
81 }
82
83 gboolean
84 mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
85 {
86         gboolean res;
87         MONO_ENTER_GC_SAFE;
88         res = ReadFile (handle, buffer, numbytes, bytesread, NULL);
89         MONO_EXIT_GC_SAFE;
90         return res;
91 }
92
93 gboolean
94 mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
95 {
96         gboolean res;
97         MONO_ENTER_GC_SAFE;
98         res = WriteFile (handle, buffer, numbytes, byteswritten, NULL);
99         MONO_EXIT_GC_SAFE;
100         return res;
101 }
102
103 gboolean
104 mono_w32file_flush (gpointer handle)
105 {
106         gboolean res;
107         MONO_ENTER_GC_SAFE;
108         res = FlushFileBuffers (handle);
109         MONO_EXIT_GC_SAFE;
110         return res;
111 }
112
113 gboolean
114 mono_w32file_truncate (gpointer handle)
115 {
116         gboolean res;
117         MONO_ENTER_GC_SAFE;
118         res = SetEndOfFile (handle);
119         MONO_EXIT_GC_SAFE;
120         return res;
121 }
122
123 guint32
124 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
125 {
126         guint32 res;
127         MONO_ENTER_GC_SAFE;
128         res = SetFilePointer (handle, movedistance, highmovedistance, method);
129         MONO_EXIT_GC_SAFE;
130         return res;
131 }
132
133 gint
134 mono_w32file_get_type (gpointer handle)
135 {
136         gint res;
137         MONO_ENTER_GC_SAFE;
138         res = GetFileType (handle);
139         MONO_EXIT_GC_SAFE;
140         return res;
141 }
142
143 gboolean
144 mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
145 {
146         gboolean res;
147         MONO_ENTER_GC_SAFE;
148         res = GetFileTime (handle, create_time, access_time, write_time);
149         MONO_EXIT_GC_SAFE;
150         return res;
151 }
152
153 gboolean
154 mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
155 {
156         gboolean res;
157         MONO_ENTER_GC_SAFE;
158         res = SetFileTime (handle, create_time, access_time, write_time);
159         MONO_EXIT_GC_SAFE;
160         return res;
161 }
162
163 gboolean
164 mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time)
165 {
166         gboolean res;
167         MONO_ENTER_GC_SAFE;
168         res = FileTimeToSystemTime (file_time, system_time);
169         MONO_EXIT_GC_SAFE;
170         return res;
171 }
172
173 gpointer
174 mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
175 {
176         gpointer res;
177         MONO_ENTER_GC_SAFE;
178         res = FindFirstFile (pattern, find_data);
179         MONO_EXIT_GC_SAFE;
180         return res;
181 }
182
183 gboolean
184 mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
185 {
186         gboolean res;
187         MONO_ENTER_GC_SAFE;
188         res = FindNextFile (handle, find_data);
189         MONO_EXIT_GC_SAFE;
190         return res;
191 }
192
193 gboolean
194 mono_w32file_find_close (gpointer handle)
195 {
196         gboolean res;
197         MONO_ENTER_GC_SAFE;
198         res = FindClose (handle);
199         MONO_EXIT_GC_SAFE;
200         return res;
201 }
202
203 gboolean
204 mono_w32file_create_directory (const gunichar2 *name)
205 {
206         gboolean res;
207         MONO_ENTER_GC_SAFE;
208         res = CreateDirectory (name, NULL);
209         MONO_EXIT_GC_SAFE;
210         return res;
211 }
212
213 gboolean
214 mono_w32file_remove_directory (const gunichar2 *name)
215 {
216         gboolean res;
217         MONO_ENTER_GC_SAFE;
218         res = RemoveDirectory (name);
219         MONO_EXIT_GC_SAFE;
220         return res;
221 }
222
223 guint32
224 mono_w32file_get_attributes (const gunichar2 *name)
225 {
226         guint32 res;
227         MONO_ENTER_GC_SAFE;
228         res = GetFileAttributes (name);
229         MONO_EXIT_GC_SAFE;
230         return res;
231 }
232
233 gboolean
234 mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
235 {
236         gboolean result;
237         WIN32_FILE_ATTRIBUTE_DATA data;
238
239         MONO_ENTER_GC_SAFE;
240         result = GetFileAttributesEx (name, GetFileExInfoStandard, &data);
241         MONO_EXIT_GC_SAFE;
242         if (result) {
243                 stat->attributes = data.dwFileAttributes;
244                 stat->creation_time = (gint64) ((((guint64) data.ftCreationTime.dwHighDateTime) << 32) + data.ftCreationTime.dwLowDateTime);
245                 stat->last_access_time = (gint64) ((((guint64) data.ftLastAccessTime.dwHighDateTime) << 32) + data.ftLastAccessTime.dwLowDateTime);
246                 stat->last_write_time = (gint64) ((((guint64) data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime);
247                 stat->length = ((gint64)data.nFileSizeHigh << 32) | data.nFileSizeLow;
248         }
249
250         return result;
251 }
252
253 gboolean
254 mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
255 {
256         gboolean res;
257         MONO_ENTER_GC_SAFE;
258         res = SetFileAttributes (name, attrs);
259         MONO_EXIT_GC_SAFE;
260         return res;
261 }
262
263 guint32
264 mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
265 {
266         guint32 res;
267         MONO_ENTER_GC_SAFE;
268         res = GetCurrentDirectory (length, buffer);
269         MONO_EXIT_GC_SAFE;
270         return res;
271 }
272
273 gboolean
274 mono_w32file_set_cwd (const gunichar2 *path)
275 {
276         gboolean res;
277         MONO_ENTER_GC_SAFE;
278         res = SetCurrentDirectory (path);
279         MONO_EXIT_GC_SAFE;
280         return res;
281 }
282
283 gboolean
284 mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
285 {
286         gboolean res;
287         SECURITY_ATTRIBUTES attr;
288         attr.nLength = sizeof(SECURITY_ATTRIBUTES);
289         attr.bInheritHandle = TRUE;
290         attr.lpSecurityDescriptor = NULL;
291         MONO_ENTER_GC_SAFE;
292         res = CreatePipe (readpipe, writepipe, &attr, size);
293         MONO_EXIT_GC_SAFE;
294         return res;
295 }
296
297 gboolean
298 mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
299 {
300         gboolean result;
301         ULARGE_INTEGER *wapi_free_bytes_avail;
302         ULARGE_INTEGER *wapi_total_number_of_bytes;
303         ULARGE_INTEGER *wapi_total_number_of_free_bytes;
304
305         MONO_ENTER_GC_SAFE;
306         result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes);
307         MONO_EXIT_GC_SAFE;
308         if (result) {
309                 if (free_bytes_avail)
310                         *free_bytes_avail = wapi_free_bytes_avail->QuadPart;
311                 if (total_number_of_bytes)
312                         *total_number_of_bytes = wapi_total_number_of_bytes->QuadPart;
313                 if (total_number_of_free_bytes)
314                         *total_number_of_free_bytes = wapi_total_number_of_free_bytes->QuadPart;
315         }
316
317         return result;
318 }
319
320 gboolean
321 mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
322 {
323         gboolean res;
324         MONO_ENTER_GC_SAFE;
325         res = GetVolumeInformation (path, volumename, volumesize, outserial, maxcomp, fsflags, fsbuffer, fsbuffersize);
326         MONO_EXIT_GC_SAFE;
327         return res;
328 }
329
330 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
331
332 gboolean
333 mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
334 {
335         gboolean result;
336
337         MONO_ENTER_GC_SAFE;
338
339         result = MoveFile (path, dest);
340         if (!result)
341                 *error = GetLastError ();
342
343         MONO_EXIT_GC_SAFE;
344
345         return result;
346 }
347
348 gboolean
349 mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
350 {
351         gboolean result;
352
353         MONO_ENTER_GC_SAFE;
354
355         result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
356         if (!result)
357                 *error = GetLastError ();
358
359         MONO_EXIT_GC_SAFE;
360
361         return result;
362 }
363
364 gboolean
365 mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
366 {
367         gboolean result;
368
369         MONO_ENTER_GC_SAFE;
370
371         result = CopyFile (path, dest, !overwrite);
372         if (!result)
373                 *error = GetLastError ();
374
375         MONO_EXIT_GC_SAFE;
376
377         return result;
378 }
379
380 gboolean
381 mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error)
382 {
383         gboolean result;
384
385         MONO_ENTER_GC_SAFE;
386
387         result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
388         if (!result)
389                 *error = GetLastError ();
390
391         MONO_EXIT_GC_SAFE;
392
393         return result;
394 }
395
396 gboolean
397 mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error)
398 {
399         gboolean result;
400
401         MONO_ENTER_GC_SAFE;
402
403         result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
404         if (!result)
405                 *error = GetLastError ();
406
407         MONO_EXIT_GC_SAFE;
408
409         return result;
410 }
411
412 HANDLE
413 mono_w32file_get_console_input (void)
414 {
415         HANDLE res;
416         MONO_ENTER_GC_SAFE;
417         res = GetStdHandle (STD_INPUT_HANDLE);
418         MONO_EXIT_GC_SAFE;
419         return res;
420 }
421
422 HANDLE
423 mono_w32file_get_console_output (void)
424 {
425         HANDLE res;
426         MONO_ENTER_GC_SAFE;
427         res = GetStdHandle (STD_OUTPUT_HANDLE);
428         MONO_EXIT_GC_SAFE;
429         return res;
430 }
431
432 HANDLE
433 mono_w32file_get_console_error (void)
434 {
435         HANDLE res;
436         MONO_ENTER_GC_SAFE;
437         res = GetStdHandle (STD_ERROR_HANDLE);
438         MONO_EXIT_GC_SAFE;
439         return res;
440 }
441
442 gint64
443 mono_w32file_get_file_size (gpointer handle, gint32 *error)
444 {
445         gint64 length;
446         guint32 length_hi;
447
448         MONO_ENTER_GC_SAFE;
449
450         length = GetFileSize (handle, &length_hi);
451         if(length==INVALID_FILE_SIZE) {
452                 *error=GetLastError ();
453         }
454
455         MONO_EXIT_GC_SAFE;
456
457         return length | ((gint64)length_hi << 32);
458 }
459
460 guint32
461 mono_w32file_get_drive_type (const gunichar2 *root_path_name)
462 {
463         guint32 res;
464         MONO_ENTER_GC_SAFE;
465         res = GetDriveType (root_path_name);
466         MONO_EXIT_GC_SAFE;
467         return res;
468 }
469
470 gint32
471 mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
472 {
473         gint32 res;
474         MONO_ENTER_GC_SAFE;
475         res = GetLogicalDriveStrings (len, buf);
476         MONO_EXIT_GC_SAFE;
477         return res;
478 }
479
480 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */