Emit various bits of OS process info into the eventlog
[ghc-hetmet.git] / rts / win32 / GetEnv.c
diff --git a/rts/win32/GetEnv.c b/rts/win32/GetEnv.c
new file mode 100644 (file)
index 0000000..b8a4395
--- /dev/null
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team 2011
+ *
+ * Access to the process environment variables
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "Rts.h"
+#include "GetEnv.h"
+
+#include <windows.h>
+
+/* Windows does it differently, though arguably the most sanely.
+ * GetEnvironmentStrings() returns a pointer to a block of
+ * environment vars with a double null terminator:
+ *   Var1=Value1\0
+ *   Var2=Value2\0
+ *   ...
+ *   VarN=ValueN\0\0 
+ * But because everyone else (ie POSIX) uses a vector of strings, we convert
+ * to that format. Fortunately this is just a matter of making an array of
+ * offsets into the environment block.
+ *
+ * Note that we have to call FreeEnvironmentStrings() at the end.
+ *
+ */
+void getProgEnvv(int *out_envc, char **out_envv[]) {
+    int envc, i;
+    char *env;
+    char *envp;
+    char **envv;
+
+    /* For now, use the 'A'nsi not 'W'ide variant.
+       Note: corresponding Free below must use the same 'A'/'W' variant. */
+    env = GetEnvironmentStringsA();
+
+    envc = 0;
+    for (envp = env; *envp != 0; envp += strlen(envp) + 1) {
+        envc++;
+    }
+
+    envv = stgMallocBytes(sizeof(char*) * (envc+1));
+
+    i = 0;
+    for (envp = env; *envp != NULL; envp += strlen(envp) + 1) {
+        envv[i] = envp;
+        i++;
+    }
+    /* stash whole env in last+1 entry */
+    envv[envc] = env;
+
+    *out_envc = envc;
+    *out_envv = envv;
+}
+
+void freeProgEnvv(int envc, char *envv[]) {
+    /* we stashed the win32 env block in the last+1 entry */
+    FreeEnvironmentStringsA(envv[envc]);
+    stgFree(envv);
+}