You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2019/05/28 09:46:55 UTC

svn commit: r1860225 [12/16] - in /tomee/deps/branches/commons-daemon: ./ src/ src/assembly/ src/changes/ src/docs/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons...

Added: tomee/deps/branches/commons-daemon/src/native/windows/src/javajni.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/windows/src/javajni.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/windows/src/javajni.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/windows/src/javajni.c Tue May 28 09:46:53 2019
@@ -0,0 +1,1349 @@
+/* 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 "handles.h"
+#include "javajni.h"
+#include "private.h"
+
+#include <jni.h>
+
+#ifndef JNI_VERSION_1_6
+#error -------------------------------------------------------
+#error JAVA 5 AND EARLIER ARE NO LONGER SUPPORTED
+#error -------------------------------------------------------
+#endif
+
+#define JNI_VERSION_DEFAULT JNI_VERSION_1_6
+
+/* Need to be able to detect Java 9 without requiring compilation against Java 9
+ * headers.
+ */
+#ifndef JNI_VERSION_9
+#define JNI_VERSION_9  0x00090000
+#endif
+
+/* Standard jvm.dll prototypes
+ * since only single jvm can exist per process
+ * make those global
+ */
+
+DYNLOAD_TYPE_DECLARE(JNI_GetDefaultJavaVMInitArgs, JNICALL, jint)(void *);
+static DYNLOAD_FPTR_DECLARE(JNI_GetDefaultJavaVMInitArgs) = NULL;
+
+DYNLOAD_TYPE_DECLARE(JNI_CreateJavaVM, JNICALL, jint)(JavaVM **, void **, void *);
+static DYNLOAD_FPTR_DECLARE(JNI_CreateJavaVM) = NULL;
+
+DYNLOAD_TYPE_DECLARE(JNI_GetCreatedJavaVMs, JNICALL, jint)(JavaVM **, jsize, jsize *);
+static DYNLOAD_FPTR_DECLARE(JNI_GetCreatedJavaVMs) = NULL;
+
+DYNLOAD_TYPE_DECLARE(JVM_DumpAllStacks, JNICALL, void)(JNIEnv *, jclass);
+static DYNLOAD_FPTR_DECLARE(JVM_DumpAllStacks) = NULL;
+
+static HANDLE  _st_sys_jvmDllHandle = NULL;
+static JavaVM *_st_sys_jvm = NULL;
+
+DYNLOAD_TYPE_DECLARE(SetDllDirectoryW, WINAPI, BOOL)(LPCWSTR);
+static DYNLOAD_FPTR_DECLARE(SetDllDirectoryW) = NULL;
+
+#define JVM_DELETE_CLAZZ(jvm, cl)                                               \
+    APXMACRO_BEGIN                                                              \
+    if ((jvm)->lpEnv && (jvm)->cl.jClazz) {                                   \
+        (*((jvm)->lpEnv))->DeleteGlobalRef((jvm)->lpEnv, (jvm)->cl.jClazz);   \
+        (jvm)->cl.jClazz = NULL;                                              \
+    } APXMACRO_END
+
+#define JVM_EXCEPTION_CHECK(jvm) \
+    ((*((jvm)->lpEnv))->ExceptionCheck((jvm)->lpEnv) != JNI_OK)
+
+#define JVM_EXCEPTION_CLEAR(jvm) \
+    APXMACRO_BEGIN                                              \
+    if ((jvm)->lpEnv) {                                         \
+        if ((*((jvm)->lpEnv))->ExceptionCheck((jvm)->lpEnv)) {  \
+            (*((jvm)->lpEnv))->ExceptionDescribe((jvm)->lpEnv); \
+            (*((jvm)->lpEnv))->ExceptionClear((jvm)->lpEnv);    \
+        }                                                       \
+    } APXMACRO_END
+
+#define JNI_LOCAL_UNREF(obj) \
+        (*(lpJava->lpEnv))->DeleteLocalRef(lpJava->lpEnv, obj)
+
+#define JNICALL_0(fName)  \
+        ((*(lpJava->lpEnv))->fName(lpJava->lpEnv))
+
+#define JNICALL_1(fName, a1)  \
+        ((*(lpJava->lpEnv))->fName(lpJava->lpEnv, (a1)))
+
+#define JNICALL_2(fName, a1, a2)  \
+        ((*(lpJava->lpEnv))->fName(lpJava->lpEnv, (a1), (a2)))
+
+#define JNICALL_3(fName, a1, a2, a3)  \
+        ((*(lpJava->lpEnv))->fName(lpJava->lpEnv, (a1), (a2), (a3)))
+
+#define JNICALL_4(fName, a1, a2, a3, a4)  \
+        ((*(lpJava->lpEnv))->fName(lpJava->lpEnv, (a1), (a2), (a3), (a4)))
+
+typedef struct APXJAVASTDCLAZZ {
+    CHAR        sClazz[1024];
+    CHAR        sMethod[512];
+    jclass      jClazz;
+    jmethodID   jMethod;
+    jobject     jObject;
+    jarray      jArgs;
+} APXJAVASTDCLAZZ, *LPAPXJAVASTDCLAZZ;
+
+typedef struct APXJAVAVM {
+    DWORD           dwOptions;
+    APXJAVASTDCLAZZ clString;
+    APXJAVASTDCLAZZ clWorker;
+    jint            iVersion;
+    jsize           iVmCount;
+    JNIEnv          *lpEnv;
+    JavaVM          *lpJvm;
+    /* JVM worker thread info */
+    HANDLE          hWorkerThread;
+    DWORD           iWorkerThread;
+    DWORD           dwWorkerStatus;
+    SIZE_T          szStackSize;
+    HANDLE          hWorkerSync;
+    HANDLE          hWorkerInit;
+} APXJAVAVM, *LPAPXJAVAVM;
+
+/* This is no longer exported in jni.h
+ * However Java uses it internally to get
+ * the default stack size
+ */
+typedef struct APX_JDK1_1InitArgs {
+    jint version;
+
+    char **properties;
+    jint checkSource;
+    jint nativeStackSize;
+    jint javaStackSize;
+    jint minHeapSize;
+    jint maxHeapSize;
+    jint verifyMode;
+    char *classpath;
+
+    char padding[128];
+} APX_JDK1_1InitArgs;
+
+#define JAVA_CLASSPATH      "-Djava.class.path="
+#define JAVA_CLASSPATH_W    L"-Djava.class.path="
+#define JAVA_CLASSSTRING    "java/lang/String"
+#define MSVCRT71_DLLNAME    L"\\msvcrt71.dll"
+
+static DWORD vmExitCode = 0;
+
+static __inline BOOL __apxJvmAttachEnv(LPAPXJAVAVM lpJava, JNIEnv **lpEnv,
+                                       LPBOOL lpAttached)
+{
+    jint _iStatus;
+
+    if (!_st_sys_jvm || !lpJava->lpJvm)
+      return FALSE;
+    _iStatus = (*(lpJava->lpJvm))->GetEnv(lpJava->lpJvm,
+                                          (void **)lpEnv,
+                                          lpJava->iVersion);
+    if (_iStatus != JNI_OK) {
+        if (_iStatus == JNI_EDETACHED) {
+            _iStatus = (*(lpJava->lpJvm))->AttachCurrentThread(lpJava->lpJvm,
+                                                (void **)lpEnv, NULL);
+            if (lpAttached)
+                *lpAttached = TRUE;
+        }
+    }
+    if (_iStatus != JNI_OK) {
+        *lpEnv = NULL;
+        return FALSE;
+    }
+    else
+        return TRUE;
+}
+
+static __inline BOOL __apxJvmAttach(LPAPXJAVAVM lpJava)
+{
+    return __apxJvmAttachEnv(lpJava, &lpJava->lpEnv, NULL);
+}
+
+static __inline BOOL __apxJvmDetach(LPAPXJAVAVM lpJava)
+{
+    if (!_st_sys_jvm || !lpJava->lpJvm)
+      return FALSE;
+    if ((*(lpJava->lpJvm))->DetachCurrentThread(lpJava->lpJvm) != JNI_OK) {
+        lpJava->lpEnv = NULL;
+        return FALSE;
+    }
+    else
+        return TRUE;
+}
+
+static BOOL __apxLoadJvmDll(APXHANDLE hPool, LPCWSTR szJvmDllPath)
+{
+    UINT errMode;
+    WCHAR  jreAltPath[SIZ_PATHLEN];
+    LPWSTR dllJvmPath = (LPWSTR)szJvmDllPath;
+    DYNLOAD_FPTR_DECLARE(SetDllDirectoryW);
+    DWORD  i, l = 0;
+    WCHAR  jreBinPath[SIZ_PATHLEN];
+
+    if (!IS_INVALID_HANDLE(_st_sys_jvmDllHandle))
+        return TRUE;    /* jvm.dll is already loaded */
+
+    if (dllJvmPath && *dllJvmPath) {
+        /* Explicit JVM path.
+         * Check if provided argument is valid
+         */
+        if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) {
+            /* DAEMON-247: Invalid RuntimeLib explicitly specified is error.
+             */
+            apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib specified '%S'", dllJvmPath);
+            return FALSE;
+        }
+    }
+    else {
+        dllJvmPath = apxGetJavaSoftRuntimeLib(NULL);
+        if (!dllJvmPath)
+            return FALSE;
+    }
+    if (GetFileAttributesW(dllJvmPath) == INVALID_FILE_ATTRIBUTES) {
+        /* DAEMON-184: RuntimeLib registry key is invalid.
+         * Check from Jre JavaHome directly
+         */
+        LPWSTR szJreHome = apxGetJavaSoftHome(NULL, TRUE);
+        apxLogWrite(APXLOG_MARK_DEBUG "Invalid RuntimeLib '%S'", dllJvmPath);
+        if (szJreHome) {
+            apxLogWrite(APXLOG_MARK_DEBUG "Using Jre JavaHome '%S'", szJreHome);
+            lstrlcpyW(jreAltPath, SIZ_PATHLEN, szJreHome);
+            lstrlcatW(jreAltPath, SIZ_PATHLEN, L"\\bin\\server\\jvm.dll");
+            dllJvmPath = jreAltPath;
+        }
+    }
+    /* Suppress the not found system popup message */
+    errMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+
+    lstrlcpyW(jreBinPath, SIZ_PATHLEN, dllJvmPath);
+
+    for (i = lstrlenW(jreBinPath); i > 0, l < 2; i--) {
+        if (jreBinPath[i] == L'\\' || jreBinPath[i] == L'/') {
+            jreBinPath[i] = L'\0';
+            l++;
+        }
+    }
+
+    /* Add java bin path to the PATH to fix loading of awt.dll */
+    apxAddToPathW(hPool, jreBinPath);
+
+    /* Set the environment using putenv, so JVM can use it */
+    apxSetInprocEnvironment();
+
+    apxLogWrite(APXLOG_MARK_DEBUG "loading jvm '%S'", dllJvmPath);
+    _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0);
+    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle) &&
+        GetFileAttributesW(dllJvmPath) != INVALID_FILE_ATTRIBUTES) {
+        /* There is a file but cannot be loaded.
+         * Try to load the MSVCRTxx.dll before JVM.dll
+         */
+        WCHAR  crtBinPath[SIZ_PATHLEN];
+
+        lstrlcpyW(jreBinPath, SIZ_PATHLEN, dllJvmPath);
+        if(l == 2) {
+            lstrlcpyW(crtBinPath, SIZ_PATHLEN, jreBinPath);
+            lstrlcatW(crtBinPath, SIZ_PATHLEN, MSVCRT71_DLLNAME);
+            if (GetFileAttributesW(crtBinPath) != INVALID_FILE_ATTRIBUTES) {
+                if (LoadLibraryW(crtBinPath)) {
+                    /* Found MSVCRTxx.dll
+                     */
+                    apxLogWrite(APXLOG_MARK_DEBUG "preloaded '%S'",
+                                crtBinPath);
+                }
+            }
+        }
+    }
+    /* This shuldn't happen, but try to search in %PATH% */
+    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle))
+        _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL,
+                                              LOAD_WITH_ALTERED_SEARCH_PATH);
+
+    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) {
+        DYNLOAD_FPTR_ADDRESS(SetDllDirectoryW, KERNEL32);
+        if(l == 2) {
+            DYNLOAD_CALL(SetDllDirectoryW)(jreBinPath);
+            apxLogWrite(APXLOG_MARK_DEBUG "Setting DLL search path to '%S'",
+                            jreBinPath);
+        }
+        _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL, 0);
+        if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle))
+            _st_sys_jvmDllHandle = LoadLibraryExW(dllJvmPath, NULL,
+                                                  LOAD_WITH_ALTERED_SEARCH_PATH);
+    }
+    /* Restore the error mode signalization */
+    SetErrorMode(errMode);
+    if (IS_INVALID_HANDLE(_st_sys_jvmDllHandle)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        return FALSE;
+    }
+    DYNLOAD_FPTR_LOAD(JNI_GetDefaultJavaVMInitArgs, _st_sys_jvmDllHandle);
+    DYNLOAD_FPTR_LOAD(JNI_CreateJavaVM,             _st_sys_jvmDllHandle);
+    DYNLOAD_FPTR_LOAD(JNI_GetCreatedJavaVMs,        _st_sys_jvmDllHandle);
+    DYNLOAD_FPTR_LOAD(JVM_DumpAllStacks,            _st_sys_jvmDllHandle);
+
+    if (!DYNLOAD_FPTR(JNI_GetDefaultJavaVMInitArgs) ||
+        !DYNLOAD_FPTR(JNI_CreateJavaVM) ||
+        !DYNLOAD_FPTR(JNI_GetCreatedJavaVMs)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        FreeLibrary(_st_sys_jvmDllHandle);
+        _st_sys_jvmDllHandle = NULL;
+        return FALSE;
+    }
+
+    /* Real voodo ... */
+    return TRUE;
+}
+
+static BOOL __apxJavaJniCallback(APXHANDLE hObject, UINT uMsg,
+                                 WPARAM wParam, LPARAM lParam)
+{
+    LPAPXJAVAVM lpJava;
+    DWORD       dwJvmRet = 0;
+
+    lpJava = APXHANDLE_DATA(hObject);
+    switch (uMsg) {
+        case WM_CLOSE:
+            if (_st_sys_jvm && lpJava->lpJvm) {
+                if (!IS_INVALID_HANDLE(lpJava->hWorkerThread)) {
+                    if (GetExitCodeThread(lpJava->hWorkerThread, &dwJvmRet) &&
+                        dwJvmRet == STILL_ACTIVE) {
+                        TerminateThread(lpJava->hWorkerThread, 5);
+                    }
+                }
+                SAFE_CLOSE_HANDLE(lpJava->hWorkerThread);
+                __apxJvmAttach(lpJava);
+                JVM_DELETE_CLAZZ(lpJava, clWorker);
+                JVM_DELETE_CLAZZ(lpJava, clString);
+                __apxJvmDetach(lpJava);
+                /* Check if this is the jvm loader */
+                if (!lpJava->iVmCount && _st_sys_jvmDllHandle) {
+                    /* Unload JVM dll */
+                    FreeLibrary(_st_sys_jvmDllHandle);
+                    _st_sys_jvmDllHandle = NULL;
+                }
+                lpJava->lpJvm = NULL;
+            }
+        break;
+        default:
+        break;
+    }
+    return TRUE;
+}
+
+APXHANDLE
+apxCreateJava(APXHANDLE hPool, LPCWSTR szJvmDllPath)
+{
+
+    APXHANDLE    hJava;
+    LPAPXJAVAVM  lpJava;
+    jsize        iVmCount;
+    JavaVM       *lpJvm = NULL;
+    struct       APX_JDK1_1InitArgs jArgs1_1;
+
+    if (!__apxLoadJvmDll(hPool, szJvmDllPath))
+        return NULL;
+
+
+    /*
+     */
+    if (DYNLOAD_FPTR(JNI_GetCreatedJavaVMs)(&lpJvm, 1, &iVmCount) != JNI_OK) {
+        return NULL;
+    }
+    if (iVmCount && !lpJvm)
+        return NULL;
+
+    hJava = apxHandleCreate(hPool, 0,
+                            NULL, sizeof(APXJAVAVM),
+                            __apxJavaJniCallback);
+    if (IS_INVALID_HANDLE(hJava))
+        return NULL;
+    hJava->dwType = APXHANDLE_TYPE_JVM;
+    lpJava = APXHANDLE_DATA(hJava);
+    lpJava->lpJvm = lpJvm;
+    lpJava->iVmCount = iVmCount;
+
+    /* Guess the stack size
+     */
+    AplZeroMemory(&jArgs1_1, sizeof(jArgs1_1));
+    jArgs1_1.version = JNI_VERSION_1_1;
+    DYNLOAD_FPTR(JNI_GetDefaultJavaVMInitArgs)(&jArgs1_1);
+    if (jArgs1_1.javaStackSize < 0 || jArgs1_1.javaStackSize > (2048 * 1024))
+        jArgs1_1.javaStackSize = 0;
+    lpJava->szStackSize = (SIZE_T)jArgs1_1.javaStackSize;
+
+    if (!_st_sys_jvm)
+        _st_sys_jvm = lpJvm;
+    return hJava;
+}
+
+static DWORD WINAPI __apxJavaDestroyThread(LPVOID lpParameter)
+{
+    JavaVM *lpJvm = (JavaVM *)lpParameter;
+    (*lpJvm)->DestroyJavaVM(lpJvm);
+    return 0;
+}
+
+BOOL
+apxDestroyJvm(DWORD dwTimeout)
+{
+    if (_st_sys_jvm) {
+        DWORD  tid;
+        HANDLE hWaiter;
+        BOOL   rv = FALSE;
+        JavaVM *lpJvm = _st_sys_jvm;
+
+        _st_sys_jvm = NULL;
+        (*lpJvm)->DetachCurrentThread(lpJvm);
+        hWaiter = CreateThread(NULL, 0, __apxJavaDestroyThread,
+                               (void *)lpJvm, 0, &tid);
+        if (IS_INVALID_HANDLE(hWaiter)) {
+            apxLogWrite(APXLOG_MARK_SYSERR);
+            return FALSE;
+        }
+        if (WaitForSingleObject(hWaiter, dwTimeout) == WAIT_OBJECT_0)
+            rv = TRUE;
+        CloseHandle(hWaiter);
+        return rv;
+    }
+    else
+        return FALSE;
+}
+
+static BOOL __apxIsJava9()
+{
+    JavaVMInitArgs  vmArgs;
+    vmArgs.version = JNI_VERSION_9;
+    /* Returns an error if requested version is not supported */
+    if (DYNLOAD_FPTR(JNI_GetDefaultJavaVMInitArgs)(&vmArgs) != JNI_OK) {
+        return FALSE;
+    }
+    else {
+        return TRUE;
+    }
+}
+
+static DWORD __apxMultiSzToJvmOptions(APXHANDLE hPool,
+                                      LPCSTR lpString,
+                                      LPCSTR lpString9,
+                                      JavaVMOption **lppArray,
+                                      DWORD  nExtra)
+{
+    DWORD i, n = 0, n9 = 0, nTotal, l = 0, l9 = 0, lTotal;
+    char *buff;
+    LPSTR p;
+
+    if (lpString) {
+        l = __apxGetMultiSzLengthA(lpString, &n);
+    }
+    if (__apxIsJava9() && lpString9) {
+        l9 = __apxGetMultiSzLengthA(lpString9, &n9);
+    }
+
+    nTotal = n + n9 + nExtra;
+    lTotal = l + l9;
+
+    buff = apxPoolAlloc(hPool, (nTotal + 1) * sizeof(JavaVMOption) + (lTotal + 1));
+
+    *lppArray = (JavaVMOption *)buff;
+    p = (LPSTR)(buff + (nTotal + 1) * sizeof(JavaVMOption));
+    if (lpString)
+        AplCopyMemory(p, lpString, l + 1);
+    for (i = 0; i < n; i++) {
+        DWORD qr = apxStrUnQuoteInplaceA(p);
+        (*lppArray)[i].optionString = p;
+        while (*p)
+            p++;
+        p++;
+        p += qr;
+    }
+    if (lpString9)
+        AplCopyMemory(p, lpString9, l9 + 1);
+    for (i = n; i < (n + n9); i++) {
+        DWORD qr = apxStrUnQuoteInplaceA(p);
+        (*lppArray)[i].optionString = p;
+        while (*p)
+            p++;
+        p++;
+        p += qr;
+    }
+
+    return nTotal;
+}
+
+/* a hook for a function that redirects all VM messages. */
+static jint JNICALL __apxJniVfprintf(FILE *fp, const char *format, va_list args)
+{
+    jint rv;
+    CHAR sBuf[1024+16];
+    rv = wvsprintfA(sBuf, format, args);
+    if (apxLogWrite(APXLOG_MARK_INFO "%s", sBuf) == 0)
+        fputs(sBuf, stdout);
+    return rv;
+}
+
+static void JNICALL __apxJniExit(jint exitCode)
+{
+    apxLogWrite(APXLOG_MARK_DEBUG "Exit hook with exit code %d", exitCode);
+    vmExitCode = exitCode;
+    return;
+}
+
+static void JNICALL __apxJniAbort()
+{
+    apxLogWrite(APXLOG_MARK_DEBUG "JVM aborted");
+    // Set the exit code to a non-zero value to indicate a non-standard exit
+    vmExitCode = 1;
+    return;
+}
+
+static LPSTR __apxStrIndexA(LPCSTR szStr, int nCh)
+{
+    LPSTR pStr;
+
+    for (pStr = (LPSTR)szStr; *pStr; pStr++) {
+        if (*pStr == nCh)
+            return pStr;
+    }
+    return NULL;
+}
+
+static LPSTR __apxStrnCatA(APXHANDLE hPool, LPSTR pOrg, LPCSTR szStr, LPCSTR szAdd)
+{
+    DWORD len = 1;
+    DWORD nas = pOrg == NULL;
+    if (pOrg)
+        len += lstrlenA(pOrg);
+    if (szStr)
+        len += lstrlenA(szStr);
+    if (szAdd)
+        len += lstrlenA(szAdd);
+    pOrg = (LPSTR)apxPoolRealloc(hPool, pOrg, len);
+    if (pOrg) {
+        if (nas)
+            *pOrg = '\0';
+        if (szStr)
+            lstrcatA(pOrg, szStr);
+        if (szAdd)
+            lstrcatA(pOrg, szAdd);
+    }
+    return pOrg;
+}
+
+static LPSTR __apxEvalPathPart(APXHANDLE hPool, LPSTR pStr, LPCSTR szPattern)
+{
+    HANDLE           hFind;
+    WIN32_FIND_DATAA stGlob;
+    char       szJars[MAX_PATH + 1];
+    char       szPath[MAX_PATH + 1];
+
+    if (lstrlenA(szPattern) > (sizeof(szJars) - 5)) {
+        return __apxStrnCatA(hPool, pStr, szPattern, NULL);
+    }
+    lstrcpyA(szJars, szPattern);
+    szPath[0] = ';';
+    szPath[1] = '\0';
+    lstrcatA(szPath, szPattern);
+    lstrcatA(szJars, ".jar");
+    /* Remove the trailing asterisk
+     */
+    szPath[lstrlenA(szPath) - 1] = '\0';
+    if ((hFind = FindFirstFileA(szJars, &stGlob)) == INVALID_HANDLE_VALUE) {
+        /* Find failed
+         */
+        return pStr;
+    }
+    pStr = __apxStrnCatA(hPool, pStr, &szPath[1], stGlob.cFileName);
+    if (pStr == NULL) {
+        FindClose(hFind);
+        return NULL;
+    }
+    while (FindNextFileA(hFind, &stGlob) != 0) {
+        pStr = __apxStrnCatA(hPool, pStr, szPath, stGlob.cFileName);
+        if (pStr == NULL)
+            break;
+    }
+    FindClose(hFind);
+    return pStr;
+}
+
+/**
+ * Call glob on each PATH like string path.
+ * Glob is called only if the part ends with asterisk in which
+ * case asterisk is replaced by *.jar when searching
+ */
+static LPSTR __apxEvalClasspath(APXHANDLE hPool, LPCSTR szCp)
+{
+    LPSTR pCpy = __apxStrnCatA(hPool, NULL, JAVA_CLASSPATH, szCp);
+    LPSTR pGcp = NULL;
+    LPSTR pPos;
+    LPSTR pPtr;
+
+    if (!pCpy)
+        return NULL;
+    pPtr = pCpy + sizeof(JAVA_CLASSPATH) - 1;
+    while ((pPos = __apxStrIndexA(pPtr, ';'))) {
+        *pPos = '\0';
+        if (pGcp)
+            pGcp = __apxStrnCatA(hPool, pGcp, ";", NULL);
+        else
+            pGcp = __apxStrnCatA(hPool, NULL, JAVA_CLASSPATH, NULL);
+        if ((pPos > pPtr) && (*(pPos - 1) == '*')) {
+            if (!(pGcp = __apxEvalPathPart(hPool, pGcp, pPtr))) {
+                /* Error.
+                * Return the original string processed so far.
+                */
+                return pCpy;
+            }
+        }
+        else {
+            /* Standard path element */
+            if (!(pGcp = __apxStrnCatA(hPool, pGcp, pPtr, NULL))) {
+                /* Error.
+                * Return the original string processed so far.
+                */
+                return pCpy;
+            }
+        }
+        pPtr = pPos + 1;
+    }
+    if (*pPtr) {
+        int end = lstrlenA(pPtr);
+        if (pGcp)
+            pGcp = __apxStrnCatA(hPool, pGcp, ";", NULL);
+        else
+            pGcp = __apxStrnCatA(hPool, NULL, JAVA_CLASSPATH, NULL);
+        if (end > 0 && pPtr[end - 1] == '*') {
+            /* Last path elemet ends with star
+             * Do a globbing.
+             */
+            pGcp = __apxEvalPathPart(hPool, pGcp, pPtr);
+        }
+        else {
+            /* Just add the part */
+            pGcp = __apxStrnCatA(hPool, pGcp, pPtr, NULL);
+        }
+    }
+    /* Free the allocated copy */
+    if (pGcp) {
+        apxFree(pCpy);
+        return pGcp;
+    }
+    else
+        return pCpy;
+}
+
+/* ANSI version only */
+BOOL
+apxJavaInitialize(APXHANDLE hJava, LPCSTR szClassPath,
+                  LPCVOID lpOptions, LPCVOID lpOptions9,
+                  DWORD dwMs, DWORD dwMx, DWORD dwSs,
+                  DWORD bJniVfprintf)
+{
+    LPAPXJAVAVM     lpJava;
+    JavaVMInitArgs  vmArgs;
+    JavaVMOption    *lpJvmOptions;
+    DWORD           i, nOptions, sOptions = 0;
+    BOOL            rv = FALSE;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return FALSE;
+
+    lpJava = APXHANDLE_DATA(hJava);
+
+    if (lpJava->iVmCount) {
+        if (!lpJava->lpEnv && !__apxJvmAttach(lpJava)) {
+            if (lpJava->iVersion == JNI_VERSION_1_6) {
+                apxLogWrite(APXLOG_MARK_ERROR "Unable To Attach the JVM");
+                return FALSE;
+            }
+            else
+                lpJava->iVersion = JNI_VERSION_1_6;
+            if (!__apxJvmAttach(lpJava)) {
+                apxLogWrite(APXLOG_MARK_ERROR "Unable To Attach the JVM");
+                return FALSE;
+            }
+        }
+        lpJava->iVersion = JNICALL_0(GetVersion);
+        if (lpJava->iVersion < JNI_VERSION_1_6) {
+            apxLogWrite(APXLOG_MARK_ERROR "Unsupported JNI version %#08x", lpJava->iVersion);
+            return FALSE;
+        }
+        rv = TRUE;
+    }
+    else {
+        CHAR  iB[3][64];
+        LPSTR szCp = NULL;
+        int result;
+        lpJava->iVersion = JNI_VERSION_DEFAULT;
+        if (dwMs)
+            ++sOptions;
+        if (dwMx)
+            ++sOptions;
+        if (dwSs)
+            ++sOptions;
+        if (bJniVfprintf)
+            ++sOptions;
+        if (szClassPath && *szClassPath)
+            ++sOptions;
+
+        sOptions++; /* unconditionally set for extraInfo exit  */
+        sOptions++; /* unconditionally set for extraInfo abort */
+
+        nOptions = __apxMultiSzToJvmOptions(hJava->hPool, lpOptions, lpOptions9,
+                                            &lpJvmOptions, sOptions);
+        if (szClassPath && *szClassPath) {
+            szCp = __apxEvalClasspath(hJava->hPool, szClassPath);
+            if (szCp == NULL) {
+                apxLogWrite(APXLOG_MARK_ERROR "Invalid classpath %s", szClassPath);
+                return FALSE;
+            }
+            lpJvmOptions[nOptions - sOptions].optionString = szCp;
+            --sOptions;
+        }
+        if (bJniVfprintf) {
+            /* default JNI error printer */
+            lpJvmOptions[nOptions - sOptions].optionString = "vfprintf";
+            lpJvmOptions[nOptions - sOptions].extraInfo    = __apxJniVfprintf;
+            --sOptions;
+        }
+
+        /* unconditionally add hook for System.exit() in order to store exit code */
+        lpJvmOptions[nOptions - sOptions].optionString = "exit";
+        lpJvmOptions[nOptions - sOptions].extraInfo    = __apxJniExit;
+        --sOptions;
+
+        /* unconditionally add hook for abort in order to store exit code */
+        lpJvmOptions[nOptions - sOptions].optionString = "abort";
+        lpJvmOptions[nOptions - sOptions].extraInfo    = __apxJniAbort;
+        --sOptions;
+
+        if (dwMs) {
+            wsprintfA(iB[0], "-Xms%dm", dwMs);
+            lpJvmOptions[nOptions - sOptions].optionString = iB[0];
+            --sOptions;
+        }
+        if (dwMx) {
+            wsprintfA(iB[1], "-Xmx%dm", dwMx);
+            lpJvmOptions[nOptions - sOptions].optionString = iB[1];
+            --sOptions;
+        }
+        if (dwSs) {
+            wsprintfA(iB[2], "-Xss%dk", dwSs);
+            lpJvmOptions[nOptions - sOptions].optionString = iB[2];
+            --sOptions;
+        }
+        for (i = 0; i < nOptions; i++) {
+            apxLogWrite(APXLOG_MARK_DEBUG "Jvm Option[%d] %s", i,
+                        lpJvmOptions[i].optionString);
+        }
+        vmArgs.options  = lpJvmOptions;
+        vmArgs.nOptions = nOptions;
+        vmArgs.version  = lpJava->iVersion;
+        vmArgs.ignoreUnrecognized = JNI_FALSE;
+        result = DYNLOAD_FPTR(JNI_CreateJavaVM)(&(lpJava->lpJvm),
+                                           (void **)&(lpJava->lpEnv),
+                                           &vmArgs);
+        if (result != JNI_OK) {
+            apxLogWrite(APXLOG_MARK_ERROR "CreateJavaVM Failed with error [%d]", result);
+            rv = FALSE;
+        }
+        else {
+            rv = TRUE;
+            if (!_st_sys_jvm)
+                _st_sys_jvm = lpJava->lpJvm;
+        }
+        apxFree(szCp);
+        apxFree(lpJvmOptions);
+    }
+    if (rv)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/* ANSI version only */
+DWORD
+apxJavaCmdInitialize(APXHANDLE hPool, LPCWSTR szClassPath, LPCWSTR szClass,
+                     LPCWSTR szOptions, DWORD dwMs, DWORD dwMx,
+                     DWORD dwSs, LPCWSTR szCmdArgs, LPWSTR **lppArray)
+{
+
+    DWORD i, nJVM, nCmd, nTotal, lJVM, lCmd;
+    LPWSTR p;
+
+    /* Calculate the number of all arguments */
+    nTotal = 0;
+    if (szClassPath)
+        ++nTotal;
+    if (szClass)
+        ++nTotal;
+    lJVM = __apxGetMultiSzLengthW(szOptions, &nJVM);
+    nTotal += nJVM;
+    lCmd = __apxGetMultiSzLengthW(szCmdArgs, &nCmd);
+    nTotal += nCmd;
+    if (dwMs)
+        ++nTotal;
+    if (dwMx)
+        ++nTotal;
+    if (dwSs)
+        ++nTotal;
+
+    if (nTotal == 0)
+        return 0;
+
+    /* Allocate the array to store all arguments' pointers
+     */
+    *lppArray = (LPWSTR *)apxPoolAlloc(hPool, (nTotal + 2) * sizeof(LPWSTR));
+
+    /* Process JVM options */
+    if (nJVM && lJVM) {
+        p = (LPWSTR)apxPoolAlloc(hPool, (lJVM + 1) * sizeof(WCHAR));
+        AplCopyMemory(p, szOptions, (lJVM + 1) * sizeof(WCHAR) + sizeof(WCHAR));
+        for (i = 0; i < nJVM; i++) {
+            (*lppArray)[i] = p;
+            while (*p)
+                p++;
+            p++;
+        }
+    }
+
+    /* Process the 3 extra JVM options */
+    if (dwMs) {
+        p = (LPWSTR)apxPoolAlloc(hPool, 64 * sizeof(WCHAR));
+        wsprintfW(p, L"-Xms%dm", dwMs);
+        (*lppArray)[i++] = p;
+    }
+    if (dwMx) {
+        p = (LPWSTR)apxPoolAlloc(hPool, 64 * sizeof(WCHAR));
+        wsprintfW(p, L"-Xmx%dm", dwMx);
+        (*lppArray)[i++] = p;
+    }
+    if (dwSs) {
+        p = (LPWSTR)apxPoolAlloc(hPool, 64 * sizeof(WCHAR));
+        wsprintfW(p, L"-Xss%dk", dwSs);
+        (*lppArray)[i++] = p;
+    }
+
+    /* Process the classpath and class */
+    if (szClassPath) {
+        p = (LPWSTR)apxPoolAlloc(hPool, (lstrlenW(JAVA_CLASSPATH_W) + lstrlenW(szClassPath)) * sizeof(WCHAR));
+        lstrcpyW(p, JAVA_CLASSPATH_W);
+        lstrcatW(p, szClassPath);
+        (*lppArray)[i++] = p;
+    }
+    if (szClass) {
+        p = (LPWSTR)apxPoolAlloc(hPool, (lstrlenW(szClass)) * sizeof(WCHAR));
+        lstrcpyW(p, szClass);
+        (*lppArray)[i++] = p;
+    }
+
+    /* Process command arguments */
+    if (nCmd && lCmd) {
+        p = (LPWSTR)apxPoolAlloc(hPool, (lCmd + 1) * sizeof(WCHAR));
+        AplCopyMemory(p, szCmdArgs, (lCmd + 1) * sizeof(WCHAR) + sizeof(WCHAR));
+        for (; i < nTotal; i++) {
+            (*lppArray)[i] = p;
+            while (*p)
+                p++;
+            p++;
+        }
+    }
+
+    (*lppArray)[++i] = NULL;
+
+    return nTotal;
+}
+
+
+BOOL
+apxJavaLoadMainClass(APXHANDLE hJava, LPCSTR szClassName,
+                     LPCSTR szMethodName,
+                     LPCVOID lpArguments)
+{
+    LPWSTR      *lpArgs = NULL;
+    DWORD       nArgs;
+    LPAPXJAVAVM lpJava;
+    jclass      jClazz;
+    LPCSTR      szSignature = "([Ljava/lang/String;)V";
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return FALSE;
+    lpJava = APXHANDLE_DATA(hJava);
+    if (!lpJava)
+        return FALSE;
+    if (IS_EMPTY_STRING(szMethodName))
+        szMethodName = "main";
+    if (lstrcmpA(szClassName, "java/lang/System") == 0) {
+        /* Usable only for exit method, so force */
+        szSignature  = "(I)V";
+        szMethodName = "exit";
+    }
+    lstrlcpyA(lpJava->clWorker.sClazz, 1024, szClassName);
+    lstrlcpyA(lpJava->clWorker.sMethod, 512, szMethodName);
+
+    jClazz = JNICALL_1(FindClass, JAVA_CLASSSTRING);
+    if (!jClazz) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "FindClass "  JAVA_CLASSSTRING " failed");
+        return FALSE;
+    }
+    lpJava->clString.jClazz = JNICALL_1(NewGlobalRef, jClazz);
+    JNI_LOCAL_UNREF(jClazz);
+    /* Find the class */
+    jClazz  = JNICALL_1(FindClass, szClassName);
+    if (!jClazz) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "FindClass %s failed", szClassName);
+        return FALSE;
+    }
+    /* Make the class global so that worker thread can attach */
+    lpJava->clWorker.jClazz  = JNICALL_1(NewGlobalRef, jClazz);
+    JNI_LOCAL_UNREF(jClazz);
+
+    lpJava->clWorker.jMethod = JNICALL_3(GetStaticMethodID,
+                                         lpJava->clWorker.jClazz,
+                                         szMethodName, szSignature);
+    if (!lpJava->clWorker.jMethod) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Method 'static void %s(String[])' not found in Class %s",
+                szMethodName, szClassName);
+        return FALSE;
+    }
+    if (lstrcmpA(szClassName, "java/lang/System")) {
+        nArgs = apxMultiSzToArrayW(hJava->hPool, lpArguments, &lpArgs);
+        lpJava->clWorker.jArgs = JNICALL_3(NewObjectArray, nArgs,
+                                           lpJava->clString.jClazz, NULL);
+        if (nArgs) {
+            DWORD i;
+            for (i = 0; i < nArgs; i++) {
+                jstring arg = JNICALL_2(NewString, lpArgs[i], lstrlenW(lpArgs[i]));
+                JNICALL_3(SetObjectArrayElement, lpJava->clWorker.jArgs, i, arg);
+                apxLogWrite(APXLOG_MARK_DEBUG "argv[%d] = %S", i, lpArgs[i]);
+            }
+        }
+        apxFree(lpArgs);
+    }
+    return TRUE;
+}
+
+/* Main Java application worker thread
+ * It will launch Java main and wait until
+ * it finishes.
+ */
+static DWORD WINAPI __apxJavaWorkerThread(LPVOID lpParameter)
+{
+#define WORKER_EXIT(x)  do { rv = x; goto finished; } while(0)
+    DWORD rv = 0;
+    LPAPXJAVAVM lpJava = NULL;
+    LPAPXJAVA_THREADARGS pArgs = (LPAPXJAVA_THREADARGS)lpParameter;
+    APXHANDLE hJava;
+
+    hJava  = (APXHANDLE)pArgs->hJava;
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        WORKER_EXIT(1);
+    lpJava = APXHANDLE_DATA(pArgs->hJava);
+    if (!lpJava)
+        WORKER_EXIT(1);
+    if (!apxJavaInitialize(pArgs->hJava,
+                           pArgs->szClassPath,
+                           pArgs->lpOptions, pArgs->lpOptions9,
+                           pArgs->dwMs, pArgs->dwMx, pArgs->dwSs,
+                           pArgs->bJniVfprintf)) {
+        WORKER_EXIT(2);
+    }
+    if (pArgs->szLibraryPath && *pArgs->szLibraryPath) {
+        DYNLOAD_FPTR_ADDRESS(SetDllDirectoryW, KERNEL32);
+        DYNLOAD_CALL(SetDllDirectoryW)(pArgs->szLibraryPath);
+        apxLogWrite(APXLOG_MARK_DEBUG "DLL search path set to '%S'",
+                    pArgs->szLibraryPath);
+    }
+    if (!apxJavaLoadMainClass(pArgs->hJava,
+                              pArgs->szClassName,
+                              pArgs->szMethodName,
+                              pArgs->lpArguments)) {
+        WORKER_EXIT(3);
+    }
+    apxJavaSetOut(pArgs->hJava, TRUE,  pArgs->szStdErrFilename);
+    apxJavaSetOut(pArgs->hJava, FALSE, pArgs->szStdOutFilename);
+
+    /* Check if we have a class and a method */
+    if (!lpJava->clWorker.jClazz || !lpJava->clWorker.jMethod)
+        WORKER_EXIT(4);
+    if (!__apxJvmAttach(lpJava))
+        WORKER_EXIT(5);
+    apxLogWrite(APXLOG_MARK_DEBUG "Java Worker thread started %s:%s",
+                lpJava->clWorker.sClazz, lpJava->clWorker.sMethod);
+    lpJava->dwWorkerStatus = 1;
+    SetEvent(lpJava->hWorkerInit);
+    /* Ensure apxJavaStart worker has read our status */
+    WaitForSingleObject(lpJava->hWorkerSync, INFINITE);
+    JNICALL_3(CallStaticVoidMethod,
+              lpJava->clWorker.jClazz,
+              lpJava->clWorker.jMethod,
+              lpJava->clWorker.jArgs);
+    if (JVM_EXCEPTION_CHECK(lpJava)) {
+        apxLogWrite(APXLOG_MARK_DEBUG "Exception has been thrown");
+        vmExitCode = 1;
+        (*((lpJava)->lpEnv))->ExceptionDescribe((lpJava)->lpEnv);
+        __apxJvmDetach(lpJava);
+        WORKER_EXIT(6);
+    }
+    else {
+        __apxJvmDetach(lpJava);
+    }
+finished:
+    if (lpJava) {
+        lpJava->dwWorkerStatus = 0;
+        apxLogWrite(APXLOG_MARK_DEBUG "Java Worker thread finished %s:%s with status = %d",
+                    lpJava->clWorker.sClazz, lpJava->clWorker.sMethod, rv);
+        SetEvent(lpJava->hWorkerInit);
+    }
+    ExitThread(rv);
+    /* never gets here but keep the compiler happy */
+    return rv;
+}
+
+BOOL
+apxJavaStart(LPAPXJAVA_THREADARGS pArgs)
+{
+    LPAPXJAVAVM lpJava;
+    lpJava = APXHANDLE_DATA(pArgs->hJava);
+    if (!lpJava)
+        return FALSE;
+    lpJava->dwWorkerStatus = 0;
+    lpJava->hWorkerInit    = CreateEvent(NULL, FALSE, FALSE, NULL);
+    lpJava->hWorkerSync    = CreateEvent(NULL, FALSE, FALSE, NULL);
+    lpJava->hWorkerThread  = CreateThread(NULL,
+                                          lpJava->szStackSize,
+                                          __apxJavaWorkerThread,
+                                          pArgs, CREATE_SUSPENDED,
+                                          &lpJava->iWorkerThread);
+    if (IS_INVALID_HANDLE(lpJava->hWorkerThread)) {
+        apxLogWrite(APXLOG_MARK_SYSERR);
+        return FALSE;
+    }
+    ResumeThread(lpJava->hWorkerThread);
+    /* Wait until the worker thread initializes */
+    WaitForSingleObject(lpJava->hWorkerInit, INFINITE);
+    if (lpJava->dwWorkerStatus == 0)
+        return FALSE;
+    SetEvent(lpJava->hWorkerSync);
+    if (lstrcmpA(lpJava->clWorker.sClazz, "java/lang/System")) {
+        /* Give some time to initialize the thread
+         * Unless we are calling System.exit(0).
+         * This will be handled by _onexit hook.
+         */
+        Sleep(1000);
+    }
+    return TRUE;
+}
+
+DWORD
+apxJavaSetOptions(APXHANDLE hJava, DWORD dwOptions)
+{
+    DWORD dwOrgOptions;
+    LPAPXJAVAVM lpJava;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return 0;
+    lpJava = APXHANDLE_DATA(hJava);
+    dwOrgOptions = lpJava->dwOptions;
+    lpJava->dwOptions = dwOptions;
+    return dwOrgOptions;
+}
+
+DWORD
+apxJavaWait(APXHANDLE hJava, DWORD dwMilliseconds, BOOL bKill)
+{
+    DWORD rv;
+    LPAPXJAVAVM lpJava;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return FALSE;
+    lpJava = APXHANDLE_DATA(hJava);
+
+    if (!lpJava->dwWorkerStatus && lpJava->hWorkerThread)
+        return WAIT_OBJECT_0;
+    rv = WaitForSingleObject(lpJava->hWorkerThread, dwMilliseconds);
+    if (rv == WAIT_TIMEOUT && bKill) {
+        __apxJavaJniCallback(hJava, WM_CLOSE, 0, 0);
+    }
+
+    return rv;
+}
+
+LPVOID
+apxJavaCreateClassV(APXHANDLE hJava, LPCSTR szClassName,
+                    LPCSTR szSignature, va_list lpArgs)
+{
+    LPAPXJAVAVM     lpJava;
+    jclass          clazz;
+    jmethodID       ccont;
+    jobject         cinst;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return NULL;
+    lpJava = APXHANDLE_DATA(hJava);
+    if (!__apxJvmAttach(lpJava))
+        return NULL;
+
+    clazz = JNICALL_1(FindClass, szClassName);
+    if (clazz == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not FindClass %s", szClassName);
+        return NULL;
+    }
+
+    ccont = JNICALL_3(GetMethodID, clazz, "<init>", szSignature);
+    if (ccont == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not find Constructor %s for %s",
+                    szSignature, szClassName);
+        return NULL;
+    }
+
+    cinst = JNICALL_3(NewObjectV, clazz, ccont, lpArgs);
+    if (cinst == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not create instance of %s",
+                    szClassName);
+        return NULL;
+    }
+
+    return cinst;
+}
+
+LPVOID
+apxJavaCreateClass(APXHANDLE hJava, LPCSTR szClassName,
+                   LPCSTR szSignature, ...)
+{
+    LPVOID rv;
+    va_list args;
+
+    va_start(args, szSignature);
+    rv = apxJavaCreateClassV(hJava, szClassName, szSignature, args);
+    va_end(args);
+
+    return rv;
+}
+
+LPVOID
+apxJavaCreateStringA(APXHANDLE hJava, LPCSTR szString)
+{
+    LPAPXJAVAVM     lpJava;
+    jstring str;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return NULL;
+    lpJava = APXHANDLE_DATA(hJava);
+
+    str = JNICALL_1(NewStringUTF, szString);
+    if (str == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not create string for %s",
+                    szString);
+        return NULL;
+    }
+
+    return str;
+}
+
+LPVOID
+apxJavaCreateStringW(APXHANDLE hJava, LPCWSTR szString)
+{
+    LPAPXJAVAVM     lpJava;
+    jstring str;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return NULL;
+    lpJava = APXHANDLE_DATA(hJava);
+
+    str = JNICALL_2(NewString, szString, lstrlenW(szString));
+    if (str == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not create string for %S",
+                    szString);
+        return NULL;
+    }
+
+    return str;
+}
+
+jvalue
+apxJavaCallStaticMethodV(APXHANDLE hJava, jclass lpClass, LPCSTR szMethodName,
+                         LPCSTR szSignature, va_list lpArgs)
+{
+    LPAPXJAVAVM     lpJava;
+    jmethodID       method;
+    jvalue          rv;
+    LPCSTR          s = szSignature;
+    rv.l = 0;
+    if (hJava->dwType != APXHANDLE_TYPE_JVM)
+        return rv;
+    lpJava = APXHANDLE_DATA(hJava);
+
+    while (*s && *s != ')')
+        ++s;
+    if (*s != ')') {
+        return rv;
+    }
+    else
+        ++s;
+    method = JNICALL_3(GetStaticMethodID, lpClass, szMethodName, szSignature);
+    if (method == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not find method %s with signature %s",
+                    szMethodName, szSignature);
+        return rv;
+    }
+    switch (*s) {
+        case 'V':
+            JNICALL_3(CallStaticVoidMethodV, lpClass, method, lpArgs);
+        break;
+        case 'L':
+        case '[':
+            rv.l = JNICALL_3(CallStaticObjectMethodV, lpClass, method, lpArgs);
+        break;
+        case 'Z':
+            rv.z = JNICALL_3(CallStaticBooleanMethodV, lpClass, method, lpArgs);
+        break;
+        case 'B':
+            rv.b = JNICALL_3(CallStaticByteMethodV, lpClass, method, lpArgs);
+        break;
+        case 'C':
+            rv.c = JNICALL_3(CallStaticCharMethodV, lpClass, method, lpArgs);
+        break;
+        case 'S':
+            rv.i = JNICALL_3(CallStaticShortMethodV, lpClass, method, lpArgs);
+        break;
+        case 'I':
+            rv.i = JNICALL_3(CallStaticIntMethodV, lpClass, method, lpArgs);
+        break;
+        case 'J':
+            rv.j = JNICALL_3(CallStaticLongMethodV, lpClass, method, lpArgs);
+        break;
+        case 'F':
+            rv.f = JNICALL_3(CallStaticFloatMethodV, lpClass, method, lpArgs);
+        break;
+        case 'D':
+            rv.d = JNICALL_3(CallStaticDoubleMethodV, lpClass, method, lpArgs);
+        break;
+        default:
+            apxLogWrite(APXLOG_MARK_ERROR "Invalid signature %s for method %s",
+                        szSignature, szMethodName);
+            return rv;
+        break;
+    }
+
+    return rv;
+}
+
+jvalue
+apxJavaCallStaticMethod(APXHANDLE hJava, jclass lpClass, LPCSTR szMethodName,
+                        LPCSTR szSignature, ...)
+{
+    jvalue rv;
+    va_list args;
+
+    va_start(args, szSignature);
+    rv = apxJavaCallStaticMethodV(hJava, lpClass, szMethodName, szSignature, args);
+    va_end(args);
+
+    return rv;
+}
+
+/* Call the Java:
+ * System.setOut(new PrintStream(new FileOutputStream(filename)));
+ */
+BOOL
+apxJavaSetOut(APXHANDLE hJava, BOOL setErrorOrOut, LPCWSTR szFilename)
+{
+    LPAPXJAVAVM lpJava;
+    jobject     fs;
+    jobject     ps;
+    jstring     fn;
+    jclass      sys;
+
+    if (hJava->dwType != APXHANDLE_TYPE_JVM || !szFilename)
+        return FALSE;
+    lpJava = APXHANDLE_DATA(hJava);
+    if (!__apxJvmAttach(lpJava))
+        return FALSE;
+
+    if ((fn = apxJavaCreateStringW(hJava, szFilename)) == NULL)
+        return FALSE;
+    if ((fs = apxJavaCreateClass(hJava, "java/io/FileOutputStream",
+                                 "(Ljava/lang/String;Z)V", fn, JNI_TRUE)) == NULL)
+        return FALSE;
+    if ((ps = apxJavaCreateClass(hJava, "java/io/PrintStream",
+                                 "(Ljava/io/OutputStream;)V", fs)) == NULL)
+        return FALSE;
+    sys = JNICALL_1(FindClass, "java/lang/System");
+    if (sys == NULL || (JVM_EXCEPTION_CHECK(lpJava))) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Could not FindClass java/lang/System");
+        return FALSE;
+    }
+
+    if (setErrorOrOut)
+        apxJavaCallStaticMethod(hJava, sys, "setErr", "(Ljava/io/PrintStream;)V", ps);
+    else
+        apxJavaCallStaticMethod(hJava, sys, "setOut", "(Ljava/io/PrintStream;)V", ps);
+
+    if (JVM_EXCEPTION_CHECK(lpJava)) {
+        JVM_EXCEPTION_CLEAR(lpJava);
+        apxLogWrite(APXLOG_MARK_ERROR "Error calling set method for java/lang/System");
+        return FALSE;
+    }
+    else
+        return TRUE;
+
+}
+
+DWORD apxGetVmExitCode(void) {
+    return vmExitCode;
+}
+
+void apxSetVmExitCode(DWORD exitCode) {
+    vmExitCode = exitCode;
+    return;
+}
+
+void
+apxJavaDumpAllStacks(APXHANDLE hJava)
+{
+    BOOL bAttached;
+    LPAPXJAVAVM lpJava;
+    JNIEnv *lpEnv = NULL;
+
+    if (DYNLOAD_FPTR(JVM_DumpAllStacks) == NULL ||
+        hJava == NULL ||
+        hJava->dwType != APXHANDLE_TYPE_JVM)
+        return;
+    lpJava = APXHANDLE_DATA(hJava);
+    if (__apxJvmAttachEnv(lpJava, &lpEnv, &bAttached)) {
+        DYNLOAD_FPTR(JVM_DumpAllStacks)(lpEnv, NULL);
+        if (bAttached)
+            (*(lpJava->lpJvm))->DetachCurrentThread(lpJava->lpJvm);
+    }
+}

