1 /*
   2  * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <ctype.h>
  29 #include <direct.h>
  30 #include <malloc.h>
  31 #include <io.h>
  32 #include <windows.h>
  33 #include <aclapi.h>
  34 #include <winioctl.h>
  35 #include <Sddl.h>
  36 
  37 #include "jni.h"
  38 #include "jni_util.h"
  39 #include "jlong.h"
  40 
  41 #include "sun_nio_fs_WindowsNativeDispatcher.h"
  42 
  43 /**
  44  * jfieldIDs
  45  */
  46 static jfieldID findFirst_handle;
  47 static jfieldID findFirst_name;
  48 static jfieldID findFirst_attributes;
  49 
  50 static jfieldID findStream_handle;
  51 static jfieldID findStream_name;
  52 
  53 static jfieldID volumeInfo_fsName;
  54 static jfieldID volumeInfo_volName;
  55 static jfieldID volumeInfo_volSN;
  56 static jfieldID volumeInfo_flags;
  57 
  58 static jfieldID diskSpace_bytesAvailable;
  59 static jfieldID diskSpace_totalBytes;
  60 static jfieldID diskSpace_totalFree;
  61 
  62 static jfieldID diskSpace_bytesPerSector;
  63 
  64 static jfieldID account_domain;
  65 static jfieldID account_name;
  66 static jfieldID account_use;
  67 
  68 static jfieldID aclInfo_aceCount;
  69 
  70 static jfieldID completionStatus_error;
  71 static jfieldID completionStatus_bytesTransferred;
  72 static jfieldID completionStatus_completionKey;
  73 
  74 static void throwWindowsException(JNIEnv* env, DWORD lastError) {
  75     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
  76         "(I)V", lastError);
  77     if (x != NULL) {
  78         (*env)->Throw(env, x);
  79     }
  80 }
  81 
  82 /**
  83  * Initializes jfieldIDs and get address of Win32 calls that are located
  84  * at runtime.
  85  */
  86 JNIEXPORT void JNICALL
  87 Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
  88 {
  89     jclass clazz;
  90 
  91     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile");
  92     CHECK_NULL(clazz);
  93     findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
  94     CHECK_NULL(findFirst_handle);
  95     findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
  96     CHECK_NULL(findFirst_name);
  97     findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I");
  98     CHECK_NULL(findFirst_attributes);
  99 
 100     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream");
 101     CHECK_NULL(clazz);
 102     findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
 103     CHECK_NULL(findStream_handle);
 104     findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
 105     CHECK_NULL(findStream_name);
 106 
 107     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation");
 108     CHECK_NULL(clazz);
 109     volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;");
 110     CHECK_NULL(volumeInfo_fsName);
 111     volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;");
 112     CHECK_NULL(volumeInfo_volName);
 113     volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I");
 114     CHECK_NULL(volumeInfo_volSN);
 115     volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I");
 116     CHECK_NULL(volumeInfo_flags);
 117 
 118     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace");
 119     CHECK_NULL(clazz);
 120     diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J");
 121     CHECK_NULL(diskSpace_bytesAvailable);
 122     diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J");
 123     CHECK_NULL(diskSpace_totalBytes);
 124     diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J");
 125     CHECK_NULL(diskSpace_totalFree);
 126     diskSpace_bytesPerSector = (*env)->GetFieldID(env, clazz, "bytesPerSector", "J");
 127     CHECK_NULL(diskSpace_bytesPerSector);
 128 
 129     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account");
 130     CHECK_NULL(clazz);
 131     account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;");
 132     CHECK_NULL(account_domain);
 133     account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
 134     CHECK_NULL(account_name);
 135     account_use = (*env)->GetFieldID(env, clazz, "use", "I");
 136     CHECK_NULL(account_use);
 137 
 138     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation");
 139     CHECK_NULL(clazz);
 140     aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I");
 141     CHECK_NULL(aclInfo_aceCount);
 142 
 143     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus");
 144     CHECK_NULL(clazz);
 145     completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
 146     CHECK_NULL(completionStatus_error);
 147     completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
 148     CHECK_NULL(completionStatus_bytesTransferred);
 149     completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
 150     CHECK_NULL(completionStatus_completionKey);
 151 }
 152 
 153 JNIEXPORT jlong JNICALL
 154 Java_sun_nio_fs_WindowsNativeDispatcher_CreateEvent(JNIEnv* env, jclass this,
 155     jboolean bManualReset, jboolean bInitialState)
 156 {
 157     HANDLE hEvent = CreateEventW(NULL, bManualReset, bInitialState, NULL);
 158     if (hEvent == NULL) {
 159         throwWindowsException(env, GetLastError());
 160     }
 161     return ptr_to_jlong(hEvent);
 162 }
 163 
 164 JNIEXPORT jstring JNICALL
 165 Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) {
 166     WCHAR message[255];
 167 
 168     DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
 169                                NULL,
 170                                (DWORD)errorCode,
 171                                0,
 172                                &message[0],
 173                                255,
 174                                NULL);
 175 
 176 
 177     if (len == 0) {
 178         return NULL;
 179     } else {
 180         if (len > 3) {
 181             // Drop final '.', CR, LF
 182             if (message[len - 1] == L'\n') len--;
 183             if (message[len - 1] == L'\r') len--;
 184             if (message[len - 1] == L'.') len--;
 185             message[len] = L'\0';
 186         }
 187 
 188         return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
 189     }
 190 }
 191 
 192 JNIEXPORT void JNICALL
 193 Java_sun_nio_fs_WindowsNativeDispatcher_LocalFree(JNIEnv* env, jclass this, jlong address)
 194 {
 195     HLOCAL hMem = (HLOCAL)jlong_to_ptr(address);
 196     LocalFree(hMem);
 197 }
 198 
 199 JNIEXPORT jlong JNICALL
 200 Java_sun_nio_fs_WindowsNativeDispatcher_CreateFile0(JNIEnv* env, jclass this,
 201     jlong address, jint dwDesiredAccess, jint dwShareMode, jlong sdAddress,
 202     jint dwCreationDisposition, jint dwFlagsAndAttributes)
 203 {
 204     HANDLE handle;
 205     LPCWSTR lpFileName = jlong_to_ptr(address);
 206 
 207     SECURITY_ATTRIBUTES securityAttributes;
 208     LPSECURITY_ATTRIBUTES lpSecurityAttributes;
 209     PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
 210 
 211 
 212     if (lpSecurityDescriptor == NULL) {
 213         lpSecurityAttributes = NULL;
 214     } else {
 215         securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
 216         securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
 217         securityAttributes.bInheritHandle = FALSE;
 218         lpSecurityAttributes = &securityAttributes;
 219     }
 220 
 221     handle = CreateFileW(lpFileName,
 222                         (DWORD)dwDesiredAccess,
 223                         (DWORD)dwShareMode,
 224                         lpSecurityAttributes,
 225                         (DWORD)dwCreationDisposition,
 226                         (DWORD)dwFlagsAndAttributes,
 227                         NULL);
 228     if (handle == INVALID_HANDLE_VALUE) {
 229         throwWindowsException(env, GetLastError());
 230     }
 231     return ptr_to_jlong(handle);
 232 }
 233 
 234 
 235 JNIEXPORT void JNICALL
 236 Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlSetSparse(JNIEnv* env, jclass this,
 237     jlong handle)
 238 {
 239     DWORD bytesReturned;
 240     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 241     if (DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesReturned, NULL) == 0) {
 242         throwWindowsException(env, GetLastError());
 243     }
 244 }
 245 
 246 JNIEXPORT void JNICALL
 247 Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlGetReparsePoint(JNIEnv* env, jclass this,
 248     jlong handle, jlong bufferAddress, jint bufferSize)
 249 {
 250     DWORD bytesReturned;
 251     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 252     LPVOID outBuffer = (LPVOID)jlong_to_ptr(bufferAddress);
 253 
 254     if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, outBuffer, (DWORD)bufferSize,
 255                         &bytesReturned, NULL) == 0)
 256     {
 257         throwWindowsException(env, GetLastError());
 258     }
 259 }
 260 
 261 JNIEXPORT void JNICALL
 262 Java_sun_nio_fs_WindowsNativeDispatcher_DeleteFile0(JNIEnv* env, jclass this, jlong address)
 263 {
 264     LPCWSTR lpFileName = jlong_to_ptr(address);
 265     if (DeleteFileW(lpFileName) == 0) {
 266         throwWindowsException(env, GetLastError());
 267     }
 268 }
 269 
 270 JNIEXPORT void JNICALL
 271 Java_sun_nio_fs_WindowsNativeDispatcher_CreateDirectory0(JNIEnv* env, jclass this,
 272     jlong address, jlong sdAddress)
 273 {
 274     LPCWSTR lpFileName = jlong_to_ptr(address);
 275 
 276     SECURITY_ATTRIBUTES securityAttributes;
 277     LPSECURITY_ATTRIBUTES lpSecurityAttributes;
 278     PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
 279 
 280 
 281     if (lpSecurityDescriptor == NULL) {
 282         lpSecurityAttributes = NULL;
 283     } else {
 284         securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
 285         securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
 286         securityAttributes.bInheritHandle = FALSE;
 287         lpSecurityAttributes = &securityAttributes;
 288     }
 289 
 290     if (CreateDirectoryW(lpFileName, lpSecurityAttributes) == 0) {
 291         throwWindowsException(env, GetLastError());
 292     }
 293 }
 294 
 295 JNIEXPORT void JNICALL
 296 Java_sun_nio_fs_WindowsNativeDispatcher_RemoveDirectory0(JNIEnv* env, jclass this, jlong address)
 297 {
 298     LPCWSTR lpFileName = jlong_to_ptr(address);
 299     if (RemoveDirectoryW(lpFileName) == 0) {
 300         throwWindowsException(env, GetLastError());
 301     }
 302 }
 303 
 304 JNIEXPORT void JNICALL
 305 Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this,
 306     jlong handle)
 307 {
 308     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 309     CloseHandle(h);
 310 }
 311 
 312 JNIEXPORT void JNICALL
 313 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
 314     jlong address, jobject obj)
 315 {
 316     WIN32_FIND_DATAW data;
 317     LPCWSTR lpFileName = jlong_to_ptr(address);
 318 
 319     HANDLE handle = FindFirstFileW(lpFileName, &data);
 320     if (handle != INVALID_HANDLE_VALUE) {
 321         jstring name = (*env)->NewString(env, data.cFileName, (jsize)wcslen(data.cFileName));
 322         if (name == NULL) {
 323             FindClose(handle);
 324             return;
 325         }
 326         (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
 327         (*env)->SetObjectField(env, obj, findFirst_name, name);
 328         (*env)->SetIntField(env, obj, findFirst_attributes, data.dwFileAttributes);
 329     } else {
 330         throwWindowsException(env, GetLastError());
 331     }
 332 }
 333 
 334 JNIEXPORT jlong JNICALL
 335 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this,
 336     jlong pathAddress, jlong dataAddress)
 337 {
 338     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 339     WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
 340 
 341     HANDLE handle = FindFirstFileW(lpFileName, data);
 342     if (handle == INVALID_HANDLE_VALUE) {
 343         throwWindowsException(env, GetLastError());
 344     }
 345     return ptr_to_jlong(handle);
 346 }
 347 
 348 JNIEXPORT jstring JNICALL
 349 Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
 350     jlong handle, jlong dataAddress)
 351 {
 352     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 353     WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
 354 
 355     if (FindNextFileW(h, data) != 0) {
 356         return (*env)->NewString(env, data->cFileName, (jsize)wcslen(data->cFileName));
 357     } else {
 358     if (GetLastError() != ERROR_NO_MORE_FILES)
 359         throwWindowsException(env, GetLastError());
 360         return NULL;
 361     }
 362 }
 363 
 364 JNIEXPORT void JNICALL
 365 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass this,
 366     jlong address, jobject obj)
 367 {
 368     WIN32_FIND_STREAM_DATA data;
 369     LPCWSTR lpFileName = jlong_to_ptr(address);
 370     HANDLE handle;
 371 
 372     handle = FindFirstStreamW(lpFileName, FindStreamInfoStandard, &data, 0);
 373     if (handle != INVALID_HANDLE_VALUE) {
 374         jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
 375         if (name == NULL) {
 376             FindClose(handle);
 377             return;
 378         }
 379         (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
 380         (*env)->SetObjectField(env, obj, findStream_name, name);
 381     } else {
 382         if (GetLastError() == ERROR_HANDLE_EOF) {
 383              (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
 384         } else {
 385             throwWindowsException(env, GetLastError());
 386         }
 387     }
 388 
 389 }
 390 
 391 JNIEXPORT jstring JNICALL
 392 Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this,
 393     jlong handle)
 394 {
 395     WIN32_FIND_STREAM_DATA data;
 396     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 397 
 398     if (FindNextStreamW(h, &data) != 0) {
 399         return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
 400     } else {
 401         if (GetLastError() != ERROR_HANDLE_EOF)
 402             throwWindowsException(env, GetLastError());
 403         return NULL;
 404     }
 405 }
 406 
 407 
 408 JNIEXPORT void JNICALL
 409 Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this,
 410     jlong handle)
 411 {
 412     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 413     if (FindClose(h) == 0) {
 414         throwWindowsException(env, GetLastError());
 415     }
 416 }
 417 
 418 
 419 JNIEXPORT void JNICALL
 420 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this,
 421     jlong handle, jlong address)
 422 {
 423     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 424     BY_HANDLE_FILE_INFORMATION* info =
 425         (BY_HANDLE_FILE_INFORMATION*)jlong_to_ptr(address);
 426     if (GetFileInformationByHandle(h, info) == 0) {
 427         throwWindowsException(env, GetLastError());
 428     }
 429 }
 430 
 431 
 432 JNIEXPORT void JNICALL
 433 Java_sun_nio_fs_WindowsNativeDispatcher_CopyFileEx0(JNIEnv* env, jclass this,
 434     jlong existingAddress, jlong newAddress, jint flags, jlong cancelAddress)
 435 {
 436     LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
 437     LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
 438     LPBOOL cancel = (LPBOOL)jlong_to_ptr(cancelAddress);
 439     if (CopyFileExW(lpExistingFileName, lpNewFileName, NULL, NULL, cancel,
 440                     (DWORD)flags) == 0)
 441     {
 442         throwWindowsException(env, GetLastError());
 443     }
 444 }
 445 
 446 JNIEXPORT void JNICALL
 447 Java_sun_nio_fs_WindowsNativeDispatcher_MoveFileEx0(JNIEnv* env, jclass this,
 448     jlong existingAddress, jlong newAddress, jint flags)
 449 {
 450     LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
 451     LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
 452     if (MoveFileExW(lpExistingFileName, lpNewFileName, (DWORD)flags) == 0) {
 453         throwWindowsException(env, GetLastError());
 454     }
 455 }
 456 
 457 JNIEXPORT jint JNICALL
 458 Java_sun_nio_fs_WindowsNativeDispatcher_GetLogicalDrives(JNIEnv* env, jclass this)
 459 {
 460     DWORD res = GetLogicalDrives();
 461     if (res == 0) {
 462         throwWindowsException(env, GetLastError());
 463     }
 464     return (jint)res;
 465 }
 466 
 467 JNIEXPORT jint JNICALL
 468 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributes0(JNIEnv* env, jclass this,
 469     jlong address)
 470 {
 471     LPCWSTR lpFileName = jlong_to_ptr(address);
 472     DWORD value = GetFileAttributesW(lpFileName);
 473 
 474     if (value == INVALID_FILE_ATTRIBUTES) {
 475         throwWindowsException(env, GetLastError());
 476     }
 477     return (jint)value;
 478 }
 479 
 480 JNIEXPORT void JNICALL
 481 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileAttributes0(JNIEnv* env, jclass this,
 482     jlong address, jint value)
 483 {
 484     LPCWSTR lpFileName = jlong_to_ptr(address);
 485     if (SetFileAttributesW(lpFileName, (DWORD)value) == 0) {
 486         throwWindowsException(env, GetLastError());
 487     }
 488 }
 489 
 490 JNIEXPORT void JNICALL
 491 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributesEx0(JNIEnv* env, jclass this,
 492     jlong pathAddress, jlong dataAddress)
 493 {
 494     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 495     WIN32_FILE_ATTRIBUTE_DATA* data = (WIN32_FILE_ATTRIBUTE_DATA*)jlong_to_ptr(dataAddress);
 496 
 497     BOOL res = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, (LPVOID)data);
 498     if (res == 0)
 499         throwWindowsException(env, GetLastError());
 500 }
 501 
 502 
 503 JNIEXPORT void JNICALL
 504 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this,
 505     jlong handle, jlong createTime, jlong lastAccessTime, jlong lastWriteTime)
 506 {
 507     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 508 
 509     if (SetFileTime(h,
 510         (createTime == (jlong)-1) ? NULL : (CONST FILETIME *)&createTime,
 511         (lastAccessTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastAccessTime,
 512         (lastWriteTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0)
 513     {
 514         throwWindowsException(env, GetLastError());
 515     }
 516 }
 517 
 518 JNIEXPORT void JNICALL
 519 Java_sun_nio_fs_WindowsNativeDispatcher_SetEndOfFile(JNIEnv* env, jclass this,
 520     jlong handle)
 521 {
 522     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 523 
 524     if (SetEndOfFile(h) == 0)
 525         throwWindowsException(env, GetLastError());
 526 }
 527 
 528 
 529 JNIEXPORT void JNICALL
 530 Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumeInformation0(JNIEnv* env, jclass this,
 531     jlong address, jobject obj)
 532 {
 533     WCHAR volumeName[MAX_PATH+1];
 534     DWORD volumeSerialNumber;
 535     DWORD maxComponentLength;
 536     DWORD flags;
 537     WCHAR fileSystemName[MAX_PATH+1];
 538     LPCWSTR lpFileName = jlong_to_ptr(address);
 539     jstring str;
 540 
 541     BOOL res = GetVolumeInformationW(lpFileName,
 542                                      &volumeName[0],
 543                                      MAX_PATH+1,
 544                                      &volumeSerialNumber,
 545                                      &maxComponentLength,
 546                                      &flags,
 547                                      &fileSystemName[0],
 548                                      MAX_PATH+1);
 549     if (res == 0) {
 550         throwWindowsException(env, GetLastError());
 551         return;
 552     }
 553 
 554     str = (*env)->NewString(env, (const jchar *)fileSystemName, (jsize)wcslen(fileSystemName));
 555     if (str == NULL) return;
 556     (*env)->SetObjectField(env, obj, volumeInfo_fsName, str);
 557 
 558     str = (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
 559     if (str == NULL) return;
 560     (*env)->SetObjectField(env, obj, volumeInfo_volName, str);
 561 
 562     (*env)->SetIntField(env, obj, volumeInfo_volSN, (jint)volumeSerialNumber);
 563     (*env)->SetIntField(env, obj, volumeInfo_flags, (jint)flags);
 564 }
 565 
 566 
 567 JNIEXPORT jint JNICALL
 568 Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0(JNIEnv* env, jclass this, jlong address) {
 569     LPCWSTR lpRootPathName = jlong_to_ptr(address);
 570     return (jint)GetDriveTypeW(lpRootPathName);
 571 }
 572 
 573 
 574 JNIEXPORT void JNICALL
 575 Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpaceEx0(JNIEnv* env, jclass this,
 576     jlong address, jobject obj)
 577 {
 578     ULARGE_INTEGER freeBytesAvailable;
 579     ULARGE_INTEGER totalNumberOfBytes;
 580     ULARGE_INTEGER totalNumberOfFreeBytes;
 581     LPCWSTR lpDirName = jlong_to_ptr(address);
 582 
 583 
 584     BOOL res = GetDiskFreeSpaceExW(lpDirName,
 585                                    &freeBytesAvailable,
 586                                    &totalNumberOfBytes,
 587                                    &totalNumberOfFreeBytes);
 588     if (res == 0) {
 589         throwWindowsException(env, GetLastError());
 590         return;
 591     }
 592 
 593     (*env)->SetLongField(env, obj, diskSpace_bytesAvailable,
 594         long_to_jlong(freeBytesAvailable.QuadPart));
 595     (*env)->SetLongField(env, obj, diskSpace_totalBytes,
 596         long_to_jlong(totalNumberOfBytes.QuadPart));
 597     (*env)->SetLongField(env, obj, diskSpace_totalFree,
 598         long_to_jlong(totalNumberOfFreeBytes.QuadPart));
 599 }
 600 
 601 JNIEXPORT void JNICALL
 602 Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpace0(JNIEnv* env, jclass this,
 603     jlong address, jobject obj)
 604 {
 605     DWORD sectorsPerCluster;
 606     DWORD bytesPerSector;
 607     DWORD numberOfFreeClusters;
 608     DWORD totalNumberOfClusters;
 609     LPCWSTR lpRootPathName = jlong_to_ptr(address);
 610 
 611 
 612     BOOL res = GetDiskFreeSpaceW(lpRootPathName,
 613                                  &sectorsPerCluster,
 614                                  &bytesPerSector,
 615                                  &numberOfFreeClusters,
 616                                  &totalNumberOfClusters);
 617     if (res == 0) {
 618         throwWindowsException(env, GetLastError());
 619         return;
 620     }
 621 
 622     (*env)->SetLongField(env, obj, diskSpace_bytesPerSector,
 623         long_to_jlong(bytesPerSector));
 624 }
 625 
 626 JNIEXPORT jstring JNICALL
 627 Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this,
 628     jlong address)
 629 {
 630     WCHAR volumeName[MAX_PATH+1];
 631     LPCWSTR lpFileName = jlong_to_ptr(address);
 632 
 633 
 634     BOOL res = GetVolumePathNameW(lpFileName,
 635                                   &volumeName[0],
 636                                   MAX_PATH+1);
 637     if (res == 0) {
 638         throwWindowsException(env, GetLastError());
 639         return NULL;
 640     } else {
 641         return (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
 642     }
 643 }
 644 
 645 JNIEXPORT void JNICALL
 646 Java_sun_nio_fs_WindowsNativeDispatcher_InitializeSecurityDescriptor(JNIEnv* env, jclass this,
 647     jlong address)
 648 {
 649     PSECURITY_DESCRIPTOR pSecurityDescriptor =
 650         (PSECURITY_DESCRIPTOR)jlong_to_ptr(address);
 651 
 652     if (InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) == 0) {
 653         throwWindowsException(env, GetLastError());
 654     }
 655 }
 656 
 657 JNIEXPORT void JNICALL
 658 Java_sun_nio_fs_WindowsNativeDispatcher_InitializeAcl(JNIEnv* env, jclass this,
 659     jlong address, jint size)
 660 {
 661     PACL pAcl = (PACL)jlong_to_ptr(address);
 662 
 663     if (InitializeAcl(pAcl, (DWORD)size, ACL_REVISION) == 0) {
 664         throwWindowsException(env, GetLastError());
 665     }
 666 }
 667 
 668 
 669 JNIEXPORT void JNICALL
 670 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this,
 671     jlong pathAddress, jint requestedInformation, jlong descAddress)
 672 {
 673     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 674     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 675     DWORD lengthNeeded = 0;
 676 
 677     BOOL res = SetFileSecurityW(lpFileName,
 678                                 (SECURITY_INFORMATION)requestedInformation,
 679                                 pSecurityDescriptor);
 680 
 681     if (res == 0) {
 682         throwWindowsException(env, GetLastError());
 683     }
 684 }
 685 
 686 JNIEXPORT jint JNICALL
 687 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSecurity0(JNIEnv* env, jclass this,
 688     jlong pathAddress, jint requestedInformation, jlong descAddress, jint nLength)
 689 {
 690     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 691     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 692     DWORD lengthNeeded = 0;
 693 
 694     BOOL res = GetFileSecurityW(lpFileName,
 695                                 (SECURITY_INFORMATION)requestedInformation,
 696                                 pSecurityDescriptor,
 697                                 (DWORD)nLength,
 698                                 &lengthNeeded);
 699 
 700     if (res == 0) {
 701         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 702             return (jint)lengthNeeded;
 703         } else {
 704             throwWindowsException(env, GetLastError());
 705             return 0;
 706         }
 707     } else {
 708         return (jint)nLength;
 709     }
 710 }
 711 
 712 JNIEXPORT jlong JNICALL
 713 Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorOwner(JNIEnv* env,
 714     jclass this, jlong address)
 715 {
 716     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
 717     PSID pOwner;
 718     BOOL bOwnerDefaulted;
 719 
 720 
 721     if (GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwner, &bOwnerDefaulted) == 0) {
 722         throwWindowsException(env, GetLastError());
 723     }
 724     return ptr_to_jlong(pOwner);
 725 }
 726 
 727 JNIEXPORT void JNICALL
 728 Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorOwner(JNIEnv* env,
 729     jclass this, jlong descAddress, jlong ownerAddress)
 730 {
 731     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 732     PSID pOwner = jlong_to_ptr(ownerAddress);
 733 
 734     if (SetSecurityDescriptorOwner(pSecurityDescriptor, pOwner, FALSE) == 0) {
 735         throwWindowsException(env, GetLastError());
 736     }
 737 }
 738 
 739 
 740 JNIEXPORT jlong JNICALL
 741 Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorDacl(JNIEnv* env,
 742     jclass this, jlong address)
 743 {
 744     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
 745     BOOL bDaclPresent;
 746     PACL pDacl;
 747     BOOL bDaclDefaulted;
 748 
 749     if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) == 0) {
 750         throwWindowsException(env, GetLastError());
 751         return (jlong)0;
 752     } else {
 753         return (bDaclPresent) ? ptr_to_jlong(pDacl) : (jlong)0;
 754     }
 755 }
 756 
 757 JNIEXPORT void JNICALL
 758 Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorDacl(JNIEnv* env,
 759     jclass this, jlong descAddress, jlong aclAddress)
 760 {
 761     PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR)jlong_to_ptr(descAddress);
 762     PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
 763 
 764     if (SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pAcl, FALSE) == 0) {
 765         throwWindowsException(env, GetLastError());
 766     }
 767 }
 768 
 769 
 770 JNIEXPORT void JNICALL
 771 Java_sun_nio_fs_WindowsNativeDispatcher_GetAclInformation0(JNIEnv* env,
 772     jclass this, jlong address, jobject obj)
 773 {
 774     PACL pAcl = (PACL)jlong_to_ptr(address);
 775     ACL_SIZE_INFORMATION acl_size_info;
 776 
 777     if (GetAclInformation(pAcl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation) == 0) {
 778         throwWindowsException(env, GetLastError());
 779     } else {
 780         (*env)->SetIntField(env, obj, aclInfo_aceCount, (jint)acl_size_info.AceCount);
 781     }
 782 }
 783 
 784 JNIEXPORT jlong JNICALL
 785 Java_sun_nio_fs_WindowsNativeDispatcher_GetAce(JNIEnv* env, jclass this, jlong address,
 786     jint aceIndex)
 787 {
 788     PACL pAcl = (PACL)jlong_to_ptr(address);
 789     LPVOID pAce;
 790 
 791     if (GetAce(pAcl, (DWORD)aceIndex, &pAce) == 0) {
 792         throwWindowsException(env, GetLastError());
 793         return (jlong)0;
 794     } else {
 795         return ptr_to_jlong(pAce);
 796     }
 797 }
 798 
 799 JNIEXPORT void JNICALL
 800 Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessAllowedAceEx(JNIEnv* env,
 801     jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
 802 {
 803     PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
 804     PSID pSid = (PSID)jlong_to_ptr(sidAddress);
 805 
 806     if (AddAccessAllowedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
 807         throwWindowsException(env, GetLastError());
 808     }
 809 }
 810 
 811 JNIEXPORT void JNICALL
 812 Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessDeniedAceEx(JNIEnv* env,
 813     jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
 814 {
 815     PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
 816     PSID pSid = (PSID)jlong_to_ptr(sidAddress);
 817 
 818     if (AddAccessDeniedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
 819         throwWindowsException(env, GetLastError());
 820     }
 821 }
 822 
 823 
 824 JNIEXPORT void JNICALL
 825 Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env,
 826     jclass this, jlong address, jobject obj)
 827 {
 828     WCHAR domain[255];
 829     WCHAR name[255];
 830     DWORD domainLen = sizeof(domain);
 831     DWORD nameLen = sizeof(name);
 832     SID_NAME_USE use;
 833     PSID sid = jlong_to_ptr(address);
 834     jstring s;
 835 
 836     if (LookupAccountSidW(NULL, sid, &name[0], &nameLen, &domain[0], &domainLen, &use) == 0) {
 837         throwWindowsException(env, GetLastError());
 838         return;
 839     }
 840 
 841     s = (*env)->NewString(env, (const jchar *)domain, (jsize)wcslen(domain));
 842     if (s == NULL)
 843         return;
 844     (*env)->SetObjectField(env, obj, account_domain, s);
 845 
 846     s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name));
 847     if (s == NULL)
 848         return;
 849     (*env)->SetObjectField(env, obj, account_name, s);
 850     (*env)->SetIntField(env, obj, account_use, (jint)use);
 851 }
 852 
 853 JNIEXPORT jint JNICALL
 854 Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env,
 855     jclass this, jlong nameAddress, jlong sidAddress, jint cbSid)
 856 {
 857 
 858     LPCWSTR accountName = jlong_to_ptr(nameAddress);
 859     PSID sid = jlong_to_ptr(sidAddress);
 860     WCHAR domain[255];
 861     DWORD domainLen = sizeof(domain);
 862     SID_NAME_USE use;
 863 
 864     if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid,
 865                            &domain[0], &domainLen, &use) == 0)
 866     {
 867         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 868             throwWindowsException(env, GetLastError());
 869         }
 870     }
 871 
 872     return cbSid;
 873 }
 874 
 875 JNIEXPORT jint JNICALL
 876 Java_sun_nio_fs_WindowsNativeDispatcher_GetLengthSid(JNIEnv* env,
 877     jclass this, jlong address)
 878 {
 879     PSID sid = jlong_to_ptr(address);
 880     return (jint)GetLengthSid(sid);
 881 }
 882 
 883 
 884 JNIEXPORT jstring JNICALL
 885 Java_sun_nio_fs_WindowsNativeDispatcher_ConvertSidToStringSid(JNIEnv* env,
 886     jclass this, jlong address)
 887 {
 888     PSID sid = jlong_to_ptr(address);
 889     LPWSTR string;
 890     if (ConvertSidToStringSidW(sid, &string) == 0) {
 891         throwWindowsException(env, GetLastError());
 892         return NULL;
 893     } else {
 894         jstring s = (*env)->NewString(env, (const jchar *)string,
 895             (jsize)wcslen(string));
 896         LocalFree(string);
 897         return s;
 898     }
 899 }
 900 
 901 JNIEXPORT jlong JNICALL
 902 Java_sun_nio_fs_WindowsNativeDispatcher_ConvertStringSidToSid0(JNIEnv* env,
 903     jclass this, jlong address)
 904 {
 905     LPWSTR lpStringSid = jlong_to_ptr(address);
 906     PSID pSid;
 907     if (ConvertStringSidToSidW(lpStringSid, &pSid) == 0)
 908         throwWindowsException(env, GetLastError());
 909     return ptr_to_jlong(pSid);
 910 }
 911 
 912 JNIEXPORT jlong JNICALL
 913 Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentProcess(JNIEnv* env, jclass this) {
 914     HANDLE hProcess = GetCurrentProcess();
 915     return ptr_to_jlong(hProcess);
 916 }
 917 
 918 JNIEXPORT jlong JNICALL
 919 Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentThread(JNIEnv* env, jclass this) {
 920     HANDLE hThread = GetCurrentThread();
 921     return ptr_to_jlong(hThread);
 922 }
 923 
 924 JNIEXPORT jlong JNICALL
 925 Java_sun_nio_fs_WindowsNativeDispatcher_OpenProcessToken(JNIEnv* env,
 926     jclass this, jlong process, jint desiredAccess)
 927 {
 928     HANDLE hProcess = (HANDLE)jlong_to_ptr(process);
 929     HANDLE hToken;
 930 
 931     if (OpenProcessToken(hProcess, (DWORD)desiredAccess, &hToken) == 0)
 932         throwWindowsException(env, GetLastError());
 933     return ptr_to_jlong(hToken);
 934 }
 935 
 936 JNIEXPORT jlong JNICALL
 937 Java_sun_nio_fs_WindowsNativeDispatcher_OpenThreadToken(JNIEnv* env,
 938     jclass this, jlong thread, jint desiredAccess, jboolean openAsSelf)
 939 {
 940     HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
 941     HANDLE hToken;
 942     BOOL bOpenAsSelf = (openAsSelf == JNI_TRUE) ? TRUE : FALSE;
 943 
 944     if (OpenThreadToken(hThread, (DWORD)desiredAccess, bOpenAsSelf, &hToken) == 0) {
 945         if (GetLastError() == ERROR_NO_TOKEN)
 946             return (jlong)0;
 947         throwWindowsException(env, GetLastError());
 948     }
 949     return ptr_to_jlong(hToken);
 950 }
 951 
 952 JNIEXPORT jlong JNICALL
 953 Java_sun_nio_fs_WindowsNativeDispatcher_DuplicateTokenEx(JNIEnv* env,
 954     jclass this, jlong token, jint desiredAccess)
 955 {
 956     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 957     HANDLE resultToken;
 958     BOOL res;
 959 
 960     res = DuplicateTokenEx(hToken,
 961                            (DWORD)desiredAccess,
 962                            NULL,
 963                            SecurityImpersonation,
 964                            TokenImpersonation,
 965                            &resultToken);
 966     if (res == 0)
 967         throwWindowsException(env, GetLastError());
 968     return ptr_to_jlong(resultToken);
 969 }
 970 
 971 JNIEXPORT void JNICALL
 972 Java_sun_nio_fs_WindowsNativeDispatcher_SetThreadToken(JNIEnv* env,
 973     jclass this, jlong thread, jlong token)
 974 {
 975     HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
 976     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 977 
 978     if (SetThreadToken(hThread, hToken) == 0)
 979         throwWindowsException(env, GetLastError());
 980 }
 981 
 982 JNIEXPORT jint JNICALL
 983 Java_sun_nio_fs_WindowsNativeDispatcher_GetTokenInformation(JNIEnv* env,
 984     jclass this, jlong token, jint tokenInfoClass, jlong tokenInfo, jint tokenInfoLength)
 985 {
 986     BOOL res;
 987     DWORD lengthNeeded;
 988     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 989     LPVOID result = (LPVOID)jlong_to_ptr(tokenInfo);
 990 
 991     res = GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)tokenInfoClass, (LPVOID)result,
 992                               tokenInfoLength, &lengthNeeded);
 993     if (res == 0) {
 994         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 995             return (jint)lengthNeeded;
 996         } else {
 997             throwWindowsException(env, GetLastError());
 998             return 0;
 999         }
