Exemplo n.º 1
7
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
    jclass infoClass = env->GetObjectClass(info);

    OSVERSIONINFOEX versionInfo;
    versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if (GetVersionEx((OSVERSIONINFO*)&versionInfo) == 0) {
        mark_failed_with_errno(env, "could not get version info", result);
        return;
    }

    SYSTEM_INFO systemInfo;
    GetNativeSystemInfo(&systemInfo);
    jstring arch = NULL;
    if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
        arch = env->NewStringUTF("amd64");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
        arch = env->NewStringUTF("x86");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
        arch = env->NewStringUTF("ia64");
    } else {
        arch = env->NewStringUTF("unknown");
    }

    jmethodID method = env->GetMethodID(infoClass, "windows", "(IIIZLjava/lang/String;)V");
    env->CallVoidMethod(info, method, versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
                        versionInfo.dwBuildNumber, versionInfo.wProductType == VER_NT_WORKSTATION,
                        arch);
}
Exemplo n.º 2
0
/*
 * File system functions
 */
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
    int fs_count = getfsstat(NULL, 0, MNT_NOWAIT);
    if (fs_count < 0) {
        mark_failed_with_errno(env, "could not stat file systems", result);
        return;
    }

    size_t len = fs_count * sizeof(struct statfs);
    struct statfs* buf = (struct statfs*)malloc(len);
    if (getfsstat(buf, len, MNT_NOWAIT) < 0 ) {
        mark_failed_with_errno(env, "could not stat file systems", result);
        free(buf);
        return;
    }

    jclass info_class = env->GetObjectClass(info);
    jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");

    for (int i = 0; i < fs_count; i++) {
        jboolean caseSensitive = JNI_TRUE;
        jboolean casePreserving = JNI_TRUE;

        jstring mount_point = char_to_java(env, buf[i].f_mntonname, result);
        jstring file_system_type = char_to_java(env, buf[i].f_fstypename, result);
        jstring device_name = char_to_java(env, buf[i].f_mntfromname, result);
        jboolean remote = (buf[i].f_flags & MNT_LOCAL) == 0;
        env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, remote, caseSensitive, casePreserving);
    }
    free(buf);
}
Exemplo n.º 3
0
JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jobject result) {
    wchar_t* varStr = java_to_wchar(env, var, result);
    DWORD len = GetEnvironmentVariableW(varStr, NULL, 0);
    if (len == 0) {
        if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
            mark_failed_with_errno(env, "could not determine length of environment variable", result);
        }
        free(varStr);
        return NULL;
    }
    wchar_t* valueStr = (wchar_t*)malloc(sizeof(wchar_t) * len);
    DWORD copied = GetEnvironmentVariableW(varStr, valueStr, len);
    if (copied == 0) {
        if (len > 1) {
            // If the value is empty, then copied will be 0
            mark_failed_with_errno(env, "could not get environment variable", result);
        }
        free(varStr);
        free(valueStr);
        return NULL;
    }
    free(varStr);
    jstring value = wchar_to_java(env, valueStr, copied, result);
    free(valueStr);
    return value;
}
Exemplo n.º 4
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_reset(JNIEnv *env, jclass target, jobject result) {
    current_attributes = original_attributes;
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
    if (!SetConsoleCursorInfo(current_console, &original_cursor)) {
        mark_failed_with_errno(env, "could not set console cursor", result);
    }
}
Exemplo n.º 5
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    DWORD count;
    if (!FillConsoleOutputCharacterW(current_console, L' ', console_info.dwSize.X - console_info.dwCursorPosition.X, console_info.dwCursorPosition, &count)) {
        mark_failed_with_errno(env, "could not clear console", result);
    }
}
Exemplo n.º 6
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_startLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X = 0;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}
Exemplo n.º 7
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_defaultForeground(JNIEnv *env, jclass target, jobject result) {
    current_attributes = (current_attributes & ~ALL_COLORS) | (original_attributes & ALL_COLORS);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}
