extern "C" JNIEXPORT jint JNICALL Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) { DWORD exitCode; WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE); BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode); if(not success){ throwNew(e, "java/lang/Exception", getErrorStr(GetLastError())); } CloseHandle(reinterpret_cast<HANDLE>(pid)); CloseHandle(reinterpret_cast<HANDLE>(tid)); return exitCode; }
extern "C" JNIEXPORT jint JNICALL Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) DWORD exitCode; WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE); BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode); if (not success) { throwNew(e, "java/lang/Exception", getErrorStr(GetLastError())); } CloseHandle(reinterpret_cast<HANDLE>(pid)); CloseHandle(reinterpret_cast<HANDLE>(tid)); return exitCode; #else throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); return -1; #endif }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i) { jstring element = (jstring)e->GetObjectArrayElement(command, i); if (element) { // worst case, assuming every character is '"', and we escape all of them size += 2 * e->GetStringUTFLength(element) + 3; } else { throwNew(e, "java/lang/NullPointerException", strdup("null string array element")); } } RUNTIME_ARRAY(char, line, size); char* linep = RUNTIME_ARRAY_BODY(line); for (int i = 0; i < e->GetArrayLength(command); ++i) { if (i) *(linep++) = _T(' '); jstring element = (jstring)e->GetObjectArrayElement(command, i); const char* s = e->GetStringUTFChars(element, 0); copyAndEscape(&linep, s, e->GetStringUTFLength(element)); e->ReleaseStringUTFChars(element, s); } *(linep++) = _T('\0'); HANDLE in[] = {0, 0}; HANDLE out[] = {0, 0}; HANDLE err[] = {0, 0}; makePipe(e, in); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 4, 1, &errDescriptor); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = in[1]; si.hStdInput = out[0]; si.hStdError = err[1]; BOOL success = CreateProcess(0, (LPSTR)RUNTIME_ARRAY_BODY(line), 0, 0, 1, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 0, 0, &si, &pi); CloseHandle(in[1]); CloseHandle(out[0]); CloseHandle(err[1]); if (not success) { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); return; } jlong pid = reinterpret_cast<jlong>(pi.hProcess); e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast<jlong>(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); #else throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); #endif }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); size += e->GetStringUTFLength(element) + 1; } RUNTIME_ARRAY(char, line, size); char* linep = RUNTIME_ARRAY_BODY(line); for (int i = 0; i < e->GetArrayLength(command); ++i) { if (i) *(linep++) = _T(' '); jstring element = (jstring) e->GetObjectArrayElement(command, i); const char* s = e->GetStringUTFChars(element, 0); #ifdef _MSC_VER _tcscpy_s(linep, size - (linep - RUNTIME_ARRAY_BODY(line)), s); #else _tcscpy(linep, s); #endif e->ReleaseStringUTFChars(element, s); linep += e->GetStringUTFLength(element); } *(linep++) = _T('\0'); HANDLE in[] = { 0, 0 }; HANDLE out[] = { 0, 0 }; HANDLE err[] = { 0, 0 }; makePipe(e, in); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 4, 1, &errDescriptor); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = in[1]; si.hStdInput = out[0]; si.hStdError = err[1]; BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 0, 0, &si, &pi); CloseHandle(in[1]); CloseHandle(out[0]); CloseHandle(err[1]); if (not success) { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); return; } jlong pid = reinterpret_cast<jlong>(pi.hProcess); e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast<jlong>(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); }
int DirectoryMonitor::Server::read() { DWORD dwBytesXFered = 0; ULONG_PTR ulKey = 0; OVERLAPPED* pOl; auto ret = GetQueuedCompletionStatus(m_hIOCP, &dwBytesXFered, &ulKey, &pOl, INFINITE); auto dwError = GetLastError(); if (!ret) { if (!m_hIOCP) { // shutting down return 0; } if (dwError == WAIT_TIMEOUT) { //harmless return 1; } } { WLock l(cs); auto mon = find_if(monitors | map_values, [ulKey](const Monitor* m) { return (ULONG_PTR)m->key == ulKey; }); if (mon.base() != monitors.end()) { if (!(*mon)->m_hDirectory) { //this is going to be deleted deleteDirectory(mon.base()); return 1; } try { if ((dwError != 0 && dwError != ERROR_INVALID_PARAMETER) || !ret) { // Too many changes to track, http://blogs.msdn.com/b/oldnewthing/archive/2011/08/12/10195186.aspx // The documentation only states the code ERROR_NOTIFY_ENUM_DIR for this, but according to the testing ERROR_NOT_ENOUGH_QUOTA and ERROR_ALREADY_EXISTS seem to be used instead.... // (and ERROR_TOO_MANY_CMDS with network drives) if (dwError == ERROR_NOTIFY_ENUM_DIR || dwError == ERROR_NOT_ENOUGH_QUOTA || dwError == ERROR_ALREADY_EXISTS || dwError == ERROR_TOO_MANY_CMDS) { (*mon)->beginRead(); auto monBase = (*mon)->server->base; monBase->callAsync([=] { monBase->fire(DirectoryMonitorListener::Overflow(), (*mon)->path); }); } else { throw MonitorException(getErrorStr(dwError)); } } else { if ((*mon)->errorCount > 0) { (*mon)->errorCount = 0; } if (dwBytesXFered > 0) { (*mon)->changes++; (*mon)->queueNotificationTask(dwBytesXFered); } /*else { LogManager::getInstance()->message("An empty notification was received when monitoring " + Text::fromT((*mon)->path) + " (report this)", LogMessage::SEV_WARNING); }*/ (*mon)->beginRead(); } } catch (const MonitorException& e) { (*mon)->errorCount++; if ((*mon)->errorCount < 60) { //we'll most likely get the error instantly again... Thread::sleep(1000); try { (*mon)->openDirectory(m_hIOCP); (*mon)->beginRead(); return 1; } catch (const MonitorException& /*e*/) { //go to removal } } failDirectory((*mon)->path, e.getError()); } } } return 1; }
Exception::Exception(EnErrors err, const char* func, const char* file, int line) : m_err(err) { #ifdef LOG_EXCEPTIONS CLog::getInstance().Log(ERROR, file, func, line, "Exception: %s", getErrorStr().c_str()); #endif }