/* * 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. */ #include #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 diskSpace_bytesPerSector; 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 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; 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$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); diskSpace_bytesPerSector = (*env)->GetFieldID(env, clazz, "bytesPerSector", "J"); CHECK_NULL(diskSpace_bytesPerSector); 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); } 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) { FindClose(handle); 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; handle = FindFirstStreamW(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 (FindNextStreamW(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 void JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpace0(JNIEnv* env, jclass this, jlong address, jobject obj) { DWORD sectorsPerCluster; DWORD bytesPerSector; DWORD numberOfFreeClusters; DWORD totalNumberOfClusters; LPCWSTR lpRootPathName = jlong_to_ptr(address); BOOL res = GetDiskFreeSpaceW(lpRootPathName, §orsPerCluster, &bytesPerSector, &numberOfFreeClusters, &totalNumberOfClusters); if (res == 0) { throwWindowsException(env, GetLastError()); return; } (*env)->SetLongField(env, obj, diskSpace_bytesPerSector, long_to_jlong(bytesPerSector)); } 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); /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */ if (CreateSymbolicLinkW(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; len = GetFinalPathNameByHandleW(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 = GetFinalPathNameByHandleW(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()); } }