/* * Copyright (c) 2008, 2009, 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 0x0500 #endif #include #include #include #include #include #include #include #include #include #include "jni.h" #include "jni_util.h" #include "jlong.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 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 defined in Visual Studio 2003 header files */ typedef enum { FindStreamInfoStandard } MY_STREAM_INFO_LEVELS; typedef struct _MY_WIN32_FIND_STREAM_DATA { LARGE_INTEGER StreamSize; WCHAR cStreamName[MAX_PATH + 36]; } MY_WIN32_FIND_STREAM_DATA; typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, MY_STREAM_INFO_LEVELS, LPVOID, DWORD); typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID); typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD); typedef BOOL (WINAPI* CreateHardLinkProc) (LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD); typedef BOOL (WINAPI* ConvertSidToStringSidProc) (PSID, LPWSTR*); typedef BOOL (WINAPI* ConvertStringSidToSidProc) (LPWSTR, PSID*); typedef DWORD (WINAPI* GetLengthSidProc) (PSID); static FindFirstStream_Proc FindFirstStream_func; static FindNextStream_Proc FindNextStream_func; static CreateSymbolicLinkProc CreateSymbolicLink_func; static CreateHardLinkProc CreateHardLink_func; static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func; static ConvertSidToStringSidProc ConvertSidToStringSid_func; static ConvertStringSidToSidProc ConvertStringSidToSid_func; static GetLengthSidProc GetLengthSid_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"); if (clazz == NULL) { return; } findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream"); if (clazz == NULL) { return; } findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation"); if (clazz == NULL) { return; } volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;"); volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;"); volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I"); volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace"); if (clazz == NULL) { return; } diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J"); diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J"); diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account"); if (clazz == NULL) { return; } account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;"); account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); account_use = (*env)->GetFieldID(env, clazz, "use", "I"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation"); if (clazz == NULL) { return; } aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus"); if (clazz == NULL) { return; } completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I"); completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult"); if (clazz == NULL) { return; } backupResult_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J"); h = LoadLibrary("kernel32"); if (h != INVALID_HANDLE_VALUE) { FindFirstStream_func = (FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW"); FindNextStream_func = (FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW"); CreateSymbolicLink_func = (CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW"); CreateHardLink_func = (CreateHardLinkProc)GetProcAddress(h, "CreateHardLinkW"); GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW"); FreeLibrary(h); } h = LoadLibrary("advapi32"); if (h != INVALID_HANDLE_VALUE) { ConvertSidToStringSid_func = (ConvertSidToStringSidProc)GetProcAddress(h, "ConvertSidToStringSidW"); ConvertStringSidToSid_func = (ConvertStringSidToSidProc)GetProcAddress(h, "ConvertStringSidToSidW"); GetLengthSid_func = (GetLengthSidProc)GetProcAddress(h, "GetLengthSid"); FreeLibrary(h); } } 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) { MY_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) { MY_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_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); if (GetLengthSid_func == NULL) { JNU_ThrowInternalError(env, "Should not get here"); return 0; } return (jint)(*GetLengthSid_func)(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 (ConvertSidToStringSid_func == NULL) { JNU_ThrowInternalError(env, "Should not get here"); return NULL; } if ((*ConvertSidToStringSid_func)(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 (ConvertStringSidToSid_func == NULL) { JNU_ThrowInternalError(env, "Should not get here"); return (jlong)0; } if ((*ConvertStringSidToSid_func)(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 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) throwWindowsException(env, GetLastError()); } return ptr_to_jlong(pLuid); } JNIEXPORT jlong JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_BuildTrusteeWithSid(JNIEnv* env, jclass this, jlong sid) { PSID pSid = (HANDLE)jlong_to_ptr(sid); PTRUSTEE_W pTrustee = LocalAlloc(0, sizeof(TRUSTEE_W)); if (pTrustee == NULL) { JNU_ThrowInternalError(env, "Unable to allocate TRUSTEE_W structure"); } else { BuildTrusteeWithSidW(pTrustee, pSid); } return ptr_to_jlong(pTrustee); } JNIEXPORT jint JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_GetEffectiveRightsFromAcl(JNIEnv* env, jclass this, jlong acl, jlong trustee) { ACCESS_MASK access; PACL pAcl = (PACL)jlong_to_ptr(acl); PTRUSTEE pTrustee = (PTRUSTEE)jlong_to_ptr(trustee); if (GetEffectiveRightsFromAcl(pAcl, pTrustee, &access) != ERROR_SUCCESS) { throwWindowsException(env, GetLastError()); } return (jint)access; } 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 (CreateHardLink_func == NULL) { JNU_ThrowInternalError(env, "Should not get here"); return; } if ((*CreateHardLink_func)(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); } } } if (len == 0) 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); } } } if (len == 0) throwWindowsException(env, GetLastError()); return rv; } JNIEXPORT jlong JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this, jlong fileHandle, jlong existingPort, jint completionKey) { ULONG_PTR ck = completionKey; HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle), (HANDLE)jlong_to_ptr(existingPort), ck, 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)->SetIntField(env, obj, completionStatus_completionKey, (jint)completionKey); } } JNIEXPORT void JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this, jlong completionPort, jint completionKey) { BOOL res; res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort), (DWORD)0, /* dwNumberOfBytesTransferred */ (DWORD)completionKey, NULL); /* lpOverlapped */ if (res == 0) { throwWindowsException(env, GetLastError()); } } 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)jlong_to_ptr(pOverlapped))->hEvent = NULL; 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()); } }