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