@@ -70,45 +70,6 @@ static HKEY roots[] =
70
70
HKEY_LOCAL_MACHINE ,
71
71
HKEY_USERS };
72
72
73
- /*
74
- * OPAMW_process_putenv is implemented using Process Injection.
75
- * Idea inspired by Bill Stewart's editvar
76
- * (see http://www.westmesatech.com/editv.html)
77
- * Full technical details at http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_3
78
- */
79
-
80
- static char * getProcessInfo (HANDLE hProcessSnapshot ,
81
- DWORD processId ,
82
- PROCESSENTRY32 * entry )
83
- {
84
- entry -> dwSize = sizeof (PROCESSENTRY32 );
85
-
86
- if (hProcessSnapshot == INVALID_HANDLE_VALUE )
87
- return "getProcessInfo: could not create snapshot" ;
88
-
89
- /*
90
- * Locate our process
91
- */
92
- if (!Process32First (hProcessSnapshot , entry ))
93
- {
94
- CloseHandle (hProcessSnapshot );
95
- return "getProcessInfo: could not walk process tree" ;
96
- }
97
- else
98
- {
99
- while (entry -> th32ProcessID != processId )
100
- {
101
- if (!Process32Next (hProcessSnapshot , entry ))
102
- {
103
- CloseHandle (hProcessSnapshot );
104
- return "getProcessInfo: could not find process!" ;
105
- }
106
- }
107
- }
108
-
109
- return NULL ;
110
- }
111
-
112
73
char * InjectSetEnvironmentVariable (DWORD , LPCWSTR , LPCWSTR );
113
74
114
75
/* Actual primitives from here */
@@ -545,6 +506,13 @@ CAMLprim value OPAMW_HasGlyph(value checker, value scalar)
545
506
return Val_bool (index != 0xffff );
546
507
}
547
508
509
+ /*
510
+ * OPAMW_process_putenv is implemented using Process Injection.
511
+ * Idea inspired by Bill Stewart's editvar
512
+ * (see http://www.westmesatech.com/editv.html)
513
+ * Full technical details at http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_3
514
+ */
515
+
548
516
CAMLprim value OPAMW_process_putenv (value pid , value key , value val )
549
517
{
550
518
char * result ;
@@ -650,41 +618,111 @@ CAMLprim value OPAMW_SendMessageTimeout_byte(value * v, int n)
650
618
return OPAMW_SendMessageTimeout (v [0 ], v [1 ], v [2 ], v [3 ], v [4 ], v [5 ]);
651
619
}
652
620
653
- CAMLprim value OPAMW_GetParentProcessID (value processId )
621
+ CAMLprim value OPAMW_GetProcessAncestry (value unit )
654
622
{
623
+ CAMLparam0 ();
624
+ CAMLlocal3 (result , tail , info );
655
625
PROCESSENTRY32 entry ;
656
- char * msg ;
657
- /*
658
- * Create a Toolhelp Snapshot of running processes
659
- */
660
- HANDLE hProcessSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS , 0 );
661
-
662
- if ((msg = getProcessInfo (hProcessSnapshot , Int32_val (processId ), & entry )))
663
- caml_failwith (msg );
664
-
665
- /*
666
- * Finished with the snapshot
667
- */
668
- CloseHandle (hProcessSnapshot );
669
-
670
- return caml_copy_int32 (entry .th32ParentProcessID );
671
- }
672
-
673
- CAMLprim value OPAMW_GetProcessName (value processId )
674
- {
675
- CAMLparam1 (processId );
676
-
677
- PROCESSENTRY32 entry ;
678
- DWORD parent_pid ;
679
- char * msg ;
680
- HANDLE hProcessSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS , 0 );
626
+ HANDLE hProcessSnapshot , hProcess ;
627
+ value cell ;
628
+ ULARGE_INTEGER * processes , * cur ;
629
+ int capacity = 512 ;
630
+ int length = 0 ;
631
+ DWORD target = GetCurrentProcessId ();
632
+ BOOL read_entry = TRUE;
633
+ WCHAR ExeName [MAX_PATH + 1 ];
634
+ DWORD dwSize ;
681
635
682
- if ((msg = getProcessInfo (hProcessSnapshot , Int32_val (processId ), & entry )))
683
- caml_failwith (msg );
636
+ result = caml_alloc_small (2 , 0 );
637
+ Field (result , 0 ) = Val_int (0 );
638
+ Field (result , 1 ) = Val_int (0 );
639
+ tail = result ;
640
+
641
+ /* Snapshot running processes */
642
+ hProcessSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS , 0 );
643
+ if (hProcessSnapshot != INVALID_HANDLE_VALUE ) {
644
+ entry .dwSize = sizeof (PROCESSENTRY32 );
645
+ /* Read the first entry (just because it's a special function) */
646
+ if (Process32First (hProcessSnapshot , & entry )) {
647
+ if ((processes = (ULARGE_INTEGER * )malloc (capacity * sizeof (ULARGE_INTEGER )))) {
648
+ /* Initialise the processes array */
649
+ if (entry .th32ProcessID == 0 ) {
650
+ processes -> QuadPart = 0LL ;
651
+ } else {
652
+ length = 1 ;
653
+ processes -> LowPart = entry .th32ProcessID ;
654
+ processes -> HighPart = entry .th32ParentProcessID ;
655
+ processes [1 ].QuadPart = 0LL ;
656
+ }
657
+
658
+ /* Build the process tree, starting with the current process */
659
+ do {
660
+ /* First search through processes we've already read */
661
+ for (cur = processes ; cur -> QuadPart != 0 ; cur ++ ) {
662
+ if (cur -> LowPart == target )
663
+ break ;
664
+ }
665
+
666
+ if (cur -> QuadPart == 0LL ) {
667
+ /* Keep reading process entries until we reach the end of the list */
668
+ while ((read_entry = Process32Next (hProcessSnapshot , & entry ))) {
669
+ if (entry .th32ProcessID != 0 ) {
670
+ if (++ length >= capacity ) {
671
+ ULARGE_INTEGER * ptr ;
672
+ capacity += 512 ;
673
+ ptr = (ULARGE_INTEGER * )realloc (processes , capacity * sizeof (ULARGE_INTEGER ));
674
+ if (ptr == NULL ) {
675
+ read_entry = FALSE;
676
+ break ;
677
+ } else {
678
+ processes = ptr ;
679
+ }
680
+ }
681
+ cur -> LowPart = entry .th32ProcessID ;
682
+ cur -> HighPart = entry .th32ParentProcessID ;
683
+ if (cur -> LowPart == target ) {
684
+ cur [1 ].QuadPart = 0LL ;
685
+ break ;
686
+ } else {
687
+ cur ++ ;
688
+ }
689
+ }
690
+ }
691
+ if (!read_entry )
692
+ break ;
693
+ }
694
+
695
+ /* Found it - construct the list entry */
696
+ hProcess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION , FALSE, target );
697
+ if (hProcess != NULL ) {
698
+ dwSize = MAX_PATH + 1 ;
699
+ if (!QueryFullProcessImageName (hProcess , 0 , ExeName , & dwSize ))
700
+ ExeName [0 ] = L'\0' ;
701
+ CloseHandle (hProcess );
702
+ } else {
703
+ ExeName [0 ] = L'\0' ;
704
+ }
705
+ info = caml_alloc_tuple (2 );
706
+ Store_field (info , 0 , caml_copy_int32 (target ));
707
+ Store_field (info , 1 , caml_copy_string_of_utf16 (ExeName ));
708
+ cell = caml_alloc_small (2 , 0 );
709
+ Field (cell , 0 ) = info ;
710
+ Field (cell , 1 ) = Val_int (0 );
711
+ Store_field (tail , 1 , cell );
712
+ tail = cell ;
713
+ /* Search for this process's parent on the next round */
714
+ target = cur -> HighPart ;
715
+ /* Guard against looping by zeroing out the parent */
716
+ cur -> HighPart = 0 ;
717
+ } while (1 );
718
+ }
719
+ free (processes );
720
+ }
684
721
685
- CloseHandle (hProcessSnapshot );
722
+ CloseHandle (hProcessSnapshot );
723
+ }
686
724
687
- CAMLreturn (caml_copy_string_of_utf16 ( entry . szExeFile ));
725
+ CAMLreturn (Field ( result , 1 ));
688
726
}
689
727
690
728
CAMLprim value OPAMW_GetConsoleAlias (value alias , value exe_name )
0 commit comments