Exemplo n.º 8
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) {
    jclass destClass = env->GetObjectClass(dest);
    jmethodID mid = env->GetMethodID(destClass, "details", "(IJJ)V");
    if (mid == NULL) {
        mark_failed_with_message(env, "could not find method", result);
        return;
    }

    WIN32_FILE_ATTRIBUTE_DATA attr;
    wchar_t* pathStr = java_to_wchar(env, path, result);
    BOOL ok = GetFileAttributesExW(pathStr, GetFileExInfoStandard, &attr);
    free(pathStr);
    if (!ok) {
        DWORD error = GetLastError();
        if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND || error == ERROR_NOT_READY) {
            // Treat device with no media as missing
            env->CallVoidMethod(dest, mid, (jint)FILE_TYPE_MISSING, (jlong)0, (jlong)0);
            return;
        }
        mark_failed_with_errno(env, "could not file attributes", result);
        return;
    }
    jlong lastModified = lastModifiedNanos(&attr.ftLastWriteTime);
    if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        env->CallVoidMethod(dest, mid, (jint)FILE_TYPE_DIRECTORY, (jlong)0, lastModified);
    } else {
        jlong size = ((jlong)attr.nFileSizeHigh << 32) | attr.nFileSizeLow;
        env->CallVoidMethod(dest, mid, (jint)FILE_TYPE_FILE, size, lastModified);
    }
}
Exemplo n.º 9
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_bold(JNIEnv *env, jclass target, jobject result) {
    current_attributes |= FOREGROUND_INTENSITY;
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}
Exemplo n.º 10
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_foreground(JNIEnv *env, jclass target, jint color, jobject result) {
    current_attributes &= ~ (FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
    switch (color) {
        case 0:
            break;
        case 1:
            current_attributes |= FOREGROUND_RED;
            break;
        case 2:
            current_attributes |= FOREGROUND_GREEN;
            break;
        case 3:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN;
            break;
        case 4:
            current_attributes |= FOREGROUND_BLUE;
            break;
        case 5:
            current_attributes |= FOREGROUND_RED|FOREGROUND_BLUE;
            break;
        case 6:
            current_attributes |= FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
        default:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
    }

    SetConsoleTextAttribute(current_console, current_attributes);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}
Exemplo n.º 11
0
void uninheritStream(JNIEnv *env, DWORD stdInputHandle, jobject result) {
    HANDLE streamHandle = GetStdHandle(stdInputHandle);
    if (streamHandle == NULL) {
        // We're not attached to a stdio (eg Desktop application). Ignore.
        return;
    }
    if (streamHandle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not get std handle", result);
        return;
    }
    boolean ok = SetHandleInformation(streamHandle, HANDLE_FLAG_INHERIT, 0);
    if (!ok) {
        if (GetLastError() != ERROR_INVALID_PARAMETER && GetLastError() != ERROR_INVALID_HANDLE) {
            mark_failed_with_errno(env, "could not change std handle", result);
        }
    }
}
Exemplo n.º 12
0
JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_FileEventFunctions_waitForNextEvent(JNIEnv *env, jclass target, jobject handle, jobject result) {
    watch_details_t* details = (watch_details_t*)env->GetDirectBufferAddress(handle);
    if (WaitForSingleObject(details->watch_handle, INFINITE) == WAIT_FAILED) {
        mark_failed_with_errno(env, "could not wait for change notification", result);
        return JNI_FALSE;
    }
    if (!FindNextChangeNotification(details->watch_handle)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            // Assumed closed
            return JNI_FALSE;
        }
        mark_failed_with_errno(env, "could not schedule next change notification", result);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
Exemplo n.º 13
0
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
    HANDLE handle = output == 1 ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE);
    if (handle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not get console handle", result);
        return NULL;
    }
    return handle;
}
Exemplo n.º 14
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_rawInputMode(JNIEnv *env, jclass target, jobject result) {
    init_input(env, result);
    DWORD mode = original_mode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
    if (!SetConsoleMode(console_buffer, mode)) {
        mark_failed_with_errno(env, "could not set console buffer mode", result);
    }
}
Exemplo n.º 15
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_detach(JNIEnv *env, jclass target, jobject result) {
    if (FreeConsole() == 0) {
        // Ignore if the error is that the process is already detached from the console
        if (GetLastError() != ERROR_INVALID_PARAMETER) {
            mark_failed_with_errno(env, "could not FreeConsole()", result);
        }
    }
}
Exemplo n.º 16
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_showCursor(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_CURSOR_INFO cursor;
    cursor = original_cursor;
    cursor.bVisible = true;
    if (!SetConsoleCursorInfo(current_console, &cursor)) {
        mark_failed_with_errno(env, "could not show cursor", result);
    }
}
Exemplo n.º 17
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_resetInputMode(JNIEnv *env, jclass target, jobject result) {
    if (console_buffer == NULL) {
        return;
    }
    if (!SetConsoleMode(console_buffer, original_mode)) {
        mark_failed_with_errno(env, "could not set console buffer mode", result);
    }
}
Exemplo n.º 18
0
void init_input(JNIEnv *env, jobject result) {
    if (console_buffer == NULL) {
        console_buffer = GetStdHandle(STD_INPUT_HANDLE);
        if (!GetConsoleMode(console_buffer, &original_mode)) {
            mark_failed_with_errno(env, "could not get console buffer mode", result);
            return;
        }
    }
}
Exemplo n.º 19
0
JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getWorkingDirectory(JNIEnv *env, jclass target, jobject result) {
    DWORD size = GetCurrentDirectoryW(0, NULL);
    if (size == 0) {
        mark_failed_with_errno(env, "could not determine length of working directory path", result);
        return NULL;
    }
    size = size+1; // Needs to include null character
    wchar_t* path = (wchar_t*)malloc(sizeof(wchar_t) * size);
    DWORD copied = GetCurrentDirectoryW(size, path);
    if (copied == 0) {
        free(path);
        mark_failed_with_errno(env, "could get working directory path", result);
        return NULL;
    }
    jstring dirName = wchar_to_java(env, path, copied, result);
    free(path);
    return dirName;
}
Exemplo n.º 20
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setWorkingDirectory(JNIEnv *env, jclass target, jstring dir, jobject result) {
    wchar_t* dirPath = java_to_wchar(env, dir, result);
    if (dirPath == NULL) {
        return;
    }
    BOOL ok = SetCurrentDirectoryW(dirPath);
    free(dirPath);
    if (!ok) {
        mark_failed_with_errno(env, "could not set current directory", result);
        return;
    }
}
Exemplo n.º 21
0
JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_FileEventFunctions_createWatch(JNIEnv *env, jclass target, jstring path, jobject result) {
    wchar_t* pathStr = java_to_wchar(env, path, result);
    HANDLE h = FindFirstChangeNotificationW(pathStr, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE);
    free(pathStr);
    if (h == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not open change notification", result);
        return NULL;
    }
    watch_details_t* details = (watch_details_t*)malloc(sizeof(watch_details_t));
    details->watch_handle = h;
    return env->NewDirectByteBuffer(details, sizeof(watch_details_t));
}
Exemplo n.º 22
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jstring value, jobject result) {
    wchar_t* varStr = java_to_wchar(env, var, result);
    wchar_t* valueStr = value == NULL ? NULL : java_to_wchar(env, value, result);
    BOOL ok = SetEnvironmentVariableW(varStr, valueStr);
    free(varStr);
    if (valueStr != NULL) {
        free(valueStr);
    }
    if (!ok && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
        mark_failed_with_errno(env, "could not set environment var", result);
        return;
    }
}
Exemplo n.º 23
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileFunctions_readdir(JNIEnv *env, jclass target, jstring path, jobject contents, jobject result) {
    jclass contentsClass = env->GetObjectClass(contents);
    jmethodID mid = env->GetMethodID(contentsClass, "addFile", "(Ljava/lang/String;IJJ)V");
    if (mid == NULL) {
        mark_failed_with_message(env, "could not find method", result);
        return;
    }

    WIN32_FIND_DATAW entry;
    wchar_t* pathStr = java_to_wchar(env, path, result);
    HANDLE dirHandle = FindFirstFileW(pathStr, &entry);
    free(pathStr);
    if (dirHandle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not open directory", result);
        return;
    }

    do {
        if (wcscmp(L".", entry.cFileName) == 0 || wcscmp(L"..", entry.cFileName) == 0) {
            continue;
        }
        jstring childName = wchar_to_java(env, entry.cFileName, wcslen(entry.cFileName), result);
        jint type = (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_TYPE_DIRECTORY : FILE_TYPE_FILE;
        jlong lastModified = lastModifiedNanos(&entry.ftLastWriteTime);
        jlong size = ((jlong)entry.nFileSizeHigh << 32) | entry.nFileSizeLow;
        env->CallVoidMethod(contents, mid, childName, type, size, lastModified);
    } while (FindNextFileW(dirHandle, &entry) != 0);

    DWORD error = GetLastError();
    if (error != ERROR_NO_MORE_FILES ) {
        mark_failed_with_errno(env, "could not read next directory entry", result);
    }

    FindClose(dirHandle);
}
Exemplo n.º 24
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_initConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a terminal", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            mark_failed_with_message(env, "not a console", result);
        } else {
            mark_failed_with_errno(env, "could not get console buffer", result);
        }
        return;
    }
    if (!GetConsoleCursorInfo(handle, &original_cursor)) {
        mark_failed_with_errno(env, "could not get console cursor", result);
        return;
    }
    current_console = handle;
    original_attributes = console_info.wAttributes;
    current_attributes = original_attributes;
}
Exemplo n.º 25
0
JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_isConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        return JNI_FALSE;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            return JNI_FALSE;
        }
        mark_failed_with_errno(env, "could not get console buffer", result);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
