Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Inglis2002-09-03 12:16:20 -0400
committerDavid Inglis2002-09-03 12:16:20 -0400
commit25863f8649290d33e14f1d3c10a22be8f2bc7ff5 (patch)
tree6c1d79e068f5dc092a1d9ae22c0bbc9be3c07bcd /core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c
parent484862d9105b974fcfb745ded4821ba691e50cac (diff)
downloadorg.eclipse.cdt-25863f8649290d33e14f1d3c10a22be8f2bc7ff5.tar.gz
org.eclipse.cdt-25863f8649290d33e14f1d3c10a22be8f2bc7ff5.tar.xz
org.eclipse.cdt-25863f8649290d33e14f1d3c10a22be8f2bc7ff5.zip
windows spawner
Diffstat (limited to 'core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c')
-rw-r--r--core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c744
1 files changed, 744 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c b/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c
new file mode 100644
index 00000000000..7c8b1f04203
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c
@@ -0,0 +1,744 @@
+/* Copyright, 2002, QNX Software Systems Ltd. All Rights Reserved
+
+ * This source code has been published by QNX Software Systems
+ * Ltd. (QSSL). However, any use, reproduction, modification, distribution
+ * or transfer of this software, or any software which includes or is based
+ * upon any of this code, is only permitted if expressly authorized by a
+ * written license agreement from QSSL. Contact the QNX Developer's Network
+ * or contact QSSL's legal department for more information.
+ *
+ *
+ * Win32ProcessEx.c
+ *
+ * This is a JNI implementation of spawner
+ */
+#include "stdafx.h"
+#include <string.h>
+#include <stdlib.h>
+#include <process.h>
+#include "Spawner.h"
+
+
+#include "jni.h"
+#include "io.h"
+
+
+#define PIPE_SIZE 512
+#define MAX_CMD_SIZE 1024
+#define MAX_ENV_SIZE 4096
+
+#define MAX_PROCS (100)
+
+typedef JNIEXPORT void * (JNICALL * JVM_GetThreadInterruptEvent)();
+typedef JNIEXPORT char * (JNICALL * JVM_NativePath)(const char *);
+
+typedef struct _procInfo {
+ int pid; // Process ID
+ int uid; // quasi-unique process ID
+ HANDLE eventBreak;
+ HANDLE eventWait;
+ HANDLE eventTerminate;
+} procInfo_t, * pProcInfo_t;
+
+static int procCounter = 0;
+
+
+JNIEXPORT void * JNICALL GetJVMProc(char * vmlib, char * procName);
+JNIEXPORT void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
+pProcInfo_t createProcInfo();
+pProcInfo_t findProcInfo(int pid);
+unsigned int _stdcall waitProcTermination(void* pv) ;
+static int copyTo(char * target, const char * source, int cpyLenght, int availSpace);
+static void cleanUpProcBlock(pProcInfo_t pCurProcInfo);
+
+
+
+typedef enum {
+ SIG_NOOP,
+ SIG_HUP,
+ SIG_INT,
+ SIG_KILL = 9,
+ SIG_TERM = 15,
+} signals;
+
+extern CRITICAL_SECTION cs;
+
+
+extern TCHAR path[MAX_PATH];
+
+static HMODULE hVM = NULL;
+
+
+static pProcInfo_t pInfo = NULL;
+
+
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
+ (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels)
+{
+
+ HANDLE hread[3], hwrite[3];
+ SECURITY_ATTRIBUTES sa;
+ PROCESS_INFORMATION pi = {0};
+ STARTUPINFO si;
+ DWORD flags = 0;
+ char * cwd = NULL;
+ LPVOID envBlk = NULL;
+ int ret = 0;
+ char szCmdLine[MAX_CMD_SIZE];
+ char szEnvBlock[MAX_ENV_SIZE];
+ jsize nCmdTokens = 0;
+ jsize nEnvVars = 0;
+ int i;
+ int nPos;
+ pProcInfo_t pCurProcInfo;
+ DWORD dwThreadId;
+ char eventBreakName[20];
+ char eventWaitName[20];
+ char eventTerminateName[20];
+#ifdef DEBUG_MONITOR
+ char buffer[100];
+#endif
+
+
+
+ if (cmdarray == 0)
+ {
+ ThrowByName(env, "java/lang/NullPointerException", "No command line specified");
+ return 0;
+ }
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = 0;
+ sa.bInheritHandle = TRUE;
+
+ memset(hread, 0, sizeof(hread));
+ memset(hwrite, 0, sizeof(hwrite));
+ if (!(CreatePipe(&hread[0], &hwrite[0], &sa, PIPE_SIZE) &&
+ CreatePipe(&hread[1], &hwrite[1], &sa, PIPE_SIZE) &&
+ CreatePipe(&hread[2], &hwrite[2], &sa, PIPE_SIZE)))
+ {
+ CloseHandle(hread[0]);
+ CloseHandle(hread[1]);
+ CloseHandle(hread[2]);
+ CloseHandle(hwrite[0]);
+ CloseHandle(hwrite[1]);
+ CloseHandle(hwrite[2]);
+ ThrowByName(env, "java/io/IOException", "CreatePipe");
+ return 0;
+ }
+
+ nCmdTokens = (*env) -> GetArrayLength(env, cmdarray);
+ nEnvVars = (*env) -> GetArrayLength(env, envp);
+
+ pCurProcInfo = createProcInfo();
+
+ if(NULL == pCurProcInfo)
+ {
+ ThrowByName(env, "java/io/IOException", "Too many processes");
+ return 0;
+ }
+
+
+ sprintf(eventBreakName, "SABreak%p", pCurProcInfo);
+ sprintf(eventWaitName, "SAWait%p", pCurProcInfo);
+ sprintf(eventTerminateName, "SATerm%p", pCurProcInfo);
+ pCurProcInfo -> eventBreak = CreateEvent(NULL, TRUE, FALSE, eventBreakName);
+ ResetEvent(pCurProcInfo -> eventBreak);
+ pCurProcInfo -> eventWait = CreateEvent(NULL, TRUE, FALSE, eventWaitName);
+ pCurProcInfo -> eventTerminate = CreateEvent(NULL, TRUE, FALSE, eventTerminateName);
+ ResetEvent(pCurProcInfo -> eventTerminate);
+
+ nPos = sprintf(szCmdLine, "%sstarter.exe %s %s %s ", path, eventBreakName, eventWaitName, eventTerminateName);
+
+ for(i = 0; i < nCmdTokens; ++i)
+ {
+ jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i);
+ jsize len = (*env) -> GetStringUTFLength(env, item);
+ int nCpyLen;
+ const char * str = (*env) -> GetStringUTFChars(env, item, 0);
+ if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos)))
+ {
+ ThrowByName(env, "java/Exception", "Too long command line");
+ return 0;
+ }
+ nPos += nCpyLen;
+ szCmdLine[nPos] = ' ';
+ ++nPos;
+ (*env) -> ReleaseStringUTFChars(env, item, str);
+ }
+
+ szCmdLine[nPos] = '\0';
+
+ if (nEnvVars > 0)
+ {
+ nPos = 0;
+ for(i = 0; i < nEnvVars; ++i)
+ {
+ jobject item = (*env) -> GetObjectArrayElement(env, envp, i);
+ jsize len = (*env) -> GetStringUTFLength(env, item);
+ int nCpyLen;
+ const char * str = (*env) -> GetStringUTFChars(env, item, 0);
+ if(0 > (nCpyLen = copyTo(szEnvBlock + nPos, str, len, MAX_ENV_SIZE - nPos - 1)))
+ {
+ ThrowByName(env, "java/Exception", "Too many environment variables");
+ return 0;
+ }
+ nPos += nCpyLen;
+ szEnvBlock[nPos] = '\0';
+ ++nPos;
+ (*env) -> ReleaseStringUTFChars(env, item, str);
+ }
+ szEnvBlock[nPos] = '\0';
+ envBlk = szEnvBlock;
+ }
+
+
+
+ if (dir != 0)
+ {
+ const char * str = NULL;
+ JVM_NativePath nativePath = GetJVMProc(NULL, "_JVM_NativePath@4");
+ cwd = strdup(nativePath(str = (*env) -> GetStringUTFChars(env, dir, 0)));
+ (*env) -> ReleaseStringUTFChars(env, dir, str);
+ }
+
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.dwFlags |= STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden
+ si.hStdInput = hread[0];
+ si.hStdOutput = hwrite[1];
+ si.hStdError = hwrite[2];
+
+
+
+
+ SetHandleInformation(hwrite[0], HANDLE_FLAG_INHERIT, FALSE);
+ SetHandleInformation(hread[1], HANDLE_FLAG_INHERIT, FALSE);
+ SetHandleInformation(hread[2], HANDLE_FLAG_INHERIT, FALSE);
+
+ flags = CREATE_NEW_CONSOLE;
+ flags |= CREATE_NO_WINDOW;
+
+#ifdef DEBUG_MONITOR
+ OutputDebugString(szCmdLine);
+#endif
+
+ ret = CreateProcess(0, /* executable name */
+ szCmdLine, /* command line */
+ 0, /* process security attribute */
+ 0, /* thread security attribute */
+ TRUE, /* inherits system handles */
+ flags, /* normal attached process */
+ envBlk, /* environment block */
+ cwd, /* change to the new current directory */
+ &si, /* (in) startup information */
+ &pi); /* (out) process information */
+
+
+
+ if(NULL != cwd)
+ free(cwd);
+
+
+ CloseHandle(hread[0]);
+ CloseHandle(hwrite[1]);
+ CloseHandle(hwrite[2]);
+
+
+ if (!ret)
+ {
+ LPTSTR lpMsgBuf;
+
+ CloseHandle(hwrite[0]);
+ CloseHandle(hread[1]);
+ CloseHandle(hread[2]);
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ ThrowByName(env, "java/io/IOException", lpMsgBuf);
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+ cleanUpProcBlock(pCurProcInfo);
+ ret = -1;
+ }
+ else
+ {
+ int file_handles[3];
+ HANDLE h[2];
+ int what;
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ EnterCriticalSection(&cs);
+
+ pCurProcInfo -> pid = pi.dwProcessId;
+ h[0] = pCurProcInfo -> eventWait;
+ h[1] = (HANDLE)_beginthreadex(NULL, 0, waitProcTermination,
+ (void *) &(pi.dwProcessId), 0, (UINT*) &dwThreadId);
+
+ what = WaitForMultipleObjects(2, h, FALSE, INFINITE);
+ if((what != WAIT_OBJECT_0) && (pCurProcInfo -> pid > 0)) // CreateProcess failed
+ {
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "Process %i failed\n", pi.dwProcessId);
+ OutputDebugString(buffer);
+#endif
+ cleanUpProcBlock(pCurProcInfo);
+ ThrowByName(env, "java/io/IOException", "Launching failed");
+ }
+ else
+ {
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "Process %i created\n", pi.dwProcessId);
+ OutputDebugString(buffer);
+#endif
+ ret = (long)(pCurProcInfo -> uid);
+ file_handles[0] = (int)hwrite[0];
+ file_handles[1] = (int)hread[1];
+ file_handles[2] = (int)hread[2];
+ (*env) -> SetIntArrayRegion(env, channels, 0, 3, file_handles);
+ }
+ CloseHandle(h[1]);
+ LeaveCriticalSection(&cs);
+
+ }
+
+
+ return ret;
+
+}
+
+
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
+ (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir)
+{
+
+ SECURITY_ATTRIBUTES sa;
+ PROCESS_INFORMATION pi = {0};
+ STARTUPINFO si;
+ DWORD flags = 0;
+ char * cwd = NULL;
+ LPVOID envBlk = NULL;
+ int ret = 0;
+ jsize nCmdTokens = 0;
+ jsize nEnvVars = 0;
+ int i;
+ int nPos;
+ char szCmdLine[MAX_CMD_SIZE];
+ char szEnvBlock[MAX_ENV_SIZE];
+
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = 0;
+ sa.bInheritHandle = TRUE;
+
+
+ nCmdTokens = (*env) -> GetArrayLength(env, cmdarray);
+ nEnvVars = (*env) -> GetArrayLength(env, envp);
+
+ nPos = 0;
+
+ for(i = 0; i < nCmdTokens; ++i)
+ {
+ jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i);
+ jsize len = (*env) -> GetStringUTFLength(env, item);
+ int nCpyLen;
+ const char * str = (*env) -> GetStringUTFChars(env, item, 0);
+ if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos)))
+ {
+ ThrowByName(env, "java/Exception", "Too long command line");
+ return 0;
+ }
+ nPos += nCpyLen;
+ szCmdLine[nPos] = ' ';
+ ++nPos;
+ (*env) -> ReleaseStringUTFChars(env, item, str);
+ }
+
+ szCmdLine[nPos] = '\0';
+
+ if (nEnvVars > 0)
+ {
+ nPos = 0;
+ for(i = 0; i < nEnvVars; ++i)
+ {
+ jobject item = (*env) -> GetObjectArrayElement(env, envp, i);
+ jsize len = (*env) -> GetStringUTFLength(env, item);
+ int nCpyLen;
+ const char * str = (*env) -> GetStringUTFChars(env, item, 0);
+ if(0 > (nCpyLen = copyTo(szEnvBlock + nPos, str, len, MAX_ENV_SIZE - nPos - 1)))
+ {
+ ThrowByName(env, "java/Exception", "Too many environment variables");
+ return 0;
+ }
+ nPos += nCpyLen;
+ szEnvBlock[nPos] = '\0';
+ ++nPos;
+ (*env) -> ReleaseStringUTFChars(env, item, str);
+ }
+ szEnvBlock[nPos] = '\0';
+ envBlk = szEnvBlock;
+ }
+
+
+
+ if (dir != 0)
+ {
+ JVM_NativePath nativePath = GetJVMProc(NULL, "_JVM_NativePath@4");
+ cwd = strdup(nativePath((*env) -> GetStringUTFChars(env, dir, 0)));
+ }
+
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+
+
+
+
+ flags = CREATE_NEW_CONSOLE;
+
+ ret = CreateProcess(0, /* executable name */
+ szCmdLine, /* command line */
+ 0, /* process security attribute */
+ 0, /* thread security attribute */
+ TRUE, /* inherits system handles */
+ flags, /* normal attached process */
+ envBlk, /* environment block */
+ cwd, /* change to the new current directory */
+ &si, /* (in) startup information */
+ &pi); /* (out) process information */
+
+
+
+ if(NULL != cwd)
+ free(cwd);
+
+ if (!ret)
+ {
+ LPTSTR lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ ThrowByName(env, "java/io/IOException", lpMsgBuf);
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+ ret = -1;
+ }
+ else
+ {
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ ret = (long)pi.dwProcessId; //hProcess;
+ }
+
+
+ return ret;
+
+}
+
+
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
+ (JNIEnv * env, jobject process, jint uid, jint signal)
+{
+ jint ret = 0;
+
+ HANDLE hProc;
+ pProcInfo_t pCurProcInfo = findProcInfo(uid);
+#ifdef DEBUG_MONITOR
+ char buffer[100];
+#endif
+
+ if(NULL == pCurProcInfo)
+ return -1;
+
+ hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pCurProcInfo -> pid);
+
+ if(NULL == hProc)
+ return -1;
+
+ switch(signal)
+ {
+ case SIG_NOOP:
+ // Wait 0 msec -just check if the process has been still running
+ ret = ((WAIT_TIMEOUT == WaitForSingleObject(hProc, 0)) ? 0 : -1);
+ break;
+ case SIG_HUP:
+ // Temporary do nothing
+ ret = 0;
+ break;
+ case SIG_KILL:
+ case SIG_TERM:
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "Spawner received KILL or TERM signal for process %i\n", pid);
+ OutputDebugString(buffer);
+#endif
+ SetEvent(pCurProcInfo -> eventTerminate);
+#ifdef DEBUG_MONITOR
+ OutputDebugString("Spawner signalled KILL event\n");
+#endif
+ ret = 0;
+ break;
+ case SIG_INT:
+ ResetEvent(pCurProcInfo -> eventWait);
+ PulseEvent(pCurProcInfo -> eventBreak);
+ ret = (WaitForSingleObject(pCurProcInfo -> eventWait, 100) == WAIT_OBJECT_0);
+ break;
+ default:
+ break;
+ }
+
+ CloseHandle(hProc);
+ return ret;
+
+
+}
+
+
+
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
+ (JNIEnv * env, jobject process, jint uid)
+{
+ long exit_code;
+ int what=0;
+ HANDLE hProc;
+ pProcInfo_t pCurProcInfo = findProcInfo(uid);
+
+ if(NULL == pCurProcInfo)
+ return -1;
+
+ hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pCurProcInfo -> pid);
+
+ if(NULL == hProc)
+ return -1;
+
+ what = WaitForSingleObject(hProc, INFINITE);
+
+
+ if (what == WAIT_OBJECT_0)
+ {
+ GetExitCodeProcess((void *)(pCurProcInfo -> pid), &exit_code);
+ }
+
+
+ if(hProc)
+ CloseHandle(hProc);
+
+ return exit_code;
+}
+
+
+
+
+
+// Utilities
+
+JNIEXPORT void JNICALL
+ThrowByName(JNIEnv *env, const char *name, const char *msg)
+{
+ jclass cls = (*env)->FindClass(env, name);
+
+ if (cls != 0) /* Otherwise an exception has already been thrown */
+ (*env)->ThrowNew(env, cls, msg);
+
+ /* It's a good practice to clean up the local references. */
+ (*env)->DeleteLocalRef(env, cls);
+}
+
+
+
+JNIEXPORT void * JNICALL
+GetJVMProc(char * vmlib, char * procName)
+{
+ if(NULL == vmlib)
+ vmlib = "jvm.dll";
+ if(NULL == hVM)
+ {
+ if(NULL == (hVM = GetModuleHandle(vmlib)))
+ return NULL;
+ }
+ return GetProcAddress(hVM, procName);
+}
+
+pProcInfo_t createProcInfo()
+{
+ int i;
+ pProcInfo_t p = NULL;
+
+ EnterCriticalSection(&cs);
+
+ if(NULL == pInfo)
+ {
+ pInfo = malloc(sizeof(procInfo_t) * MAX_PROCS);
+ memset(pInfo, 0, sizeof(procInfo_t) * MAX_PROCS);
+ }
+
+ for(i = 0; i < MAX_PROCS; ++i)
+ {
+ if(pInfo[i].pid == 0)
+ {
+ pInfo[i].pid = -1;
+ pInfo[i].uid = ++procCounter;
+ p = pInfo + i;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&cs);
+
+ return p;
+}
+
+pProcInfo_t findProcInfo(int uid)
+{
+ int i;
+ pProcInfo_t p = NULL;
+ if(NULL == pInfo)
+ return NULL;
+
+ for(i = 0; i < MAX_PROCS; ++i)
+ {
+ if(pInfo[i].uid == uid)
+ {
+ p = pInfo + i;
+ break;
+ }
+ }
+
+ return p;
+}
+
+void cleanUpProcBlock(pProcInfo_t pCurProcInfo)
+{
+ if(0 != pCurProcInfo -> eventBreak)
+ {
+ CloseHandle(pCurProcInfo -> eventBreak);
+ pCurProcInfo -> eventBreak = 0;
+ }
+ if(0 != pCurProcInfo -> eventWait)
+ {
+ CloseHandle(pCurProcInfo -> eventWait);
+ pCurProcInfo -> eventWait = 0;
+ }
+ if(0 != pCurProcInfo -> eventTerminate)
+ {
+ CloseHandle(pCurProcInfo -> eventTerminate);
+ pCurProcInfo -> eventTerminate = 0;
+ }
+
+ pCurProcInfo -> pid = 0;
+}
+
+unsigned int _stdcall waitProcTermination(void* pv)
+{
+ int i;
+ int pid = *(int *)pv;
+ DWORD rc = 0;
+#ifdef DEBUG_MONITOR
+ char buffer[100];
+#endif
+
+ HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
+
+ if(NULL == hProc)
+ {
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "waitProcTermination: cannot get handler for PID %i (error %i)\n", pid, GetLastError());
+ OutputDebugString(buffer);
+#endif
+ }
+ else
+ {
+ WaitForSingleObject(hProc, INFINITE);
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "Process PID %i terminated\n", pid);
+ OutputDebugString(buffer);
+#endif
+ }
+
+
+ for(i = 0; i < MAX_PROCS; ++i)
+ {
+ if(pInfo[i].pid == pid)
+ {
+#ifdef DEBUG_MONITOR
+ sprintf(buffer, "waitProcTermination: set PID %i to 0\n", pid, GetLastError());
+ OutputDebugString(buffer);
+#endif
+ cleanUpProcBlock(pInfo + i);
+ break;
+ }
+ }
+
+ CloseHandle(hProc);
+
+
+ return 0;
+}
+
+// Return number of bytes in target or -1 in case of error
+int copyTo(char * target, const char * source, int cpyLength, int availSpace)
+{
+ BOOL bSlash = FALSE;
+ int i, j;
+ int totCpyLength = cpyLength;
+
+ if(availSpace < cpyLength)
+ return -1;
+ strncpy(target, source, cpyLength);
+ return cpyLength;
+
+ // Don't open this feature for a while
+
+ for(i = 0, j = 0; i < cpyLength; ++i, ++j)
+ {
+ if(source[i] == '\\')
+ bSlash = TRUE;
+ else
+ if(source[i] == '"')
+ {
+ if(bSlash)
+ {
+ if(j == availSpace)
+ return -1;
+ target[j] = '\\';
+ ++j;
+ bSlash = FALSE;
+ }
+ if(j == availSpace)
+ return -1;
+ target[j] = '\\';
+ ++j;
+ }
+ else
+ bSlash = FALSE;
+
+ if(j == availSpace)
+ return -1;
+ target[j] = source[i];
+ }
+
+ return j;
+}
+

Back to the top