SOLVED y my dolphin not working lol y tho

Samuel Venable

Time Killer
Dontrel would be proud.


ok no seriously, why is this extension function I wrote not working?

Download the 2.3.x yyp project and source code here.

Create:
GML:
procId = 0; parentProcId = 0;
widget_set_system(ws_x11_kdialog);
exefname = ""; cwddname = ""; cmdstr = "";
widget_set_owner(string(int64(window_handle())));
pause = false; window_set_showborder(false);
var i = 0; var list = ProcListCreate();
var size = ProcessInfoLength(list);
if (size) {
  if (i < size) {
    var info = ProcessInfo(list, i);
    var ppid = ParentProcessId(info);
    var exe = ExecutableImageFilePath(info);
    var cwd = CurrentWorkingDirectory(info);
    procId = ProcessId(info); parentProcId = ppid;
    exefname = (exe != 0) ? exe : "<undefined>";
    cwddname = (cwd != 0) ? cwd : "<undefined>";
    var ii = 0; cmdstr = "";
    var cmdsize = CommandLineLength(info);
    if (cmdsize) {
      for (ii = 0; ii < cmdsize; ii++) {
        tmpstr = string_replace_all(CommandLine(info, i), @'\', @'\\');
        cmdstr += @'"' + string_replace_all(tmpstr, @'"', @'\"') + @'" ';
      }
      cmdstr = string_copy(cmdstr, 0, string_length(cmdstr) - 1);
    }
    FreeProcInfo(info);
  }
  FreeProcList(list);
  i++; j = i;
  alarm[0] = 10;
}
Alarm 0:
GML:
if (!pause) {
  var list = ProcListCreate();
  var size = ProcessInfoLength(list);
  if (size) {
    if (j < size) {
      var info = ProcessInfo(list, j);
      var ppid = ParentProcessId(info);
      var exe = ExecutableImageFilePath(info);
      var cwd = CurrentWorkingDirectory(info);
      procId = ProcessId(info); parentProcId = ppid;
      exefname = (exe != 0) ? exe : "<undefined>";
      cwddname = (cwd != 0) ? cwd : "<undefined>";
      var ii = 0; cmdstr = "";
      var cmdsize = CommandLineLength(info);
      if (cmdsize) {
        for (ii = 0; ii < cmdsize; ii++) {
          tmpstr = string_replace_all(CommandLine(info, j), @'\', @'\\');
          cmdstr += @'"' + string_replace_all(tmpstr, @'"', @'\"') + @'" ';
        }
        cmdstr = string_copy(cmdstr, 0, string_length(cmdstr) - 1);
      }
      FreeProcInfo(info);
    } else {
      FreeProcList(list);
      room_restart();
      exit;
    }
    FreeProcList(list);
    j++;
    alarm[0] = 10;
  }
}
Draw GUI:
GML:
draw_set_color(c_white);
draw_set_font(fnt_example);
display_set_gui_size(window_get_width(), window_get_height());
var str = "press <space> to " + string(!pause ? "pause" : "resume") + " enumeration, or press <enter> to inspect" +
"\nthe environment variables belonging to the process identifier.\n" +
"\npid="  + string(procId) +
"\nppid=" + string(parentProcId) +
"\nexe="  + ((!file_exists(exefname)) ? "<undefined>": exefname) +
"\ncwd="  + ((!directory_exists(cwddname)) ? "<undefined>": cwddname) +
"\ncmd="  + ((!ProcIdExists(procId) || cmdstr == "") ? "<undefined>": cmdstr);
display_set_gui_size(string_width(str) + 64, string_height(str) + 64);
draw_set_color(c_black);
draw_rectangle(16, 16, string_width(str) + 48, string_height(str) + 48, 0);
draw_set_color(c_white);
draw_text(32, 32, str);
draw_set_color(c_black);
draw_rectangle(0, 0, string_width(str) + 64, string_height(str) + 64, 1);
draw_rectangle(1, 1, string_width(str) + 63, string_height(str) + 63, 1);
window_set_size(string_width(str) + 64, string_height(str) + 64);
if (!pause) window_center();
draw_set_color(c_white);
Global Left Mouse Down:
GML:
if (pause) {
  window_set_position(display_mouse_get_x() - (window_get_width() / 2), display_mouse_get_y() - (window_get_height() / 2));
  if (window_get_cursor() == cr_arrow) window_set_cursor(cr_drag);
}
Mouse Wheel Up:
GML:
if (!pause) {
  var list = ProcListCreate();
  var size = ProcessInfoLength(list);
  if (size) {
    j++; if (j > size - 1) j = 0;
    if (j < size) {
      var info = ProcessInfo(list, j);
      var ppid = ParentProcessId(info);
      var exe = ExecutableImageFilePath(info);
      var cwd = CurrentWorkingDirectory(info);
      procId = ProcessId(info); parentProcId = ppid;
      exefname = (exe != 0) ? exe : "<undefined>";
      cwddname = (cwd != 0) ? cwd : "<undefined>";
      var ii = 0; cmdstr = "";
      var cmdsize = CommandLineLength(info);
      if (cmdsize) {
        for (ii = 0; ii < cmdsize; ii++) {
          tmpstr = string_replace_all(CommandLine(info, j), @'\', @'\\');
          cmdstr += @'"' + string_replace_all(tmpstr, @'"', @'\"') + @'" ';
        }
        cmdstr = string_copy(cmdstr, 0, string_length(cmdstr) - 1);
      }
      FreeProcInfo(info);
    }
    FreeProcList(list);
  }
}
Mouse Wheel Down:
GML:
if (!pause) {
  var list = ProcListCreate();
  var size = ProcessInfoLength(list);
  if (size) {
    j--; if (j < 0) j = size - 1;
    if (j < size) {
      var info = ProcessInfo(list, j);
      var ppid = ParentProcessId(info);
      var exe = ExecutableImageFilePath(info);
      var cwd = CurrentWorkingDirectory(info);
      procId = ProcessId(info); parentProcId = ppid;
      exefname = (exe != 0) ? exe : "<undefined>";
      cwddname = (cwd != 0) ? cwd : "<undefined>";
      var ii = 0; cmdstr = "";
      var cmdsize = CommandLineLength(info);
      if (cmdsize) {
        for (ii = 0; ii < cmdsize; ii++) {
          tmpstr = string_replace_all(CommandLine(info, j), @'\', @'\\');
          cmdstr += @'"' + string_replace_all(tmpstr, @'"', @'\"') + @'" ';
        }
        cmdstr = string_copy(cmdstr, 0, string_length(cmdstr) - 1);
      }
      FreeProcInfo(info);
    }
    FreeProcList(list);
  }
}
Enter Key Pressed:
GML:
widget_set_caption("PEB Inspector");
var list = ProcListCreate();
if (ProcessInfoLength(list)) {
  for (var i = 0; i < ProcessInfoLength(list); i++) {
    var info = ProcessInfo(info, i)
    var env = 0; var envsize = 0; Environment(info, i);
    if (EnvironmentLength(info)) {
      if (ProcIdExists(procId)) {
        for (var jj = 0; jj < envsize; jj++) {
          var q = show_question("Continue environment iteration?\n\n" + string(env[jj]));
          keyboard_clear(keyboard_lastkey);
          if (!q) { FreeProcInfo(list); exit; }
        }
      }
    } else {
      show_message("No environment to iterate.\n\n<undefined>");
      keyboard_clear(keyboard_lastkey);
    }
    FreeProcInfo(info);
  }
}
Escape Key Pressed:
GML:
game_end();
Space Key Pressed:
GML:
pause = !pause;
if (!pause) {
  alarm[0] = 10;
}
'R' Key Pressed:
GML:
if (!keyboard_check(vk_control)) exit;
widget_set_caption("Run");
var command = get_string("Execute command:", "");
keyboard_clear(keyboard_lastkey);
ProcessExecuteAsync(command);
'S' Key Pressed
GML:
if (!keyboard_check(vk_control)) exit;
widget_set_caption("Save procfs?");
q = show_question("Save the current process information state to filesystem? The output files' contents will be NULL character separated; view the output files in Notepad++ to see all characters after the first NULL byte.");
keyboard_clear(keyboard_lastkey);
if (q) {
  var dname = get_directory_alt("Choose a directory to save output filesystem tree...", working_directory);
  keyboard_clear(keyboard_lastkey);
  if (dname != "") {
    directory_create(dname + "/proc");
    var procList = ProcListCreate();
    if (ProcessInfoLength(procList)) {
      for (var iii = 0; iii < ProcessInfoLength(procList); iii++) {
        var procInfo = ProcessInfo(procList, iii);
        directory_create(dname + "/proc/" + string(ProcessId(procInfo)));
        if (string_length(ExecutableImageFilePath(procInfo))) {
          if (file_exists(ExecutableImageFilePath(procInfo))) {
            file_delete(dname + "/proc/" + string(ProcessId(procInfo)) + "/exe");
            var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/exe");
            file_text_write_string(f, string(ExecutableImageFilePath(procInfo)) + chr(0));
            file_text_close(f);
          }
        }
        if (string_length(CurrentWorkingDirectory(procInfo))) {
          if (directory_exists(CurrentWorkingDirectory(procInfo))) {
            file_delete(dname + "/proc/" + string(ProcessId(procInfo)) + "/cwd");
            var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/cwd");
            file_text_write_string(f, string(CurrentWorkingDirectory(procInfo)) + chr(0));
            file_text_close(f);
          }
        }
        if (CommandLineLength(procInfo)) {
          file_delete(dname + "/proc/" + string(ProcessId(procInfo)) + "/cmdline");
          for (var jjj = 0; jjj < CommandLineLength(procInfo); jjj++) {
            var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/cmdline");
            file_text_write_string(f, string(CommandLine(procInfo, jjj) + chr(0)));
            file_text_close(f);
          }
          var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/cmdline");
          file_text_write_string(f, chr(0));
          file_text_close(f);
        }
        if (EnvironmentLength(procInfo)) {
          file_delete(dname + "/proc/" + string(ProcessId(procInfo)) + "/environ");
          for (var jjj = 0; jjj < EnvironmentLength(procInfo); jjj++) {
            var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/environ");
            file_text_write_string(f, string(Environment(procInfo, jjj) + chr(0)));
            file_text_close(f);
          }
          var f = file_text_open_append(dname + "/proc/" + string(ProcessId(procInfo)) + "/environ");
          file_text_write_string(f, chr(0));
          file_text_close(f);
        }
        FreeProcInfo(procInfo);
      }
      FreeProcList(procList);
    }
    widget_set_caption("Complete!");
    show_message("Done!");
    keyboard_clear(keyboard_lastkey);
  }
}
- 1x1 game window with full scale game option. though not relevant to issue
- uses my dialog module and border toggle extensions though not relevant to issue
- let's try to break down one problem at a time, and I'll let you know what i figure out
- most of the code above does not work, and on windows it doesn't even draw text
- on mac it does draw text, but all the variables are as though not being set
- dll/dylib on github along with source code for those see this link right here

libxproc.yy:
JSON:
{
  "optionsFile": "options.json",
  "options": [],
  "exportToGame": true,
  "supportedTargets": -1,
  "extensionVersion": "0.0.1",
  "packageId": "",
  "productId": "",
  "author": "",
  "date": "2021-06-09T06:32:23.3229009-04:00",
  "license": "",
  "description": "",
  "helpfile": "",
  "iosProps": false,
  "tvosProps": false,
  "androidProps": false,
  "installdir": "",
  "files": [
    {"filename":"libxproc.dll","origname":"","init":"","final":"","kind":1,"uncompress":false,"functions":[
        {"externalName":"ProcessExecute","kind":1,"help":"ProcessExecute(command)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ProcessExecute","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcessExecuteAsync","kind":1,"help":"ProcessExecuteAsync(command)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ProcessExecuteAsync","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"CompletionStatusFromExecutedProcess","kind":1,"help":"CompletionStatusFromExecutedProcess(procIndex)","hidden":false,"returnType":2,"argCount":0,"args":[
            2,
          ],"resourceVersion":"1.0","name":"CompletionStatusFromExecutedProcess","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ExecutedProcessWriteToStandardInput","kind":1,"help":"ExecutedProcessWriteToStandardInput(procId,input)","hidden":false,"returnType":2,"argCount":0,"args":[
            2,
            1,
          ],"resourceVersion":"1.0","name":"ExecutedProcessWriteToStandardInput","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ExecutedProcessReadFromStandardOutput","kind":1,"help":"ExecutedProcessReadFromStandardOutput(procId)","hidden":false,"returnType":1,"argCount":0,"args":[
            2,
          ],"resourceVersion":"1.0","name":"ExecutedProcessReadFromStandardOutput","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcIdExists","kind":1,"help":"ProcIdExists(procId)","hidden":false,"returnType":2,"argCount":0,"args":[
            2,
          ],"resourceVersion":"1.0","name":"ProcIdExists","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcIdKill","kind":1,"help":"ProcIdKill(procId)","hidden":false,"returnType":2,"argCount":0,"args":[
            2,
          ],"resourceVersion":"1.0","name":"ProcIdKill","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcListCreate","kind":1,"help":"ProcListCreate()","hidden":false,"returnType":1,"argCount":0,"args":[],"resourceVersion":"1.0","name":"ProcListCreate","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcessInfo","kind":1,"help":"ProcessInfo(procList,i)","hidden":false,"returnType":1,"argCount":0,"args":[
            1,
            2,
          ],"resourceVersion":"1.0","name":"ProcessInfo","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcessInfoLength","kind":1,"help":"ProcessInfoLength(procList)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ProcessInfoLength","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"FreeProcInfo","kind":1,"help":"FreeProcInfo(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"FreeProcInfo","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"FreeProcList","kind":1,"help":"FreeProcList(procList)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"FreeProcList","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ProcessId","kind":1,"help":"ProcessId(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ProcessId","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ExecutableImageFilePath","kind":1,"help":"ExecutableImageFilePath(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ExecutableImageFilePath","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"CurrentWorkingDirectory","kind":1,"help":"CurrentWorkingDirectory(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"CurrentWorkingDirectory","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ParentProcessId","kind":1,"help":"ParentProcessId(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ParentProcessId","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ChildProcessId","kind":1,"help":"ChildProcessId(procInfo,i)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
            2,
          ],"resourceVersion":"1.0","name":"ChildProcessId","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"ChildProcessIdLength","kind":1,"help":"ChildProcessIdLength(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"ChildProcessIdLength","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"CommandLine","kind":1,"help":"CommandLine(procInfo,i)","hidden":false,"returnType":1,"argCount":0,"args":[
            1,
            2,
          ],"resourceVersion":"1.0","name":"CommandLine","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"CommandLineLength","kind":1,"help":"CommandLineLength(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"CommandLineLength","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"Environment","kind":1,"help":"Environment(procInfo,i)","hidden":false,"returnType":1,"argCount":0,"args":[
            1,
            2,
          ],"resourceVersion":"1.0","name":"Environment","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"EnvironmentLength","kind":1,"help":"EnvironmentLength(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"EnvironmentLength","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"OwnedWindowId","kind":1,"help":"OwnedWindowId(procInfo,i)","hidden":false,"returnType":1,"argCount":0,"args":[
            1,
            2,
          ],"resourceVersion":"1.0","name":"OwnedWindowId","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"OwnedWindowIdLength","kind":1,"help":"OwnedWindowIdLength(procInfo)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"OwnedWindowIdLength","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"WindowIdExists","kind":1,"help":"WindowIdExists(winId)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"WindowIdExists","tags":[],"resourceType":"GMExtensionFunction",},
        {"externalName":"WindowIdKill","kind":1,"help":"WindowIdKill(winId)","hidden":false,"returnType":2,"argCount":0,"args":[
            1,
          ],"resourceVersion":"1.0","name":"WindowIdKill","tags":[],"resourceType":"GMExtensionFunction",},
      ],"constants":[],"ProxyFiles":[
        {"TargetMask":1,"resourceVersion":"1.0","name":"libxproc.dylib","tags":[],"resourceType":"GMProxyFile",},
      ],"copyToTargets":194,"order":[
        {"name":"ProcessExecute","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcessExecuteAsync","path":"extensions/libxproc/libxproc.yy",},
        {"name":"CompletionStatusFromExecutedProcess","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ExecutedProcessWriteToStandardInput","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ExecutedProcessReadFromStandardOutput","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcIdExists","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcIdKill","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcListCreate","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcessInfo","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcessInfoLength","path":"extensions/libxproc/libxproc.yy",},
        {"name":"FreeProcInfo","path":"extensions/libxproc/libxproc.yy",},
        {"name":"FreeProcList","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ProcessId","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ExecutableImageFilePath","path":"extensions/libxproc/libxproc.yy",},
        {"name":"CurrentWorkingDirectory","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ParentProcessId","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ChildProcessId","path":"extensions/libxproc/libxproc.yy",},
        {"name":"ChildProcessIdLength","path":"extensions/libxproc/libxproc.yy",},
        {"name":"CommandLine","path":"extensions/libxproc/libxproc.yy",},
        {"name":"CommandLineLength","path":"extensions/libxproc/libxproc.yy",},
        {"name":"Environment","path":"extensions/libxproc/libxproc.yy",},
        {"name":"EnvironmentLength","path":"extensions/libxproc/libxproc.yy",},
        {"name":"OwnedWindowId","path":"extensions/libxproc/libxproc.yy",},
        {"name":"OwnedWindowIdLength","path":"extensions/libxproc/libxproc.yy",},
        {"name":"WindowIdExists","path":"extensions/libxproc/libxproc.yy",},
        {"name":"WindowIdKill","path":"extensions/libxproc/libxproc.yy",},
      ],"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMExtensionFile",},
  ],
  "classname": "",
  "tvosclassname": null,
  "tvosdelegatename": null,
  "iosdelegatename": "",
  "androidclassname": "",
  "sourcedir": "",
  "androidsourcedir": "",
  "macsourcedir": "",
  "maccompilerflags": "",
  "tvosmaccompilerflags": "",
  "maclinkerflags": "",
  "tvosmaclinkerflags": "",
  "iosplistinject": null,
  "tvosplistinject": null,
  "androidinject": null,
  "androidmanifestinject": null,
  "androidactivityinject": null,
  "gradleinject": null,
  "iosSystemFrameworkEntries": [],
  "tvosSystemFrameworkEntries": [],
  "iosThirdPartyFrameworkEntries": [],
  "tvosThirdPartyFrameworkEntries": [],
  "IncludedResources": [],
  "androidPermissions": [],
  "copyToTargets": 194,
  "iosCocoaPods": "",
  "tvosCocoaPods": "",
  "iosCocoaPodDependencies": "",
  "tvosCocoaPodDependencies": "",
  "parent": {
    "name": "Extensions",
    "path": "folders/Extensions.yy",
  },
  "resourceVersion": "1.2",
  "name": "libxproc",
  "tags": [],
  "resourceType": "GMExtension",
}
and last but not least here's what I managed to narrow down so far, and we'll take this one issue at a time so bear with me.

Create Event (narrowed down):
GML:
var i = 0; var list = ProcListCreate();
var size = ProcessInfoLength(list);
if (size) {
  if (i < size) {
....
size is returning undefined. so ProcessInfoLength() isn't behaving like it should. Oddly enough when I use it in a empty C++ main() function with std::cout << the result << std::endl; it returns the number of processes in counting that are running on my current user session, which is the expected behavior. Though in GM i can only seem to get it to spit out undefined in the return value.

ProcListCreate(); however is working ok because when i show_message() to see what it returns it is giving me the correct pointer address stored in a formatted string, which is expected behavior in GM with this function in particular. Both work in C++ and other game engines I've tried it in, or rather all of my functions work in anything I try them in besides GM. Not sure why? It's really weird, and I don't know what to make of it. Now for relevant C++ code isolated out here...

C++:
...
#if !defined(_WIN32)
typedef int PROCID; // POSIX pid_t
#else
typedef unsigned long PROCID; // Win32 DWORD
#endif
...
typedef char *PROCLIST; // address space of process vector
typedef char *PROCINFO; // address space of procinfo struct
typedef struct {
  PROCID ProcessId;
  char *ExecutableImageFilePath;
  char *CurrentWorkingDirectory;
  PROCID ParentProcessId;
  PROCID *ChildProcessId;
  int ChildProcessIdLength;
  char **CommandLine;
  int CommandLineLength;
  char **Environment;
  int EnvironmentLength;
  #if defined(XPROCESS_GUIWINDOW_IMPL)
  WINDOWID *OwnedWindowId;
  int OwnedWindowIdLength;
  #endif
} _PROCINFO; // struct for internal use on C++ side
...
void ProcIdEnumerate(PROCID **procId, int *size) {
  std::vector<PROCID> vec; int i = 0;
  #if defined(_WIN32)
  HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  PROCESSENTRY32 pe = { 0 };
  pe.dwSize = sizeof(PROCESSENTRY32);
  if (Process32First(hp, &pe)) {
    do {
      vec.push_back(pe.th32ProcessID); i++;
    } while (Process32Next(hp, &pe));
  }
  CloseHandle(hp);
  #elif (defined(__APPLE__) && defined(__MACH__))
  if (ProcIdExists(0)) { vec.push_back(0); i++; }
  int cntp = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0);
  std::vector<PROCID> proc_info(cntp);
  std::fill(proc_info.begin(), proc_info.end(), 0);
  proc_listpids(PROC_ALL_PIDS, 0, &proc_info[0], sizeof(PROCID) * cntp);
  for (int j = cntp - 1; j >= 0; j--) {
    if (proc_info[j] == 0) { continue; }
    vec.push_back(proc_info[j]); i++;
  }
  #elif (defined(__linux__) && !defined(__ANDROID__))
  if (ProcIdExists(0)) { vec.push_back(0); i++; }
  PROCTAB *proc = openproc(PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS);
  while (proc_t *proc_info = readproc(proc, nullptr)) {
    vec.push_back(proc_info->tgid); i++;
    freeproc(proc_info);
  }
  closeproc(proc);
  #elif defined(__FreeBSD__)
  int cntp; if (kinfo_proc *proc_info = kinfo_getallproc(&cntp)) {
    for (int j = 0; j < cntp; j++) {
      vec.push_back(proc_info[j].ki_pid); i++;
    }
    free(proc_info);
  }
  #endif
  *procId = (PROCID *)malloc(sizeof(PROCID) * vec.size());
  if (procId) {
    std::copy(vec.begin(), vec.end(), *procId);
    *size = i;
  }
}

void FreeProcId(PROCID *procId) {
  if (procId) {
    free(procId);
  }
}
...
PROCINFO ProcInfoFromInternalProcInfo(_PROCINFO *procInfo) {
  static std::string res;
  const void *address = static_cast<const void *>(procInfo);
  std::stringstream ss; ss << address;
  res = ss.str();
  return (PROCINFO)res.c_str();
}

_PROCINFO *InternalProcInfoFromProcInfo(PROCINFO procInfo) {
  void *address; sscanf(procInfo, "%p", &address);
  _PROCINFO *res = (_PROCINFO *)address;
  return res;
}

PROCLIST ProcListFromProcId(PROCID *procInfo) {
  static std::string res;
  const void *address = static_cast<const void *>(procInfo);
  std::stringstream ss; ss << address;
  res = ss.str();
  return (PROCLIST)res.c_str();
}

PROCID *ProcIdFromProcList(PROCLIST procInfo) {
  void *address; sscanf(procInfo, "%p", &address);
  PROCID *res = (PROCID *)address;
  return res;
}

_PROCINFO *InternalProcInfoFromProcId(PROCID procId) {
  char *exe    = nullptr; ExeFromProcId(procId, &exe);
  char *cwd    = nullptr; CwdFromProcId(procId, &cwd);
  PROCID ppid; ParentProcIdFromProcId(procId, &ppid);
  PROCID *pid  = nullptr; int pidsize;
  ProcIdFromParentProcId(procId, &pid, &pidsize);
  char **cmd   = nullptr; int cmdsize;
  CmdlineFromProcId(procId, &cmd, &cmdsize);
  char **env   = nullptr; int envsize;
  EnvironFromProcId(procId, &env, &envsize);
  #if defined(XPROCESS_GUIWINDOW_IMPL)
  WINDOWID *wid = nullptr; int widsize;
  WindowIdFromProcId(procId, &wid, &widsize);
  #endif
  _PROCINFO *procInfo = new _PROCINFO();
  procInfo->ProcessId               = procId;
  procInfo->ExecutableImageFilePath = exe;
  procInfo->CurrentWorkingDirectory = cwd;
  procInfo->ParentProcessId         = ppid;
  procInfo->ChildProcessId          = pid;
  procInfo->ChildProcessIdLength    = pidsize;
  procInfo->CommandLine             = cmd;
  procInfo->CommandLineLength       = cmdsize;
  procInfo->Environment             = env;
  procInfo->EnvironmentLength       = envsize;
  #if defined(XPROCESS_GUIWINDOW_IMPL)
  procInfo->OwnedWindowId           = wid;
  procInfo->OwnedWindowIdLength     = widsize;
  #endif
  return procInfo;
}
...
/* random memory freeing helper functions here,
not posted; too much content in this post as-is */
...
static std::unordered_map<PROCLIST, int> procListSize;

PROCLIST ProcListCreate() {  // create process iteration vector
  PROCID *procId; int size; ProcIdEnumerate(&procId, &size);
  PROCLIST procList = ProcListFromProcId(procId);
  procListSize[procList] = size; return procList;
}

// get process info from process vector at index
PROCINFO ProcessInfo(PROCLIST procList, int i) {
  PROCID *procId = ProcIdFromProcList(procList);
  return ProcInfoFromProcId(procId[i]);
}

// get size of vector, i.e. number of items
int ProcessInfoLength(PROCLIST procList) {
  return procListSize[procList];
}

// free from memory, crashes game iirc but not in c++
void FreeProcList(PROCLIST procList) {
  procListSize.erase(procList);
  FreeProcId(ProcIdFromProcList(procList));
}
...
// create a list for all process info
char *ProcListCreate() {
  return CrossProcess::ProcListCreate();
}

// get process info pointer based on process list at index
char *ProcessInfo(char *procList, double i) {
  return CrossProcess::ProcessInfo((PROCLIST)procList, (int)i);
}

// get the amount of process info available for iteration
double ProcessInfoLength(char *procList) {
  return CrossProcess::ProcessInfoLength((PROCLIST)procList);
}
...
I hope someone will be willing to halp me I need to be saved from the great white shark
Yes, this post is serious, well, mostly.
Samuel
 
Last edited:

Samuel Venable

Time Killer
Hey guys, I found this issue to all my problems and every problem had the same solution!

I had functions I was exporting which wrapped inline functions in my header. Instead of having the functions inline and including their bodies in the header, I moved that over into the c++ source and called the function from there instead while still having their declaration in tact in the header, but not the function body. Solved everything!
 
Top