Exemplo n.º 26
0
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
    HANDLE handle = INVALID_HANDLE_VALUE;
    switch (output) {
    case STDIN_DESCRIPTOR:
        handle = GetStdHandle(STD_INPUT_HANDLE);
        break;
    case STDOUT_DESCRIPTOR:
        handle = GetStdHandle(STD_OUTPUT_HANDLE);
        break;
    case STDERR_DESCRIPTOR:
        handle = GetStdHandle(STD_ERROR_HANDLE);
        break;
    }
    if (handle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not get console handle", result);
        return NULL;
    }
    return handle;
}
Exemplo n.º 27
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_getConsoleSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a console", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }

    jclass dimensionClass = env->GetObjectClass(dimension);
    jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
    env->SetIntField(dimension, widthField, console_info.srWindow.Right - console_info.srWindow.Left + 1);
    jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
    env->SetIntField(dimension, heightField, console_info.srWindow.Bottom - console_info.srWindow.Top + 1);
}
Exemplo n.º 28
0
/*
 * File system functions
 */
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
    FILE *fp = setmntent(MOUNTED, "r");
    if (fp == NULL) {
        mark_failed_with_errno(env, "could not open mount file", result);
        return;
    }
    char buf[1024];
    struct mntent mount_info;

    jclass info_class = env->GetObjectClass(info);
    jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");

    while (getmntent_r(fp, &mount_info, buf, sizeof(buf)) != NULL) {
        jstring mount_point = char_to_java(env, mount_info.mnt_dir, result);
        jstring file_system_type = char_to_java(env, mount_info.mnt_type, result);
        jstring device_name = char_to_java(env, mount_info.mnt_fsname, result);
        env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, JNI_FALSE);
    }

    endmntent(fp);
}
Exemplo n.º 29
0
/*
 * File system functions
 */
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
    wchar_t* volumeName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    jclass info_class = env->GetObjectClass(info);
    jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");

    HANDLE handle = FindFirstVolumeW(volumeName, MAX_PATH+1);
    if (handle == INVALID_HANDLE_VALUE) {
        free(volumeName);
        mark_failed_with_errno(env, "could not find first volume", result);
        return;
    }

    wchar_t* deviceName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* pathNames = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* fsName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    while(true) {
        // Chop off the trailing '\'
        size_t len = wcslen(volumeName);
        if (len < 5) {
            mark_failed_with_message(env, "volume name is too short", result);
            break;
        }
        volumeName[len-1] = L'\0';

        if (QueryDosDeviceW(&volumeName[4], deviceName, MAX_PATH+1) == 0) {
            mark_failed_with_errno(env, "could not query dos device", result);
            break;
        }
        volumeName[len-1] = L'\\';

        DWORD used;
        if (GetVolumePathNamesForVolumeNameW(volumeName, pathNames, MAX_PATH+1, &used) == 0) {
            // TODO - try again if the buffer is too small
            mark_failed_with_errno(env, "could not query volume paths", result);
            break;
        }

        wchar_t* cur = pathNames;
        if (cur[0] != L'\0') {
            if(GetVolumeInformationW(cur, NULL, 0, NULL, NULL, NULL, fsName, MAX_PATH+1) == 0) {
                if (GetLastError() != ERROR_NOT_READY) {
                    mark_failed_with_errno(env, "could not query volume information", result);
                    break;
                }
                wcscpy(fsName, L"unknown");
            }
            for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) {
                env->CallVoidMethod(info, method, env->NewString((jchar*)deviceName, wcslen(deviceName)),
                                    env->NewString((jchar*)fsName, wcslen(fsName)), env->NewString((jchar*)cur, wcslen(cur)), JNI_FALSE);
            }
        }

        if (FindNextVolumeW(handle, volumeName, MAX_PATH) == 0) {
            if (GetLastError() != ERROR_NO_MORE_FILES) {
                mark_failed_with_errno(env, "could find next volume", result);
            }
            break;
        }
    }
    free(volumeName);
    free(deviceName);
    free(pathNames);
    free(fsName);
    FindVolumeClose(handle);
}
Exemplo n.º 30
0
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_readInput(JNIEnv *env, jclass target, jobject char_buffer, jobject result) {
    init_input(env, result);
    INPUT_RECORD events[1];
    DWORD nread;
    while(TRUE) {
        if (!ReadConsoleInputW(console_buffer, events, 1, &nread)) {
            mark_failed_with_errno(env, "could not read from console", result);
            return;
        }
        if (events[0].EventType != KEY_EVENT) {
            continue;
        }
        KEY_EVENT_RECORD keyEvent = events[0].Event.KeyEvent;
        if (!keyEvent.bKeyDown) {
            if (keyEvent.wVirtualKeyCode == 0x43 && keyEvent.uChar.UnicodeChar == 3) {
                // key down event for ctrl-c doesn't seem to be delivered, but key up event does
                return;
            }
            continue;
        }

        if ((keyEvent.dwControlKeyState & (LEFT_ALT_PRESSED|LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED|SHIFT_PRESSED)) == 0) {
            if (keyEvent.wVirtualKeyCode == VK_RETURN) {
                control_key(env, 0, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_UP) {
                control_key(env, 1, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_DOWN) {
                control_key(env, 2, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_LEFT) {
                control_key(env, 3, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_RIGHT) {
                control_key(env, 4, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_HOME) {
                control_key(env, 5, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_END) {
                control_key(env, 6, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_BACK) {
                control_key(env, 7, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_DELETE) {
                control_key(env, 8, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_PRIOR) { // page up
                control_key(env, 10, char_buffer, result);
                return;
            } else if (keyEvent.wVirtualKeyCode == VK_NEXT) { // page down
                control_key(env, 11, char_buffer, result);
                return;
            }
        }
        if (keyEvent.wVirtualKeyCode == 0x44 && keyEvent.uChar.UnicodeChar == 4) {
            // ctrl-d
            return;
        }
        if (keyEvent.uChar.UnicodeChar == 0) {
            // Some other control key
            continue;
        }
        if (keyEvent.uChar.UnicodeChar == '\t' && (keyEvent.dwControlKeyState & (SHIFT_PRESSED)) == 0) {
            // shift-tab
            control_key(env, 9, char_buffer, result);
        } else {
            character(env, (jchar)keyEvent.uChar.UnicodeChar, char_buffer, result);
        }
        return;
    }
}