Added: tomee/deps/branches/commons-daemon/src/native/windows/src/log.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/windows/src/log.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/windows/src/log.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/windows/src/log.c Tue May 28 09:46:53 2019
@@ -0,0 +1,506 @@
+/* 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"
+#include <stdio.h>
+
+#define LINE_SEP    "\r\n"
+#define LOGF_EXT    L".%04d-%02d-%02d.log"
+#define LOGF_EXR    L".%04d-%02d-%02d.%02d%02d%02d.log"
+
+static LPCSTR _log_level[] = {
+    "[debug] ",
+    "[info]  ",
+    "[warn]  ",
+    "[error] ",
+    NULL
+};
+
+typedef struct apx_logfile_st {
+    HANDLE      hFile;
+    DWORD       dwLogLevel;
+    DWORD       dwRotate;
+    SYSTEMTIME  sysTime;
+    WCHAR       szPath[SIZ_PATHLEN];
+    WCHAR       szPrefix[MAX_PATH];
+    WCHAR       szFile[MAX_PATH];
+} apx_logfile_st;
+
+/* Per-application master log file */
+static apx_logfile_st   *_st_sys_loghandle = NULL;
+static CRITICAL_SECTION  _st_sys_loglock;
+static CRITICAL_SECTION *_pt_sys_loglock = NULL;
+static apx_logfile_st    _st_sys_errhandle = { NULL, APXLOG_LEVEL_WARN, FALSE};
+
+static void logRotate(apx_logfile_st *lf, LPSYSTEMTIME t)
+{
+    WCHAR sName[SIZ_PATHLEN];
+    ULARGE_INTEGER cft;
+    ULARGE_INTEGER lft;
+    HANDLE h;
+
+    if (lf->dwRotate == 0)
+        return;
+
+    SystemTimeToFileTime(&lf->sysTime, (LPFILETIME)&lft);
+    SystemTimeToFileTime(t, (LPFILETIME)&cft);
+    if (cft.QuadPart < (lft.QuadPart + lf->dwRotate * 10000000ULL))
+        return;
+    /* Rotate time */
+    lf->sysTime = *t;
+    if (lf->dwRotate < 86400)
+        wsprintfW(sName, L"\\%s"  LOGF_EXR,
+                  lf->szPrefix,
+                  lf->sysTime.wYear,
+                  lf->sysTime.wMonth,
+                  lf->sysTime.wDay,
+                  lf->sysTime.wHour,
+                  lf->sysTime.wMinute,
+                  lf->sysTime.wSecond);
+    else
+        wsprintfW(sName, L"\\%s"  LOGF_EXT,
+                  lf->szPrefix,
+                  lf->sysTime.wYear,
+                  lf->sysTime.wMonth,
+                  lf->sysTime.wDay);
+    lstrlcpyW(lf->szFile, MAX_PATH, lf->szPath);
+    lstrlcatW(lf->szFile, MAX_PATH, sName);
+    h =  CreateFileW(lf->szFile,
+                     GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL,
+                     OPEN_ALWAYS,
+                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_SEQUENTIAL_SCAN,
+                     NULL);
+    if (h == INVALID_HANDLE_VALUE) {
+        /* TODO: Log something */
+        return;
+    }
+    /* Make sure we relock the correct file */
+    APX_LOGLOCK(h);
+    APX_LOGUNLOCK(lf->hFile);
+    /* Close original handle */
+    CloseHandle(lf->hFile);
+    lf->hFile = h;
+}
+
+LPWSTR apxLogFile(
+    APXHANDLE hPool,
+    LPCWSTR szPath,
+    LPCWSTR szPrefix,
+    LPCWSTR szName,
+    BOOL bTimeStamp,
+    DWORD dwRotate)
+{
+    LPWSTR sRet;
+    WCHAR sPath[SIZ_PATHLEN];
+    WCHAR sName[SIZ_PATHLEN];
+    SYSTEMTIME sysTime;
+
+    GetLocalTime(&sysTime);
+    if (!szPath) {
+        if (GetSystemDirectoryW(sPath, MAX_PATH) == 0)
+            return INVALID_HANDLE_VALUE;
+        lstrlcatW(sPath, MAX_PATH, L"\\LogFiles\\Apache");
+    }
+    else {
+        lstrlcpyW(sPath, MAX_PATH, szPath);
+    }
+    if (!szPrefix)
+        szPrefix = L"";
+    if (!szName)
+        szName   = L"";
+    if (bTimeStamp) {
+        if (dwRotate != 0 && dwRotate < 86400)
+            wsprintfW(sName,
+                  L"\\%s%s" LOGF_EXR,
+                  szPrefix,
+                  szName,
+                  sysTime.wYear,
+                  sysTime.wMonth,
+                  sysTime.wDay,
+                  0,
+                  0,
+                  0);
+        else
+            wsprintfW(sName,
+                      L"\\%s%s" LOGF_EXT,
+                      szPrefix,
+                      szName,
+                      sysTime.wYear,
+                      sysTime.wMonth,
+                      sysTime.wDay);
+    }
+    else {
+        wsprintfW(sName,
+                  L"\\%s%s",
+                  szPrefix,
+                  szName);
+    }
+    sRet = apxPoolAlloc(hPool, (SIZ_PATHLEN) * sizeof(WCHAR));
+    /* Set default level to info */
+    CreateDirectoryW(sPath, NULL);
+
+    lstrlcpyW(sRet, SIZ_PATHMAX, sPath);
+    lstrlcatW(sRet, SIZ_PATHMAX, sName);
+
+    return sRet;
+}
+
+/* Open the log file
+ * TODO: format like standard apache error.log
+ * Add the EventLogger
+ */
+HANDLE apxLogOpen(
+    APXHANDLE hPool,
+    LPCWSTR szPath,
+    LPCWSTR szPrefix,
+    DWORD dwRotate)
+{
+
+    WCHAR sPath[SIZ_PATHLEN];
+    WCHAR sName[SIZ_PATHLEN];
+    SYSTEMTIME sysTime;
+    apx_logfile_st *h;
+
+    if (_pt_sys_loglock == NULL) {
+        InitializeCriticalSection(&_st_sys_loglock);
+        _pt_sys_loglock = &_st_sys_loglock;
+    }
+    GetLocalTime(&sysTime);
+    if (!szPath) {
+        if (GetSystemDirectoryW(sPath, MAX_PATH) == 0)
+            return INVALID_HANDLE_VALUE;
+        lstrlcatW(sPath, MAX_PATH, L"\\LogFiles");
+        if (!CreateDirectoryW(sPath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
+            if (!CreateDirectoryW(sPath, NULL))
+                return INVALID_HANDLE_VALUE;
+        }
+        lstrlcatW(sPath, MAX_PATH, L"\\Apache");
+        if (!CreateDirectoryW(sPath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
+            if (!CreateDirectoryW(sPath, NULL))
+                return INVALID_HANDLE_VALUE;
+        }
+    }
+    else {
+        lstrlcpyW(sPath, MAX_PATH, szPath);
+    }
+    if (!szPrefix)
+        szPrefix = L"commons-daemon";
+    if (dwRotate != 0 && dwRotate < 86400)
+        wsprintfW(sName, L"\\%s"  LOGF_EXR,
+                  szPrefix,
+                  sysTime.wYear,
+                  sysTime.wMonth,
+                  sysTime.wDay,
+                  0,
+                  0,
+                  0);
+    else
+        wsprintfW(sName, L"\\%s"  LOGF_EXT,
+                  szPrefix,
+                  sysTime.wYear,
+                  sysTime.wMonth,
+                  sysTime.wDay);
+    if (!(h = (apx_logfile_st *)apxPoolCalloc(hPool, sizeof(apx_logfile_st))))
+        return INVALID_HANDLE_VALUE;
+    /* Set default level to info */
+    h->dwLogLevel = APXLOG_LEVEL_INFO;
+    CreateDirectoryW(sPath, NULL);
+
+    h->sysTime = sysTime;
+    lstrlcpyW(h->szPath, MAX_PATH, sPath);
+    lstrlcpyW(h->szFile, MAX_PATH, sPath);
+    lstrlcatW(h->szFile, MAX_PATH, sName);
+    lstrlcpyW(h->szPrefix, MAX_PATH, szPrefix);
+
+    h->hFile =  CreateFileW(h->szFile,
+                      GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                      NULL,
+                      OPEN_ALWAYS,
+                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_SEQUENTIAL_SCAN,
+                      NULL);
+    if (h->hFile == INVALID_HANDLE_VALUE) {
+        /* Make sure we write somewhere */
+        h = &_st_sys_errhandle;
+        apxDisplayError(FALSE, NULL, 0,
+                        "Unable to create logger at '%S'\n", h->szFile);
+        return (HANDLE)h;
+    }
+    else {
+        h->dwRotate = dwRotate;
+    }
+    /* Set this file as system log file */
+    if (!_st_sys_loghandle)
+        _st_sys_loghandle = h;
+
+    return (HANDLE)h;
+}
+
+void apxLogLevelSet(HANDLE hFile, DWORD dwLevel)
+{
+    apx_logfile_st *lf = (apx_logfile_st *)hFile;
+    if (IS_INVALID_HANDLE(lf))
+        lf = _st_sys_loghandle;
+    if (IS_INVALID_HANDLE(lf))
+        return;
+    if (dwLevel < 4)
+        lf->dwLogLevel = dwLevel;
+}
+
+void apxLogLevelSetW(HANDLE  hFile,
+                     LPCWSTR szLevel)
+{
+    apx_logfile_st *lf = (apx_logfile_st *)hFile;
+
+    if (IS_INVALID_HANDLE(lf))
+        lf = _st_sys_loghandle;
+    if (IS_INVALID_HANDLE(lf))
+        return;
+    if (szLevel) {
+        if (!lstrcmpiW(szLevel, L"error"))
+            lf->dwLogLevel = APXLOG_LEVEL_ERROR;
+        else if (!lstrcmpiW(szLevel, L"warn"))
+            lf->dwLogLevel = APXLOG_LEVEL_WARN;
+        else if (!lstrcmpiW(szLevel, L"info"))
+            lf->dwLogLevel = APXLOG_LEVEL_INFO;
+        else if (!lstrcmpiW(szLevel, L"debug"))
+            lf->dwLogLevel = APXLOG_LEVEL_DEBUG;
+    }
+}
+
+int
+apxLogWrite(
+    HANDLE  hFile,
+    DWORD   dwLevel,
+    BOOL    bTimeStamp,
+    LPCSTR  szFile,
+    DWORD   dwLine,
+    LPCSTR  szFormat,
+    ...)
+{
+    va_list args;
+    CHAR    buffer[1024+32] = "";
+    LPSTR   szBp;
+    int     len = 0;
+    LPCSTR  f = szFile;
+    CHAR    sb[SIZ_PATHLEN];
+    DWORD   wr;
+    DWORD   err;
+    BOOL    dolock = TRUE;
+    apx_logfile_st *lf = (apx_logfile_st *)hFile;
+
+    err = GetLastError(); /* save the last Error code */
+    if (IS_INVALID_HANDLE(lf))
+        lf = _st_sys_loghandle;
+    if (IS_INVALID_HANDLE(lf)) {
+        lf = &_st_sys_errhandle;
+        lf->hFile = GetStdHandle(STD_ERROR_HANDLE);
+    }
+    if (lf == &_st_sys_errhandle) {
+        /* Do not rotate if redirected to console */
+        dolock = FALSE;
+    }
+    if (dwLevel < lf->dwLogLevel)
+        return 0;
+    APX_LOGENTER();
+    if (f && (lf->dwLogLevel == APXLOG_LEVEL_DEBUG || dwLevel == APXLOG_LEVEL_ERROR)) {
+        f = (szFile + lstrlenA(szFile) - 1);
+        while(f != szFile && '\\' != *f && '/' != *f)
+            f--;
+        if(f != szFile)
+            f++;
+    }
+    else
+        f = NULL;
+    szBp = buffer;
+    if (!szFormat) {
+        if (err == 0) {
+            lstrcpyA(szBp, "Unknown error code");
+            if (dwLevel == APXLOG_LEVEL_ERROR) {
+                szBp += 18;
+                wsprintfA(szBp, " occured in (%s:%d) ", f, dwLine);
+            }
+        }
+        else
+            FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+                           FORMAT_MESSAGE_IGNORE_INSERTS,
+                           NULL,
+                           err,
+                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                           szBp,
+                           1000,
+                           NULL);
+    }
+    else {
+        va_start(args, szFormat);
+        wvsprintfA(szBp, szFormat, args);
+        va_end(args);
+    }
+    len = lstrlenA(buffer);
+    if (len > 0) {
+        /* Remove trailing line separator */
+        if (buffer[len - 1] == '\n')
+            buffer[--len] = '\0';
+        if (len > 0 && buffer[len - 1] == '\r')
+            buffer[--len] = '\0';
+        if (!IS_INVALID_HANDLE(lf->hFile)) {
+            SYSTEMTIME t;
+            /* Append operation */
+            SetFilePointer(lf->hFile, 0, &wr, FILE_END);
+            GetLocalTime(&t);
+            if (dolock) {
+                APX_LOGLOCK(lf->hFile);
+                logRotate(lf, &t);
+            }
+            if (bTimeStamp) {
+                wsprintfA(sb, "[%d-%02d-%02d %02d:%02d:%02d] ",
+                          t.wYear, t.wMonth, t.wDay,
+                          t.wHour, t.wMinute, t.wSecond);
+                WriteFile(lf->hFile, sb, lstrlenA(sb), &wr, NULL);
+            }
+            WriteFile(lf->hFile, _log_level[dwLevel],
+                      lstrlenA(_log_level[dwLevel]), &wr, NULL);
+            if (f && lf->dwLogLevel == APXLOG_LEVEL_DEBUG) {
+                wsprintfA(sb, "(%10s:%-4d) ", f, dwLine);
+                WriteFile(lf->hFile, sb, lstrlenA(sb), &wr, NULL);
+            }
+
+            /* add thread ID to log output */
+            wsprintfA(sb, "[%5d] ", GetCurrentThreadId());
+            WriteFile(lf->hFile, sb, lstrlenA(sb), &wr, NULL);
+
+            if (len)
+                WriteFile(lf->hFile, buffer, len, &wr, NULL);
+
+            /* Terminate the line */
+            WriteFile(lf->hFile, LINE_SEP, sizeof(LINE_SEP) - 1, &wr, NULL);
+            if (dwLevel)
+                FlushFileBuffers(lf->hFile);
+            if (dolock) {
+                APX_LOGUNLOCK(lf->hFile);
+            }
+        }
+#ifdef _DEBUG_FULL
+        {
+            char tid[1024 + 16];
+            wsprintfA(tid, "[%04d] %s", GetCurrentThreadId(), buffer);
+            OutputDebugStringA(tid);
+        }
+#endif
+    }
+    APX_LOGLEAVE();
+    /* Restore the last Error code */
+    SetLastError(err);
+    if (szFormat && err != 0 && dwLevel == APXLOG_LEVEL_ERROR) {
+        /* Print the System error description
+         */
+        apxLogWrite(hFile, dwLevel, bTimeStamp, szFile, dwLine, NULL);
+    }
+    return len;
+}
+
+void apxLogClose(
+    HANDLE hFile)
+{
+    apx_logfile_st *lf = (apx_logfile_st *)hFile;
+
+    if (IS_INVALID_HANDLE(lf))
+        lf = _st_sys_loghandle;
+    if (IS_INVALID_HANDLE(lf))
+        return;
+
+    FlushFileBuffers(lf->hFile);
+    CloseHandle(lf->hFile);
+    if (lf == _st_sys_loghandle)
+        _st_sys_loghandle = NULL;
+    apxFree(lf);
+}
+
+int
+apxDisplayError(
+    BOOL    bDisplay,
+    LPCSTR  szFile,
+    DWORD   dwLine,
+    LPCSTR  szFormat,
+    ...)
+{
+    va_list args;
+    CHAR    buffer[SIZ_HUGLEN];
+    CHAR    sysbuf[SIZ_HUGLEN];
+    int     len = 0, nRet;
+    LPCSTR  f = szFile;
+    DWORD   err = GetLastError(); /* save the last Error code */
+    if (f) {
+        f = (szFile + lstrlenA(szFile) - 1);
+        while(f != szFile && '\\' != *f && '/' != *f)
+            f--;
+        if(f != szFile)
+            f++;
+    }
+    else
+        f = "";
+    sysbuf[0] = '\0';
+    if (err != ERROR_SUCCESS) {
+        len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+                             FORMAT_MESSAGE_IGNORE_INSERTS,
+                             NULL,
+                             err,
+                             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                             sysbuf,
+                             SIZ_DESLEN,
+                             NULL);
+        sysbuf[len] = '\0';
+        if (len > 0) {
+            if (sysbuf[len - 1] == '\n')
+                sysbuf[--len] = '\0';
+            if (len > 0 && sysbuf[len - 1] == '\r')
+                sysbuf[--len] = '\0';
+        }
+    }
+    if (szFormat) {
+        va_start(args, szFormat);
+        wvsprintfA(buffer, szFormat, args);
+        va_end(args);
+        if (f && *f) {
+            CHAR sb[SIZ_PATHLEN];
+            wsprintfA(sb, "%s (%d)", f, dwLine);
+            lstrcatA(sysbuf, sb);
+        }
+        lstrlcatA(sysbuf, SIZ_HUGLEN, LINE_SEP);
+        lstrlcatA(sysbuf, SIZ_HUGLEN, buffer);
+    }
+    len = lstrlenA(sysbuf);
+#ifdef _DEBUG_FULL
+    OutputDebugStringA(sysbuf);
+#endif
+    if (len > 0) {
+        if (bDisplay) {
+            nRet = MessageBoxA(NULL, sysbuf,
+                               "Application System Error",
+                               MB_ICONERROR | MB_OK | MB_SYSTEMMODAL);
+        }
+        else {
+            fputs(sysbuf, stderr);
+            if (!szFormat)
+                fputs(LINE_SEP, stderr);
+            fflush(stderr);
+        }
+    }
+    /* Restore the last Error code */
+    SetLastError(err);
+    return len;
+}

