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_ */