commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mt...@apache.org
Subject svn commit: r980662 [9/15] - in /commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3: ./ src/ src/assembly/ src/docs/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/commons/ src/java/org/apache/commons/daemon/ src/java/org/apache/comm...
Date Fri, 30 Jul 2010 06:50:16 GMT
Added: commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/registry.c
URL: http://svn.apache.org/viewvc/commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/registry.c?rev=980662&view=auto
==============================================================================
--- commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/registry.c (added)
+++ commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/registry.c Fri Jul 30 06:50:12 2010
@@ -0,0 +1,1160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apxwin.h"
+#include "private.h"
+
+static LPCWSTR REGSERVICE_ROOT  = L"SYSTEM\\CurrentControlSet\\Services\\";
+static LPCWSTR REGSOFTWARE_ROOT = L"SOFTWARE\\";
+static LPCWSTR REGSERVICE_START = L"Start";
+static LPCWSTR REGSERVICE_USER  = L"ObjectName";
+static LPCWSTR REGPARAMS        = L"Parameters";
+static LPCWSTR REGDESCRIPTION   = L"Description";
+static LPCWSTR REGSEPARATOR     = L"\\";
+static LPCWSTR REGAPACHE_ROOT   = L"Apache Software Foundation";
+/* predefined java keys */
+static LPCWSTR JRE_REGKEY       = L"SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
+static LPCWSTR JDK_REGKEY       = L"SOFTWARE\\JavaSoft\\Java Development Kit\\";
+static LPCWSTR JAVA_CURRENT     = L"CurrentVersion";
+static LPCWSTR JAVA_RUNTIME     = L"RuntimeLib";
+static LPCWSTR JAVA_HOME        = L"JAVA_HOME";
+static LPCWSTR JAVAHOME         = L"JavaHome";
+static LPCWSTR CONTROL_REGKEY   = L"SYSTEM\\CurrentControlSet\\Control";
+static LPCWSTR REGTIMEOUT       = L"WaitToKillServiceTimeout";
+
+#define REG_CAN_CREATE(r)   \
+    ((r)->samOptions & KEY_CREATE_SUB_KEY)
+
+#define REG_CAN_WRITE(r)   \
+    ((r)->samOptions & KEY_SET_VALUE)
+
+
+#define REG_GET_KEY(r, w, k)    \
+    APXMACRO_BEGIN              \
+    switch(w) {                                                     \
+        case APXREG_SOFTWARE:       k = (r)->hRootKey;      break;  \
+        case APXREG_PARAMSOFTWARE:  k = (r)->hRparamKey;    break;  \
+        case APXREG_SERVICE:        k = (r)->hServKey;      break;  \
+        case APXREG_PARAMSERVICE:   k = (r)->hSparamKey;    break;  \
+        case APXREG_USER:           k = (r)->hUserKey;      break;  \
+        case APXREG_PARAMUSER:      k = (r)->hUparamKey;    break;  \
+        default: k = NULL; break;                                   \
+    } APXMACRO_END
+
+
+typedef struct APXREGISTRY  APXREGISTRY;
+typedef APXREGISTRY*        LPAPXREGISTRY;
+typedef struct APXREGSUBKEY APXREGSUBKEY;
+
+struct APXREGSUBKEY {
+    APXHANDLE   hRegistry;
+    HKEY        hKey;
+    LPCTSTR     syKeyName;
+    TAILQ_ENTRY(APXREGSUBKEY);
+};
+
+struct APXREGISTRY {
+    HKEY    hRootKey;   /* root key */
+    HKEY    hServKey;   /* service key */
+    HKEY    hUserKey;   /* user key */
+    HKEY    hCurrKey;   /* Current opened key */
+    LPVOID  pCurrVal;   /* Current value, overwitten on a next call */
+    HKEY    hRparamKey; /* root\\Parameters */
+    HKEY    hSparamKey; /* service\\Parameters */
+    HKEY    hUparamKey; /* service\\Parameters */
+    REGSAM  samOptions;
+    /** list enty for opened subkeys  */
+    TAILQ_HEAD(_lSubkeys, APXREGSUBKEY) lSubkeys;
+
+};
+
+#define SAFE_CLOSE_KEY(k) \
+    if ((k) != NULL && (k) != INVALID_HANDLE_VALUE) {   \
+        RegCloseKey((k));                               \
+        (k) = NULL;                                     \
+    }
+
+static BOOL __apxRegistryCallback(APXHANDLE hObject, UINT uMsg,
+                                 WPARAM wParam, LPARAM lParam)
+{
+    LPAPXREGISTRY lpReg;
+
+    lpReg = APXHANDLE_DATA(hObject);
+    switch (uMsg) {
+        case WM_CLOSE:
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        SAFE_CLOSE_KEY(lpReg->hRparamKey);
+        SAFE_CLOSE_KEY(lpReg->hSparamKey);
+        SAFE_CLOSE_KEY(lpReg->hUparamKey);
+        SAFE_CLOSE_KEY(lpReg->hRootKey);
+        SAFE_CLOSE_KEY(lpReg->hServKey);
+        SAFE_CLOSE_KEY(lpReg->hUserKey);
+        break;
+        default:
+        break;
+    }
+    return TRUE;
+}
+
+LPSTR __apxGetRegistrySzA(APXHANDLE hPool, HKEY hKey, LPCSTR szValueName)
+{
+    LPSTR  szRet;
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize;
+
+    rc = RegQueryValueExA(hKey, szValueName, NULL, &dwType, NULL, &dwSize);
+    if (rc != ERROR_SUCCESS || dwType != REG_SZ) {
+        return NULL;
+    }
+    if (!(szRet = apxPoolAlloc(hPool, dwSize)))
+        return NULL;
+    RegQueryValueExA(hKey, szValueName, NULL, &dwType, (LPBYTE)szRet, &dwSize);
+
+    return szRet;
+}
+
+LPWSTR __apxGetRegistrySzW(APXHANDLE hPool, HKEY hKey, LPCWSTR wsValueName)
+{
+    LPWSTR wsRet;
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize;
+
+    rc = RegQueryValueExW(hKey, wsValueName, NULL, &dwType, NULL, &dwSize);
+    if (rc != ERROR_SUCCESS || dwType != REG_SZ) {
+        return NULL;
+    }
+    if (!(wsRet = apxPoolAlloc(hPool, dwSize * sizeof(WCHAR))))
+        return NULL;
+    RegQueryValueExW(hKey, wsValueName, NULL, &dwType, (LPBYTE)wsRet, &dwSize);
+
+    return wsRet;
+}
+
+BOOL __apxGetRegistryStrW(APXHANDLE hPool, HKEY hKey, LPCWSTR wsValueName,
+                          LPWSTR lpRetval, DWORD dwMaxLen)
+{
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize = dwMaxLen;
+
+    rc = RegQueryValueExW(hKey, wsValueName, NULL, &dwType, (LPBYTE)lpRetval, &dwSize);
+    if (rc != ERROR_SUCCESS || dwType != REG_SZ) {
+        lpRetval = L'\0';
+        return FALSE;
+    }
+    else
+        return TRUE;
+}
+
+LPBYTE __apxGetRegistryBinaryA(APXHANDLE hPool, HKEY hKey, LPCSTR szValueName,
+                               LPDWORD lpdwLength)
+{
+    LPBYTE lpRet;
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize;
+
+    rc = RegQueryValueExA(hKey, szValueName, NULL, &dwType, NULL, &dwSize);
+    if (rc != ERROR_SUCCESS || dwSize == 0) {
+        return NULL;
+    }
+    if (!(lpRet = apxPoolAlloc(hPool, dwSize)))
+        return NULL;
+    RegQueryValueExA(hKey, szValueName, NULL, &dwType, lpRet, &dwSize);
+    if (lpdwLength)
+        *lpdwLength = dwSize;
+    return lpRet;
+}
+
+LPBYTE __apxGetRegistryBinaryW(APXHANDLE hPool, HKEY hKey, LPCWSTR wsValueName,
+                               LPDWORD lpdwLength)
+{
+    LPBYTE lpRet;
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize;
+
+    rc = RegQueryValueExW(hKey, wsValueName, NULL, &dwType, NULL, &dwSize);
+    if (rc != ERROR_SUCCESS || dwSize == 0) {
+        return NULL;
+    }
+    if (!(lpRet = apxPoolAlloc(hPool, dwSize)))
+        return NULL;
+    RegQueryValueExW(hKey, wsValueName, NULL, &dwType, lpRet, &dwSize);
+    if (lpdwLength)
+        *lpdwLength = dwSize;
+
+    return lpRet;
+}
+
+DWORD __apxGetRegistryDwordW(APXHANDLE hPool, HKEY hKey, LPCWSTR wsValueName)
+{
+    DWORD  dwRet;
+    DWORD  rc;
+    DWORD  dwType;
+    DWORD  dwSize = sizeof(DWORD);
+
+    rc = RegQueryValueExW(hKey, wsValueName, NULL, &dwType, (LPBYTE)&dwRet, &dwSize);
+    if (rc != ERROR_SUCCESS || dwType != REG_DWORD) {
+        return 0xFFFFFFFF;
+    }
+
+    return dwRet;
+}
+
+
+APXHANDLE
+apxCreateRegistryW(APXHANDLE hPool, REGSAM samDesired,
+                   LPCWSTR szRoot,
+                   LPCWSTR szKeyName,
+                   DWORD dwOptions)
+{
+    APXHANDLE hRegistry;
+    LPAPXREGISTRY lpReg;
+     /* maximum key length is 512 characters. */
+    WCHAR     buff[SIZ_BUFLEN];
+    LONG      rc = ERROR_SUCCESS;
+    HKEY      hRootKey   = NULL;
+    HKEY      hUserKey   = NULL;
+    HKEY      hServKey   = NULL;
+    HKEY      hRparamKey = NULL;
+    HKEY      hSparamKey = NULL;
+    HKEY      hUparamKey = NULL;
+
+    if (!szKeyName || lstrlenW(szKeyName) > SIZ_RESMAX)
+        return NULL;
+    if (szRoot && lstrlenW(szRoot) > SIZ_RESMAX)
+        return NULL;
+
+    /* make the HKLM\\SOFTWARE key */
+    lstrcpyW(buff, REGSOFTWARE_ROOT);
+    if (szRoot)
+        lstrcatW(buff, szRoot);
+    else
+        lstrcatW(buff, REGAPACHE_ROOT);
+    lstrcatW(buff, REGSEPARATOR);
+    lstrcatW(buff, szKeyName);
+    /* Open or create the root key */
+    if (dwOptions & APXREG_SOFTWARE) {
+        if (samDesired & KEY_CREATE_SUB_KEY)
+            rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, buff, 0, NULL, 0,
+                                 samDesired, NULL,
+                                 &hRootKey, NULL);
+        else
+            rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buff, 0,
+                               samDesired, &hRootKey);
+        if (rc != ERROR_SUCCESS) {
+            hRootKey = NULL;
+            goto cleanup;
+        }
+        /* Open or create the root parameters key */
+        if (samDesired & KEY_CREATE_SUB_KEY)
+            rc = RegCreateKeyExW(hRootKey, REGPARAMS, 0, NULL, 0,
+                                 samDesired, NULL,
+                                 &hRparamKey, NULL);
+        else
+            rc = RegOpenKeyExW(hRootKey, REGPARAMS, 0,
+                               samDesired, &hRparamKey);
+        if (rc != ERROR_SUCCESS) {
+            hRparamKey = NULL;
+            goto cleanup;
+        }
+    }
+
+    if (dwOptions & APXREG_USER) {
+        /* Open or create the users root key */
+        if (samDesired & KEY_CREATE_SUB_KEY)
+            rc = RegCreateKeyExW(HKEY_CURRENT_USER, buff, 0, NULL, 0,
+                                 samDesired, NULL,
+                                 &hUserKey, NULL);
+        else
+            rc = RegOpenKeyExW(HKEY_CURRENT_USER, buff, 0,
+                               samDesired, &hUserKey);
+        if (rc != ERROR_SUCCESS) {
+            hUserKey = NULL;
+            goto cleanup;
+        }
+        /* Open or create the users parameters key */
+        if (samDesired & KEY_CREATE_SUB_KEY)
+            rc = RegCreateKeyExW(hUserKey, REGPARAMS, 0, NULL, 0,
+                                 samDesired, NULL,
+                             &hUparamKey, NULL);
+        else
+            rc = RegOpenKeyExW(hUserKey, REGPARAMS, 0,
+                               samDesired, &hUparamKey);
+        if (rc != ERROR_SUCCESS) {
+            hUparamKey = NULL;
+            goto cleanup;
+        }
+    }
+    /* Check if we need a service key */
+    if (dwOptions & APXREG_SERVICE) {
+        lstrcpyW(buff, REGSERVICE_ROOT);
+        lstrcatW(buff, szKeyName);
+        /* Service has to be created allready */
+        rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buff, 0,
+                           samDesired, &hServKey);
+        if (rc != ERROR_SUCCESS) {
+            hServKey = NULL;
+            goto cleanup;
+        }
+        /* Open or create the root parameters key */
+        if (samDesired & KEY_CREATE_SUB_KEY)
+            rc = RegCreateKeyExW(hServKey, REGPARAMS, 0, NULL, 0,
+                                 samDesired, NULL,
+                                 &hSparamKey, NULL);
+        else
+            rc = RegOpenKeyExW(hServKey, REGPARAMS, 0,
+                               samDesired, &hSparamKey);
+        if (rc != ERROR_SUCCESS) {
+            hSparamKey = NULL;
+            goto cleanup;
+        }
+    }
+    hRegistry = apxHandleCreate(hPool, 0,
+                                NULL, sizeof(APXREGISTRY),
+                                __apxRegistryCallback);
+    if (IS_INVALID_HANDLE(hRegistry))
+        return NULL;
+    hRegistry->dwType = APXHANDLE_TYPE_REGISTRY;
+    lpReg = APXHANDLE_DATA(hRegistry);
+    lpReg->samOptions = samDesired;
+    lpReg->hRootKey   = hRootKey;
+    lpReg->hUserKey   = hUserKey;
+    lpReg->hServKey   = hServKey;
+    lpReg->hRparamKey = hRparamKey;
+    lpReg->hUparamKey = hUparamKey;
+    lpReg->hSparamKey = hSparamKey;
+    TAILQ_INIT(&lpReg->lSubkeys);
+
+    SetLastError(rc);
+    return hRegistry;
+
+cleanup:
+    SAFE_CLOSE_KEY(hRparamKey);
+    SAFE_CLOSE_KEY(hSparamKey);
+    SAFE_CLOSE_KEY(hUparamKey);
+    SAFE_CLOSE_KEY(hRootKey);
+    SAFE_CLOSE_KEY(hServKey);
+    SAFE_CLOSE_KEY(hUserKey);
+
+    SetLastError(rc);
+    return NULL;
+}
+
+APXHANDLE
+apxCreateRegistryA(APXHANDLE hPool, REGSAM samDesired,
+                   LPCSTR szRoot,
+                   LPCSTR szKeyName,
+                   DWORD dwOptions)
+{
+    WCHAR    wcRoot[SIZ_RESLEN];
+    WCHAR    wcKey[SIZ_RESLEN];
+    LPWSTR   wsRoot = NULL;
+    if (szRoot) {
+        AsciiToWide(szRoot, wcRoot);
+        wsRoot = wcRoot;
+    }
+    AsciiToWide(szKeyName, wcKey);
+    return apxCreateRegistryW(hPool, samDesired, wsRoot, wcKey, dwOptions);
+}
+
+LPSTR
+apxRegistryGetStringA(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCSTR szSubkey, LPCSTR szValueName)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return NULL;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return NULL;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExA(hKey, szSubkey, 0,
+                         lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return NULL;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    lpReg->pCurrVal = __apxGetRegistrySzA(hRegistry->hPool, hKey, szValueName);
+
+    return lpReg->pCurrVal;
+}
+
+LPWSTR
+apxRegistryGetStringW(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCWSTR szSubkey, LPCWSTR szValueName)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return NULL;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return NULL;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExW(hKey, szSubkey, 0,
+                         lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return NULL;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    lpReg->pCurrVal = __apxGetRegistrySzW(hRegistry->hPool, hKey, szValueName);
+
+    return lpReg->pCurrVal;
+}
+
+LPBYTE
+apxRegistryGetBinaryA(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCSTR szSubkey, LPCSTR szValueName,
+                      LPBYTE lpData, LPDWORD lpdwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return NULL;
+    lpReg = APXHANDLE_DATA(hRegistry);
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return NULL;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExA(hKey, szSubkey, 0,
+                         lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return NULL;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (lpData && lpdwLength && *lpdwLength) {
+        DWORD rc, dwType = REG_BINARY;
+        rc = RegQueryValueExA(hKey, szValueName, NULL, &dwType, lpData, lpdwLength);
+        if (rc != ERROR_SUCCESS || dwType != REG_BINARY) {
+            apxLogWrite(APXLOG_MARK_SYSERR);
+            return NULL;
+        }
+        lpReg->pCurrVal = lpData;
+    }
+    else {
+        lpReg->pCurrVal = __apxGetRegistryBinaryA(hRegistry->hPool, hKey, szValueName, lpdwLength);
+    }
+
+    return lpReg->pCurrVal;
+}
+
+LPBYTE
+apxRegistryGetBinaryW(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCWSTR szSubkey, LPCWSTR szValueName,
+                      LPBYTE lpData, LPDWORD lpdwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return NULL;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return NULL;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExW(hKey, szSubkey, 0,
+                          lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return NULL;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (lpData && lpdwLength && *lpdwLength) {
+        DWORD rc, dwType = REG_BINARY;
+        rc = RegQueryValueExW(hKey, szValueName, NULL, &dwType, lpData, lpdwLength);
+        if (rc != ERROR_SUCCESS || dwType != REG_BINARY) {
+            return NULL;
+        }
+        lpReg->pCurrVal = lpData;
+    }
+    else {
+        lpReg->pCurrVal = __apxGetRegistryBinaryW(hRegistry->hPool, hKey, szValueName, lpdwLength);
+    }
+    return lpReg->pCurrVal;
+}
+
+DWORD
+apxRegistryGetNumberW(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCWSTR szSubkey, LPCWSTR szValueName)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwRval, rl;
+    DWORD rc, dwType = REG_DWORD;
+
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return 0;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return 0;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExW(hKey, szSubkey, 0,
+                          lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return 0;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    rl = sizeof(DWORD);
+    rc = RegQueryValueExW(hKey, szValueName, NULL, &dwType, (LPBYTE)&dwRval, &rl);
+    if (rc != ERROR_SUCCESS || dwType != REG_DWORD)
+        return 0;
+    else
+        return dwRval;
+}
+
+LPWSTR
+apxRegistryGetMzStrW(APXHANDLE hRegistry, DWORD dwFrom,
+                     LPCWSTR szSubkey, LPCWSTR szValueName,
+                     LPWSTR lpData, LPDWORD lpdwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return NULL;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return NULL;
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExW(hKey, szSubkey, 0,
+                          lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return NULL;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (lpData && lpdwLength && *lpdwLength) {
+        DWORD rc, dwType = REG_MULTI_SZ;
+        rc = RegQueryValueExW(hKey, szValueName, NULL, &dwType, (BYTE *)lpData, lpdwLength);
+        if (rc != ERROR_SUCCESS || dwType != REG_MULTI_SZ) {
+            return NULL;
+        }
+        lpReg->pCurrVal = lpData;
+    }
+    else {
+        lpReg->pCurrVal = __apxGetRegistryBinaryW(hRegistry->hPool, hKey, szValueName, lpdwLength);
+        if (lpReg->pCurrVal && lpdwLength)
+            *lpdwLength = *lpdwLength * sizeof(WCHAR);
+    }
+    return lpReg->pCurrVal;
+}
+
+BOOL
+apxRegistrySetBinaryA(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCSTR szSubkey, LPCSTR szValueName,
+                      const LPBYTE lpData, DWORD dwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_BINARY;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExA(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (RegSetValueExA(hKey, szValueName, 0, dwType,
+                      lpData, dwLength) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+BOOL
+apxRegistrySetBinaryW(APXHANDLE hRegistry, DWORD dwFrom,
+                      LPCWSTR szSubkey, LPCWSTR szValueName,
+                      const LPBYTE lpData, DWORD dwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_BINARY;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExW(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (RegSetValueExW(hKey, szValueName, 0, dwType,
+                      lpData, dwLength) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+BOOL
+apxRegistrySetMzStrW(APXHANDLE hRegistry, DWORD dwFrom,
+                     LPCWSTR szSubkey, LPCWSTR szValueName,
+                     LPCWSTR lpData, DWORD dwLength)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_MULTI_SZ;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExW(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (RegSetValueExW(hKey, szValueName, 0, dwType,
+                       (const BYTE *)lpData, dwLength) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+BOOL
+apxRegistrySetStrA(APXHANDLE hRegistry, DWORD dwFrom,
+                   LPCSTR szSubkey, LPCSTR szValueName,
+                   LPCSTR szValue)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_SZ;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExA(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (!szValue || !lstrlenA(szValue)) {
+        if (RegDeleteValueA(hKey, szValueName) != ERROR_SUCCESS)
+            return FALSE;
+    }
+    else if (RegSetValueExA(hKey, szValueName, 0, dwType,
+                       (LPBYTE)szValue, lstrlenA(szValue) + 1) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+BOOL
+apxRegistrySetStrW(APXHANDLE hRegistry, DWORD dwFrom,
+                   LPCWSTR szSubkey, LPCWSTR szValueName,
+                   LPCWSTR szValue)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_SZ;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExW(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (!szValue || !lstrlenW(szValue)) {
+        if (RegDeleteValueW(hKey, szValueName) != ERROR_SUCCESS)
+            return FALSE;
+    }
+    else if (RegSetValueExW(hKey, szValueName, 0, dwType,
+                       (LPBYTE)szValue,
+                       (lstrlenW(szValue) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+BOOL
+apxRegistrySetNumW(APXHANDLE hRegistry, DWORD dwFrom,
+                   LPCWSTR szSubkey, LPCWSTR szValueName,
+                   DWORD dwValue)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_DWORD;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegCreateKeyExW(hKey, szSubkey, 0,
+                            NULL, 0, lpReg->samOptions,
+                            NULL, &hSub, NULL) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (RegSetValueExW(hKey, szValueName, 0, dwType,
+                       (LPBYTE)&dwValue,
+                       sizeof(DWORD)) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+
+BOOL
+apxRegistryDeleteW(APXHANDLE hRegistry, DWORD dwFrom,
+                   LPCWSTR szSubkey, LPCWSTR szValueName)
+{
+    LPAPXREGISTRY lpReg;
+    HKEY          hKey, hSub = NULL;
+    DWORD         dwType = REG_SZ;
+    if (IS_INVALID_HANDLE(hRegistry) ||
+        hRegistry->dwType != APXHANDLE_TYPE_REGISTRY)
+        return FALSE;
+    lpReg = APXHANDLE_DATA(hRegistry);
+
+    REG_GET_KEY(lpReg, dwFrom, hKey);
+    if (!hKey)
+        return FALSE;
+
+    if (szSubkey) {
+        SAFE_CLOSE_KEY(lpReg->hCurrKey);
+        if (RegOpenKeyExW(hKey, szSubkey, 0,
+                          lpReg->samOptions, &hSub) != ERROR_SUCCESS)
+            return FALSE;
+        lpReg->hCurrKey = hSub;
+        hKey = hSub;
+    }
+    if (RegDeleteValueW(hKey, szValueName) != ERROR_SUCCESS)
+        return FALSE;
+
+    return TRUE;
+}
+
+
+LONG apxDeleteRegistryRecursive(HKEY hKeyRoot, LPCWSTR szSubKey) {
+    LONG rc = ERROR_SUCCESS;
+    DWORD dwSize = 0;
+    WCHAR szName[SIZ_BUFLEN];
+    HKEY hKey = NULL;
+
+    if (ERROR_SUCCESS == RegDeleteKeyW(hKeyRoot, szSubKey)) {
+        return ERROR_SUCCESS;
+    }
+
+    rc = RegOpenKeyExW(hKeyRoot, szSubKey, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey);
+    if (rc != ERROR_SUCCESS) {
+        if (rc == ERROR_FILE_NOT_FOUND) {
+            return ERROR_SUCCESS;
+        } else {
+            return rc;
+        }
+    }
+    while (rc == ERROR_SUCCESS) {
+        dwSize = SIZ_BUFLEN;
+        rc = RegEnumKeyExW(hKey, 0, szName, &dwSize, NULL, NULL, NULL, NULL );
+
+        if (rc == ERROR_NO_MORE_ITEMS) {
+            rc = RegDeleteKeyW(hKeyRoot, szSubKey);
+            break;
+        } else {
+            rc = apxDeleteRegistryRecursive(hKey, szName);
+            if (rc != ERROR_SUCCESS) {
+                break;   // abort when we start failing
+            }
+        }
+    }
+    RegCloseKey(hKey);
+    return rc;
+}
+
+
+BOOL
+apxDeleteRegistryW(LPCWSTR szRoot,
+                   LPCWSTR szKeyName,
+                   REGSAM samDesired,
+                   BOOL bDeleteEmptyRoot)
+{
+    WCHAR     buff[SIZ_BUFLEN];
+    LONG      rc = ERROR_SUCCESS;
+    HKEY      hKey = NULL;
+    BOOL      rv = TRUE;
+    HKEY      hives[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, NULL}, *hive = NULL;
+
+    if (!szKeyName || lstrlenW(szKeyName) > SIZ_RESMAX)
+        return FALSE;
+    if (szRoot && lstrlenW(szRoot) > SIZ_RESMAX)
+        return FALSE;
+
+    if (szRoot)
+        lstrcpyW(buff, szRoot);
+    else
+        lstrcpyW(buff, REGAPACHE_ROOT);
+    lstrcatW(buff, REGSEPARATOR);
+
+    for (hive = &hives[0]; *hive; hive++) {
+        HKEY hkeySoftware = NULL;
+
+        rc = RegOpenKeyExW(*hive, REGSOFTWARE_ROOT, 0, KEY_READ | samDesired, &hkeySoftware);
+        if (rc != ERROR_SUCCESS) {
+            rv = FALSE;
+        } else {
+            rc = RegOpenKeyExW(hkeySoftware, buff, 0, samDesired | KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey);
+            if (rc == ERROR_SUCCESS) {
+                rc = apxDeleteRegistryRecursive(hKey, szKeyName);
+                RegCloseKey(hKey);
+                hKey = NULL;
+                rv |= (rc == ERROR_SUCCESS);
+            }
+            if (bDeleteEmptyRoot) {
+                // will fail if there are subkeys, just like we want
+                RegDeleteKeyW(hkeySoftware, buff);
+            }
+            RegCloseKey(hkeySoftware);
+        }
+    }
+    return rv;
+}
+
+BOOL
+apxDeleteRegistryA(LPCSTR szRoot,
+                   LPCSTR szKeyName,
+                   REGSAM samDesired,
+                   BOOL bDeleteEmptyRoot)
+{
+    WCHAR    wcRoot[SIZ_RESLEN];
+    WCHAR    wcKey[SIZ_RESLEN];
+    LPWSTR   wsRoot = NULL;
+    if (szRoot) {
+        AsciiToWide(szRoot, wcRoot);
+        wsRoot = wcRoot;
+    }
+    AsciiToWide(szKeyName, wcKey);
+
+    return apxDeleteRegistryW(wsRoot, wcKey, samDesired, bDeleteEmptyRoot);
+}
+
+
+LPWSTR apxGetJavaSoftHome(APXHANDLE hPool, BOOL bPreferJre)
+{
+    LPWSTR  wsJhome, off;
+    DWORD   err, dwLen;
+    HKEY    hKey;
+    WCHAR   wsBuf[SIZ_BUFLEN];
+    WCHAR   wsKey[SIZ_RESLEN];
+#if 1 /* XXX: Add that customizable using function call arg */
+    if (!bPreferJre && (wsJhome = __apxGetEnvironmentVariableW(hPool, JAVA_HOME)))
+        return wsJhome;
+#endif
+    lstrcpyW(wsKey, JAVA_CURRENT);
+    if (bPreferJre)
+        lstrcpyW(wsBuf, JRE_REGKEY);
+    else
+        lstrcpyW(wsBuf, JDK_REGKEY);
+    dwLen = lstrlenW(wsBuf);
+    off = &wsBuf[dwLen];
+    dwLen = SIZ_RESMAX;
+    if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsBuf,
+                             0, KEY_READ, &hKey)) != ERROR_SUCCESS) {
+        return NULL;
+    }
+    if ((err = RegQueryValueExW(hKey, JAVA_CURRENT, NULL, NULL,
+                                (LPBYTE)off,
+                                &dwLen)) != ERROR_SUCCESS) {
+        RegCloseKey(hKey);
+        return NULL;
+    }
+    RegCloseKey(hKey);
+    if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsBuf,
+                             0, KEY_READ, &hKey)) != ERROR_SUCCESS) {
+        return NULL;
+    }
+    wsJhome = __apxGetRegistrySzW(hPool, hKey, JAVAHOME);
+    if (wsJhome)
+        SetEnvironmentVariableW(JAVA_HOME, wsJhome);
+    RegCloseKey(hKey);
+
+    return wsJhome;
+}
+
+LPWSTR apxGetJavaSoftRuntimeLib(APXHANDLE hPool)
+{
+    LPWSTR  wsRtlib, off;
+    DWORD   err, dwLen = SIZ_RESLEN;
+    HKEY    hKey;
+    WCHAR   wsBuf[SIZ_BUFLEN];
+
+    lstrcpyW(wsBuf, JRE_REGKEY);
+
+    dwLen = lstrlenW(wsBuf);
+    off = &wsBuf[dwLen];
+    dwLen = SIZ_RESLEN;
+    if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsBuf,
+                             0, KEY_READ, &hKey)) != ERROR_SUCCESS) {
+        return NULL;
+    }
+    if ((err = RegQueryValueExW(hKey, JAVA_CURRENT, NULL, NULL,
+                                (LPBYTE)off,
+                                &dwLen)) != ERROR_SUCCESS) {
+        RegCloseKey(hKey);
+        return NULL;
+    }
+    RegCloseKey(hKey);
+    if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsBuf,
+                             0, KEY_READ, &hKey)) != ERROR_SUCCESS) {
+        return NULL;
+    }
+    wsRtlib = __apxGetRegistrySzW(hPool, hKey, JAVA_RUNTIME);
+    RegCloseKey(hKey);
+
+    return wsRtlib;
+}
+
+/* Service Registry helper functions */
+
+BOOL apxRegistryEnumServices(LPAPXREGENUM lpEnum, LPAPXSERVENTRY lpEntry)
+{
+    DWORD rc, dwLength = SIZ_RESLEN;
+
+    if (IS_INVALID_HANDLE(lpEnum->hServicesKey)) {
+        rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGSERVICE_ROOT, 0,
+                       KEY_READ, &(lpEnum->hServicesKey));
+        if (rc != ERROR_SUCCESS) {
+            return FALSE;
+        }
+        rc = RegQueryInfoKeyW(lpEnum->hServicesKey,
+                              NULL,
+                              NULL,
+                              NULL,
+                              &lpEnum->cSubKeys,
+                              &lpEnum->cbMaxSubKey,
+                              &lpEnum->cchMaxClass,
+                              &lpEnum->cValues,
+                              &lpEnum->cchMaxValue,
+                              &lpEnum->cbMaxValueData,
+                              NULL,
+                              NULL);
+        /* TODO: add dynamic maxsubkey length */
+        if (rc != ERROR_SUCCESS || lpEnum->cbMaxSubKey > SIZ_RESLEN) {
+            SAFE_CLOSE_KEY(lpEnum->hServicesKey);
+            return FALSE;
+        }
+    }
+    if (lpEnum->dwIndex >= lpEnum->cSubKeys) {
+        SAFE_CLOSE_KEY(lpEnum->hServicesKey);
+        return FALSE;
+    }
+    rc = RegEnumKeyExW(lpEnum->hServicesKey,
+                       lpEnum->dwIndex++,
+                       lpEntry->szServiceName,
+                       &dwLength,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL);
+    if (rc != ERROR_SUCCESS) {
+        SAFE_CLOSE_KEY(lpEnum->hServicesKey);
+        return FALSE;
+    }
+    else {
+        HKEY hKey;
+        rc = RegOpenKeyExW(lpEnum->hServicesKey, lpEntry->szServiceName,
+                           0, KEY_READ, &hKey);
+        if (rc != ERROR_SUCCESS) {
+            SAFE_CLOSE_KEY(lpEnum->hServicesKey);
+            return FALSE;
+        }
+        __apxGetRegistryStrW(NULL, hKey, REGDESCRIPTION,
+                            lpEntry->szServiceDescription, SIZ_DESLEN);
+        __apxGetRegistryStrW(NULL, hKey, REGSERVICE_USER,
+                            lpEntry->szObjectName, SIZ_RESLEN);
+        lpEntry->dwStart = __apxGetRegistryDwordW(NULL, hKey, REGSERVICE_START);
+        RegCloseKey(hKey);
+
+    }
+    return TRUE;
+}
+
+/* We could use the ChangeServiceConfig2 on WIN2K+
+ * For now use the registry.
+ */
+BOOL apxSetServiceDescriptionW(LPCWSTR szServiceName, LPCWSTR szDescription)
+{
+    HKEY  hKey;
+    WCHAR wcName[SIZ_RESLEN];
+    DWORD rc;
+
+    if (lstrlenW(szServiceName) > SIZ_RESMAX)
+        return FALSE;
+    lstrcpyW(wcName, REGSERVICE_ROOT);
+    lstrcatW(wcName, szServiceName);
+
+    rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wcName, 0, KEY_WRITE, &hKey);
+    if (rc != ERROR_SUCCESS) {
+        return FALSE;
+    }
+
+    rc = RegSetValueExW(hKey, REGDESCRIPTION, 0, REG_SZ, (CONST BYTE *)szDescription,
+                        (lstrlenW(szDescription) + 1) * sizeof(WCHAR));
+    SAFE_CLOSE_KEY(hKey);
+
+    return rc == ERROR_SUCCESS;
+}
+
+BOOL apxGetServiceDescriptionW(LPCWSTR szServiceName, LPWSTR szDescription,
+                               DWORD dwDescriptionLength)
+{
+    HKEY  hKey;
+    WCHAR wcName[SIZ_RESLEN];
+    DWORD rc, l = dwDescriptionLength * sizeof(WCHAR);
+    DWORD t = REG_SZ;
+    if (lstrlenW(szServiceName) > SIZ_RESMAX)
+        return FALSE;
+    lstrcpyW(wcName, REGSERVICE_ROOT);
+    lstrcatW(wcName, szServiceName);
+
+    rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wcName, 0, KEY_READ, &hKey);
+    if (rc != ERROR_SUCCESS) {
+        return FALSE;
+    }
+    rc = RegQueryValueExW(hKey, REGDESCRIPTION, NULL, &t, (BYTE *)szDescription,
+                          &l);
+    SAFE_CLOSE_KEY(hKey);
+    if (rc == ERROR_SUCCESS && t == REG_SZ)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+BOOL apxGetServiceUserW(LPCWSTR szServiceName, LPWSTR szUser,
+                        DWORD dwUserLength)
+{
+    HKEY  hKey;
+    WCHAR wcName[SIZ_RESLEN];
+    DWORD rc, l = dwUserLength * sizeof(WCHAR);
+    DWORD t = REG_SZ;
+    if (lstrlenW(szServiceName) > SIZ_RESMAX)
+        return FALSE;
+    lstrcpyW(wcName, REGSERVICE_ROOT);
+    lstrcatW(wcName, szServiceName);
+
+    rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wcName, 0, KEY_READ, &hKey);
+    if (rc != ERROR_SUCCESS) {
+        return FALSE;
+    }
+    rc = RegQueryValueExW(hKey, REGSERVICE_USER, NULL, &t, (BYTE *)szUser,
+                          &l);
+    SAFE_CLOSE_KEY(hKey);
+    if (rc == ERROR_SUCCESS && t == REG_SZ)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+DWORD apxGetMaxServiceTimeout(APXHANDLE hPool)
+{
+    DWORD   maxTimeout  = 20000;
+    LPWSTR  wsMaxTimeout;
+    DWORD   err;
+    HKEY    hKey;
+    WCHAR   wsBuf[SIZ_BUFLEN];
+
+    lstrcpyW(wsBuf, CONTROL_REGKEY);
+
+    if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsBuf,
+                             0, KEY_READ, &hKey)) != ERROR_SUCCESS) {
+        return maxTimeout;
+    }
+    wsMaxTimeout = __apxGetRegistrySzW(hPool, hKey, REGTIMEOUT);
+    RegCloseKey(hKey);
+
+    if (wsMaxTimeout[0]) {
+        maxTimeout = (DWORD)apxAtoulW(wsMaxTimeout);
+    }
+    apxFree(wsMaxTimeout);
+
+    return maxTimeout;
+}

Propchange: commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/registry.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/rprocess.c
URL: http://svn.apache.org/viewvc/commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/rprocess.c?rev=980662&view=auto
==============================================================================
--- commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/rprocess.c (added)
+++ commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/rprocess.c Fri Jul 30 06:50:12 2010
@@ -0,0 +1,943 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apxwin.h"
+#include "private.h"
+
+#define CHILD_RUNNING               0x0001
+#define CHILD_INITIALIZED           0x0002
+#define CHILD_MAINTREAD_FINISHED    0x0004
+#define PROC_INITIALIZED            0x0008
+#define CHILD_TERMINATE_CODE        19640323 /* Could be any value like my birthday ;-)*/
+
+DYNOLAD_TYPE_DECLARE(CreateRemoteThread,
+                     __stdcall, HANDLE)(HANDLE, LPSECURITY_ATTRIBUTES,
+                                        DWORD, LPTHREAD_START_ROUTINE,
+                                        LPVOID, DWORD, LPDWORD);
+
+DYNOLAD_TYPE_DECLARE(ExitProcess, __stdcall, void)(UINT);
+
+#define CHECK_IF_ACTIVE(proc) \
+    APXMACRO_BEGIN                                                      \
+        DWORD __st;                                                     \
+        if (!GetExitCodeProcess((proc)->stProcInfo.hProcess, &__st) ||  \
+                                (__st != STILL_ACTIVE))                 \
+            goto cleanup;                                               \
+    APXMACRO_END
+
+#define SAVE_STD_HANDLES(p) \
+    APXMACRO_BEGIN                                                      \
+    if ((p)->bSaveHandles) {                                            \
+    (p)->hParentStdSave[0] = GetStdHandle(STD_INPUT_HANDLE);            \
+    (p)->hParentStdSave[1] = GetStdHandle(STD_OUTPUT_HANDLE);           \
+    (p)->hParentStdSave[2] = GetStdHandle(STD_ERROR_HANDLE);            \
+    } APXMACRO_END
+
+#define RESTORE_STD_HANDLES(p) \
+    APXMACRO_BEGIN                                                      \
+    if ((p)->bSaveHandles) {                                            \
+    SetStdHandle(STD_INPUT_HANDLE,  (p)->hParentStdSave[0]);            \
+    SetStdHandle(STD_OUTPUT_HANDLE, (p)->hParentStdSave[1]);            \
+    SetStdHandle(STD_ERROR_HANDLE,  (p)->hParentStdSave[2]);            \
+    } APXMACRO_END
+
+#define REDIRECT_STD_HANDLES(p) \
+    APXMACRO_BEGIN                                                      \
+    if ((p)->bSaveHandles) {                                            \
+    SetStdHandle(STD_INPUT_HANDLE,  (p)->hChildStdInp);                 \
+    SetStdHandle(STD_OUTPUT_HANDLE, (p)->hChildStdOut);                 \
+    SetStdHandle(STD_ERROR_HANDLE,  (p)->hChildStdErr);                 \
+    } APXMACRO_END
+
+typedef struct APXPROCESS {
+    DWORD                   dwChildStatus;
+    DWORD                   dwOptions;
+    PROCESS_INFORMATION     stProcInfo;
+    /* Size of chars for ANSI/Unicode programs */
+    DWORD                   chSize;
+    /* application working path */
+    LPWSTR                  szWorkingPath;
+    /* executable name */
+    LPWSTR                  szApplicationExec;
+    /* command line (first arg is program name for argv[0]) */
+    LPWSTR                  szCommandLine;
+    LPWSTR                  lpEnvironment;
+    /* set of child inherited pipes */
+    HANDLE                  hChildStdInp;
+    HANDLE                  hChildStdOut;
+    HANDLE                  hChildStdErr;
+    /* parent ends of child pipes */
+    HANDLE                  hChildInpWr;
+    HANDLE                  hChildOutRd;
+    HANDLE                  hChildErrRd;
+    /* Saved console pipes */
+    HANDLE                  hParentStdSave[3];
+    HANDLE                  hWorkerThreads[3];
+    HANDLE                  hUserToken;
+    HANDLE                  hCurrentProcess;
+    BOOL                    bSaveHandles;
+    /** callback function */
+    LPAPXFNCALLBACK         fnUserCallback;
+    LPSECURITY_ATTRIBUTES   lpSA;
+    LPVOID                  lpSD;
+    BYTE                    bSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
+    BYTE                    bSA[sizeof(SECURITY_ATTRIBUTES)];
+
+} APXPROCESS, *LPAPXPROCESS;
+
+/** Process worker thread
+ * Monitors the process thread
+ */
+static DWORD WINAPI __apxProcWorkerThread(LPVOID lpParameter)
+{
+    APXHANDLE hProcess = (APXHANDLE)lpParameter;
+    LPAPXPROCESS lpProc;
+    DWORD dwExitCode = 0;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    /* Wait util a process has finished its initialization.
+     */
+    WaitForInputIdle(lpProc->stProcInfo.hProcess, INFINITE);
+    lpProc->dwChildStatus |= CHILD_INITIALIZED;
+    /* Wait until the child process exits */
+    if (WaitForSingleObject(lpProc->stProcInfo.hProcess,
+                            INFINITE) == WAIT_OBJECT_0) {
+        lpProc->dwChildStatus |= CHILD_MAINTREAD_FINISHED;
+#if 0
+        if (hProcess->fnCallback)
+            (*hProcess->fnCallback)(hProcess, WM_QUIT, (WPARAM)dwExitCode, 0);
+        lpProc->dwChildStatus &= ~CHILD_RUNNING;
+        GetExitCodeProcess(lpProc->stProcInfo.hProcess, &dwExitCode);
+
+        /* Close that handle */
+#endif
+    }
+    ExitThread(0);
+    return 0;
+}
+
+static DWORD WINAPI __apxProcStdoutThread(LPVOID lpParameter)
+{
+    APXHANDLE hProcess = (APXHANDLE)lpParameter;
+    LPAPXPROCESS lpProc;
+    APXCALLHOOK *lpCall;
+    INT ch;
+    DWORD dwReaded;
+    lpProc = APXHANDLE_DATA(hProcess);
+    while (lpProc->dwChildStatus & CHILD_RUNNING) {
+        ch = 0;
+        if (!ReadFile(lpProc->hChildOutRd, &ch, lpProc->chSize,
+                      &dwReaded, NULL) || !dwReaded) {
+
+            break;
+        }
+        if (lpProc->fnUserCallback)
+            (*lpProc->fnUserCallback)(hProcess, WM_CHAR, (WPARAM)ch, (LPARAM)0);
+        TAILQ_FOREACH(lpCall, &hProcess->lCallbacks, queue) {
+            (*lpCall->fnCallback)(hProcess, WM_CHAR, (WPARAM)ch, (LPARAM)0);
+        }
+        dwReaded = 0;
+        SwitchToThread();
+    }
+    ExitThread(0);
+    return 0;
+}
+
+static DWORD WINAPI __apxProcStderrThread(LPVOID lpParameter)
+{
+    APXHANDLE hProcess = (APXHANDLE)lpParameter;
+    LPAPXPROCESS lpProc;
+    APXCALLHOOK *lpCall;
+    INT ch;
+    DWORD dwReaded;
+    lpProc = APXHANDLE_DATA(hProcess);
+    while (lpProc->dwChildStatus & CHILD_RUNNING) {
+        if (!ReadFile(lpProc->hChildErrRd, &ch, lpProc->chSize,
+                      &dwReaded, NULL) || !dwReaded) {
+
+            break;
+        }
+        if (lpProc->fnUserCallback)
+            (*lpProc->fnUserCallback)(hProcess, WM_CHAR, (WPARAM)ch, (LPARAM)1);
+        TAILQ_FOREACH(lpCall, &hProcess->lCallbacks, queue) {
+            (*lpCall->fnCallback)(hProcess, WM_CHAR, (WPARAM)ch, (LPARAM)1);
+        }
+
+        dwReaded = 0;
+        SwitchToThread();
+    }
+
+    ExitThread(0);
+    return 0;
+}
+
+static DWORD __apxProcessPutc(LPAPXPROCESS lpProc, INT ch, DWORD dwSize)
+{
+    if (lpProc->dwChildStatus & CHILD_RUNNING) {
+        DWORD wr = 0;
+        if (WriteFile(lpProc->hChildInpWr, &ch, dwSize, &wr, NULL) &&
+                      wr == dwSize) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static DWORD __apxProcessPuts(LPAPXPROCESS lpProc, LPCTSTR szString)
+{
+    DWORD l, n = 0;
+    l = lstrlen(szString) * lpProc->chSize;
+    if (lpProc->dwChildStatus & CHILD_RUNNING && l) {
+        DWORD wr = 0;
+        while (TRUE) {
+            if (WriteFile(lpProc->hChildInpWr, szString, l,
+                          &wr, NULL)) {
+                n += wr;
+                if (wr < l) {
+                    l -= wr;
+                    szString += wr;
+                }
+                else {
+                    /* Flush the buffer */
+                    FlushFileBuffers(lpProc->hChildInpWr);
+                    break;
+                }
+            }
+            else
+                break;
+        }
+    }
+
+    return n;
+}
+
+static DWORD __apxProcessWrite(LPAPXPROCESS lpProc, LPCVOID lpData, DWORD dwLen)
+{
+    LPBYTE buf = (LPBYTE)lpData;
+    DWORD  n = 0;
+    if (!lpData || !dwLen)
+        return 0;
+
+    if (lpProc->dwChildStatus & CHILD_RUNNING) {
+        DWORD wr = 0;
+        while (lpProc->dwChildStatus & CHILD_RUNNING) {
+            if (WriteFile(lpProc->hChildInpWr, buf, dwLen,
+                          &wr, NULL)) {
+                n += wr;
+                if (wr < dwLen) {
+                    dwLen -= wr;
+                    buf += wr;
+                }
+                else
+                    break;
+            }
+            else
+                break;
+        }
+    }
+
+    return n;
+}
+
+/** Helper functions */
+static BOOL __apxProcCreateChildPipes(LPAPXPROCESS lpProc)
+{
+    BOOL   rv = FALSE;
+
+    if (!CreatePipe(&(lpProc->hChildStdInp),
+                    &(lpProc->hChildInpWr),
+                    lpProc->lpSA, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+    if (!SetHandleInformation(lpProc->hChildInpWr,
+                              HANDLE_FLAG_INHERIT, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+
+    if (!CreatePipe(&(lpProc->hChildOutRd),
+                    &(lpProc->hChildStdOut),
+                    lpProc->lpSA, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+
+    if (!SetHandleInformation(lpProc->hChildOutRd,
+                              HANDLE_FLAG_INHERIT, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+
+    if (!CreatePipe(&(lpProc->hChildErrRd),
+                    &(lpProc->hChildStdErr),
+                    lpProc->lpSA, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+
+    if (!SetHandleInformation(lpProc->hChildErrRd,
+                              HANDLE_FLAG_INHERIT, 0)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        goto cleanup;
+    }
+    rv = TRUE;
+cleanup:
+
+    return rv;
+}
+
+/* Close the process.
+ * Create the remote thread and call the ExitProcess
+ * Terminate the process, if all of the above fails.
+ */
+static BOOL __apxProcessClose(APXHANDLE hProcess)
+{
+    LPAPXPROCESS lpProc;
+    DYNLOAD_FPTR_DECLARE(CreateRemoteThread);
+    DYNLOAD_FPTR_DECLARE(ExitProcess);
+
+    UINT    uExitCode = CHILD_TERMINATE_CODE; /* Could be any value like my birthday ;-)*/
+    HANDLE  hDup, hRemote;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    CHECK_IF_ACTIVE(lpProc);
+
+    /* Try to close the child's stdin first */
+    SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
+    /* Wait 1 sec for child process to
+     * recognize that the stdin has been closed.
+     */
+    if (WaitForSingleObject(lpProc->stProcInfo.hProcess, 1000) == WAIT_OBJECT_0)
+        goto cleanup;
+
+    CHECK_IF_ACTIVE(lpProc);
+
+    /* Try to create the remote thread in the child address space */
+    DYNLOAD_FPTR_ADDRESS(CreateRemoteThread, KERNEL32);
+    if (DuplicateHandle(lpProc->hCurrentProcess,
+                        lpProc->stProcInfo.hProcess,
+                        lpProc->hCurrentProcess,
+                        &hDup,
+                        PROCESS_ALL_ACCESS,
+                        FALSE, 0)) {
+        DYNLOAD_FPTR_ADDRESS(ExitProcess, KERNEL32);
+        /* Now call the ExitProcess from inside the client
+         * This will safely unload all the dll's.
+         */
+        hRemote = DYNLOAD_CALL(CreateRemoteThread)(hDup,
+                                NULL, 0,
+                                (LPTHREAD_START_ROUTINE)DYNLOAD_FPTR(ExitProcess),
+                                (PVOID)&uExitCode, 0, NULL);
+        if (!IS_INVALID_HANDLE(hRemote)) {
+            if (WaitForSingleObject(lpProc->stProcInfo.hProcess,
+                    2000) == WAIT_OBJECT_0) {
+
+            }
+            else {
+                TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
+            }
+            CloseHandle(hRemote);
+        }
+        CloseHandle(hDup);
+        goto cleanup;
+    }
+
+    TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
+
+cleanup:
+     /* Close the process handle */
+    SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
+    lpProc->dwChildStatus &= ~CHILD_RUNNING;
+    return TRUE;
+}
+
+static BOOL __apxProcessCallback(APXHANDLE hObject, UINT uMsg,
+                                 WPARAM wParam, LPARAM lParam)
+{
+    LPAPXPROCESS lpProc;
+
+    lpProc = APXHANDLE_DATA(hObject);
+    /* Call the user supplied callback first */
+    if (lpProc->fnUserCallback)
+        (*lpProc->fnUserCallback)(hObject, uMsg, wParam, lParam);
+    switch (uMsg) {
+        case WM_CLOSE:
+            if (lpProc->dwChildStatus & CHILD_RUNNING) {
+                __apxProcessClose(hObject);
+                /* Wait for all worker threads to exit */
+                WaitForMultipleObjects(3, lpProc->hWorkerThreads, TRUE, INFINITE);
+            }
+            SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
+
+            /* Close parent side of the pipes */
+            SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
+            SAFE_CLOSE_HANDLE(lpProc->hChildOutRd);
+            SAFE_CLOSE_HANDLE(lpProc->hChildErrRd);
+
+            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[0]);
+            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[1]);
+            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[2]);
+            SAFE_CLOSE_HANDLE(lpProc->hUserToken);
+            apxFree(lpProc->szApplicationExec);
+            apxFree(lpProc->szCommandLine);
+            apxFree(lpProc->szWorkingPath);
+            RESTORE_STD_HANDLES(lpProc);
+            SAFE_CLOSE_HANDLE(lpProc->hCurrentProcess);
+            if (lpProc->lpEnvironment)
+                FreeEnvironmentStringsW(lpProc->lpEnvironment);
+
+        case WM_QUIT:
+            /* The process has finished
+             * This is a WorkerThread message
+             */
+            lpProc->dwChildStatus &= ~CHILD_RUNNING;
+        break;
+        case WM_CHAR:
+            __apxProcessPutc(lpProc, (INT)lParam, lpProc->chSize);
+        break;
+        case WM_SETTEXT:
+            if (wParam)
+                __apxProcessWrite(lpProc, (LPCVOID)lParam, (DWORD)wParam);
+            else
+                __apxProcessPuts(lpProc, (LPCTSTR)lParam);
+        break;
+        default:
+        break;
+    }
+
+    return TRUE;
+}
+
+/** Create the process but don't start it
+ *
+ APXHANDLE
+apxCreateProcessW(APXHANDLE hPool, DWORD dwOptions,
+                  LPAPXFNCALLBACK fnCallback,
+                  LPCWSTR szUsername, LPCWSTR szPassword,
+                  BOOL bLogonAsService)
+{
+    APXHANDLE hProcess;
+    LPAPXPROCESS lpProc;
+    HANDLE hUserToken = NULL;
+    if (szUsername && (APX_GET_OSLEVEL() >= APX_WINVER_NT_4)) {
+        HANDLE hUser;
+#ifndef _UNICODE
+        WCHAR wsUsername[256];
+        WCHAR wsPassword[256];
+        AsciiToWide(szUsername, wsUsername);
+        AsciiToWide(szPassword, wsPassword);
+#else
+        LPCWSTR wsUsername = szUsername;
+        LPCWSTR wsPassword = szPassword;
+#endif
+
+ */
+
+
+ APXHANDLE
+apxCreateProcessA(APXHANDLE hPool, DWORD dwOptions,
+                  LPAPXFNCALLBACK fnCallback,
+                  LPCSTR szUsername, LPCSTR szPassword,
+                  BOOL bLogonAsService)
+{
+
+    if (szUsername && szPassword) {
+        WCHAR wsUsername[256];
+        WCHAR wsPassword[256];
+        AsciiToWide(szUsername, wsUsername);
+        AsciiToWide(szPassword, wsPassword);
+        return apxCreateProcessW(hPool, dwOptions, fnCallback,
+                                 wsUsername, wsPassword, bLogonAsService);
+    }
+    else
+        return apxCreateProcessW(hPool, dwOptions, fnCallback,
+                                 NULL, NULL, bLogonAsService);
+}
+
+APXHANDLE
+apxCreateProcessW(APXHANDLE hPool, DWORD dwOptions,
+                  LPAPXFNCALLBACK fnCallback,
+                  LPCWSTR szUsername, LPCWSTR szPassword,
+                  BOOL bLogonAsService)
+{
+    APXHANDLE hProcess;
+    LPAPXPROCESS lpProc;
+    HANDLE hUserToken = NULL;
+    /* CreateProcessAsUser is supported only on NT */
+    if (szUsername && (APX_GET_OSLEVEL() >= APX_WINVER_NT_4)) {
+        HANDLE hUser;
+        if (!LogonUserW(szUsername,
+                        NULL,
+                        szPassword,
+                        bLogonAsService ? LOGON32_LOGON_SERVICE : LOGON32_LOGON_NETWORK,
+                        LOGON32_PROVIDER_DEFAULT,
+                        &hUser)) {
+            /* Logon Failed */
+            apxLogWrite(APXLOG_MARK_SYSERR);
+            return NULL;
+        }
+        if (!DuplicateTokenEx(hUser,
+                              TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
+                              NULL,
+                              SecurityImpersonation,
+                              TokenPrimary,
+                              &hUserToken)) {
+            CloseHandle(hUser);
+            /* Failed to duplicate the user token */
+            apxLogWrite(APXLOG_MARK_SYSERR);
+            return NULL;
+        }
+        if (!ImpersonateLoggedOnUser(hUserToken)) {
+            CloseHandle(hUser);
+            CloseHandle(hUserToken);
+            /* failed to impersonate the logged user */
+            apxLogWrite(APXLOG_MARK_SYSERR);
+            return NULL;
+        }
+        CloseHandle(hUser);
+    }
+
+    hProcess = apxHandleCreate(hPool, APXHANDLE_HAS_EVENT,
+                               NULL, sizeof(APXPROCESS),
+                               __apxProcessCallback);
+    if (IS_INVALID_HANDLE(hProcess))
+        return NULL;
+    hProcess->dwType = APXHANDLE_TYPE_PROCESS;
+    lpProc = APXHANDLE_DATA(hProcess);
+    lpProc->dwOptions = dwOptions;
+    lpProc->fnUserCallback = fnCallback;
+    lpProc->hUserToken  = hUserToken;
+    /* set the CHAR length */
+    if (dwOptions & CREATE_UNICODE_ENVIRONMENT)
+        lpProc->chSize = sizeof(WCHAR);
+    else
+        lpProc->chSize = sizeof(CHAR);
+#if 1
+    DuplicateHandle(GetCurrentProcess(),
+                    GetCurrentProcess(),
+                    GetCurrentProcess(),
+                    &lpProc->hCurrentProcess,
+                    PROCESS_ALL_ACCESS,
+                    FALSE,
+                    0);
+#else
+    lpProc->hCurrentProcess = GetCurrentProcess();
+#endif
+    lpProc->lpSD = &lpProc->bSD;
+
+    InitializeSecurityDescriptor(lpProc->lpSD, SECURITY_DESCRIPTOR_REVISION);
+    SetSecurityDescriptorDacl(lpProc->lpSD, -1, 0, 0);
+
+    lpProc->lpSA = (LPSECURITY_ATTRIBUTES)&lpProc->bSA[0];
+    lpProc->lpSA->nLength = sizeof (SECURITY_ATTRIBUTES);
+    lpProc->lpSA->lpSecurityDescriptor = lpProc->lpSD;
+    lpProc->lpSA->bInheritHandle = TRUE;
+
+    return hProcess;
+}
+
+static WCHAR _desktop_name[] =
+    {'W', 'i', 'n', 's', 't', 'a', '0', '\\', 'D', 'e', 'f', 'a', 'u', 'l', 't', 0};
+
+BOOL
+apxProcessExecute(APXHANDLE hProcess)
+{
+    LPAPXPROCESS lpProc;
+    STARTUPINFOW si;
+    DWORD id;
+    BOOL  bS = FALSE;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    /* don't allow multiple execute calls on the same object */
+    if (lpProc->dwChildStatus & PROC_INITIALIZED)
+        return FALSE;
+    lpProc->bSaveHandles = TRUE;
+    SAVE_STD_HANDLES(lpProc);
+    if (!__apxProcCreateChildPipes(lpProc))
+        goto cleanup;
+    REDIRECT_STD_HANDLES(lpProc);
+    AplZeroMemory(&si, sizeof(STARTUPINFO));
+
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_HIDE;
+    /* Set the redirected handles */
+    si.hStdOutput = lpProc->hChildStdOut;
+    si.hStdError  = lpProc->hChildStdErr;
+    si.hStdInput  = lpProc->hChildStdInp;
+
+    if (lpProc->lpEnvironment)
+        FreeEnvironmentStringsW(lpProc->lpEnvironment);
+    lpProc->lpEnvironment = GetEnvironmentStringsW();
+
+    if (!IS_INVALID_HANDLE(lpProc->hUserToken)) {
+        si.lpDesktop = _desktop_name;
+        bS = CreateProcessAsUserW(lpProc->hUserToken,
+                                  lpProc->szApplicationExec,
+                                  lpProc->szCommandLine,
+                                  lpProc->lpSA,
+                                  NULL,
+                                  TRUE,
+                                  CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | lpProc->dwOptions,
+                                  lpProc->lpEnvironment,
+                                  lpProc->szWorkingPath,
+                                  &si,
+                                  &(lpProc->stProcInfo));
+    }
+    else {
+        OutputDebugStringW(lpProc->szApplicationExec);
+        OutputDebugStringW(lpProc->szCommandLine);
+
+        bS = CreateProcessW(lpProc->szApplicationExec,
+                            lpProc->szCommandLine,
+                            lpProc->lpSA,
+                            NULL,
+                            TRUE,
+                            CREATE_SUSPENDED  | CREATE_UNICODE_ENVIRONMENT | lpProc->dwOptions,
+                            lpProc->lpEnvironment,
+                            lpProc->szWorkingPath,
+                            &si,
+                            &(lpProc->stProcInfo));
+    }
+    /* Close unused sides of pipes */
+    SAFE_CLOSE_HANDLE(lpProc->hChildStdInp);
+    SAFE_CLOSE_HANDLE(lpProc->hChildStdOut);
+    SAFE_CLOSE_HANDLE(lpProc->hChildStdErr);
+    if (!bS)
+        goto cleanup;
+    /* Set the running flag */
+    lpProc->dwChildStatus |= (CHILD_RUNNING | PROC_INITIALIZED);
+
+    lpProc->hWorkerThreads[0] = CreateThread(NULL, 0, __apxProcStdoutThread,
+                                             hProcess, 0, &id);
+    lpProc->hWorkerThreads[1] = CreateThread(NULL, 0, __apxProcStderrThread,
+                                             hProcess, 0, &id);
+    ResumeThread(lpProc->stProcInfo.hThread);
+    lpProc->hWorkerThreads[2] = CreateThread(NULL, 0, __apxProcWorkerThread,
+                                            hProcess, 0, &id);
+
+    SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hThread);
+    /* Close child handles first */
+    return TRUE;
+cleanup:
+    /* Close parent side of the pipes */
+    SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
+    SAFE_CLOSE_HANDLE(lpProc->hChildOutRd);
+    SAFE_CLOSE_HANDLE(lpProc->hChildErrRd);
+
+    return FALSE;
+}
+
+BOOL
+apxProcessSetExecutableA(APXHANDLE hProcess, LPCSTR szName)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szApplicationExec);
+    lpProc->szApplicationExec = apxPoolWStrdupA(hProcess->hPool, szName);
+    OutputDebugStringW(lpProc->szApplicationExec);
+    return lpProc->szApplicationExec != NULL;
+}
+
+BOOL
+apxProcessSetExecutableW(APXHANDLE hProcess, LPCWSTR szName)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szApplicationExec);
+    lpProc->szApplicationExec = apxPoolStrdupW(hProcess->hPool, szName);
+    OutputDebugStringW(lpProc->szApplicationExec);
+    return lpProc->szApplicationExec != NULL;
+}
+
+BOOL
+apxProcessSetCommandLineA(APXHANDLE hProcess, LPCSTR szCmdline)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szCommandLine);
+    lpProc->szCommandLine = apxPoolWStrdupA(hProcess->hPool, szCmdline);
+
+    return lpProc->szCommandLine != NULL;
+}
+
+BOOL
+apxProcessSetCommandLineW(APXHANDLE hProcess, LPCWSTR szCmdline)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szCommandLine);
+    lpProc->szCommandLine = apxPoolStrdupW(hProcess->hPool, szCmdline);
+
+    return lpProc->szCommandLine != NULL;
+}
+
+BOOL
+apxProcessSetWorkingPathA(APXHANDLE hProcess, LPCSTR szPath)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szWorkingPath);
+    lpProc->szWorkingPath = apxPoolWStrdupA(hProcess->hPool, szPath);
+
+    return lpProc->szWorkingPath != NULL;
+}
+
+BOOL
+apxProcessSetWorkingPathW(APXHANDLE hProcess, LPCWSTR szPath)
+{
+    LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szWorkingPath);
+    if (!szPath) {
+        /* Clear the WorkingPath */
+        lpProc->szWorkingPath = NULL;
+        return TRUE;
+    }
+    lpProc->szWorkingPath = apxPoolWStrdupW(hProcess->hPool, szPath);
+
+    return lpProc->szWorkingPath != NULL;
+}
+
+DWORD
+apxProcessPutcA(APXHANDLE hProcess, INT ch)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return 0;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    return __apxProcessPutc(lpProc, ch, sizeof(CHAR));
+}
+
+DWORD
+apxProcessPutcW(APXHANDLE hProcess, INT ch)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return 0;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    return __apxProcessPutc(lpProc, ch, sizeof(WCHAR));
+}
+
+DWORD
+apxProcessPutsA(APXHANDLE hProcess, LPCSTR szString)
+{
+    LPAPXPROCESS lpProc;
+    DWORD len;
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS || !szString)
+        return 0;
+    lpProc = APXHANDLE_DATA(hProcess);
+    len = lstrlenA(szString);
+    len = __apxProcessWrite(lpProc, szString, len);
+    if (len) {
+        FlushFileBuffers(lpProc->hChildInpWr);
+        return len;
+    }
+    else
+        return 0;
+}
+
+DWORD
+apxProcessPutsW(APXHANDLE hProcess, LPCWSTR szString)
+{
+    LPAPXPROCESS lpProc;
+    DWORD len;
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS || !szString)
+        return 0;
+    lpProc = APXHANDLE_DATA(hProcess);
+    len = lstrlenW(szString);
+    len = __apxProcessWrite(lpProc, szString, len * 2);
+    if (len) {
+        FlushFileBuffers(lpProc->hChildInpWr);
+        return (len / sizeof(WCHAR));
+    }
+    else
+        return 0;
+}
+
+DWORD
+apxProcessWrite(APXHANDLE hProcess, LPCVOID lpData, DWORD dwLen)
+{
+    LPAPXPROCESS lpProc;
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return 0;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    return __apxProcessWrite(lpProc, lpData, dwLen);
+}
+
+BOOL
+apxProcessFlushStdin(APXHANDLE hProcess)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    if (lpProc->dwChildStatus & CHILD_RUNNING) {
+        return FlushFileBuffers(lpProc->hChildInpWr);
+    }
+
+    return FALSE;
+}
+
+VOID
+apxProcessCloseInputStream(APXHANDLE hProcess)
+{
+   if (hProcess->dwType == APXHANDLE_TYPE_PROCESS) {
+       LPAPXPROCESS lpProc = APXHANDLE_DATA(hProcess);
+       if (lpProc->dwChildStatus & CHILD_RUNNING)
+           SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
+   }
+}
+
+DWORD
+apxProcessWait(APXHANDLE hProcess, DWORD dwMilliseconds, BOOL bKill)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return WAIT_ABANDONED;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    if (lpProc->dwChildStatus & CHILD_RUNNING) {
+        DWORD rv = WaitForMultipleObjects(3, lpProc->hWorkerThreads,
+                                          TRUE, dwMilliseconds);
+        if (rv == WAIT_TIMEOUT && bKill) {
+            __apxProcessCallback(hProcess, WM_CLOSE, 0, 0);
+        }
+        return rv;
+    }
+    else
+        return WAIT_OBJECT_0;
+}
+
+BOOL
+apxProcessRunning(APXHANDLE hProcess)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    return (lpProc->dwChildStatus & CHILD_RUNNING);
+}
+
+DWORD
+apxProcessGetPid(APXHANDLE hProcess)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return 0;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    return lpProc->stProcInfo.dwProcessId;
+}
+
+static LPWSTR __apxStrQuote(LPWSTR lpDest, LPCWSTR szSrc)
+{
+    LPWSTR p;
+    BOOL   space = FALSE, quote = FALSE;
+
+    /* Find if string has embeded spaces, add quotes only if no quotes found
+     */
+    for (p = (LPWSTR)szSrc; *p; p++) {
+        if (*p == L' ' || *p == '\t') {
+            space = TRUE;
+        } else if (*p == L'"') {
+            quote = TRUE;
+        }
+    }
+    p = lpDest;
+    if (space && !quote) *p++ = L'"';
+    while (*szSrc) {
+        *p++ = *szSrc++;
+    }
+    if (space && !quote) *p++ = L'"';
+    return p;
+}
+
+BOOL
+apxProcessSetCommandArgsW(APXHANDLE hProcess, LPCWSTR szTitle,
+                          DWORD dwArgc, LPCWSTR *lpArgs)
+{
+    LPAPXPROCESS lpProc;
+    DWORD  i, l = 0;
+    LPWSTR p;
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+    apxFree(lpProc->szCommandLine);
+
+    l = lstrlenW(szTitle) + 3;
+    for (i = 0; i < dwArgc; i++) {
+        int q = 0;
+        l += (lstrlenW(lpArgs[i]) + 3);
+        l += q;
+    }
+    p = lpProc->szCommandLine = apxPoolAlloc(hProcess->hPool, l * sizeof(WCHAR));
+    p = __apxStrQuote(p, szTitle);
+    for (i = 0; i < dwArgc; i++) {
+        *p++ = L' ';
+        p = __apxStrQuote(p, lpArgs[i]);
+    }
+    *p = L'\0';
+    OutputDebugStringW(lpProc->szCommandLine);
+    return lpProc->szCommandLine != NULL;
+}
+

Propchange: commons/proper/daemon/tags/COMMONS_DAEMON_1_0_3_RC3/src/native/nt/procrun/src/rprocess.c
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message