Added: tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.c Tue May 28 09:46:53 2019
@@ -0,0 +1,406 @@
+/* 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.
+ */
+
+/*
+ * Copyright (c) 1994
+ *  The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Andrew Hume of AT&T Bell Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "apxwin.h"
+#include "private.h"
+
+typedef UINT    word;       /* "word" used for optimal copy speed */
+#define wsize   sizeof(UINT)
+#define wmask   (wsize - 1)
+
+LPVOID AplFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill)
+{
+
+    SIZE_T t;
+#ifdef WIN64
+    UINT64 c;
+#else
+    UINT   c;
+#endif
+    LPBYTE dst;
+
+    dst = Destination;
+    /*
+     * If not enough words, just fill bytes.  A length >= 2 words
+     * guarantees that at least one of them is `complete' after
+     * any necessary alignment.  For instance:
+     *
+     *  |-----------|-----------|-----------|
+     *  |00|01|02|03|04|05|06|07|08|09|0A|00|
+     *            ^---------------------^
+     *       dst         dst+length-1
+     *
+     * but we use a minimum of 3 here since the overhead of the code
+     * to do word writes is substantial.
+     */
+    if (Length < 3 * wsize) {
+        while (Length != 0) {
+            *dst++ = Fill;
+            --Length;
+        }
+        return (Destination);
+    }
+
+    if ((c = Fill) != 0) {  /* Fill the word. */
+        c = (c << 8) | c;   /* u_int is 16 bits. */
+        c = (c << 16) | c;  /* u_int is 32 bits. */
+#ifdef WIN64
+        c = (c << 32) | c;  /* u_int is 64 bits. */
+#endif
+    }
+    /* Align destination by filling in bytes. */
+    if ((t = (SIZE_T)dst & wmask) != 0) {
+        t = wsize - t;
+        Length -= t;
+        do {
+            *dst++ = Fill;
+        } while (--t != 0);
+    }
+
+    /* Fill words.  Length was >= 2*words so we know t >= 1 here. */
+    t = Length / wsize;
+    do {
+#ifdef WIN64
+        *(UINT64 *)dst = c;
+#else
+        *(UINT   *)dst = c;
+#endif
+        dst += wsize;
+    } while (--t != 0);
+
+    /* Mop up trailing bytes, if any. */
+    t = Length & wmask;
+    if (t != 0)
+        do {
+            *dst++ = Fill;
+        } while (--t != 0);
+    return (Destination);
+}
+
+void AplZeroMemory(PVOID Destination, SIZE_T Length)
+{
+
+    SIZE_T t;
+    LPBYTE dst;
+
+    dst = Destination;
+    /*
+     * If not enough words, just fill bytes.  A length >= 2 words
+     * guarantees that at least one of them is `complete' after
+     * any necessary alignment.  For instance:
+     *
+     *  |-----------|-----------|-----------|
+     *  |00|01|02|03|04|05|06|07|08|09|0A|00|
+     *            ^---------------------^
+     *       dst         dst+length-1
+     *
+     * but we use a minimum of 3 here since the overhead of the code
+     * to do word writes is substantial.
+     */
+    if (Length < 3 * wsize) {
+        while (Length != 0) {
+            *dst++ = 0;
+            --Length;
+        }
+        return;
+    }
+
+    /* Align destination by filling in bytes. */
+    if ((t = (SIZE_T)dst & wmask) != 0) {
+        t = wsize - t;
+        Length -= t;
+        do {
+            *dst++ = 0;
+        } while (--t != 0);
+    }
+
+    /* Fill words.  Length was >= 2*words so we know t >= 1 here. */
+    t = Length / wsize;
+    do {
+        *(UINT *)dst = 0;
+        dst += wsize;
+    } while (--t != 0);
+
+    /* Mop up trailing bytes, if any. */
+    t = Length & wmask;
+    if (t != 0)
+        do {
+            *dst++ = 0;
+        } while (--t != 0);
+}
+
+LPVOID AplCopyMemory(PVOID Destination, const VOID* Source, SIZE_T Length)
+{
+    char *dst = Destination;
+    const char *src = Source;
+    SIZE_T t;
+
+    if (Length == 0 || dst == src)      /* nothing to do */
+        goto done;
+
+    /*
+     * Macros: loop-t-times; and loop-t-times, t>0
+     */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+    if ((SIZE_T)dst < (SIZE_T)src) {
+        /*
+         * Copy forward.
+         */
+        t = (int)(SIZE_T)src;   /* only need low bits */
+        if ((t | (int)(SIZE_T)dst) & wmask) {
+            /*
+             * Try to align operands.  This cannot be done
+             * unless the low bits match.
+             */
+            if ((t ^ (int)(SIZE_T)dst) & wmask || Length < wsize)
+                t = Length;
+            else
+                t = wsize - (t & wmask);
+            Length -= t;
+            TLOOP1(*dst++ = *src++);
+        }
+        /*
+         * Copy whole words, then mop up any trailing bytes.
+         */
+        t = Length / wsize;
+        TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+        t = Length & wmask;
+        TLOOP(*dst++ = *src++);
+    } else {
+        /*
+         * Copy backwards.  Otherwise essentially the same.
+         * Alignment works as before, except that it takes
+         * (t&wmask) bytes to align, not wsize-(t&wmask).
+         */
+        src += Length;
+        dst += Length;
+        t = (int)(SIZE_T)src;
+        if ((t | (int)(SIZE_T)dst) & wmask) {
+            if ((t ^ (int)(SIZE_T)dst) & wmask || Length <= wsize)
+                t = Length;
+            else
+                t &= wmask;
+            Length -= t;
+            TLOOP1(*--dst = *--src);
+        }
+        t = Length / wsize;
+        TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+        t = Length & wmask;
+        TLOOP(*--dst = *--src);
+    }
+done:
+    return (Destination);
+}
+
+
+INT
+AplMemCmp(LPCVOID lpA, LPCVOID lpB, SIZE_T nBytes)
+{
+    if (nBytes != 0) {
+        const BYTE *p1 = lpA, *p2 = lpB;
+
+        do {
+            if (*p1++ != *p2++)
+                return (*--p1 - *--p2);
+        } while (--nBytes != 0);
+    }
+    return 0;
+}
+
+/*
+ * Find the first occurrence of lpFind in lpMem.
+ * dwLen:   The length of lpFind
+ * dwSize:  The length of lpMem
+ */
+LPBYTE
+ApcMemSearch(LPCVOID lpMem, LPCVOID lpFind, SIZE_T dwLen, SIZE_T dwSize)
+{
+    BYTE   c, sc;
+    SIZE_T cnt = 0;
+    const BYTE *s = lpMem, *find = lpFind;
+
+    if ((c = *find++) != 0) {
+        do {
+            do {
+                sc = *s++;
+                if (cnt++ > dwSize)
+                    return NULL;
+            } while (sc != c);
+        } while (AplMemCmp(s, find, dwLen - 1) != 0);
+        s--;
+    }
+    return (LPBYTE)s;
+}
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+LPSTR
+lstrlcatA(LPSTR dst, int siz, LPCSTR src)
+{
+    LPSTR  d = dst;
+    LPCSTR s = src;
+    int n = siz;
+    int dlen;
+
+    /* Find the end of dst and adjust bytes left but don't go past end */
+    while (n-- != 0 && *d != '\0')
+        d++;
+    dlen = (int)(d - dst);
+    n = siz - dlen;
+
+    if (n == 0)
+        return NULL;
+    while (*s != '\0') {
+        if (n != 1) {
+            *d++ = *s;
+            n--;
+        }
+        s++;
+    }
+    *d = '\0';
+
+    return dst;
+}
+
+LPWSTR
+lstrlcatW(LPWSTR dst, int siz, LPCWSTR src)
+{
+    LPWSTR  d = dst;
+    LPCWSTR s = src;
+    int n = siz;
+    int dlen;
+
+    /* Find the end of dst and adjust bytes left but don't go past end */
+    while (n-- != 0 && *d != '\0')
+        d++;
+    dlen = (int)(d - dst);
+    n = siz - dlen;
+
+    if (n == 0)
+        return NULL;
+    while (*s != L'\0') {
+        if (n != 1) {
+            *d++ = *s;
+            n--;
+        }
+        s++;
+    }
+    *d = L'\0';
+
+    return dst;
+}
+
+LPSTR
+lstrlcpyA(LPSTR dst, int siz, LPCSTR src)
+{
+    LPSTR  d = dst;
+    LPCSTR s = src;
+    int    n = siz;
+
+    /* Copy as many bytes as will fit */
+    if (n != 0) {
+        while (--n != 0) {
+            if ((*d++ = *s++) == '\0')
+                break;
+        }
+    }
+
+    /* Not enough room in dst, add NUL and traverse rest of src */
+    if (n == 0) {
+        if (siz != 0)
+            *d = '\0';      /* NUL-terminate dst */
+        while (*s++)
+            ;
+    }
+
+    return d;
+}
+
+LPWSTR
+lstrlcpyW(LPWSTR dst, int siz, LPCWSTR src)
+{
+    LPWSTR  d = dst;
+    LPCWSTR s = src;
+    int    n = siz;
+
+    /* Copy as many bytes as will fit */
+    if (n != 0) {
+        while (--n != 0) {
+            if ((*d++ = *s++) == L'\0')
+                break;
+        }
+    }
+
+    /* Not enough room in dst, add NUL and traverse rest of src */
+    if (n == 0) {
+        if (siz != 0)
+            *d = L'\0';      /* NUL-terminate dst */
+        while (*s++)
+            ;
+    }
+
+    return d;
+}
+
+LPWSTR
+lstrlocaseW(LPWSTR str)
+{
+    LPWSTR  p = str;
+    while (p && *p != 0) {
+        *p = towlower(*p);
+        p++;
+    }
+    return str;
+}

