2 * process.c: System.Diagnostics.Process support
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
14 #include <mono/metadata/object.h>
15 #include <mono/metadata/process.h>
16 #include <mono/metadata/assembly.h>
17 #include <mono/metadata/appdomain.h>
18 #include <mono/metadata/image.h>
19 #include <mono/metadata/cil-coff.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/io-layer/io-layer.h>
25 HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
31 /* GetCurrentProcess returns a pseudo-handle, so use
34 handle=OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
37 /* FIXME: Throw an exception */
44 guint32 ves_icall_System_Diagnostics_Process_GetPid_internal (void)
48 return(GetCurrentProcessId ());
51 void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this,
57 g_message (G_GNUC_PRETTY_FUNCTION ": Closing process %p, handle %p",
61 CloseHandle (process);
64 #define STASH_SYS_ASS(this) \
65 if(system_assembly == NULL) { \
66 system_assembly=this->vtable->klass->image; \
69 static MonoImage *system_assembly=NULL;
71 static guint32 unicode_chars (const gunichar2 *str)
83 static guint32 unicode_bytes (const gunichar2 *str)
89 /* Include the terminators */
96 static void process_set_field_object (MonoObject *obj, const guchar *fieldname,
99 MonoClassField *field;
102 g_message (G_GNUC_PRETTY_FUNCTION ": Setting field %s to object at %p",
106 field=mono_class_get_field_from_name (mono_object_class (obj),
108 *(MonoObject **)(((char *)obj) + field->offset)=data;
111 static void process_set_field_string (MonoObject *obj, const guchar *fieldname,
112 const gunichar2 *val, guint32 len)
114 MonoClassField *field;
118 g_message (G_GNUC_PRETTY_FUNCTION ": Setting field %s to [%s]",
119 fieldname, g_utf16_to_utf8 (val, len, NULL, NULL, NULL));
122 string=mono_string_new_utf16 (mono_object_domain (obj), val, len);
124 field=mono_class_get_field_from_name (mono_object_class (obj),
126 *(MonoString **)(((char *)obj) + field->offset)=string;
129 static void process_set_field_string_utf8 (MonoObject *obj,
130 const guchar *fieldname,
133 MonoClassField *field;
137 g_message (G_GNUC_PRETTY_FUNCTION ": Setting field %s to [%s]",
141 string=mono_string_new (mono_object_domain (obj), val);
143 field=mono_class_get_field_from_name (mono_object_class (obj),
145 *(MonoString **)(((char *)obj) + field->offset)=string;
148 static void process_set_field_int (MonoObject *obj, const guchar *fieldname,
151 MonoClassField *field;
154 g_message (G_GNUC_PRETTY_FUNCTION ": Setting field %s to %d",
158 field=mono_class_get_field_from_name (mono_object_class (obj),
160 *(guint32 *)(((char *)obj) + field->offset)=val;
163 static void process_set_field_bool (MonoObject *obj, const guchar *fieldname,
166 MonoClassField *field;
169 g_message (G_GNUC_PRETTY_FUNCTION ": Setting field %s to %s",
170 fieldname, val?"TRUE":"FALSE");
173 field=mono_class_get_field_from_name (mono_object_class (obj),
175 *(guint8 *)(((char *)obj) + field->offset)=val;
185 /* Returns a pointer to the value data, because theres no way to know
186 * how big that data is (value_len is set to zero for most blocks :-()
188 static gpointer process_get_versioninfo_block (gpointer data,
191 block->data_len=*(((guint16 *)data)++);
192 block->value_len=*(((guint16 *)data)++);
194 /* No idea what the type is supposed to indicate */
195 block->type=*(((guint16 *)data)++);
196 block->key=((gunichar2 *)data);
198 /* skip over the key (including the terminator) */
199 data=((gunichar2 *)data)+(unicode_chars (block->key)+1);
201 /* align on a 32-bit boundary */
202 data=(gpointer)(((unsigned)data+3) & (~3));
207 /* Returns a pointer to the byte following the Var block */
208 static gpointer process_read_var_block (MonoObject *filever, gpointer data_ptr,
211 /* Not currently interested in the VarFileInfo block. This
212 * might change if language support is needed for file version
213 * strings (VarFileInfo contains lists of supported
218 /* data_ptr is pointing at a Var block of length data_len */
219 data_ptr=process_get_versioninfo_block (data_ptr, &block);
220 data_ptr=((guchar *)data_ptr)+block.value_len;
225 /* Returns a pointer to the byte following the String block */
226 static gpointer process_read_string_block (MonoObject *filever,
232 guint16 string_len=0;
233 guchar comments_key[]= {'C', '\0', 'o', '\0', 'm', '\0',
234 'm', '\0', 'e', '\0', 'n', '\0',
235 't', '\0', 's', '\0', '\0', '\0'};
236 guchar compname_key[]= {'C', '\0', 'o', '\0', 'm', '\0',
237 'p', '\0', 'a', '\0', 'n', '\0',
238 'y', '\0', 'N', '\0', 'a', '\0',
239 'm', '\0', 'e', '\0', '\0', '\0'};
240 guchar filedesc_key[]= {'F', '\0', 'i', '\0', 'l', '\0',
241 'e', '\0', 'D', '\0', 'e', '\0',
242 's', '\0', 'c', '\0', 'r', '\0',
243 'i', '\0', 'p', '\0', 't', '\0',
244 'i', '\0', 'o', '\0', 'n', '\0',
246 guchar filever_key[]= {'F', '\0', 'i', '\0', 'l', '\0',
247 'e', '\0', 'V', '\0', 'e', '\0',
248 'r', '\0', 's', '\0', 'i', '\0',
249 'o', '\0', 'n', '\0', '\0', '\0'};
250 guchar internal_key[]= {'I', '\0', 'n', '\0', 't', '\0',
251 'e', '\0', 'r', '\0', 'n', '\0',
252 'a', '\0', 'l', '\0', 'N', '\0',
253 'a', '\0', 'm', '\0', 'e', '\0',
255 guchar legalcpy_key[]= {'L', '\0', 'e', '\0', 'g', '\0',
256 'a', '\0', 'l', '\0', 'C', '\0',
257 'o', '\0', 'p', '\0', 'y', '\0',
258 'r', '\0', 'i', '\0', 'g', '\0',
259 'h', '\0', 't', '\0', '\0', '\0'};
260 guchar legaltrade_key[]= {'L', '\0', 'e', '\0', 'g', '\0',
261 'a', '\0', 'l', '\0', 'T', '\0',
262 'r', '\0', 'a', '\0', 'd', '\0',
263 'e', '\0', 'm', '\0', 'a', '\0',
264 'r', '\0', 'k', '\0', 's', '\0',
266 guchar origfile_key[]= {'O', '\0', 'r', '\0', 'i', '\0',
267 'g', '\0', 'i', '\0', 'n', '\0',
268 'a', '\0', 'l', '\0', 'F', '\0',
269 'i', '\0', 'l', '\0', 'e', '\0',
270 'n', '\0', 'a', '\0', 'm', '\0',
271 'e', '\0', '\0', '\0'};
272 guchar privbuild_key[]= {'P', '\0', 'r', '\0', 'i', '\0',
273 'v', '\0', 'a', '\0', 't', '\0',
274 'e', '\0', 'B', '\0', 'u', '\0',
275 'i', '\0', 'l', '\0', 'd', '\0',
277 guchar prodname_key[]= {'P', '\0', 'r', '\0', 'o', '\0',
278 'd', '\0', 'u', '\0', 'c', '\0',
279 't', '\0', 'N', '\0', 'a', '\0',
280 'm', '\0', 'e', '\0', '\0', '\0'};
281 guchar prodver_key[]= {'P', '\0', 'r', '\0', 'o', '\0',
282 'd', '\0', 'u', '\0', 'c', '\0',
283 't', '\0', 'V', '\0', 'e', '\0',
284 'r', '\0', 's', '\0', 'i', '\0',
285 'o', '\0', 'n', '\0', '\0', '\0'};
286 guchar specbuild_key[]= {'S', '\0', 'p', '\0', 'e', '\0',
287 'c', '\0', 'i', '\0', 'a', '\0',
288 'l', '\0', 'B', '\0', 'u', '\0',
289 'i', '\0', 'l', '\0', 'd', '\0',
292 /* data_ptr is pointing at an array of one or more String
293 * blocks with total length (not including alignment padding)
296 while(string_len<data_len) {
299 /* align on a 32-bit boundary */
300 data_ptr=(gpointer)(((unsigned)data_ptr+3) & (~3));
302 data_ptr=process_get_versioninfo_block (data_ptr, &block);
303 string_len=string_len+block.data_len;
304 value=(gunichar2 *)data_ptr;
305 /* Skip over the value */
306 data_ptr=((gunichar2 *)data_ptr)+block.value_len;
309 if(!memcmp (block.key, &comments_key,
310 unicode_bytes (block.key))) {
311 process_set_field_string (filever, "comments", value, unicode_chars (value));
312 } else if (!memcmp (block.key, &compname_key,
313 unicode_bytes (block.key))) {
314 process_set_field_string (filever, "companyname", value, unicode_chars (value));
315 } else if (!memcmp (block.key, &filedesc_key,
316 unicode_bytes (block.key))) {
317 process_set_field_string (filever, "filedescription", value, unicode_chars (value));
318 } else if (!memcmp (block.key, &filever_key,
319 unicode_bytes (block.key))) {
320 process_set_field_string (filever, "fileversion", value, unicode_chars (value));
321 } else if (!memcmp (block.key, &internal_key,
322 unicode_bytes (block.key))) {
323 process_set_field_string (filever, "internalname", value, unicode_chars (value));
324 } else if (!memcmp (block.key, &legalcpy_key,
325 unicode_bytes (block.key))) {
326 process_set_field_string (filever, "legalcopyright", value, unicode_chars (value));
327 } else if (!memcmp (block.key, &legaltrade_key,
328 unicode_bytes (block.key))) {
329 process_set_field_string (filever, "legaltrademarks", value, unicode_chars (value));
330 } else if (!memcmp (block.key, &origfile_key,
331 unicode_bytes (block.key))) {
332 process_set_field_string (filever, "originalfilename", value, unicode_chars (value));
333 } else if (!memcmp (block.key, &privbuild_key,
334 unicode_bytes (block.key))) {
335 process_set_field_string (filever, "privatebuild", value, unicode_chars (value));
336 } else if (!memcmp (block.key, &prodname_key,
337 unicode_bytes (block.key))) {
338 process_set_field_string (filever, "productname", value, unicode_chars (value));
339 } else if (!memcmp (block.key, &prodver_key,
340 unicode_bytes (block.key))) {
341 process_set_field_string (filever, "productversion", value, unicode_chars (value));
342 } else if (!memcmp (block.key, &specbuild_key,
343 unicode_bytes (block.key))) {
344 process_set_field_string (filever, "specialbuild", value, unicode_chars (value));
346 /* Not an error, just not interesting
356 /* returns a pointer to the byte following the Stringtable block */
357 static gpointer process_read_stringtable_block (MonoObject *filever,
362 guint16 string_len=36; /* length of the StringFileInfo block */
364 /* Specifies language-neutral unicode string block */
365 guchar uni_key[]= {'0', '\0', '0', '\0', '0', '\0', '0', '\0',
366 '0', '\0', '4', '\0', 'b', '\0', '0', '\0',
369 guchar uni_key_uc[]= {'0', '\0', '0', '\0', '0', '\0', '0', '\0',
370 '0', '\0', '4', '\0', 'B', '\0', '0', '\0',
374 /* data_ptr is pointing at an array of StringTable blocks,
375 * with total length (not including alignment padding) of
379 while(string_len<data_len) {
380 /* align on a 32-bit boundary */
381 data_ptr=(gpointer)(((unsigned)data_ptr+3) & (~3));
383 data_ptr=process_get_versioninfo_block (data_ptr, &block);
384 string_len=string_len+block.data_len;
386 if(!memcmp (block.key, &uni_key, unicode_bytes (block.key)) ||
387 !memcmp (block.key, &uni_key_uc, unicode_bytes (block.key))) {
388 /* Got the one we're interested in */
389 process_set_field_string_utf8 (filever, "language",
392 data_ptr=process_read_string_block (filever, data_ptr,
396 /* Some other language. We might want to do
397 * something with this in the future.
399 data_ptr=process_read_string_block (filever, data_ptr,
408 static void process_read_fixedfileinfo_block (MonoObject *filever,
409 VS_FIXEDFILEINFO *ffi)
412 g_message (G_GNUC_PRETTY_FUNCTION ": ffi: sig 0x%x, strucver 0x%x, fileverm 0x%x, fileverl 0x%x, prodverm 0x%x, prodverl 0x%x, ffmask 0x%x, ff 0x%x, os 0x%x, type 0x%x, subtype 0x%x, datem 0x%x, datel 0x%x", ffi->dwSignature, ffi->dwStrucVersion, ffi->dwFileVersionMS, ffi->dwFileVersionLS, ffi->dwProductVersionMS, ffi->dwProductVersionLS, ffi->dwFileFlagsMask, ffi->dwFileFlags, ffi->dwFileOS, ffi->dwFileType, ffi->dwFileSubtype, ffi->dwFileDateMS, ffi->dwFileDateLS);
415 process_set_field_int (filever, "filemajorpart",
416 HIWORD (ffi->dwFileVersionMS));
417 process_set_field_int (filever, "fileminorpart",
418 LOWORD (ffi->dwFileVersionMS));
419 process_set_field_int (filever, "filebuildpart",
420 HIWORD (ffi->dwFileVersionLS));
421 process_set_field_int (filever, "fileprivatepart",
422 LOWORD (ffi->dwFileVersionLS));
424 process_set_field_int (filever, "productmajorpart",
425 HIWORD (ffi->dwProductVersionMS));
426 process_set_field_int (filever, "productminorpart",
427 LOWORD (ffi->dwProductVersionMS));
428 process_set_field_int (filever, "productbuildpart",
429 HIWORD (ffi->dwProductVersionLS));
430 process_set_field_int (filever, "productprivatepart",
431 LOWORD (ffi->dwProductVersionLS));
433 process_set_field_bool (filever, "isdebug",
434 ffi->dwFileFlags&VS_FF_DEBUG);
435 process_set_field_bool (filever, "isprerelease",
436 ffi->dwFileFlags&VS_FF_PRERELEASE);
437 process_set_field_bool (filever, "ispatched",
438 ffi->dwFileFlags&VS_FF_PATCHED);
439 process_set_field_bool (filever, "isprivatebuild",
440 ffi->dwFileFlags&VS_FF_PRIVATEBUILD);
441 process_set_field_bool (filever, "isspecialbuild",
442 ffi->dwFileFlags&VS_FF_SPECIALBUILD);
445 static void process_get_fileversion (MonoObject *filever, MonoImage *image)
447 MonoPEResourceDataEntry *version_info;
449 VS_FIXEDFILEINFO *ffi;
452 gint32 data_len; /* signed to guard against underflow */
453 guchar vs_key[]= {'V', '\0', 'S', '\0', '_', '\0', 'V', '\0',
454 'E', '\0', 'R', '\0', 'S', '\0', 'I', '\0',
455 'O', '\0', 'N', '\0', '_', '\0', 'I', '\0',
456 'N', '\0', 'F', '\0', 'O', '\0', '\0', '\0'
458 guchar var_key[]= {'V', '\0', 'a', '\0', 'r', '\0', 'F', '\0',
459 'i', '\0', 'l', '\0', 'e', '\0', 'I', '\0',
460 'n', '\0', 'f', '\0', 'o', '\0', '\0', '\0',
462 guchar str_key[]= {'S', '\0', 't', '\0', 'r', '\0', 'i', '\0',
463 'n', '\0', 'g', '\0', 'F', '\0', 'i', '\0',
464 'l', '\0', 'e', '\0', 'I', '\0', 'n', '\0',
465 'f', '\0', 'o', '\0', '\0', '\0',
468 version_info=mono_image_lookup_resource (image,
469 MONO_PE_RESOURCE_ID_VERSION,
472 g_message (G_GNUC_PRETTY_FUNCTION ": image_lookup returned %p",
476 if(version_info==NULL) {
480 data=mono_cli_rva_map (image->image_info,
481 version_info->rde_data_offset);
486 /* See io-layer/versioninfo.h for the gory details on how this
487 * data is laid out. (data should be pointing to
488 * VS_VERSIONINFO data).
491 data_ptr=process_get_versioninfo_block (data, &block);
493 data_len=block.data_len;
495 if(block.value_len!=sizeof(VS_FIXEDFILEINFO)) {
497 g_message (G_GNUC_PRETTY_FUNCTION
498 ": FIXEDFILEINFO size mismatch");
503 if(memcmp (block.key, &vs_key, unicode_bytes (block.key))) {
505 g_message (G_GNUC_PRETTY_FUNCTION
506 ": VS_VERSION_INFO mismatch");
511 ffi=(((VS_FIXEDFILEINFO *)data_ptr)++);
512 if((ffi->dwSignature!=VS_FFI_SIGNATURE) ||
513 (ffi->dwStrucVersion!=VS_FFI_STRUCVERSION)) {
515 g_message (G_GNUC_PRETTY_FUNCTION
516 ": FIXEDFILEINFO bad signature");
520 process_read_fixedfileinfo_block (filever, ffi);
522 /* Subtract the 92 bytes we've already seen */
525 /* There now follow zero or one StringFileInfo blocks and zero
526 * or one VarFileInfo blocks
528 while(data_len > 0) {
529 /* align on a 32-bit boundary */
530 data_ptr=(gpointer)(((unsigned)data_ptr+3) & (~3));
532 data_ptr=process_get_versioninfo_block (data_ptr, &block);
533 data_len=data_len-block.data_len;
535 if(!memcmp (block.key, &var_key, unicode_bytes (block.key))) {
536 data_ptr=process_read_var_block (filever, data_ptr,
538 } else if (!memcmp (block.key, &str_key,
539 unicode_bytes (block.key))) {
540 data_ptr=process_read_stringtable_block (filever, data_ptr, block.data_len);
544 g_message (G_GNUC_PRETTY_FUNCTION
545 ": Not a valid VERSIONINFO child block");
552 static void process_add_module (GPtrArray *modules, MonoAssembly *ass)
554 MonoClass *proc_class, *filever_class;
555 MonoObject *item, *filever;
556 MonoDomain *domain=mono_domain_get ();
559 /* Build a System.Diagnostics.ProcessModule with the data.
560 * Leave BaseAddress and EntryPointAddress set to NULL,
561 * FileName is ass->image->name, FileVersionInfo is an object
562 * constructed from the PE image data referenced by
563 * ass->image, ModuleMemorySize set to 0, ModuleName the last
564 * component of FileName.
566 proc_class=mono_class_from_name (system_assembly, "System.Diagnostics",
568 item=mono_object_new (domain, proc_class);
570 filever_class=mono_class_from_name (system_assembly,
571 "System.Diagnostics",
573 filever=mono_object_new (domain, filever_class);
576 g_message (G_GNUC_PRETTY_FUNCTION ": recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d], ModuleName [%s]", ass->image->name, ass->aname.major, ass->aname.minor, ass->aname.build, ass->aname.revision, ass->image->name);
579 process_get_fileversion (filever, ass->image);
581 process_set_field_string_utf8 (filever, "filename", ass->image->name);
582 process_set_field_string_utf8 (item, "filename", ass->image->name);
583 process_set_field_object (item, "version_info", filever);
585 modulename=g_path_get_basename (ass->image->name);
586 process_set_field_string_utf8 (item, "modulename", modulename);
589 g_ptr_array_add (modules, item);
592 static void process_scan_modules (gpointer data, gpointer user_data)
594 MonoAssembly *ass=data;
595 GPtrArray *modules=user_data;
597 /* The main assembly is already in the list */
598 if(mono_assembly_get_main () != ass) {
599 process_add_module (modules, ass);
604 /* Returns an array of System.Diagnostics.ProcessModule */
605 MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this)
607 /* I was going to use toolhelp for this, but then realised I
608 * was being an idiot :)
610 * (Toolhelp would give shared libraries open by the runtime,
611 * as well as open assemblies. On windows my tests didnt find
612 * the assemblies loaded by mono either.)
614 GPtrArray *modules_list=g_ptr_array_new ();
620 STASH_SYS_ASS (this);
622 /* Make sure the first entry is the main module */
623 process_add_module (modules_list, mono_assembly_get_main ());
625 mono_assembly_foreach (process_scan_modules, modules_list);
627 /* Build a MonoArray out of modules_list */
628 arr=mono_array_new (mono_domain_get (), mono_defaults.object_class,
631 for(i=0; i<modules_list->len; i++) {
632 mono_array_set (arr, MonoObject *, i,
633 g_ptr_array_index (modules_list, i));
636 g_ptr_array_free (modules_list, FALSE);
641 void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this, MonoString *filename)
644 guchar *filename_utf8;
648 STASH_SYS_ASS (this);
650 filename_utf8=mono_string_to_utf8 (filename);
651 image=mono_image_open (filename_utf8, NULL);
652 g_free (filename_utf8);
655 /* FIXME: an exception might be appropriate here */
657 g_message (G_GNUC_PRETTY_FUNCTION ": Failed to load image");
663 process_get_fileversion (this, image);
664 process_set_field_string_utf8 (this, "filename", image->name);
666 mono_image_close (image);
669 MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd, MonoString *dirname, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info)
673 STARTUPINFO startinfo={0};
674 PROCESS_INFORMATION procinfo;
678 startinfo.cb=sizeof(STARTUPINFO);
679 startinfo.dwFlags=STARTF_USESTDHANDLES;
680 startinfo.hStdInput=stdin_handle;
681 startinfo.hStdOutput=stdout_handle;
682 startinfo.hStdError=stderr_handle;
684 /* The default dir name is "". Turn that into NULL to mean
685 * "current directory"
687 if(mono_string_length (dirname)==0) {
690 dir=mono_string_chars (dirname);
693 ret=CreateProcess (NULL, mono_string_chars (cmd), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, dir, &startinfo, &procinfo);
696 process_info->process_handle=procinfo.hProcess;
697 process_info->thread_handle=procinfo.hThread;
698 process_info->pid=procinfo.dwProcessId;
699 process_info->tid=procinfo.dwThreadId;
705 MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObject *this, HANDLE process, gint32 ms)
713 ret=WaitForSingleObject (process, INFINITE);
715 ret=WaitForSingleObject (process, ms);
718 if(ret==WAIT_OBJECT_0) {
725 gint64 ves_icall_System_Diagnostics_Process_ExitTime_internal (HANDLE process)
729 FILETIME create_time, exit_time, kernel_time, user_time;
733 ret=GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
736 ticks=((guint64)exit_time.dwHighDateTime << 32) +
737 exit_time.dwLowDateTime;
745 gint64 ves_icall_System_Diagnostics_Process_StartTime_internal (HANDLE process)
749 FILETIME create_time, exit_time, kernel_time, user_time;
753 ret=GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
756 ticks=((guint64)create_time.dwHighDateTime << 32) +
757 create_time.dwLowDateTime;
765 gint32 ves_icall_System_Diagnostics_Process_ExitCode_internal (HANDLE process)
771 GetExitCodeProcess (process, &code);
774 g_message (G_GNUC_PRETTY_FUNCTION ": process exit code is %d", code);
780 MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
785 gunichar2 name[MAX_PATH];
791 ok=EnumProcessModules (process, &mod, sizeof(mod), &needed);
796 len=GetModuleBaseName (process, mod, name, sizeof(name));
802 g_message (G_GNUC_PRETTY_FUNCTION ": process name is [%s]",
803 g_utf16_to_utf8 (name, -1, NULL, NULL, NULL));
806 string=mono_string_new_utf16 (mono_domain_get (), name, len);
811 /* Returns an array of pids */
812 MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
816 guint32 needed, count, i;
821 ret=EnumProcesses (pids, sizeof(pids), &needed);
823 /* FIXME: throw an exception */
827 count=needed/sizeof(guint32);
828 procs=mono_array_new (mono_domain_get (), mono_defaults.int_class,
830 for(i=0; i<count; i++) {
831 mono_array_set (procs, guint32, i, pids[i]);
837 MonoBoolean ves_icall_System_Diagnostics_Process_GetWorkingSet_internal (HANDLE process, guint32 *min, guint32 *max)
843 ret=GetProcessWorkingSetSize (process, min, max);
848 MonoBoolean ves_icall_System_Diagnostics_Process_SetWorkingSet_internal (HANDLE process, guint32 min, guint32 max, MonoBoolean use_min)
856 ret=GetProcessWorkingSetSize (process, &ws_min, &ws_max);
867 ret=SetProcessWorkingSetSize (process, min, max);