Merge pull request #3274 from Unity-Technologies/fix-path-getfullpath-windows
[mono.git] / mono / io-layer / wapi.c
1
2 #include "wapi.h"
3
4 #include "process-private.h"
5 #include "thread-private.h"
6 #include "io-trace.h"
7
8 #include "mono/utils/mono-lazy-init.h"
9 #include "mono/utils/w32handle.h"
10
11 gboolean _wapi_has_shut_down = FALSE;
12
13 void
14 wapi_init (void)
15 {
16         _wapi_shm_semaphores_init ();
17         _wapi_io_init ();
18         _wapi_processes_init ();
19         _wapi_thread_init ();
20         _wapi_semaphore_init ();
21         _wapi_mutex_init ();
22         _wapi_event_init ();
23         _wapi_socket_init ();
24 }
25
26 void
27 wapi_cleanup (void)
28 {
29         g_assert (_wapi_has_shut_down == FALSE);
30         _wapi_has_shut_down = TRUE;
31
32         _wapi_error_cleanup ();
33         _wapi_thread_cleanup ();
34         wapi_processes_cleanup ();
35         _wapi_io_cleanup ();
36 }
37
38 /* Use this instead of getpid(), to cope with linuxthreads.  It's a
39  * function rather than a variable lookup because we need to get at
40  * this before share_init() might have been called. */
41 static mono_lazy_init_t _wapi_pid_init_lazy = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
42 static pid_t _wapi_pid;
43
44 static void
45 _wapi_pid_init (void)
46 {
47         _wapi_pid = getpid ();
48 }
49
50 pid_t
51 _wapi_getpid (void)
52 {
53         mono_lazy_initialize (&_wapi_pid_init_lazy, _wapi_pid_init);
54         return _wapi_pid;
55 }
56
57 static gboolean
58 _WAPI_SHARED_NAMESPACE (MonoW32HandleType type)
59 {
60         switch (type) {
61         case MONO_W32HANDLE_NAMEDMUTEX:
62         case MONO_W32HANDLE_NAMEDSEM:
63         case MONO_W32HANDLE_NAMEDEVENT:
64                 return TRUE;
65         default:
66                 return FALSE;
67         }
68 }
69
70 typedef struct {
71         gpointer ret;
72         MonoW32HandleType type;
73         gchar *utf8_name;
74 } _WapiSearchHandleNamespaceData;
75
76 static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
77 {
78         _WapiSearchHandleNamespaceData *search_data;
79         MonoW32HandleType type;
80         WapiSharedNamespace *sharedns;
81
82         type = mono_w32handle_get_type (handle);
83         if (!_WAPI_SHARED_NAMESPACE (type))
84                 return FALSE;
85
86         search_data = (_WapiSearchHandleNamespaceData*) user_data;
87
88         switch (type) {
89         case MONO_W32HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break;
90         case MONO_W32HANDLE_NAMEDSEM:   sharedns = &((struct _WapiHandle_namedsem*)   data)->sharedns; break;
91         case MONO_W32HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break;
92         default:
93                 g_assert_not_reached ();
94         }
95
96         if (strcmp (sharedns->name, search_data->utf8_name) == 0) {
97                 if (type != search_data->type) {
98                         /* Its the wrong type, so fail now */
99                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
100                                 __func__, handle, mono_w32handle_ops_typename (type));
101                         search_data->ret = INVALID_HANDLE_VALUE;
102                 } else {
103                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
104                                 __func__, handle);
105                         search_data->ret = handle;
106                 }
107
108                 return TRUE;
109         }
110
111         return FALSE;
112 }
113
114 /* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for
115  * not found
116  */
117 gpointer _wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name)
118 {
119         _WapiSearchHandleNamespaceData search_data;
120
121         g_assert(_WAPI_SHARED_NAMESPACE(type));
122
123         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
124                 __func__, utf8_name, mono_w32handle_ops_typename (type));
125
126         search_data.ret = NULL;
127         search_data.type = type;
128         search_data.utf8_name = utf8_name;
129         mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data);
130         return search_data.ret;
131 }
132
133 /* Lots more to implement here, but this is all we need at the moment */
134 gboolean
135 DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
136         guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
137 {
138         if (srcprocess != _WAPI_PROCESS_CURRENT || targetprocess != _WAPI_PROCESS_CURRENT) {
139                 /* Duplicating other process's handles is not supported */
140                 SetLastError (ERROR_INVALID_HANDLE);
141                 return FALSE;
142         }
143
144         if (src == _WAPI_PROCESS_CURRENT) {
145                 *target = _wapi_process_duplicate ();
146         } else if (src == _WAPI_THREAD_CURRENT) {
147                 g_assert_not_reached ();
148         } else {
149                 mono_w32handle_ref (src);
150                 *target = src;
151         }
152
153         return TRUE;
154 }
155
156 /**
157  * CloseHandle:
158  * @handle: The handle to release
159  *
160  * Closes and invalidates @handle, releasing any resources it
161  * consumes.  When the last handle to a temporary or non-persistent
162  * object is closed, that object can be deleted.  Closing the same
163  * handle twice is an error.
164  *
165  * Return value: %TRUE on success, %FALSE otherwise.
166  */
167 gboolean CloseHandle(gpointer handle)
168 {
169         if (handle == INVALID_HANDLE_VALUE){
170                 SetLastError (ERROR_INVALID_PARAMETER);
171                 return FALSE;
172         }
173         if (handle == (gpointer)0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
174                 /* Problem: because we map file descriptors to the
175                  * same-numbered handle we can't tell the difference
176                  * between a bogus handle and the handle to stdin.
177                  * Assume that it's the console handle if that handle
178                  * exists...
179                  */
180                 SetLastError (ERROR_INVALID_PARAMETER);
181                 return FALSE;
182         }
183
184         mono_w32handle_unref (handle);
185         return TRUE;
186 }