Added: tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/windows/src/mclib.h Tue May 28 09:46:53 2019
@@ -0,0 +1,27 @@
+/* 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.
+ */
+
+#ifndef _MCLIB_H_INCLUDED_
+#define _MCLIB_H_INCLUDED_
+
+#ifndef  MIN
+#define  MIN(a,b)    (((a)<(b)) ? (a) : (b))
+#endif
+#ifndef  MAX
+#define  MAX(a,b)    (((a)>(b)) ? (a) : (b))
+#endif
+
+#endif /* _MCLIB_H_INCLUDED_ */

Added: tomee/deps/branches/commons-daemon/src/native/windows/src/private.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/windows/src/private.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/windows/src/private.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/windows/src/private.h Tue May 28 09:46:53 2019
@@ -0,0 +1,262 @@
+/* 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.
+ */
+ 
+#ifndef _PRIVATE_H_INCLUDED_
+#define _PRIVATE_H_INCLUDED_
+
+#include "mclib.h"
+
+#ifdef _DEBUG
+
+HANDLE  HeapCREATE(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);
+BOOL    HeapDESTROY(HANDLE hHeap);
+
+LPVOID  HeapALLOC(HANDLE hHeap, DWORD dwFlags, SIZE_T nSize);
+BOOL    HeapFREE(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
+LPVOID  HeapREALLOC(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes);
+
+#else
+
+#define HeapCREATE  HeapCreate
+#define HeapDESTROY HeapDestroy
+#define HeapALLOC   HeapAlloc
+#define HeapFREE    HeapFree
+#define HeapREALLOC HeapReAlloc
+
+#endif
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type)                                          \
+struct name {                                                           \
+        struct type *tqh_first; /* first element */                     \
+        struct type **tqh_last; /* addr of last next element */         \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head)                                    \
+        { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type)                                               \
+struct {                                                                \
+        struct type *tqe_next;  /* next element */                      \
+        struct type **tqe_prev; /* address of previous next element */  \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_CONCAT(head1, head2, field) do {                          \
+        if (!TAILQ_EMPTY(head2)) {                                      \
+                *(head1)->tqh_last = (head2)->tqh_first;                \
+                (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+                (head1)->tqh_last = (head2)->tqh_last;                  \
+                TAILQ_INIT((head2));                                    \
+        }                                                               \
+} while (0)
+
+#define TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head)       ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field)                                 \
+        for ((var) = TAILQ_FIRST((head));                               \
+            (var);                                                      \
+            (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+        for ((var) = TAILQ_LAST((head), headname);                      \
+            (var);                                                      \
+            (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_INIT(head) do {                                           \
+        TAILQ_FIRST((head)) = NULL;                                     \
+        (head)->tqh_last = &TAILQ_FIRST((head));                        \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+        if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+                TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                    &TAILQ_NEXT((elm), field);                          \
+        else {                                                          \
+                (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+        }                                                               \
+        TAILQ_NEXT((listelm), field) = (elm);                           \
+        (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);          \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+        TAILQ_NEXT((elm), field) = (listelm);                           \
+        *(listelm)->field.tqe_prev = (elm);                             \
+        (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);          \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+        if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   \
+                TAILQ_FIRST((head))->field.tqe_prev =                   \
+                    &TAILQ_NEXT((elm), field);                          \
+        else                                                            \
+                (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+        TAILQ_FIRST((head)) = (elm);                                    \
+        (elm)->field.tqe_prev = &TAILQ_FIRST((head));                   \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+        TAILQ_NEXT((elm), field) = NULL;                                \
+        (elm)->field.tqe_prev = (head)->tqh_last;                       \
+        *(head)->tqh_last = (elm);                                      \
+        (head)->tqh_last = &TAILQ_NEXT((elm), field);                   \
+} while (0)
+
+#define TAILQ_LAST(head, headname)                                      \
+        (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field)                                \
+        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do {                             \
+        if ((TAILQ_NEXT((elm), field)) != NULL)                         \
+                TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                    (elm)->field.tqe_prev;                              \
+        else {                                                          \
+                (head)->tqh_last = (elm)->field.tqe_prev;               \
+        }                                                               \
+        *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);              \
+} while (0)
+  
+/** Some usefull macros */
+
+#define APXHANDLE_SPINLOCK(h)               \
+    APXMACRO_BEGIN                          \
+    while (InterlockedCompareExchange(&((h)->lvSpin), 1, 0) != 0) { \
+        Sleep(10);                          \
+        SwitchToThread();                   \
+    }                                       \
+    APXMACRO_END
+
+#define APXHANDLE_SPINUNLOCK(h)             \
+    APXMACRO_BEGIN                          \
+    InterlockedExchange(&((h)->lvSpin), 0); \
+    APXMACRO_END
+
+#define APX_SPINLOCK(lock)                  \
+    APXMACRO_BEGIN                          \
+    while (InterlockedCompareExchange(&(lock), 1, 0) != 0) \
+        SwitchToThread();                   \
+    APXMACRO_END
+
+#define APX_SPINUNLOCK(lock)                \
+    APXMACRO_BEGIN                          \
+    InterlockedExchange(&(lock), 0);        \
+    APXMACRO_END
+
+/*
+ * Define a union with types which are likely to have the longest
+ * *relevant* CPU-specific memory word alignment restrictions...
+ */ 
+typedef union APXMEMWORD {
+    void  *vp;
+    void (*fp)(void);
+    char  *cp;
+    long   l;
+    double d;
+} APXMEMWORD;
+
+typedef struct APXCALLHOOK APXCALLHOOK;
+
+struct APXCALLHOOK {
+
+    LPAPXFNCALLBACK     fnCallback;
+    TAILQ_ENTRY(APXCALLHOOK)  queue;
+};
+
+struct stAPXHANDLE {
+    /** The type of the handle */ 
+    DWORD               dwType;         
+    /** Handle Flags */ 
+    DWORD               dwFlags;
+    /** Handle user data size */ 
+    DWORD               dwSize;
+    /** parameters for event callback */ 
+    WPARAM              wParam;
+    LPARAM              lParam;
+    UINT                uMsg;
+    /** main callback function (using default if not specified) */ 
+    LPAPXFNCALLBACK     fnCallback;
+    /** callback functions hook list */
+    TAILQ_HEAD(_lCallbacks, APXCALLHOOK) lCallbacks;
+    /** allocation pool  */
+    APXHANDLE           hPool;
+    /** interlocking value */ 
+    LONG volatile       lvSpin;
+
+    /** message event handle  */ 
+    HANDLE              hEventHandle;
+    /** message event thread  */ 
+    HANDLE              hEventThread;
+    /** message event thread id  */ 
+    DWORD               hEventThreadId;
+    /** private local heap */
+    HANDLE              hHeap;
+    /** list enty for pool  */ 
+    TAILQ_ENTRY(stAPXHANDLE)  queue;
+    /** small userdata pointer  */ 
+    union   {
+        LPVOID          lpPtr;
+        HANDLE          hWinHandle;
+        double          dValue;
+        void            (*fpValue)();
+    } uData;
+
+    APXMEMWORD          stAlign;
+};
+
+#define APXHANDLE_DATA(h)       ((void *)((char*)(h) + sizeof(stAPXHANDLE)))
+#define APXHANDLE_SZ            sizeof(stAPXHANDLE)
+
+/* zero separated, double zero terminated string */
+struct APXMULTISZ {
+    DWORD   dwAllocated;  /* length including terminators */
+    DWORD   dwInsert;     /* next insert position */
+};
+
+typedef struct APXREGENUM {
+    HKEY     hServicesKey;
+    DWORD    dwIndex;                   /* current enum index           */
+    DWORD    cSubKeys;                  /* number of subkeys            */
+    DWORD    cbMaxSubKey;               /* longest subkey size          */
+    DWORD    cchMaxClass;               /* longest class string         */
+    DWORD    cValues;                   /* number of values for key     */
+    DWORD    cchMaxValue;               /* longest value name           */
+    DWORD    cbMaxValueData;            /* longest value data           */
+
+} APXREGENUM, *LPAPXREGENUM;
+
+BOOL    apxRegistryEnumServices(LPAPXREGENUM lpEnum, LPAPXSERVENTRY lpEntry);
+BOOL    apxGetServiceDescriptionW(LPCWSTR szServiceName, LPWSTR szDescription,
+                                  DWORD dwDescriptionLength);
+BOOL    apxGetServiceUserW(LPCWSTR szServiceName, LPWSTR szUser,
+                           DWORD dwUserLength);
+
+DWORD   __apxGetMultiSzLengthA(LPCSTR lpStr, LPDWORD lpdwCount);
+DWORD   __apxGetMultiSzLengthW(LPCWSTR lpStr, LPDWORD lpdwCount);
+LPSTR   __apxGetEnvironmentVariableA(APXHANDLE hPool, LPCSTR szName);
+LPWSTR  __apxGetEnvironmentVariableW(APXHANDLE hPool, LPCWSTR wsName);
+
+#endif /* _PRIVATE_H_INCLUDED_ */