1000     } else {
1001         return tokenInfoLength;
1002     }
1003 }
1004 
1005 JNIEXPORT void JNICALL
1006 Java_sun_nio_fs_WindowsNativeDispatcher_AdjustTokenPrivileges(JNIEnv* env,
1007     jclass this, jlong token, jlong luid, jint attributes)
1008 {
1009     TOKEN_PRIVILEGES privs[1];
1010     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
1011     PLUID pLuid = (PLUID)jlong_to_ptr(luid);
1012 
1013     privs[0].PrivilegeCount = 1;
1014     privs[0].Privileges[0].Luid = *pLuid;
1015     privs[0].Privileges[0].Attributes = (DWORD)attributes;
1016 
1017     if (AdjustTokenPrivileges(hToken, FALSE, &privs[0], 1, NULL, NULL) == 0)
1018         throwWindowsException(env, GetLastError());
1019 }
1020 
1021 JNIEXPORT jboolean JNICALL
1022 Java_sun_nio_fs_WindowsNativeDispatcher_AccessCheck(JNIEnv* env,
1023     jclass this, jlong token, jlong securityInfo, jint accessMask,
1024     jint genericRead, jint genericWrite, jint genericExecute, jint genericAll)
1025 {
1026     HANDLE hImpersonatedToken = (HANDLE)jlong_to_ptr(token);
1027     PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)jlong_to_ptr(securityInfo);
1028     DWORD checkAccessRights = (DWORD)accessMask;
1029     GENERIC_MAPPING mapping = {
1030         genericRead,
1031         genericWrite,
1032         genericExecute,
1033         genericAll};
1034     PRIVILEGE_SET privileges = {0};
1035     DWORD privilegesLength = sizeof(privileges);
1036     DWORD grantedAccess = 0;
1037     BOOL result = FALSE;
1038 
1039     /* checkAccessRights is in-out parameter */
1040     MapGenericMask(&checkAccessRights, &mapping);
1041     if (AccessCheck(security, hImpersonatedToken, checkAccessRights,
1042             &mapping, &privileges, &privilegesLength, &grantedAccess, &result) == 0)
1043         throwWindowsException(env, GetLastError());
1044 
1045     return (result == FALSE) ? JNI_FALSE : JNI_TRUE;
1046 }
1047 
1048 JNIEXPORT jlong JNICALL
1049 Java_sun_nio_fs_WindowsNativeDispatcher_LookupPrivilegeValue0(JNIEnv* env,
1050     jclass this, jlong name)
1051 {
1052     LPCWSTR lpName = (LPCWSTR)jlong_to_ptr(name);
1053     PLUID pLuid = LocalAlloc(0, sizeof(LUID));
1054 
1055     if (pLuid == NULL) {
1056         JNU_ThrowInternalError(env, "Unable to allocate LUID structure");
1057     } else {
1058         if (LookupPrivilegeValueW(NULL, lpName, pLuid) == 0) {
1059             LocalFree(pLuid);
1060             throwWindowsException(env, GetLastError());
1061             return (jlong)0;
1062         }
1063     }
1064     return ptr_to_jlong(pLuid);
1065 }
1066 
1067 JNIEXPORT void JNICALL
1068 Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
1069     jclass this, jlong linkAddress, jlong targetAddress, jint flags)
1070 {
1071     LPCWSTR link = jlong_to_ptr(linkAddress);
1072     LPCWSTR target = jlong_to_ptr(targetAddress);
1073 
1074     if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0)
1075         throwWindowsException(env, GetLastError());
1076 }
1077 
1078 JNIEXPORT void JNICALL
1079 Java_sun_nio_fs_WindowsNativeDispatcher_CreateHardLink0(JNIEnv* env,
1080     jclass this, jlong newFileAddress, jlong existingFileAddress)
1081 {
1082     LPCWSTR newFile = jlong_to_ptr(newFileAddress);
1083     LPCWSTR existingFile = jlong_to_ptr(existingFileAddress);
1084 
1085     if (CreateHardLinkW(newFile, existingFile, NULL) == 0)
1086         throwWindowsException(env, GetLastError());
1087 }
1088 
1089 JNIEXPORT jstring JNICALL
1090 Java_sun_nio_fs_WindowsNativeDispatcher_GetFullPathName0(JNIEnv *env,
1091                                                          jclass clz,
1092                                                          jlong pathAddress)
1093 {
1094     jstring rv = NULL;
1095     WCHAR *lpBuf = NULL;
1096     WCHAR buf[MAX_PATH];
1097     DWORD len;
1098     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
1099 
1100     len = GetFullPathNameW(lpFileName, MAX_PATH, buf, NULL);
1101     if (len > 0) {
1102         if (len < MAX_PATH) {
1103             rv = (*env)->NewString(env, buf, len);
1104         } else {
1105             len += 1;  /* return length does not include terminator */
1106             lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
1107             if (lpBuf != NULL) {
1108                 len = GetFullPathNameW(lpFileName, len, lpBuf, NULL);
1109                 if (len > 0) {
1110                     rv = (*env)->NewString(env, lpBuf, len);
1111                 } else {
1112                     JNU_ThrowInternalError(env, "GetFullPathNameW failed");
1113                 }
1114                 free(lpBuf);
1115             } else {
1116                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
1117             }
1118         }
1119     } else {
1120         throwWindowsException(env, GetLastError());
1121     }
1122 
1123     return rv;
1124 }
1125 
1126 JNIEXPORT jstring JNICALL
1127 Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
1128     jclass this, jlong handle)
1129 {
1130     jstring rv = NULL;
1131     WCHAR *lpBuf = NULL;
1132     WCHAR path[MAX_PATH];
1133     HANDLE h = (HANDLE)jlong_to_ptr(handle);
1134     DWORD len;
1135 
1136     len = GetFinalPathNameByHandleW(h, path, MAX_PATH, 0);
1137     if (len > 0) {
1138         if (len < MAX_PATH) {
1139             rv = (*env)->NewString(env, (const jchar *)path, (jsize)len);
1140         } else {
1141             len += 1;  /* return length does not include terminator */
1142             lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
1143             if (lpBuf != NULL) {
1144                 len = GetFinalPathNameByHandleW(h, lpBuf, len, 0);
1145                 if (len > 0)  {
1146                     rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len);
1147                 } else {
1148                     JNU_ThrowInternalError(env, "GetFinalPathNameByHandleW failed");
1149                 }
1150                 free(lpBuf);
1151             } else {
1152                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
1153             }
1154         }
1155     } else {
1156         throwWindowsException(env, GetLastError());
1157     }
1158     return rv;
1159 }
1160 
1161 JNIEXPORT jlong JNICALL
1162 Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
1163     jlong fileHandle, jlong existingPort, jlong completionKey)
1164 {
1165     HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
1166                                          (HANDLE)jlong_to_ptr(existingPort),
1167                                          (ULONG_PTR)completionKey,
1168                                          0);
1169     if (port == NULL) {
1170         throwWindowsException(env, GetLastError());
1171     }
1172     return ptr_to_jlong(port);
1173 }
1174 
1175 JNIEXPORT void JNICALL
1176 Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jclass this,
1177     jlong completionPort, jobject obj)
1178 {
1179     DWORD bytesTransferred;
1180     ULONG_PTR completionKey;
1181     OVERLAPPED *lpOverlapped;
1182     BOOL res;
1183 
1184     res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
1185                                   &bytesTransferred,
1186                                   &completionKey,
1187                                   &lpOverlapped,
1188                                   INFINITE);
1189     if (res == 0 && lpOverlapped == NULL) {
1190         throwWindowsException(env, GetLastError());
1191     } else {
1192         DWORD ioResult = (res == 0) ? GetLastError() : 0;
1193         (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
1194         (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
1195             (jint)bytesTransferred);
1196         (*env)->SetLongField(env, obj, completionStatus_completionKey,
1197             (jlong)completionKey);
1198     }
1199 }
1200 
1201 JNIEXPORT void JNICALL
1202 Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
1203     jlong completionPort, jlong completionKey)
1204 {
1205     BOOL res;
1206 
1207     res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
1208                                      (DWORD)0,  /* dwNumberOfBytesTransferred */
1209                                      (ULONG_PTR)completionKey,
1210                                      NULL);  /* lpOverlapped */
1211     if (res == 0) {
1212         throwWindowsException(env, GetLastError());
1213     }
1214 }
1215 
1216 JNIEXPORT void JNICALL
1217 Java_sun_nio_fs_WindowsNativeDispatcher_CancelIo(JNIEnv* env, jclass this, jlong hFile) {
1218     if (CancelIo((HANDLE)jlong_to_ptr(hFile)) == 0) {
1219         throwWindowsException(env, GetLastError());
1220     }
1221 }
1222 
1223 JNIEXPORT jint JNICALL
1224 Java_sun_nio_fs_WindowsNativeDispatcher_GetOverlappedResult(JNIEnv *env, jclass this,
1225     jlong hFile, jlong lpOverlapped)
1226 {
1227     BOOL res;
1228     DWORD bytesTransferred = -1;
1229 
1230     res = GetOverlappedResult((HANDLE)jlong_to_ptr(hFile),
1231                               (LPOVERLAPPED)jlong_to_ptr(lpOverlapped),
1232                               &bytesTransferred,
1233                               TRUE);
1234     if (res == 0) {
1235         throwWindowsException(env, GetLastError());
1236     }
1237 
1238     return (jint)bytesTransferred;
1239 }
1240 
1241 JNIEXPORT void JNICALL
1242 Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this,
1243     jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter,
1244     jlong bytesReturnedAddress, jlong pOverlapped)
1245 {
1246     BOOL res;
1247     BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
1248     LPOVERLAPPED ov = (LPOVERLAPPED)jlong_to_ptr(pOverlapped);
1249 
1250     res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
1251                                 (LPVOID)jlong_to_ptr(bufferAddress),
1252                                 (DWORD)bufferLength,
1253                                 subtree,
1254                                 (DWORD)filter,
1255                                 (LPDWORD)jlong_to_ptr(bytesReturnedAddress),
1256                                 (LPOVERLAPPED)jlong_to_ptr(pOverlapped),
1257                                 NULL);
1258     if (res == 0) {
1259         throwWindowsException(env, GetLastError());
1260     }
1261 }