w32process-win32.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /**
  2. * \file
  3. * System.Diagnostics.Process support
  4. *
  5. * Author:
  6. * Dick Porter (dick@ximian.com)
  7. *
  8. * Copyright 2002 Ximian, Inc.
  9. * Copyright 2002-2006 Novell, Inc.
  10. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  11. */
  12. #include <config.h>
  13. #include <glib.h>
  14. #include <string.h>
  15. #include <winsock2.h>
  16. #include <windows.h>
  17. #include <mono/metadata/w32process.h>
  18. #include <mono/metadata/assembly.h>
  19. #include <mono/metadata/appdomain.h>
  20. #include <mono/metadata/image.h>
  21. #include <mono/metadata/cil-coff.h>
  22. #include <mono/metadata/exception.h>
  23. #include <mono/metadata/threadpool-io.h>
  24. #include <mono/utils/strenc.h>
  25. #include <mono/utils/mono-proclib.h>
  26. #include <mono/metadata/w32handle.h>
  27. #include <mono/utils/w32api.h>
  28. #include <mono/utils/mono-threads-coop.h>
  29. #include <mono/utils/w32subset.h>
  30. void
  31. mono_w32process_init (void)
  32. {
  33. }
  34. void
  35. mono_w32process_cleanup (void)
  36. {
  37. }
  38. void
  39. mono_w32process_signal_finished (void)
  40. {
  41. }
  42. guint32
  43. mono_w32process_get_pid (gpointer handle)
  44. {
  45. return GetProcessId (handle);
  46. }
  47. #if HAVE_API_SUPPORT_WIN32_ENUM_WINDOWS
  48. typedef struct {
  49. DWORD pid;
  50. HWND hwnd;
  51. } EnumWindowsArgs;
  52. static BOOL CALLBACK
  53. mono_enum_windows_callback(HWND hwnd, LPARAM lparam)
  54. {
  55. EnumWindowsArgs *args = (EnumWindowsArgs *)lparam;
  56. DWORD pid = 0;
  57. GetWindowThreadProcessId(hwnd, &pid);
  58. if (pid != args->pid || GetWindow(hwnd, GW_OWNER) != NULL || !IsWindowVisible(hwnd)) return TRUE;
  59. args->hwnd = hwnd;
  60. return FALSE;
  61. }
  62. HANDLE
  63. ves_icall_System_Diagnostics_Process_MainWindowHandle_internal (guint32 pid, MonoError *error)
  64. {
  65. EnumWindowsArgs args = {pid, NULL};
  66. EnumWindows(mono_enum_windows_callback, (LPARAM)&args);
  67. return args.hwnd;
  68. }
  69. #elif !HAVE_EXTERN_DEFINED_WIN32_ENUM_WINDOWS
  70. HANDLE
  71. ves_icall_System_Diagnostics_Process_MainWindowHandle_internal (guint32 pid, MonoError *error)
  72. {
  73. /*TODO: Implement for uwp*/
  74. return NULL;
  75. }
  76. #endif /* HAVE_API_SUPPORT_WIN32_ENUM_WINDOWS */
  77. #if HAVE_API_SUPPORT_WIN32_ENUM_PROCESS_MODULES
  78. gboolean
  79. mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
  80. {
  81. return EnumProcessModules (process, (HMODULE *)modules, size, (PDWORD)needed);
  82. }
  83. #elif !HAVE_EXTERN_DEFINED_WIN32_ENUM_PROCESS_MODULES
  84. gboolean
  85. mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
  86. {
  87. g_unsupported_api ("EnumProcessModules");
  88. SetLastError (ERROR_NOT_SUPPORTED);
  89. return FALSE;
  90. }
  91. #endif
  92. #if HAVE_API_SUPPORT_WIN32_GET_MODULE_BASE_NAME
  93. gboolean
  94. mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 **str, guint32 *len)
  95. {
  96. return mono_get_module_basename (process, module, str, len);
  97. }
  98. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_MODULE_BASE_NAME
  99. gboolean
  100. mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 **str, guint32 *len)
  101. {
  102. g_unsupported_api ("GetModuleBaseName");
  103. SetLastError (ERROR_NOT_SUPPORTED);
  104. return FALSE;
  105. }
  106. #endif /* HAVE_API_SUPPORT_WIN32_GET_MODULE_BASE_NAME */
  107. #if HAVE_API_SUPPORT_WIN32_GET_MODULE_FILE_NAME_EX
  108. gboolean
  109. mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 **str, guint32 *len)
  110. {
  111. return mono_get_module_filename_ex (process, module, str, len);
  112. }
  113. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_MODULE_FILE_NAME_EX
  114. gboolean
  115. mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 **str, guint32 *len)
  116. {
  117. g_unsupported_api ("GetModuleFileNameEx");
  118. SetLastError (ERROR_NOT_SUPPORTED);
  119. return FALSE;
  120. }
  121. #endif /* HAVE_API_SUPPORT_WIN32_GET_MODULE_FILE_NAME_EX */
  122. #if HAVE_API_SUPPORT_WIN32_GET_MODULE_INFORMATION
  123. gboolean
  124. mono_w32process_module_get_information (gpointer process, gpointer module, gpointer modinfo, guint32 size)
  125. {
  126. return GetModuleInformation (process, (HMODULE)module, (MODULEINFO *)modinfo, size);
  127. }
  128. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_MODULE_INFORMATION
  129. gboolean
  130. mono_w32process_module_get_information (gpointer process, gpointer module, gpointer modinfo, guint32 size)
  131. {
  132. g_unsupported_api ("GetModuleInformation");
  133. SetLastError (ERROR_NOT_SUPPORTED);
  134. return FALSE;
  135. }
  136. #endif /* HAVE_API_SUPPORT_WIN32_GET_MODULE_INFORMATION */
  137. #if HAVE_API_SUPPORT_WIN32_GET_FILE_VERSION_INFO
  138. gboolean
  139. mono_w32process_get_fileversion_info (const gunichar2 *filename, gpointer *data)
  140. {
  141. DWORD handle;
  142. g_assert (data);
  143. *data = NULL;
  144. DWORD datasize = GetFileVersionInfoSizeW (filename, &handle);
  145. if (datasize <= 0)
  146. return FALSE;
  147. *data = g_malloc0 (datasize);
  148. if (!GetFileVersionInfoW (filename, handle, datasize, *data)) {
  149. g_free (*data);
  150. return FALSE;
  151. }
  152. return TRUE;
  153. }
  154. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_FILE_VERSION_INFO
  155. gboolean
  156. mono_w32process_get_fileversion_info (const gunichar2 *filename, gpointer *data)
  157. {
  158. g_unsupported_api ("GetFileVersionInfo");
  159. SetLastError (ERROR_NOT_SUPPORTED);
  160. return FALSE;
  161. }
  162. #endif /* HAVE_API_SUPPORT_WIN32_GET_FILE_VERSION_INFO */
  163. #if HAVE_API_SUPPORT_WIN32_VER_QUERY_VALUE
  164. gboolean
  165. mono_w32process_ver_query_value (gconstpointer datablock, const gunichar2 *subblock, gpointer *buffer, guint32 *len)
  166. {
  167. return VerQueryValueW (datablock, subblock, buffer, len);
  168. }
  169. #elif !HAVE_EXTERN_DEFINED_WIN32_VER_QUERY_VALUE
  170. gboolean
  171. mono_w32process_ver_query_value (gconstpointer datablock, const gunichar2 *subblock, gpointer *buffer, guint32 *len)
  172. {
  173. g_unsupported_api ("VerQueryValue");
  174. SetLastError (ERROR_NOT_SUPPORTED);
  175. return FALSE;
  176. }
  177. #endif /* HAVE_API_SUPPORT_WIN32_VER_QUERY_VALUE */
  178. #if HAVE_API_SUPPORT_WIN32_VER_LANGUAGE_NAME
  179. guint32
  180. mono_w32process_ver_language_name (guint32 lang, gunichar2 *lang_out, guint32 lang_len)
  181. {
  182. return VerLanguageNameW (lang, lang_out, lang_len);
  183. }
  184. #elif !HAVE_EXTERN_DEFINED_WIN32_VER_LANGUAGE_NAME
  185. guint32
  186. mono_w32process_ver_language_name (guint32 lang, gunichar2 *lang_out, guint32 lang_len)
  187. {
  188. g_unsupported_api ("VerLanguageName");
  189. SetLastError (ERROR_NOT_SUPPORTED);
  190. return 0;
  191. }
  192. #endif /* HAVE_API_SUPPORT_WIN32_VER_LANGUAGE_NAME */
  193. #if HAVE_API_SUPPORT_WIN32_OPEN_PROCESS
  194. HANDLE
  195. ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid, MonoError *error)
  196. {
  197. HANDLE handle;
  198. /* GetCurrentProcess returns a pseudo-handle, so use
  199. * OpenProcess instead
  200. */
  201. handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
  202. if (handle == NULL)
  203. /* FIXME: Throw an exception */
  204. return NULL;
  205. return handle;
  206. }
  207. #elif !HAVE_EXTERN_DEFINED_WIN32_OPEN_PROCESS
  208. HANDLE
  209. ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid, MonoError *error)
  210. {
  211. g_unsupported_api ("OpenProcess");
  212. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "OpenProcess");
  213. SetLastError (ERROR_NOT_SUPPORTED);
  214. return NULL;
  215. }
  216. #endif /* HAVE_API_SUPPORT_WIN32_OPEN_PROCESS */
  217. #if HAVE_API_SUPPORT_WIN32_SHELL_EXECUTE_EX
  218. #include <shellapi.h>
  219. MonoBoolean
  220. ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfoHandle proc_start_info, MonoW32ProcessInfo *process_info, MonoError *error)
  221. {
  222. MonoCreateProcessCoop coop;
  223. mono_createprocess_coop_init (&coop, proc_start_info, process_info);
  224. SHELLEXECUTEINFOW shellex = {0};
  225. gboolean ret;
  226. shellex.cbSize = sizeof(SHELLEXECUTEINFO);
  227. shellex.fMask = (gulong)(SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE);
  228. shellex.nShow = (gulong)MONO_HANDLE_GETVAL (proc_start_info, window_style);
  229. shellex.nShow = (gulong)((shellex.nShow == 0) ? 1 : (shellex.nShow == 1 ? 0 : shellex.nShow));
  230. shellex.lpFile = coop.filename;
  231. shellex.lpParameters = coop.arguments;
  232. if (coop.length.verb)
  233. shellex.lpVerb = coop.verb;
  234. if (coop.length.working_directory)
  235. shellex.lpDirectory = coop.working_directory;
  236. if (MONO_HANDLE_GETVAL (proc_start_info, error_dialog))
  237. shellex.hwnd = (HWND)MONO_HANDLE_GETVAL (proc_start_info, error_dialog_parent_handle);
  238. else
  239. shellex.fMask = (gulong)(shellex.fMask | SEE_MASK_FLAG_NO_UI);
  240. MONO_ENTER_GC_SAFE;
  241. ret = ShellExecuteExW (&shellex);
  242. MONO_EXIT_GC_SAFE;
  243. if (ret == FALSE) {
  244. process_info->pid = -GetLastError ();
  245. } else {
  246. process_info->process_handle = shellex.hProcess;
  247. #if !defined(MONO_CROSS_COMPILE)
  248. process_info->pid = GetProcessId (shellex.hProcess);
  249. #else
  250. process_info->pid = 0;
  251. #endif
  252. }
  253. mono_createprocess_coop_cleanup (&coop);
  254. return ret;
  255. }
  256. #elif !HAVE_EXTERN_DEFINED_WIN32_SHELL_EXECUTE_EX
  257. MonoBoolean
  258. ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfoHandle proc_start_info, MonoW32ProcessInfo *process_info, MonoError *error)
  259. {
  260. g_unsupported_api ("ShellExecuteEx");
  261. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "ShellExecuteEx");
  262. process_info->pid = (guint32)(-ERROR_NOT_SUPPORTED);
  263. SetLastError (ERROR_NOT_SUPPORTED);
  264. return FALSE;
  265. }
  266. #endif /* HAVE_API_SUPPORT_WIN32_SHELL_EXECUTE_EX */
  267. #if HAVE_API_SUPPORT_WIN32_CREATE_PROCESS_WITH_LOGON || HAVE_API_SUPPORT_WIN32_CREATE_PROCESS
  268. static gboolean
  269. mono_process_create_process (MonoCreateProcessCoop *coop, MonoW32ProcessInfo *mono_process_info,
  270. MonoStringHandle cmd, guint32 creation_flags, gunichar2 *env_vars, gunichar2 *dir,
  271. HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, PROCESS_INFORMATION *process_info, MonoError *error)
  272. {
  273. gboolean result = FALSE;
  274. MonoGCHandle cmd_gchandle = NULL;
  275. gunichar2 *cmd_chars = MONO_HANDLE_IS_NULL (cmd) ? NULL : mono_string_handle_pin_chars (cmd, &cmd_gchandle);
  276. STARTUPINFOW start_info={0};
  277. #if HAVE_API_SUPPORT_WIN32_CONSOLE
  278. start_info.cb = sizeof(STARTUPINFOW);
  279. start_info.dwFlags = STARTF_USESTDHANDLES;
  280. start_info.hStdInput = stdin_handle;
  281. start_info.hStdOutput = stdout_handle;
  282. start_info.hStdError = stderr_handle;
  283. #else
  284. start_info.dwFlags = 0;
  285. start_info.hStdInput = INVALID_HANDLE_VALUE;
  286. start_info.hStdOutput = INVALID_HANDLE_VALUE;
  287. start_info.hStdError = INVALID_HANDLE_VALUE;
  288. #endif /* HAVE_API_SUPPORT_WIN32_CONSOLE */
  289. MONO_ENTER_GC_SAFE;
  290. if (coop->username) {
  291. #if HAVE_API_SUPPORT_WIN32_CREATE_PROCESS_WITH_LOGON
  292. guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
  293. result = CreateProcessWithLogonW (coop->username,
  294. coop->domain,
  295. mono_process_info->password,
  296. logon_flags,
  297. NULL,
  298. cmd_chars,
  299. creation_flags,
  300. env_vars, dir, &start_info, process_info);
  301. #else
  302. memset (process_info, 0, sizeof (PROCESS_INFORMATION));
  303. g_unsupported_api ("CreateProcessWithLogon");
  304. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "CreateProcessWithLogon");
  305. SetLastError (ERROR_NOT_SUPPORTED);
  306. #endif /* HAVE_API_SUPPORT_WIN32_CREATE_PROCESS_WITH_LOGON */
  307. } else {
  308. #if HAVE_API_SUPPORT_WIN32_CREATE_PROCESS
  309. result = CreateProcessW (NULL,
  310. cmd_chars,
  311. NULL,
  312. NULL,
  313. TRUE,
  314. creation_flags,
  315. env_vars,
  316. dir,
  317. &start_info,
  318. process_info);
  319. #else
  320. memset (process_info, 0, sizeof (PROCESS_INFORMATION));
  321. g_unsupported_api ("CreateProcess");
  322. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "CreateProcess");
  323. SetLastError (ERROR_NOT_SUPPORTED);
  324. #endif
  325. }
  326. MONO_EXIT_GC_SAFE;
  327. mono_gchandle_free_internal (cmd_gchandle);
  328. return result;
  329. }
  330. #elif !HAVE_EXTERN_DEFINED_WIN32_CREATE_PROCESS_WITH_LOGON && !HAVE_EXTERN_DEFINED_WIN32_CREATE_PROCESS
  331. static gboolean
  332. mono_process_create_process (MonoCreateProcessCoop *coop, MonoW32ProcessInfo *mono_process_info,
  333. MonoStringHandle cmd, guint32 creation_flags, gunichar2 *env_vars, gunichar2 *dir,
  334. HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, PROCESS_INFORMATION *process_info, MonoError *error)
  335. {
  336. memset (process_info, 0, sizeof (PROCESS_INFORMATION));
  337. g_unsupported_api ("CreateProcessWithLogon, CreateProcess");
  338. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "CreateProcessWithLogon, CreateProcess");
  339. SetLastError (ERROR_NOT_SUPPORTED);
  340. return FALSE;
  341. }
  342. #endif /* HAVE_API_SUPPORT_WIN32_CREATE_PROCESS_WITH_LOGON || HAVE_API_SUPPORT_WIN32_CREATE_PROCESS */
  343. static gchar*
  344. process_unquote_application_name (gchar *appname)
  345. {
  346. size_t len = strlen (appname);
  347. if (len) {
  348. if (appname[len-1] == '\"')
  349. appname[len-1] = '\0';
  350. if (appname[0] == '\"')
  351. appname++;
  352. }
  353. return appname;
  354. }
  355. static gchar*
  356. process_quote_path (const gchar *path)
  357. {
  358. gchar *res = g_shell_quote (path);
  359. gchar *q = res;
  360. while (*q) {
  361. if (*q == '\'')
  362. *q = '\"';
  363. q++;
  364. }
  365. return res;
  366. }
  367. /* Only used when UseShellExecute is false */
  368. static gchar*
  369. process_complete_path (const gunichar2 *appname)
  370. {
  371. // FIXME This function should stick to gunichar2.
  372. char *utf8app;
  373. char *utf8appmemory = NULL;
  374. char *result;
  375. utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
  376. utf8app = process_unquote_application_name (utf8appmemory);
  377. result = process_quote_path (utf8app);
  378. g_free (utf8appmemory);
  379. return result;
  380. }
  381. static gboolean
  382. process_get_shell_arguments (MonoCreateProcessCoop *proc_start_info, MonoStringHandle *cmd, MonoError *error)
  383. {
  384. char *spath = NULL;
  385. char *new_cmd = NULL;
  386. char *cmd_utf8 = NULL;
  387. *cmd = proc_start_info->coophandle.arguments;
  388. // FIXME There are excess utf8 <=> gunichar2 conversions here.
  389. // We are either returning spath, or spath + " " + cmd.
  390. // Just use gunichar2. Maybe move logic to C#.
  391. spath = process_complete_path (proc_start_info->filename);
  392. /* Seems like our CreateProcess does not work as the windows one.
  393. * This hack is needed to deal with paths containing spaces */
  394. if (!MONO_HANDLE_IS_NULL (*cmd)) {
  395. cmd_utf8 = mono_string_handle_to_utf8 (*cmd, error);
  396. goto_if_nok (error, error);
  397. new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
  398. *cmd = mono_string_new_utf8_len (mono_domain_get (), new_cmd, strlen (new_cmd), error);
  399. goto_if_nok (error, error);
  400. }
  401. else {
  402. *cmd = mono_string_new_utf8_len (mono_domain_get (), spath, strlen (spath), error);
  403. goto_if_nok (error, error);
  404. }
  405. exit:
  406. g_free (spath);
  407. g_free (cmd_utf8);
  408. g_free (new_cmd);
  409. return !MONO_HANDLE_IS_NULL (*cmd);
  410. error:
  411. *cmd = NULL_HANDLE_STRING;
  412. goto exit;
  413. }
  414. MonoBoolean
  415. ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfoHandle proc_start_info,
  416. HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info, MonoError *error)
  417. {
  418. MonoCreateProcessCoop coop;
  419. mono_createprocess_coop_init (&coop, proc_start_info, process_info);
  420. gboolean ret;
  421. gunichar2 *dir = NULL;
  422. PROCESS_INFORMATION procinfo;
  423. gunichar2 *env_vars = NULL;
  424. MonoStringHandle cmd = NULL_HANDLE_STRING;
  425. guint32 creation_flags;
  426. creation_flags = CREATE_UNICODE_ENVIRONMENT;
  427. if (MONO_HANDLE_GETVAL (proc_start_info, create_no_window))
  428. creation_flags |= CREATE_NO_WINDOW;
  429. if (process_get_shell_arguments (&coop, &cmd, error) == FALSE) {
  430. // FIXME This should be passed back separately.
  431. process_info->pid = -ERROR_FILE_NOT_FOUND;
  432. ret = FALSE;
  433. goto exit;
  434. }
  435. if (process_info->env_variables) {
  436. MonoArrayHandle array = MONO_HANDLE_NEW (MonoArray, process_info->env_variables);
  437. MonoStringHandle var = MONO_HANDLE_NEW (MonoString, NULL);
  438. gsize const array_length = mono_array_handle_length (array);
  439. // nul-separated and nul-terminated
  440. gsize len = array_length + 1 + !array_length;
  441. for (gsize i = 0; i < array_length; i++) {
  442. MONO_HANDLE_ARRAY_GETREF (var, array, i);
  443. len += mono_string_handle_length (var);
  444. }
  445. gunichar2 *ptr = g_new0 (gunichar2, len);
  446. env_vars = ptr;
  447. for (gsize i = 0; i < array_length; i++) {
  448. MONO_HANDLE_ARRAY_GETREF (var, array, i);
  449. MonoGCHandle gchandle = NULL;
  450. memcpy (ptr, mono_string_handle_pin_chars (var, &gchandle), mono_string_handle_length (var) * sizeof (gunichar2));
  451. mono_gchandle_free_internal (gchandle);
  452. ptr += mono_string_handle_length (var);
  453. ptr += 1; // Skip over the null-separator
  454. }
  455. }
  456. /* The default dir name is "". Turn that into NULL to mean
  457. * "current directory"
  458. */
  459. if (coop.length.working_directory)
  460. dir = coop.working_directory;
  461. ret = mono_process_create_process (&coop, process_info, cmd, creation_flags, env_vars, dir, stdin_handle, stdout_handle, stderr_handle, &procinfo, error);
  462. g_free (env_vars);
  463. if (ret) {
  464. process_info->process_handle = procinfo.hProcess;
  465. /*process_info->thread_handle=procinfo.hThread;*/
  466. if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
  467. CloseHandle (procinfo.hThread);
  468. process_info->pid = procinfo.dwProcessId;
  469. } else {
  470. // FIXME This should be passed back separately.
  471. process_info->pid = -GetLastError ();
  472. }
  473. exit:
  474. mono_createprocess_coop_cleanup (&coop);
  475. return ret;
  476. }
  477. #if HAVE_API_SUPPORT_WIN32_ENUM_PROCESSES
  478. MonoArrayHandle
  479. ves_icall_System_Diagnostics_Process_GetProcesses_internal (MonoError *error)
  480. {
  481. MonoArrayHandle procs = NULL_HANDLE_ARRAY;
  482. DWORD needed = 0;
  483. DWORD *pids = NULL;
  484. int count = 512;
  485. gboolean success;
  486. do {
  487. pids = g_new0 (DWORD, count);
  488. MONO_ENTER_GC_SAFE;
  489. success = EnumProcesses (pids, count * sizeof (DWORD), &needed);
  490. MONO_EXIT_GC_SAFE;
  491. if (!success)
  492. goto exit;
  493. if (needed < (count * sizeof (guint32)))
  494. break;
  495. g_free (pids);
  496. pids = NULL;
  497. count = (count * 3) / 2;
  498. } while (TRUE);
  499. count = needed / sizeof (guint32);
  500. procs = mono_array_new_handle (mono_domain_get (), mono_get_int32_class (), count, error);
  501. if (!is_ok (error)) {
  502. procs = NULL_HANDLE_ARRAY;
  503. goto exit;
  504. }
  505. MONO_ENTER_NO_SAFEPOINTS;
  506. memcpy (mono_array_addr_internal (MONO_HANDLE_RAW (procs), guint32, 0), pids, needed);
  507. MONO_EXIT_NO_SAFEPOINTS;
  508. exit:
  509. g_free (pids);
  510. return procs;
  511. }
  512. #elif !HAVE_EXTERN_DEFINED_WIN32_ENUM_PROCESSES
  513. MonoArrayHandle
  514. ves_icall_System_Diagnostics_Process_GetProcesses_internal (MonoError *error)
  515. {
  516. g_unsupported_api ("EnumProcesses");
  517. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "EnumProcesses");
  518. SetLastError (ERROR_NOT_SUPPORTED);
  519. return NULL_HANDLE_ARRAY;
  520. }
  521. #endif /* HAVE_API_SUPPORT_WIN32_ENUM_PROCESSES */
  522. MonoBoolean
  523. ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
  524. {
  525. return CloseHandle (handle);
  526. }
  527. MonoBoolean
  528. ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
  529. {
  530. return TerminateProcess (handle, exitcode);
  531. }
  532. MonoBoolean
  533. ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
  534. {
  535. return GetExitCodeProcess (handle, (PDWORD)exitcode);
  536. }
  537. #if HAVE_API_SUPPORT_WIN32_GET_WORKING_SET_SIZE
  538. MonoBoolean
  539. ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
  540. {
  541. return GetProcessWorkingSetSize (handle, (PSIZE_T)min, (PSIZE_T)max);
  542. }
  543. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_WORKING_SET_SIZE
  544. MonoBoolean
  545. ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
  546. {
  547. ERROR_DECL (error);
  548. g_unsupported_api ("GetProcessWorkingSetSize");
  549. mono_error_set_not_supported(error, G_UNSUPPORTED_API, "GetProcessWorkingSetSize");
  550. mono_error_set_pending_exception (error);
  551. SetLastError (ERROR_NOT_SUPPORTED);
  552. return FALSE;
  553. }
  554. #endif /* HAVE_API_SUPPORT_WIN32_GET_WORKING_SET_SIZE */
  555. #if HAVE_API_SUPPORT_WIN32_SET_WORKING_SET_SIZE
  556. MonoBoolean
  557. ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
  558. {
  559. return SetProcessWorkingSetSize (handle, min, max);
  560. }
  561. #elif !HAVE_EXTERN_DEFINED_WIN32_SET_WORKING_SET_SIZE
  562. MonoBoolean
  563. ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
  564. {
  565. ERROR_DECL (error);
  566. g_unsupported_api ("SetProcessWorkingSetSize");
  567. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "SetProcessWorkingSetSize");
  568. mono_error_set_pending_exception (error);
  569. SetLastError (ERROR_NOT_SUPPORTED);
  570. return FALSE;
  571. }
  572. #endif /* HAVE_API_SUPPORT_WIN32_SET_WORKING_SET_SIZE */
  573. #if HAVE_API_SUPPORT_WIN32_GET_PRIORITY_CLASS
  574. gint32
  575. ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
  576. {
  577. return GetPriorityClass (handle);
  578. }
  579. #elif !HAVE_EXTERN_DEFINED_WIN32_GET_PRIORITY_CLASS
  580. gint32
  581. ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
  582. {
  583. ERROR_DECL (error);
  584. g_unsupported_api ("GetPriorityClass");
  585. mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetPriorityClass");
  586. mono_error_set_pending_exception (error);
  587. SetLastError (ERROR_NOT_SUPPORTED);
  588. return FALSE;
  589. }
  590. #endif /* HAVE_API_SUPPORT_WIN32_GET_PRIORITY_CLASS */
  591. #if HAVE_API_SUPPORT_WIN32_SET_PRIORITY_CLASS
  592. MonoBoolean
  593. ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
  594. {
  595. return SetPriorityClass (handle, (guint32) priorityClass);
  596. }
  597. #elif !HAVE_EXTERN_DEFINED_WIN32_SET_PRIORITY_CLASS
  598. MonoBoolean
  599. ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
  600. {
  601. ERROR_DECL (error);
  602. g_unsupported_api ("SetPriorityClass");
  603. mono_error_set_not_supported(error, G_UNSUPPORTED_API, "SetPriorityClass");
  604. mono_error_set_pending_exception (error);
  605. SetLastError (ERROR_NOT_SUPPORTED);
  606. return FALSE;
  607. }
  608. #endif /* HAVE_API_SUPPORT_WIN32_SET_PRIORITY_CLASS */
  609. MonoBoolean
  610. ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
  611. {
  612. return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
  613. }
  614. gpointer
  615. ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
  616. {
  617. return GetCurrentProcess ();
  618. }