blob: e20ebb72222b5736f62fbff3448250ed70e488fb [file] [log] [blame]
/*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <direct.h>
#include <malloc.h>
#include <io.h>
#include <windows.h>
#include <aclapi.h>
#include <winioctl.h>
#include <Sddl.h>
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "ntifs_min.h"
#include "sun_nio_fs_WindowsNativeDispatcher.h"
/**
* jfieldIDs
*/
static jfieldID findFirst_handle;
static jfieldID findFirst_name;
static jfieldID findFirst_attributes;
static jfieldID findStream_handle;
static jfieldID findStream_name;
static jfieldID queryDirectoryInformation_handle;
static jfieldID queryDirectoryInformation_volSerialNumber;
static jfieldID volumeInfo_fsName;
static jfieldID volumeInfo_volName;
static jfieldID volumeInfo_volSN;
static jfieldID volumeInfo_flags;
static jfieldID diskSpace_bytesAvailable;
static jfieldID diskSpace_totalBytes;
static jfieldID diskSpace_totalFree;
static jfieldID account_domain;
static jfieldID account_name;
static jfieldID account_use;
static jfieldID aclInfo_aceCount;
static jfieldID completionStatus_error;
static jfieldID completionStatus_bytesTransferred;
static jfieldID completionStatus_completionKey;
static jfieldID backupResult_bytesTransferred;
static jfieldID backupResult_context;
/**
* Win32 APIs not available in Windows XP
*/
typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, STREAM_INFO_LEVELS, LPVOID, DWORD);
typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID);
typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD);
typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
typedef NTSYSCALLAPI NTSTATUS (NTAPI *NtQueryDirectoryFile_Proc) (HANDLE, HANDLE, PIO_APC_ROUTINE,
PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
typedef ULONG (NTAPI *RtlNtStatusToDosError_Proc) (NTSTATUS);
static FindFirstStream_Proc FindFirstStream_func;
static FindNextStream_Proc FindNextStream_func;
static CreateSymbolicLinkProc CreateSymbolicLink_func;
static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
static NtQueryDirectoryFile_Proc NtQueryDirectoryFile_func;
static RtlNtStatusToDosError_Proc RtlNtStatusToDosError_func;
static void throwWindowsException(JNIEnv* env, DWORD lastError) {
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
"(I)V", lastError);
if (x != NULL) {
(*env)->Throw(env, x);
}
}
/**
* Initializes jfieldIDs and get address of Win32 calls that are located
* at runtime.
*/
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
{
jclass clazz;
HMODULE h;
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile");
CHECK_NULL(clazz);
findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
CHECK_NULL(findFirst_handle);
findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
CHECK_NULL(findFirst_name);
findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I");
CHECK_NULL(findFirst_attributes);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream");
CHECK_NULL(clazz);
findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
CHECK_NULL(findStream_handle);
findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
CHECK_NULL(findStream_name);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$QueryDirectoryInformation");
CHECK_NULL(clazz);
queryDirectoryInformation_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
CHECK_NULL(queryDirectoryInformation_handle);
queryDirectoryInformation_volSerialNumber = (*env)->GetFieldID(env, clazz, "volSerialNumber", "I");;
CHECK_NULL(queryDirectoryInformation_volSerialNumber);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation");
CHECK_NULL(clazz);
volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;");
CHECK_NULL(volumeInfo_fsName);
volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;");
CHECK_NULL(volumeInfo_volName);
volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I");
CHECK_NULL(volumeInfo_volSN);
volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I");
CHECK_NULL(volumeInfo_flags);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace");
CHECK_NULL(clazz);
diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J");
CHECK_NULL(diskSpace_bytesAvailable);
diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J");
CHECK_NULL(diskSpace_totalBytes);
diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J");
CHECK_NULL(diskSpace_totalFree);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account");
CHECK_NULL(clazz);
account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;");
CHECK_NULL(account_domain);
account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
CHECK_NULL(account_name);
account_use = (*env)->GetFieldID(env, clazz, "use", "I");
CHECK_NULL(account_use);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation");
CHECK_NULL(clazz);
aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I");
CHECK_NULL(aclInfo_aceCount);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus");
CHECK_NULL(clazz);
completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
CHECK_NULL(completionStatus_error);
completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
CHECK_NULL(completionStatus_bytesTransferred);
completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
CHECK_NULL(completionStatus_completionKey);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
CHECK_NULL(clazz);
backupResult_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
CHECK_NULL(backupResult_bytesTransferred);
backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J");
CHECK_NULL(backupResult_context);
// get handle to kernel32
if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
(LPCWSTR)&CreateFileW, &h) != 0)
{
// requires Windows Server 2003 or newer
FindFirstStream_func =
(FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW");
FindNextStream_func =
(FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW");
// requires Windows Vista or newer
CreateSymbolicLink_func =
(CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW");
GetFinalPathNameByHandle_func =
(GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW");
}
// get handle to ntdll
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
L"ntdll.dll", &h) != 0)
{
NtQueryDirectoryFile_func =
(NtQueryDirectoryFile_Proc)GetProcAddress(h, "NtQueryDirectoryFile");
RtlNtStatusToDosError_func =
(RtlNtStatusToDosError_Proc)GetProcAddress(h, "RtlNtStatusToDosError");
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateEvent(JNIEnv* env, jclass this,
jboolean bManualReset, jboolean bInitialState)
{
HANDLE hEvent = CreateEventW(NULL, bManualReset, bInitialState, NULL);
if (hEvent == NULL) {
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(hEvent);
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) {
WCHAR message[255];
DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
(DWORD)errorCode,
0,
&message[0],
255,
NULL);
if (len == 0) {
return NULL;
} else {
return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_LocalFree(JNIEnv* env, jclass this, jlong address)
{
HLOCAL hMem = (HLOCAL)jlong_to_ptr(address);
LocalFree(hMem);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateFile0(JNIEnv* env, jclass this,
jlong address, jint dwDesiredAccess, jint dwShareMode, jlong sdAddress,
jint dwCreationDisposition, jint dwFlagsAndAttributes)
{
HANDLE handle;
LPCWSTR lpFileName = jlong_to_ptr(address);
SECURITY_ATTRIBUTES securityAttributes;
LPSECURITY_ATTRIBUTES lpSecurityAttributes;
PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
if (lpSecurityDescriptor == NULL) {
lpSecurityAttributes = NULL;
} else {
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
securityAttributes.bInheritHandle = FALSE;
lpSecurityAttributes = &securityAttributes;
}
handle = CreateFileW(lpFileName,
(DWORD)dwDesiredAccess,
(DWORD)dwShareMode,
lpSecurityAttributes,
(DWORD)dwCreationDisposition,
(DWORD)dwFlagsAndAttributes,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(handle);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlSetSparse(JNIEnv* env, jclass this,
jlong handle)
{
DWORD bytesReturned;
HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesReturned, NULL) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlGetReparsePoint(JNIEnv* env, jclass this,
jlong handle, jlong bufferAddress, jint bufferSize)
{
DWORD bytesReturned;
HANDLE h = (HANDLE)jlong_to_ptr(handle);
LPVOID outBuffer = (LPVOID)jlong_to_ptr(bufferAddress);
if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, outBuffer, (DWORD)bufferSize,
&bytesReturned, NULL) == 0)
{
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_DeleteFile0(JNIEnv* env, jclass this, jlong address)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
if (DeleteFileW(lpFileName) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateDirectory0(JNIEnv* env, jclass this,
jlong address, jlong sdAddress)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
SECURITY_ATTRIBUTES securityAttributes;
LPSECURITY_ATTRIBUTES lpSecurityAttributes;
PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
if (lpSecurityDescriptor == NULL) {
lpSecurityAttributes = NULL;
} else {
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
securityAttributes.bInheritHandle = FALSE;
lpSecurityAttributes = &securityAttributes;
}
if (CreateDirectoryW(lpFileName, lpSecurityAttributes) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_RemoveDirectory0(JNIEnv* env, jclass this, jlong address)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
if (RemoveDirectoryW(lpFileName) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this,
jlong handle)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
CloseHandle(h);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
jlong address, jobject obj)
{
WIN32_FIND_DATAW data;
LPCWSTR lpFileName = jlong_to_ptr(address);
HANDLE handle = FindFirstFileW(lpFileName, &data);
if (handle != INVALID_HANDLE_VALUE) {
jstring name = (*env)->NewString(env, data.cFileName, (jsize)wcslen(data.cFileName));
if (name == NULL)
return;
(*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
(*env)->SetObjectField(env, obj, findFirst_name, name);
(*env)->SetIntField(env, obj, findFirst_attributes, data.dwFileAttributes);
} else {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this,
jlong pathAddress, jlong dataAddress)
{
LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
HANDLE handle = FindFirstFileW(lpFileName, data);
if (handle == INVALID_HANDLE_VALUE) {
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(handle);
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
jlong handle, jlong dataAddress)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
if (FindNextFileW(h, data) != 0) {
return (*env)->NewString(env, data->cFileName, (jsize)wcslen(data->cFileName));
} else {
if (GetLastError() != ERROR_NO_MORE_FILES)
throwWindowsException(env, GetLastError());
return NULL;
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass this,
jlong address, jobject obj)
{
WIN32_FIND_STREAM_DATA data;
LPCWSTR lpFileName = jlong_to_ptr(address);
HANDLE handle;
if (FindFirstStream_func == NULL) {
JNU_ThrowInternalError(env, "Should not get here");
return;
}
handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0);
if (handle != INVALID_HANDLE_VALUE) {
jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
if (name == NULL)
return;
(*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
(*env)->SetObjectField(env, obj, findStream_name, name);
} else {
if (GetLastError() == ERROR_HANDLE_EOF) {
(*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
} else {
throwWindowsException(env, GetLastError());
}
}
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this,
jlong handle)
{
WIN32_FIND_STREAM_DATA data;
HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (FindNextStream_func == NULL) {
JNU_ThrowInternalError(env, "Should not get here");
return NULL;
}
if ((*FindNextStream_func)(h, &data) != 0) {
return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
} else {
if (GetLastError() != ERROR_HANDLE_EOF)
throwWindowsException(env, GetLastError());
return NULL;
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this,
jlong handle)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (FindClose(h) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_OpenNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
jlong address, jlong bufferAddress, jint bufferSize, jobject obj)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
BOOL ok;
BY_HANDLE_FILE_INFORMATION info;
HANDLE handle;
NTSTATUS status;
ULONG win32ErrorCode;
IO_STATUS_BLOCK ioStatusBlock;
if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
JNU_ThrowInternalError(env, "Should not get here");
return;
}
handle = CreateFileW(lpFileName, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (handle == INVALID_HANDLE_VALUE) {
throwWindowsException(env, GetLastError());
return;
}
status = NtQueryDirectoryFile_func(
handle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
jlong_to_ptr(bufferAddress), // FileInformation
bufferSize, // Length
FileIdFullDirectoryInformation, // FileInformationClass
FALSE, // ReturnSingleEntry
NULL, // FileName
FALSE); // RestartScan
if (!NT_SUCCESS(status)) {
/*
* NtQueryDirectoryFile returns STATUS_INVALID_PARAMETER when
* asked to enumerate an invalid directory (ie it is a file
* instead of a directory). Verify that is the actual cause
* of the error.
*/
if (status == STATUS_INVALID_PARAMETER) {
DWORD attributes = GetFileAttributesW(lpFileName);
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
status = STATUS_NOT_A_DIRECTORY;
}
}
win32ErrorCode = RtlNtStatusToDosError_func(status);
throwWindowsException(env, win32ErrorCode);
CloseHandle(handle);
return;
}
// This call allows retrieving the volume ID of this directory (and all its entries)
ok = GetFileInformationByHandle(handle, &info);
if (!ok) {
throwWindowsException(env, GetLastError());
CloseHandle(handle);
return;
}
(*env)->SetLongField(env, obj, queryDirectoryInformation_handle, ptr_to_jlong(handle));
(*env)->SetIntField(env, obj, queryDirectoryInformation_volSerialNumber, info.dwVolumeSerialNumber);
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_NextNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
jlong handle, jlong address, jint size)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
ULONG win32ErrorCode;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
JNU_ThrowInternalError(env, "Should not get here");
return JNI_FALSE;
}
status = NtQueryDirectoryFile_func(
h, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
jlong_to_ptr(address), // FileInformation
size, // Length
FileIdFullDirectoryInformation, // FileInformationClass
FALSE, // ReturnSingleEntry
NULL, // FileName
FALSE); // RestartScan
if (NT_SUCCESS(status)) {
return JNI_TRUE;
}
// Normal completion: no more files in directory
if (status == STATUS_NO_MORE_FILES) {
return JNI_FALSE;
}
win32ErrorCode = RtlNtStatusToDosError_func(status);
throwWindowsException(env, win32ErrorCode);
return JNI_FALSE;
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this,
jlong handle, jlong address)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
BY_HANDLE_FILE_INFORMATION* info =
(BY_HANDLE_FILE_INFORMATION*)jlong_to_ptr(address);
if (GetFileInformationByHandle(h, info) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CopyFileEx0(JNIEnv* env, jclass this,
jlong existingAddress, jlong newAddress, jint flags, jlong cancelAddress)
{
LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
LPBOOL cancel = (LPBOOL)jlong_to_ptr(cancelAddress);
if (CopyFileExW(lpExistingFileName, lpNewFileName, NULL, NULL, cancel,
(DWORD)flags) == 0)
{
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_MoveFileEx0(JNIEnv* env, jclass this,
jlong existingAddress, jlong newAddress, jint flags)
{
LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
if (MoveFileExW(lpExistingFileName, lpNewFileName, (DWORD)flags) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetLogicalDrives(JNIEnv* env, jclass this)
{
DWORD res = GetLogicalDrives();
if (res == 0) {
throwWindowsException(env, GetLastError());
}
return (jint)res;
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributes0(JNIEnv* env, jclass this,
jlong address)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
DWORD value = GetFileAttributesW(lpFileName);
if (value == INVALID_FILE_ATTRIBUTES) {
throwWindowsException(env, GetLastError());
}
return (jint)value;
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetFileAttributes0(JNIEnv* env, jclass this,
jlong address, jint value)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
if (SetFileAttributesW(lpFileName, (DWORD)value) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributesEx0(JNIEnv* env, jclass this,
jlong pathAddress, jlong dataAddress)
{
LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
WIN32_FILE_ATTRIBUTE_DATA* data = (WIN32_FILE_ATTRIBUTE_DATA*)jlong_to_ptr(dataAddress);
BOOL res = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, (LPVOID)data);
if (res == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this,
jlong handle, jlong createTime, jlong lastAccessTime, jlong lastWriteTime)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (SetFileTime(h,
(createTime == (jlong)-1) ? NULL : (CONST FILETIME *)&createTime,
(lastAccessTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastAccessTime,
(lastWriteTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0)
{
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetEndOfFile(JNIEnv* env, jclass this,
jlong handle)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (SetEndOfFile(h) == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumeInformation0(JNIEnv* env, jclass this,
jlong address, jobject obj)
{
WCHAR volumeName[MAX_PATH+1];
DWORD volumeSerialNumber;
DWORD maxComponentLength;
DWORD flags;
WCHAR fileSystemName[MAX_PATH+1];
LPCWSTR lpFileName = jlong_to_ptr(address);
jstring str;
BOOL res = GetVolumeInformationW(lpFileName,
&volumeName[0],
MAX_PATH+1,
&volumeSerialNumber,
&maxComponentLength,
&flags,
&fileSystemName[0],
MAX_PATH+1);
if (res == 0) {
throwWindowsException(env, GetLastError());
return;
}
str = (*env)->NewString(env, (const jchar *)fileSystemName, (jsize)wcslen(fileSystemName));
if (str == NULL) return;
(*env)->SetObjectField(env, obj, volumeInfo_fsName, str);
str = (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
if (str == NULL) return;
(*env)->SetObjectField(env, obj, volumeInfo_volName, str);
(*env)->SetIntField(env, obj, volumeInfo_volSN, (jint)volumeSerialNumber);
(*env)->SetIntField(env, obj, volumeInfo_flags, (jint)flags);
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0(JNIEnv* env, jclass this, jlong address) {
LPCWSTR lpRootPathName = jlong_to_ptr(address);
return (jint)GetDriveTypeW(lpRootPathName);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpaceEx0(JNIEnv* env, jclass this,
jlong address, jobject obj)
{
ULARGE_INTEGER freeBytesAvailable;
ULARGE_INTEGER totalNumberOfBytes;
ULARGE_INTEGER totalNumberOfFreeBytes;
LPCWSTR lpDirName = jlong_to_ptr(address);
BOOL res = GetDiskFreeSpaceExW(lpDirName,
&freeBytesAvailable,
&totalNumberOfBytes,
&totalNumberOfFreeBytes);
if (res == 0) {
throwWindowsException(env, GetLastError());
return;
}
(*env)->SetLongField(env, obj, diskSpace_bytesAvailable,
long_to_jlong(freeBytesAvailable.QuadPart));
(*env)->SetLongField(env, obj, diskSpace_totalBytes,
long_to_jlong(totalNumberOfBytes.QuadPart));
(*env)->SetLongField(env, obj, diskSpace_totalFree,
long_to_jlong(totalNumberOfFreeBytes.QuadPart));
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this,
jlong address)
{
WCHAR volumeName[MAX_PATH+1];
LPCWSTR lpFileName = jlong_to_ptr(address);
BOOL res = GetVolumePathNameW(lpFileName,
&volumeName[0],
MAX_PATH+1);
if (res == 0) {
throwWindowsException(env, GetLastError());
return NULL;
} else {
return (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_InitializeSecurityDescriptor(JNIEnv* env, jclass this,
jlong address)
{
PSECURITY_DESCRIPTOR pSecurityDescriptor =
(PSECURITY_DESCRIPTOR)jlong_to_ptr(address);
if (InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_InitializeAcl(JNIEnv* env, jclass this,
jlong address, jint size)
{
PACL pAcl = (PACL)jlong_to_ptr(address);
if (InitializeAcl(pAcl, (DWORD)size, ACL_REVISION) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this,
jlong pathAddress, jint requestedInformation, jlong descAddress)
{
LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
DWORD lengthNeeded = 0;
BOOL res = SetFileSecurityW(lpFileName,
(SECURITY_INFORMATION)requestedInformation,
pSecurityDescriptor);
if (res == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSecurity0(JNIEnv* env, jclass this,
jlong pathAddress, jint requestedInformation, jlong descAddress, jint nLength)
{
LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
DWORD lengthNeeded = 0;
BOOL res = GetFileSecurityW(lpFileName,
(SECURITY_INFORMATION)requestedInformation,
pSecurityDescriptor,
(DWORD)nLength,
&lengthNeeded);
if (res == 0) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
return (jint)lengthNeeded;
} else {
throwWindowsException(env, GetLastError());
return 0;
}
} else {
return (jint)nLength;
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorOwner(JNIEnv* env,
jclass this, jlong address)
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
PSID pOwner;
BOOL bOwnerDefaulted;
if (GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwner, &bOwnerDefaulted) == 0) {
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(pOwner);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorOwner(JNIEnv* env,
jclass this, jlong descAddress, jlong ownerAddress)
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
PSID pOwner = jlong_to_ptr(ownerAddress);
if (SetSecurityDescriptorOwner(pSecurityDescriptor, pOwner, FALSE) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorDacl(JNIEnv* env,
jclass this, jlong address)
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
BOOL bDaclPresent;
PACL pDacl;
BOOL bDaclDefaulted;
if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) == 0) {
throwWindowsException(env, GetLastError());
return (jlong)0;
} else {
return (bDaclPresent) ? ptr_to_jlong(pDacl) : (jlong)0;
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorDacl(JNIEnv* env,
jclass this, jlong descAddress, jlong aclAddress)
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR)jlong_to_ptr(descAddress);
PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
if (SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pAcl, FALSE) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetAclInformation0(JNIEnv* env,
jclass this, jlong address, jobject obj)
{
PACL pAcl = (PACL)jlong_to_ptr(address);
ACL_SIZE_INFORMATION acl_size_info;
if (GetAclInformation(pAcl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation) == 0) {
throwWindowsException(env, GetLastError());
} else {
(*env)->SetIntField(env, obj, aclInfo_aceCount, (jint)acl_size_info.AceCount);
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetAce(JNIEnv* env, jclass this, jlong address,
jint aceIndex)
{
PACL pAcl = (PACL)jlong_to_ptr(address);
LPVOID pAce;
if (GetAce(pAcl, (DWORD)aceIndex, &pAce) == 0) {
throwWindowsException(env, GetLastError());
return (jlong)0;
} else {
return ptr_to_jlong(pAce);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessAllowedAceEx(JNIEnv* env,
jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
{
PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
PSID pSid = (PSID)jlong_to_ptr(sidAddress);
if (AddAccessAllowedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessDeniedAceEx(JNIEnv* env,
jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
{
PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
PSID pSid = (PSID)jlong_to_ptr(sidAddress);
if (AddAccessDeniedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env,
jclass this, jlong address, jobject obj)
{
WCHAR domain[255];
WCHAR name[255];
DWORD domainLen = sizeof(domain);
DWORD nameLen = sizeof(name);
SID_NAME_USE use;
PSID sid = jlong_to_ptr(address);
jstring s;
if (LookupAccountSidW(NULL, sid, &name[0], &nameLen, &domain[0], &domainLen, &use) == 0) {
throwWindowsException(env, GetLastError());
return;
}
s = (*env)->NewString(env, (const jchar *)domain, (jsize)wcslen(domain));
if (s == NULL)
return;
(*env)->SetObjectField(env, obj, account_domain, s);
s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name));
if (s == NULL)
return;
(*env)->SetObjectField(env, obj, account_name, s);
(*env)->SetIntField(env, obj, account_use, (jint)use);
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env,
jclass this, jlong nameAddress, jlong sidAddress, jint cbSid)
{
LPCWSTR accountName = jlong_to_ptr(nameAddress);
PSID sid = jlong_to_ptr(sidAddress);
WCHAR domain[255];
DWORD domainLen = sizeof(domain);
SID_NAME_USE use;
if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid,
&domain[0], &domainLen, &use) == 0)
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
throwWindowsException(env, GetLastError());
}
}
return cbSid;
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetLengthSid(JNIEnv* env,
jclass this, jlong address)
{
PSID sid = jlong_to_ptr(address);
return (jint)GetLengthSid(sid);
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_ConvertSidToStringSid(JNIEnv* env,
jclass this, jlong address)
{
PSID sid = jlong_to_ptr(address);
LPWSTR string;
if (ConvertSidToStringSidW(sid, &string) == 0) {
throwWindowsException(env, GetLastError());
return NULL;
} else {
jstring s = (*env)->NewString(env, (const jchar *)string,
(jsize)wcslen(string));
LocalFree(string);
return s;
}
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_ConvertStringSidToSid0(JNIEnv* env,
jclass this, jlong address)
{
LPWSTR lpStringSid = jlong_to_ptr(address);
PSID pSid;
if (ConvertStringSidToSidW(lpStringSid, &pSid) == 0)
throwWindowsException(env, GetLastError());
return ptr_to_jlong(pSid);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentProcess(JNIEnv* env, jclass this) {
HANDLE hProcess = GetCurrentProcess();
return ptr_to_jlong(hProcess);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentThread(JNIEnv* env, jclass this) {
HANDLE hThread = GetCurrentThread();
return ptr_to_jlong(hThread);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_OpenProcessToken(JNIEnv* env,
jclass this, jlong process, jint desiredAccess)
{
HANDLE hProcess = (HANDLE)jlong_to_ptr(process);
HANDLE hToken;
if (OpenProcessToken(hProcess, (DWORD)desiredAccess, &hToken) == 0)
throwWindowsException(env, GetLastError());
return ptr_to_jlong(hToken);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_OpenThreadToken(JNIEnv* env,
jclass this, jlong thread, jint desiredAccess, jboolean openAsSelf)
{
HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
HANDLE hToken;
BOOL bOpenAsSelf = (openAsSelf == JNI_TRUE) ? TRUE : FALSE;
if (OpenThreadToken(hThread, (DWORD)desiredAccess, bOpenAsSelf, &hToken) == 0) {
if (GetLastError() == ERROR_NO_TOKEN)
return (jlong)0;
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(hToken);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_DuplicateTokenEx(JNIEnv* env,
jclass this, jlong token, jint desiredAccess)
{
HANDLE hToken = (HANDLE)jlong_to_ptr(token);
HANDLE resultToken;
BOOL res;
res = DuplicateTokenEx(hToken,
(DWORD)desiredAccess,
NULL,
SecurityImpersonation,
TokenImpersonation,
&resultToken);
if (res == 0)
throwWindowsException(env, GetLastError());
return ptr_to_jlong(resultToken);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetThreadToken(JNIEnv* env,
jclass this, jlong thread, jlong token)
{
HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
HANDLE hToken = (HANDLE)jlong_to_ptr(token);
if (SetThreadToken(hThread, hToken) == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetTokenInformation(JNIEnv* env,
jclass this, jlong token, jint tokenInfoClass, jlong tokenInfo, jint tokenInfoLength)
{
BOOL res;
DWORD lengthNeeded;
HANDLE hToken = (HANDLE)jlong_to_ptr(token);
LPVOID result = (LPVOID)jlong_to_ptr(tokenInfo);
res = GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)tokenInfoClass, (LPVOID)result,
tokenInfoLength, &lengthNeeded);
if (res == 0) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
return (jint)lengthNeeded;
} else {
throwWindowsException(env, GetLastError());
return 0;
}
} else {
return tokenInfoLength;
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_AdjustTokenPrivileges(JNIEnv* env,
jclass this, jlong token, jlong luid, jint attributes)
{
TOKEN_PRIVILEGES privs[1];
HANDLE hToken = (HANDLE)jlong_to_ptr(token);
PLUID pLuid = (PLUID)jlong_to_ptr(luid);
privs[0].PrivilegeCount = 1;
privs[0].Privileges[0].Luid = *pLuid;
privs[0].Privileges[0].Attributes = (DWORD)attributes;
if (AdjustTokenPrivileges(hToken, FALSE, &privs[0], 1, NULL, NULL) == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_AccessCheck(JNIEnv* env,
jclass this, jlong token, jlong securityInfo, jint accessMask,
jint genericRead, jint genericWrite, jint genericExecute, jint genericAll)
{
HANDLE hImpersonatedToken = (HANDLE)jlong_to_ptr(token);
PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)jlong_to_ptr(securityInfo);
DWORD checkAccessRights = (DWORD)accessMask;
GENERIC_MAPPING mapping = {
genericRead,
genericWrite,
genericExecute,
genericAll};
PRIVILEGE_SET privileges = {0};
DWORD privilegesLength = sizeof(privileges);
DWORD grantedAccess = 0;
BOOL result = FALSE;
/* checkAccessRights is in-out parameter */
MapGenericMask(&checkAccessRights, &mapping);
if (AccessCheck(security, hImpersonatedToken, checkAccessRights,
&mapping, &privileges, &privilegesLength, &grantedAccess, &result) == 0)
throwWindowsException(env, GetLastError());
return (result == FALSE) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_LookupPrivilegeValue0(JNIEnv* env,
jclass this, jlong name)
{
LPCWSTR lpName = (LPCWSTR)jlong_to_ptr(name);
PLUID pLuid = LocalAlloc(0, sizeof(LUID));
if (pLuid == NULL) {
JNU_ThrowInternalError(env, "Unable to allocate LUID structure");
} else {
if (LookupPrivilegeValueW(NULL, lpName, pLuid) == 0) {
LocalFree(pLuid);
throwWindowsException(env, GetLastError());
return (jlong)0;
}
}
return ptr_to_jlong(pLuid);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
jclass this, jlong linkAddress, jlong targetAddress, jint flags)
{
LPCWSTR link = jlong_to_ptr(linkAddress);
LPCWSTR target = jlong_to_ptr(targetAddress);
if (CreateSymbolicLink_func == NULL) {
JNU_ThrowInternalError(env, "Should not get here");
return;
}
/* On Windows 64-bit this appears to succeed even when there is insufficient privileges */
if ((*CreateSymbolicLink_func)(link, target, (DWORD)flags) == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateHardLink0(JNIEnv* env,
jclass this, jlong newFileAddress, jlong existingFileAddress)
{
LPCWSTR newFile = jlong_to_ptr(newFileAddress);
LPCWSTR existingFile = jlong_to_ptr(existingFileAddress);
if (CreateHardLinkW(newFile, existingFile, NULL) == 0)
throwWindowsException(env, GetLastError());
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFullPathName0(JNIEnv *env,
jclass clz,
jlong pathAddress)
{
jstring rv = NULL;
WCHAR *lpBuf = NULL;
WCHAR buf[MAX_PATH];
DWORD len;
LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
len = GetFullPathNameW(lpFileName, MAX_PATH, buf, NULL);
if (len > 0) {
if (len < MAX_PATH) {
rv = (*env)->NewString(env, buf, len);
} else {
len += 1; /* return length does not include terminator */
lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
if (lpBuf != NULL) {
len = GetFullPathNameW(lpFileName, len, lpBuf, NULL);
if (len > 0) {
rv = (*env)->NewString(env, lpBuf, len);
} else {
JNU_ThrowInternalError(env, "GetFullPathNameW failed");
}
free(lpBuf);
} else {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
}
}
} else {
throwWindowsException(env, GetLastError());
}
return rv;
}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
jclass this, jlong handle)
{
jstring rv = NULL;
WCHAR *lpBuf = NULL;
WCHAR path[MAX_PATH];
HANDLE h = (HANDLE)jlong_to_ptr(handle);
DWORD len;
if (GetFinalPathNameByHandle_func == NULL) {
JNU_ThrowInternalError(env, "Should not get here");
return NULL;
}
len = (*GetFinalPathNameByHandle_func)(h, path, MAX_PATH, 0);
if (len > 0) {
if (len < MAX_PATH) {
rv = (*env)->NewString(env, (const jchar *)path, (jsize)len);
} else {
len += 1; /* return length does not include terminator */
lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
if (lpBuf != NULL) {
len = (*GetFinalPathNameByHandle_func)(h, lpBuf, len, 0);
if (len > 0) {
rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len);
} else {
JNU_ThrowInternalError(env, "GetFinalPathNameByHandleW failed");
}
free(lpBuf);
} else {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
}
}
} else {
throwWindowsException(env, GetLastError());
}
return rv;
}
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
jlong fileHandle, jlong existingPort, jlong completionKey)
{
HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
(HANDLE)jlong_to_ptr(existingPort),
(ULONG_PTR)completionKey,
0);
if (port == NULL) {
throwWindowsException(env, GetLastError());
}
return ptr_to_jlong(port);
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jclass this,
jlong completionPort, jobject obj)
{
DWORD bytesTransferred;
ULONG_PTR completionKey;
OVERLAPPED *lpOverlapped;
BOOL res;
res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
&bytesTransferred,
&completionKey,
&lpOverlapped,
INFINITE);
if (res == 0 && lpOverlapped == NULL) {
throwWindowsException(env, GetLastError());
} else {
DWORD ioResult = (res == 0) ? GetLastError() : 0;
(*env)->SetIntField(env, obj, completionStatus_error, ioResult);
(*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
(jint)bytesTransferred);
(*env)->SetLongField(env, obj, completionStatus_completionKey,
(jlong)completionKey);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
jlong completionPort, jlong completionKey)
{
BOOL res;
res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
(DWORD)0, /* dwNumberOfBytesTransferred */
(ULONG_PTR)completionKey,
NULL); /* lpOverlapped */
if (res == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CancelIo(JNIEnv* env, jclass this, jlong hFile) {
if (CancelIo((HANDLE)jlong_to_ptr(hFile)) == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetOverlappedResult(JNIEnv *env, jclass this,
jlong hFile, jlong lpOverlapped)
{
BOOL res;
DWORD bytesTransferred = -1;
res = GetOverlappedResult((HANDLE)jlong_to_ptr(hFile),
(LPOVERLAPPED)jlong_to_ptr(lpOverlapped),
&bytesTransferred,
TRUE);
if (res == 0) {
throwWindowsException(env, GetLastError());
}
return (jint)bytesTransferred;
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this,
jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter,
jlong bytesReturnedAddress, jlong pOverlapped)
{
BOOL res;
BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
LPOVERLAPPED ov = (LPOVERLAPPED)jlong_to_ptr(pOverlapped);
res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
(LPVOID)jlong_to_ptr(bufferAddress),
(DWORD)bufferLength,
subtree,
(DWORD)filter,
(LPDWORD)jlong_to_ptr(bytesReturnedAddress),
(LPOVERLAPPED)jlong_to_ptr(pOverlapped),
NULL);
if (res == 0) {
throwWindowsException(env, GetLastError());
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_BackupRead0(JNIEnv* env, jclass this,
jlong hFile, jlong bufferAddress, jint bufferSize, jboolean abort,
jlong context, jobject obj)
{
BOOL res;
DWORD bytesTransferred;
BOOL a = (abort == JNI_TRUE) ? TRUE : FALSE;
VOID* pContext = (VOID*)jlong_to_ptr(context);
res = BackupRead((HANDLE)jlong_to_ptr(hFile),
(LPBYTE)jlong_to_ptr(bufferAddress),
(DWORD)bufferSize,
&bytesTransferred,
a,
FALSE,
&pContext);
if (res == 0) {
throwWindowsException(env, GetLastError());
} else {
(*env)->SetIntField(env, obj, backupResult_bytesTransferred,
bytesTransferred);
(*env)->SetLongField(env, obj, backupResult_context,
ptr_to_jlong(pContext));
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_BackupSeek(JNIEnv* env, jclass this,
jlong hFile, jlong bytesToSeek, jlong context)
{
BOOL res;
jint lowBytesToSeek = (jint)bytesToSeek;
jint highBytesToSeek = (jint)(bytesToSeek >> 32);
DWORD lowBytesSeeked;
DWORD highBytesSeeked;
VOID* pContext = jlong_to_ptr(context);
res = BackupSeek((HANDLE)jlong_to_ptr(hFile),
(DWORD)lowBytesToSeek,
(DWORD)highBytesToSeek,
&lowBytesSeeked,
&highBytesSeeked,
&pContext);
if (res == 0) {
throwWindowsException(env, GetLastError());
}
}