2 * file-io.c: File IO internal calls
5 * Dick Porter (dick@ximian.com)
6 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
20 #ifdef HAVE_SYS_STAT_H
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
27 #include <mono/metadata/object.h>
28 #include <mono/io-layer/io-layer.h>
29 #include <mono/metadata/file-io.h>
30 #include <mono/metadata/exception.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/marshal.h>
33 #include <mono/utils/strenc.h>
37 /* conversion functions */
39 static guint32
convert_mode(MonoFileMode mono_mode
)
44 case FileMode_CreateNew
:
53 case FileMode_OpenOrCreate
:
56 case FileMode_Truncate
:
57 mode
=TRUNCATE_EXISTING
;
63 g_warning("System.IO.FileMode has unknown value 0x%x",
72 static guint32
convert_access(MonoFileAccess mono_access
)
80 case FileAccess_Write
:
83 case FileAccess_ReadWrite
:
84 access
=GENERIC_READ
|GENERIC_WRITE
;
87 g_warning("System.IO.FileAccess has unknown value 0x%x",
96 static guint32
convert_share(MonoFileShare mono_share
)
100 if (mono_share
& FileShare_Read
) {
101 share
|= FILE_SHARE_READ
;
103 if (mono_share
& FileShare_Write
) {
104 share
|= FILE_SHARE_WRITE
;
106 if (mono_share
& FileShare_Delete
) {
107 share
|= FILE_SHARE_DELETE
;
110 if (mono_share
& ~(FileShare_Read
|FileShare_Write
|FileShare_Delete
)) {
111 g_warning("System.IO.FileShare has unknown value 0x%x",
121 static guint32
convert_stdhandle(guint32 fd
)
127 stdhandle
=STD_INPUT_HANDLE
;
130 stdhandle
=STD_OUTPUT_HANDLE
;
133 stdhandle
=STD_ERROR_HANDLE
;
136 g_warning("unknown standard file descriptor %d", fd
);
137 stdhandle
=STD_INPUT_HANDLE
;
144 static guint32
convert_seekorigin(MonoSeekOrigin origin
)
149 case SeekOrigin_Begin
:
150 w32origin
=FILE_BEGIN
;
152 case SeekOrigin_Current
:
153 w32origin
=FILE_CURRENT
;
159 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
162 w32origin
=FILE_CURRENT
;
168 static gint64
convert_filetime (const FILETIME
*filetime
)
170 guint64 ticks
= filetime
->dwHighDateTime
;
172 ticks
+= filetime
->dwLowDateTime
;
173 return (gint64
)ticks
;
176 static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA
*data
, const gunichar2
*name
, MonoIOStat
*stat
)
180 stat
->attributes
= data
->dwFileAttributes
;
181 stat
->creation_time
= convert_filetime (&data
->ftCreationTime
);
182 stat
->last_access_time
= convert_filetime (&data
->ftLastAccessTime
);
183 stat
->last_write_time
= convert_filetime (&data
->ftLastWriteTime
);
184 stat
->length
= ((gint64
)data
->nFileSizeHigh
<< 32) | data
->nFileSizeLow
;
190 MONO_STRUCT_SETREF (stat
, name
, mono_string_new_utf16 (mono_domain_get (), name
, len
));
193 /* Managed file attributes have nearly but not quite the same values
194 * as the w32 equivalents.
196 static guint32
convert_attrs(MonoFileAttributes attrs
)
198 if(attrs
& FileAttributes_Encrypted
) {
199 attrs
|= FILE_ATTRIBUTE_ENCRYPTED
;
206 * On Win32, GetFileAttributes|Ex () seems to try opening the file,
207 * which might lead to sharing violation errors, whereas FindFirstFile
208 * always succeeds. These 2 wrappers resort to FindFirstFile if
209 * GetFileAttributes|Ex () has failed.
212 get_file_attributes (const gunichar2
*path
)
215 WIN32_FIND_DATA find_data
;
219 res
= GetFileAttributes (path
);
223 error
= GetLastError ();
225 if (error
!= ERROR_SHARING_VIOLATION
)
228 find_handle
= FindFirstFile (path
, &find_data
);
230 if (find_handle
== INVALID_HANDLE_VALUE
)
233 FindClose (find_handle
);
235 return find_data
.dwFileAttributes
;
239 get_file_attributes_ex (const gunichar2
*path
, WIN32_FILE_ATTRIBUTE_DATA
*data
)
242 WIN32_FIND_DATA find_data
;
246 res
= GetFileAttributesEx (path
, GetFileExInfoStandard
, data
);
250 error
= GetLastError ();
252 if (error
!= ERROR_SHARING_VIOLATION
)
255 find_handle
= FindFirstFile (path
, &find_data
);
257 if (find_handle
== INVALID_HANDLE_VALUE
)
260 FindClose (find_handle
);
262 data
->dwFileAttributes
= find_data
.dwFileAttributes
;
263 data
->ftCreationTime
= find_data
.ftCreationTime
;
264 data
->ftLastAccessTime
= find_data
.ftLastAccessTime
;
265 data
->ftLastWriteTime
= find_data
.ftLastWriteTime
;
266 data
->nFileSizeHigh
= find_data
.nFileSizeHigh
;
267 data
->nFileSizeLow
= find_data
.nFileSizeLow
;
272 /* System.IO.MonoIO internal calls */
275 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString
*path
, gint32
*error
)
281 *error
=ERROR_SUCCESS
;
283 ret
=CreateDirectory (mono_string_chars (path
), NULL
);
285 *error
=GetLastError ();
292 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString
*path
, gint32
*error
)
298 *error
=ERROR_SUCCESS
;
300 ret
=RemoveDirectory (mono_string_chars (path
));
302 *error
=GetLastError ();
309 ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString
*path
,
310 MonoString
*path_with_pattern
,
311 gint attrs
, gint mask
,
317 WIN32_FIND_DATA data
;
320 gchar
*utf8_path
, *utf8_result
, *full_name
;
324 *error
= ERROR_SUCCESS
;
326 domain
= mono_domain_get ();
327 mask
= convert_attrs (mask
);
329 find_handle
= FindFirstFile (mono_string_chars (path_with_pattern
),
331 if (find_handle
== INVALID_HANDLE_VALUE
) {
332 gint32 find_error
= GetLastError ();
334 if (find_error
== ERROR_FILE_NOT_FOUND
) {
335 /* No files, so just return an empty array */
336 result
= mono_array_new (domain
,
337 mono_defaults
.string_class
,
347 utf8_path
= mono_string_to_utf8 (path
); /*If this raises there is not memory to release*/
348 names
= g_ptr_array_new ();
351 if ((data
.cFileName
[0] == '.' && data
.cFileName
[1] == 0) ||
352 (data
.cFileName
[0] == '.' && data
.cFileName
[1] == '.' && data
.cFileName
[2] == 0)) {
356 if ((data
.dwFileAttributes
& mask
) == attrs
) {
357 utf8_result
= g_utf16_to_utf8 (data
.cFileName
, -1, NULL
, NULL
, NULL
);
358 if (utf8_result
== NULL
) {
362 full_name
= g_build_filename (utf8_path
, utf8_result
, NULL
);
363 g_ptr_array_add (names
, full_name
);
365 g_free (utf8_result
);
367 } while(FindNextFile (find_handle
, &data
));
369 if (FindClose (find_handle
) == FALSE
) {
370 *error
= GetLastError ();
373 result
= mono_array_new (domain
, mono_defaults
.string_class
, names
->len
);
374 for (i
= 0; i
< names
->len
; i
++) {
375 mono_array_setref (result
, i
, mono_string_new (domain
, g_ptr_array_index (names
, i
)));
379 for (i
= 0; i
< names
->len
; i
++) {
380 g_free (g_ptr_array_index (names
, i
));
382 g_ptr_array_free (names
, TRUE
);
395 incremental_find_check_match (IncrementalFind
*handle
, WIN32_FIND_DATA
*data
, MonoString
**result
)
400 if ((data
->cFileName
[0] == '.' && data
->cFileName
[1] == 0) || (data
->cFileName
[0] == '.' && data
->cFileName
[1] == '.' && data
->cFileName
[2] == 0))
403 utf8_result
= g_utf16_to_utf8 (data
->cFileName
, -1, NULL
, NULL
, NULL
);
404 if (utf8_result
== NULL
)
407 full_name
= g_build_filename (handle
->utf8_path
, utf8_result
, NULL
);
408 g_free (utf8_result
);
409 *result
= mono_string_new (mono_domain_get (), full_name
);
416 ves_icall_System_IO_MonoIO_FindFirst (MonoString
*path
,
417 MonoString
*path_with_pattern
,
418 gint32
*result_attr
, gint32
*error
,
421 WIN32_FIND_DATA data
;
423 IncrementalFind
*ifh
;
426 *error
= ERROR_SUCCESS
;
428 find_handle
= FindFirstFile (mono_string_chars (path_with_pattern
), &data
);
430 if (find_handle
== INVALID_HANDLE_VALUE
) {
431 gint32 find_error
= GetLastError ();
434 if (find_error
== ERROR_FILE_NOT_FOUND
)
441 ifh
= g_new (IncrementalFind
, 1);
442 ifh
->find_handle
= find_handle
;
443 ifh
->utf8_path
= mono_string_to_utf8 (path
);
444 ifh
->domain
= mono_domain_get ();
447 while (incremental_find_check_match (ifh
, &data
, &result
) == 0){
448 if (FindNextFile (find_handle
, &data
) == FALSE
){
449 int e
= GetLastError ();
450 if (e
!= ERROR_NO_MORE_FILES
)
455 *result_attr
= data
.dwFileAttributes
;
461 ves_icall_System_IO_MonoIO_FindNext (gpointer handle
, gint32
*result_attr
, gint32
*error
)
463 IncrementalFind
*ifh
= handle
;
464 WIN32_FIND_DATA data
;
467 error
= ERROR_SUCCESS
;
469 if (FindNextFile (ifh
->find_handle
, &data
) == FALSE
){
470 int e
= GetLastError ();
471 if (e
!= ERROR_NO_MORE_FILES
)
475 } while (incremental_find_check_match (ifh
, &data
, &result
) == 0);
477 *result_attr
= data
.dwFileAttributes
;
482 ves_icall_System_IO_MonoIO_FindClose (gpointer handle
)
484 IncrementalFind
*ifh
= handle
;
487 if (FindClose (ifh
->find_handle
) == FALSE
){
488 error
= GetLastError ();
490 error
= ERROR_SUCCESS
;
491 g_free (ifh
->utf8_path
);
498 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32
*error
)
506 len
= MAX_PATH
+ 1; /*FIXME this is too smal under most unix systems.*/
507 buf
= g_new (gunichar2
, len
);
509 *error
=ERROR_SUCCESS
;
512 res_len
= GetCurrentDirectory (len
, buf
);
513 if (res_len
> len
) { /*buf is too small.*/
514 int old_res_len
= res_len
;
516 buf
= g_new (gunichar2
, res_len
);
517 res_len
= GetCurrentDirectory (res_len
, buf
) == old_res_len
;
525 result
= mono_string_new_utf16 (mono_domain_get (), buf
, len
);
527 *error
=GetLastError ();
535 ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString
*path
,
542 *error
=ERROR_SUCCESS
;
544 ret
=SetCurrentDirectory (mono_string_chars (path
));
546 *error
=GetLastError ();
553 ves_icall_System_IO_MonoIO_MoveFile (MonoString
*path
, MonoString
*dest
,
560 *error
=ERROR_SUCCESS
;
562 ret
=MoveFile (mono_string_chars (path
), mono_string_chars (dest
));
564 *error
=GetLastError ();
571 ves_icall_System_IO_MonoIO_ReplaceFile (MonoString
*sourceFileName
, MonoString
*destinationFileName
,
572 MonoString
*destinationBackupFileName
, MonoBoolean ignoreMetadataErrors
,
576 gunichar2
*utf16_sourceFileName
= NULL
, *utf16_destinationFileName
= NULL
, *utf16_destinationBackupFileName
= NULL
;
577 guint32 replaceFlags
= REPLACEFILE_WRITE_THROUGH
;
582 utf16_sourceFileName
= mono_string_chars (sourceFileName
);
583 if (destinationFileName
)
584 utf16_destinationFileName
= mono_string_chars (destinationFileName
);
585 if (destinationBackupFileName
)
586 utf16_destinationBackupFileName
= mono_string_chars (destinationBackupFileName
);
588 *error
= ERROR_SUCCESS
;
589 if (ignoreMetadataErrors
)
590 replaceFlags
|= REPLACEFILE_IGNORE_MERGE_ERRORS
;
592 ret
= ReplaceFile (utf16_destinationFileName
, utf16_sourceFileName
, utf16_destinationBackupFileName
,
593 replaceFlags
, NULL
, NULL
);
595 *error
= GetLastError ();
601 ves_icall_System_IO_MonoIO_CopyFile (MonoString
*path
, MonoString
*dest
,
602 MonoBoolean overwrite
, gint32
*error
)
608 *error
=ERROR_SUCCESS
;
610 ret
=CopyFile (mono_string_chars (path
), mono_string_chars (dest
), !overwrite
);
612 *error
=GetLastError ();
619 ves_icall_System_IO_MonoIO_DeleteFile (MonoString
*path
, gint32
*error
)
625 *error
=ERROR_SUCCESS
;
627 ret
=DeleteFile (mono_string_chars (path
));
629 *error
=GetLastError ();
636 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString
*path
, gint32
*error
)
642 *error
=ERROR_SUCCESS
;
644 ret
=get_file_attributes (mono_string_chars (path
));
647 * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
648 * headers is wrong, hence this temporary workaround.
650 * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
653 /* if(ret==INVALID_FILE_ATTRIBUTES) { */
654 *error
=GetLastError ();
661 ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString
*path
, gint32 attrs
,
668 *error
=ERROR_SUCCESS
;
670 ret
=SetFileAttributes (mono_string_chars (path
),
671 convert_attrs (attrs
));
673 *error
=GetLastError ();
680 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle
, gint32
*error
)
686 *error
=ERROR_SUCCESS
;
688 ret
=GetFileType (handle
);
689 if(ret
==FILE_TYPE_UNKNOWN
) {
690 /* Not necessarily an error, but the caller will have
691 * to decide based on the error value.
693 *error
=GetLastError ();
700 ves_icall_System_IO_MonoIO_GetFileStat (MonoString
*path
, MonoIOStat
*stat
,
704 WIN32_FILE_ATTRIBUTE_DATA data
;
708 *error
=ERROR_SUCCESS
;
710 result
= get_file_attributes_ex (mono_string_chars (path
), &data
);
713 convert_win32_file_attribute_data (&data
,
714 mono_string_chars (path
),
717 *error
=GetLastError ();
724 ves_icall_System_IO_MonoIO_Open (MonoString
*filename
, gint32 mode
,
725 gint32 access_mode
, gint32 share
, gint32 options
,
729 int attributes
, attrs
;
730 gunichar2
*chars
= mono_string_chars (filename
);
734 *error
=ERROR_SUCCESS
;
737 if (options
& FileOptions_Encrypted
)
738 attributes
= FILE_ATTRIBUTE_ENCRYPTED
;
740 attributes
= FILE_ATTRIBUTE_NORMAL
;
741 if (options
& FileOptions_DeleteOnClose
)
742 attributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
743 if (options
& FileOptions_SequentialScan
)
744 attributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
745 if (options
& FileOptions_RandomAccess
)
746 attributes
|= FILE_FLAG_RANDOM_ACCESS
;
748 if (options
& FileOptions_Temporary
)
749 attributes
|= FILE_ATTRIBUTE_TEMPORARY
;
751 /* Not sure if we should set FILE_FLAG_OVERLAPPED, how does this mix with the "Async" bool here? */
752 if (options
& FileOptions_Asynchronous
)
753 attributes
|= FILE_FLAG_OVERLAPPED
;
755 if (options
& FileOptions_WriteThrough
)
756 attributes
|= FILE_FLAG_WRITE_THROUGH
;
758 attributes
= FILE_ATTRIBUTE_NORMAL
;
760 /* If we're opening a directory we need to set the extra flag
762 attrs
= get_file_attributes (chars
);
763 if (attrs
!= INVALID_FILE_ATTRIBUTES
) {
764 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
765 attributes
|= FILE_FLAG_BACKUP_SEMANTICS
;
769 ret
=CreateFile (chars
, convert_access (access_mode
),
770 convert_share (share
), NULL
, convert_mode (mode
),
772 if(ret
==INVALID_HANDLE_VALUE
) {
773 *error
=GetLastError ();
780 ves_icall_System_IO_MonoIO_Close (HANDLE handle
, gint32
*error
)
786 *error
=ERROR_SUCCESS
;
788 ret
=CloseHandle (handle
);
790 *error
=GetLastError ();
797 ves_icall_System_IO_MonoIO_Read (HANDLE handle
, MonoArray
*dest
,
798 gint32 dest_offset
, gint32 count
,
807 *error
=ERROR_SUCCESS
;
809 if (dest_offset
+ count
> mono_array_length (dest
))
812 buffer
= mono_array_addr (dest
, guchar
, dest_offset
);
813 result
= ReadFile (handle
, buffer
, count
, &n
, NULL
);
816 *error
=GetLastError ();
824 ves_icall_System_IO_MonoIO_Write (HANDLE handle
, MonoArray
*src
,
825 gint32 src_offset
, gint32 count
,
834 *error
=ERROR_SUCCESS
;
836 if (src_offset
+ count
> mono_array_length (src
))
839 buffer
= mono_array_addr (src
, guchar
, src_offset
);
840 result
= WriteFile (handle
, buffer
, count
, &n
, NULL
);
843 *error
=GetLastError ();
851 ves_icall_System_IO_MonoIO_Seek (HANDLE handle
, gint64 offset
, gint32 origin
,
858 *error
=ERROR_SUCCESS
;
860 offset_hi
= offset
>> 32;
861 offset
= SetFilePointer (handle
, (gint32
) (offset
& 0xFFFFFFFF), &offset_hi
,
862 convert_seekorigin (origin
));
864 if(offset
==INVALID_SET_FILE_POINTER
) {
865 *error
=GetLastError ();
868 return offset
| ((gint64
)offset_hi
<< 32);
872 ves_icall_System_IO_MonoIO_Flush (HANDLE handle
, gint32
*error
)
878 *error
=ERROR_SUCCESS
;
880 ret
=FlushFileBuffers (handle
);
882 *error
=GetLastError ();
889 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle
, gint32
*error
)
896 *error
=ERROR_SUCCESS
;
898 length
= GetFileSize (handle
, &length_hi
);
899 if(length
==INVALID_FILE_SIZE
) {
900 *error
=GetLastError ();
903 return length
| ((gint64
)length_hi
<< 32);
907 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle
, gint64 length
,
910 gint64 offset
, offset_set
;
917 *error
=ERROR_SUCCESS
;
919 /* save file pointer */
922 offset
= SetFilePointer (handle
, 0, &offset_hi
, FILE_CURRENT
);
923 if(offset
==INVALID_SET_FILE_POINTER
) {
924 *error
=GetLastError ();
928 /* extend or truncate */
930 length_hi
= length
>> 32;
931 offset_set
=SetFilePointer (handle
, length
& 0xFFFFFFFF, &length_hi
,
933 if(offset_set
==INVALID_SET_FILE_POINTER
) {
934 *error
=GetLastError ();
938 result
= SetEndOfFile (handle
);
940 *error
=GetLastError ();
944 /* restore file pointer */
946 offset_set
=SetFilePointer (handle
, offset
& 0xFFFFFFFF, &offset_hi
,
948 if(offset_set
==INVALID_SET_FILE_POINTER
) {
949 *error
=GetLastError ();
957 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle
, gint64 creation_time
,
958 gint64 last_access_time
,
959 gint64 last_write_time
, gint32
*error
)
962 const FILETIME
*creation_filetime
;
963 const FILETIME
*last_access_filetime
;
964 const FILETIME
*last_write_filetime
;
968 *error
=ERROR_SUCCESS
;
970 if (creation_time
< 0)
971 creation_filetime
= NULL
;
973 creation_filetime
= (FILETIME
*)&creation_time
;
975 if (last_access_time
< 0)
976 last_access_filetime
= NULL
;
978 last_access_filetime
= (FILETIME
*)&last_access_time
;
980 if (last_write_time
< 0)
981 last_write_filetime
= NULL
;
983 last_write_filetime
= (FILETIME
*)&last_write_time
;
985 ret
=SetFileTime (handle
, creation_filetime
, last_access_filetime
, last_write_filetime
);
987 *error
=GetLastError ();
994 ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
998 return GetStdHandle (STD_OUTPUT_HANDLE
);
1002 ves_icall_System_IO_MonoIO_get_ConsoleInput ()
1004 MONO_ARCH_SAVE_REGS
;
1006 return GetStdHandle (STD_INPUT_HANDLE
);
1010 ves_icall_System_IO_MonoIO_get_ConsoleError ()
1012 MONO_ARCH_SAVE_REGS
;
1014 return GetStdHandle (STD_ERROR_HANDLE
);
1018 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE
*read_handle
,
1019 HANDLE
*write_handle
)
1021 SECURITY_ATTRIBUTES attr
;
1024 MONO_ARCH_SAVE_REGS
;
1026 attr
.nLength
=sizeof(SECURITY_ATTRIBUTES
);
1027 attr
.bInheritHandle
=TRUE
;
1028 attr
.lpSecurityDescriptor
=NULL
;
1030 ret
=CreatePipe (read_handle
, write_handle
, &attr
, 0);
1032 /* FIXME: throw an exception? */
1039 MonoBoolean
ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle
,
1040 HANDLE source_handle
, HANDLE target_process_handle
, HANDLE
*target_handle
,
1041 gint32 access
, gint32 inherit
, gint32 options
)
1043 /* This is only used on Windows */
1046 MONO_ARCH_SAVE_REGS
;
1048 ret
=DuplicateHandle (source_process_handle
, source_handle
, target_process_handle
, target_handle
, access
, inherit
, options
);
1050 /* FIXME: throw an exception? */
1058 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
1060 #if defined (TARGET_WIN32)
1061 return (gunichar2
) ':'; /* colon */
1063 return (gunichar2
) '/'; /* forward slash */
1068 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
1070 #if defined (TARGET_WIN32)
1071 return (gunichar2
) '\\'; /* backslash */
1073 return (gunichar2
) '/'; /* forward slash */
1078 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
1080 #if defined (TARGET_WIN32)
1081 return (gunichar2
) '/'; /* forward slash */
1083 return (gunichar2
) '/'; /* slash, same as DirectorySeparatorChar */
1088 ves_icall_System_IO_MonoIO_get_PathSeparator ()
1090 #if defined (TARGET_WIN32)
1091 return (gunichar2
) ';'; /* semicolon */
1093 return (gunichar2
) ':'; /* colon */
1097 static const gunichar2
1098 invalid_path_chars
[] = {
1099 #if defined (TARGET_WIN32)
1100 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
1101 0x003c, /* less than */
1102 0x003e, /* greater than */
1119 ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
1125 MONO_ARCH_SAVE_REGS
;
1127 domain
= mono_domain_get ();
1128 n
= sizeof (invalid_path_chars
) / sizeof (gunichar2
);
1129 chars
= mono_array_new (domain
, mono_defaults
.char_class
, n
);
1131 for (i
= 0; i
< n
; ++ i
)
1132 mono_array_set (chars
, gunichar2
, i
, invalid_path_chars
[i
]);
1138 ves_icall_System_IO_MonoIO_GetTempPath (MonoString
**mono_name
)
1143 name
=g_new0 (gunichar2
, 256);
1145 ret
=GetTempPath (256, name
);
1147 /* Buffer was too short. Try again... */
1149 name
=g_new0 (gunichar2
, ret
+2); /* include the terminator */
1150 ret
=GetTempPath (ret
, name
);
1155 g_message ("%s: Temp path is [%s] (len %d)", __func__
, name
, ret
);
1158 mono_gc_wbarrier_generic_store ((gpointer
) mono_name
,
1159 (MonoObject
*) mono_string_new_utf16 (mono_domain_get (), name
, ret
));
1167 void ves_icall_System_IO_MonoIO_Lock (HANDLE handle
, gint64 position
,
1168 gint64 length
, gint32
*error
)
1172 *error
=ERROR_SUCCESS
;
1174 ret
=LockFile (handle
, position
& 0xFFFFFFFF, position
>> 32,
1175 length
& 0xFFFFFFFF, length
>> 32);
1177 *error
= GetLastError ();
1181 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle
, gint64 position
,
1182 gint64 length
, gint32
*error
)
1186 *error
=ERROR_SUCCESS
;
1188 ret
=UnlockFile (handle
, position
& 0xFFFFFFFF, position
>> 32,
1189 length
& 0xFFFFFFFF, length
>> 32);
1191 *error
= GetLastError ();