1 /*
   2  * Copyright (c) 2008, 2016, 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         return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
 181     }
 182 }
 183 
 184 JNIEXPORT void JNICALL
 185 Java_sun_nio_fs_WindowsNativeDispatcher_LocalFree(JNIEnv* env, jclass this, jlong address)
 186 {
 187     HLOCAL hMem = (HLOCAL)jlong_to_ptr(address);
 188     LocalFree(hMem);
 189 }
 190 
 191 JNIEXPORT jlong JNICALL
 192 Java_sun_nio_fs_WindowsNativeDispatcher_CreateFile0(JNIEnv* env, jclass this,
 193     jlong address, jint dwDesiredAccess, jint dwShareMode, jlong sdAddress,
 194     jint dwCreationDisposition, jint dwFlagsAndAttributes)
 195 {
 196     HANDLE handle;
 197     LPCWSTR lpFileName = jlong_to_ptr(address);
 198 
 199     SECURITY_ATTRIBUTES securityAttributes;
 200     LPSECURITY_ATTRIBUTES lpSecurityAttributes;
 201     PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
 202 
 203 
 204     if (lpSecurityDescriptor == NULL) {
 205         lpSecurityAttributes = NULL;
 206     } else {
 207         securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
 208         securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
 209         securityAttributes.bInheritHandle = FALSE;
 210         lpSecurityAttributes = &securityAttributes;
 211     }
 212 
 213     handle = CreateFileW(lpFileName,
 214                         (DWORD)dwDesiredAccess,
 215                         (DWORD)dwShareMode,
 216                         lpSecurityAttributes,
 217                         (DWORD)dwCreationDisposition,
 218                         (DWORD)dwFlagsAndAttributes,
 219                         NULL);
 220     if (handle == INVALID_HANDLE_VALUE) {
 221         throwWindowsException(env, GetLastError());
 222     }
 223     return ptr_to_jlong(handle);
 224 }
 225 
 226 
 227 JNIEXPORT void JNICALL
 228 Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlSetSparse(JNIEnv* env, jclass this,
 229     jlong handle)
 230 {
 231     DWORD bytesReturned;
 232     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 233     if (DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesReturned, NULL) == 0) {
 234         throwWindowsException(env, GetLastError());
 235     }
 236 }
 237 
 238 JNIEXPORT void JNICALL
 239 Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlGetReparsePoint(JNIEnv* env, jclass this,
 240     jlong handle, jlong bufferAddress, jint bufferSize)
 241 {
 242     DWORD bytesReturned;
 243     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 244     LPVOID outBuffer = (LPVOID)jlong_to_ptr(bufferAddress);
 245 
 246     if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, outBuffer, (DWORD)bufferSize,
 247                         &bytesReturned, NULL) == 0)
 248     {
 249         throwWindowsException(env, GetLastError());
 250     }
 251 }
 252 
 253 JNIEXPORT void JNICALL
 254 Java_sun_nio_fs_WindowsNativeDispatcher_DeleteFile0(JNIEnv* env, jclass this, jlong address)
 255 {
 256     LPCWSTR lpFileName = jlong_to_ptr(address);
 257     if (DeleteFileW(lpFileName) == 0) {
 258         throwWindowsException(env, GetLastError());
 259     }
 260 }
 261 
 262 JNIEXPORT void JNICALL
 263 Java_sun_nio_fs_WindowsNativeDispatcher_CreateDirectory0(JNIEnv* env, jclass this,
 264     jlong address, jlong sdAddress)
 265 {
 266     LPCWSTR lpFileName = jlong_to_ptr(address);
 267 
 268     SECURITY_ATTRIBUTES securityAttributes;
 269     LPSECURITY_ATTRIBUTES lpSecurityAttributes;
 270     PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress);
 271 
 272 
 273     if (lpSecurityDescriptor == NULL) {
 274         lpSecurityAttributes = NULL;
 275     } else {
 276         securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
 277         securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
 278         securityAttributes.bInheritHandle = FALSE;
 279         lpSecurityAttributes = &securityAttributes;
 280     }
 281 
 282     if (CreateDirectoryW(lpFileName, lpSecurityAttributes) == 0) {
 283         throwWindowsException(env, GetLastError());
 284     }
 285 }
 286 
 287 JNIEXPORT void JNICALL
 288 Java_sun_nio_fs_WindowsNativeDispatcher_RemoveDirectory0(JNIEnv* env, jclass this, jlong address)
 289 {
 290     LPCWSTR lpFileName = jlong_to_ptr(address);
 291     if (RemoveDirectoryW(lpFileName) == 0) {
 292         throwWindowsException(env, GetLastError());
 293     }
 294 }
 295 
 296 JNIEXPORT void JNICALL
 297 Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this,
 298     jlong handle)
 299 {
 300     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 301     CloseHandle(h);
 302 }
 303 
 304 JNIEXPORT void JNICALL
 305 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
 306     jlong address, jobject obj)
 307 {
 308     WIN32_FIND_DATAW data;
 309     LPCWSTR lpFileName = jlong_to_ptr(address);
 310 
 311     HANDLE handle = FindFirstFileW(lpFileName, &data);
 312     if (handle != INVALID_HANDLE_VALUE) {
 313         jstring name = (*env)->NewString(env, data.cFileName, (jsize)wcslen(data.cFileName));
 314         if (name == NULL)
 315             return;
 316         (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
 317         (*env)->SetObjectField(env, obj, findFirst_name, name);
 318         (*env)->SetIntField(env, obj, findFirst_attributes, data.dwFileAttributes);
 319     } else {
 320         throwWindowsException(env, GetLastError());
 321     }
 322 }
 323 
 324 JNIEXPORT jlong JNICALL
 325 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this,
 326     jlong pathAddress, jlong dataAddress)
 327 {
 328     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 329     WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
 330 
 331     HANDLE handle = FindFirstFileW(lpFileName, data);
 332     if (handle == INVALID_HANDLE_VALUE) {
 333         throwWindowsException(env, GetLastError());
 334     }
 335     return ptr_to_jlong(handle);
 336 }
 337 
 338 JNIEXPORT jstring JNICALL
 339 Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
 340     jlong handle, jlong dataAddress)
 341 {
 342     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 343     WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
 344 
 345     if (FindNextFileW(h, data) != 0) {
 346         return (*env)->NewString(env, data->cFileName, (jsize)wcslen(data->cFileName));
 347     } else {
 348     if (GetLastError() != ERROR_NO_MORE_FILES)
 349         throwWindowsException(env, GetLastError());
 350         return NULL;
 351     }
 352 }
 353 
 354 JNIEXPORT void JNICALL
 355 Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass this,
 356     jlong address, jobject obj)
 357 {
 358     WIN32_FIND_STREAM_DATA data;
 359     LPCWSTR lpFileName = jlong_to_ptr(address);
 360     HANDLE handle;
 361 
 362     handle = FindFirstStreamW(lpFileName, FindStreamInfoStandard, &data, 0);
 363     if (handle != INVALID_HANDLE_VALUE) {
 364         jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
 365         if (name == NULL)
 366             return;
 367         (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
 368         (*env)->SetObjectField(env, obj, findStream_name, name);
 369     } else {
 370         if (GetLastError() == ERROR_HANDLE_EOF) {
 371              (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle));
 372         } else {
 373             throwWindowsException(env, GetLastError());
 374         }
 375     }
 376 
 377 }
 378 
 379 JNIEXPORT jstring JNICALL
 380 Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this,
 381     jlong handle)
 382 {
 383     WIN32_FIND_STREAM_DATA data;
 384     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 385 
 386     if (FindNextStreamW(h, &data) != 0) {
 387         return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
 388     } else {
 389         if (GetLastError() != ERROR_HANDLE_EOF)
 390             throwWindowsException(env, GetLastError());
 391         return NULL;
 392     }
 393 }
 394 
 395 
 396 JNIEXPORT void JNICALL
 397 Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this,
 398     jlong handle)
 399 {
 400     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 401     if (FindClose(h) == 0) {
 402         throwWindowsException(env, GetLastError());
 403     }
 404 }
 405 
 406 
 407 JNIEXPORT void JNICALL
 408 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this,
 409     jlong handle, jlong address)
 410 {
 411     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 412     BY_HANDLE_FILE_INFORMATION* info =
 413         (BY_HANDLE_FILE_INFORMATION*)jlong_to_ptr(address);
 414     if (GetFileInformationByHandle(h, info) == 0) {
 415         throwWindowsException(env, GetLastError());
 416     }
 417 }
 418 
 419 
 420 JNIEXPORT void JNICALL
 421 Java_sun_nio_fs_WindowsNativeDispatcher_CopyFileEx0(JNIEnv* env, jclass this,
 422     jlong existingAddress, jlong newAddress, jint flags, jlong cancelAddress)
 423 {
 424     LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
 425     LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
 426     LPBOOL cancel = (LPBOOL)jlong_to_ptr(cancelAddress);
 427     if (CopyFileExW(lpExistingFileName, lpNewFileName, NULL, NULL, cancel,
 428                     (DWORD)flags) == 0)
 429     {
 430         throwWindowsException(env, GetLastError());
 431     }
 432 }
 433 
 434 JNIEXPORT void JNICALL
 435 Java_sun_nio_fs_WindowsNativeDispatcher_MoveFileEx0(JNIEnv* env, jclass this,
 436     jlong existingAddress, jlong newAddress, jint flags)
 437 {
 438     LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress);
 439     LPCWSTR lpNewFileName = jlong_to_ptr(newAddress);
 440     if (MoveFileExW(lpExistingFileName, lpNewFileName, (DWORD)flags) == 0) {
 441         throwWindowsException(env, GetLastError());
 442     }
 443 }
 444 
 445 JNIEXPORT jint JNICALL
 446 Java_sun_nio_fs_WindowsNativeDispatcher_GetLogicalDrives(JNIEnv* env, jclass this)
 447 {
 448     DWORD res = GetLogicalDrives();
 449     if (res == 0) {
 450         throwWindowsException(env, GetLastError());
 451     }
 452     return (jint)res;
 453 }
 454 
 455 JNIEXPORT jint JNICALL
 456 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributes0(JNIEnv* env, jclass this,
 457     jlong address)
 458 {
 459     LPCWSTR lpFileName = jlong_to_ptr(address);
 460     DWORD value = GetFileAttributesW(lpFileName);
 461 
 462     if (value == INVALID_FILE_ATTRIBUTES) {
 463         throwWindowsException(env, GetLastError());
 464     }
 465     return (jint)value;
 466 }
 467 
 468 JNIEXPORT void JNICALL
 469 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileAttributes0(JNIEnv* env, jclass this,
 470     jlong address, jint value)
 471 {
 472     LPCWSTR lpFileName = jlong_to_ptr(address);
 473     if (SetFileAttributesW(lpFileName, (DWORD)value) == 0) {
 474         throwWindowsException(env, GetLastError());
 475     }
 476 }
 477 
 478 JNIEXPORT void JNICALL
 479 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributesEx0(JNIEnv* env, jclass this,
 480     jlong pathAddress, jlong dataAddress)
 481 {
 482     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 483     WIN32_FILE_ATTRIBUTE_DATA* data = (WIN32_FILE_ATTRIBUTE_DATA*)jlong_to_ptr(dataAddress);
 484 
 485     BOOL res = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, (LPVOID)data);
 486     if (res == 0)
 487         throwWindowsException(env, GetLastError());
 488 }
 489 
 490 
 491 JNIEXPORT void JNICALL
 492 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this,
 493     jlong handle, jlong createTime, jlong lastAccessTime, jlong lastWriteTime)
 494 {
 495     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 496 
 497     if (SetFileTime(h,
 498         (createTime == (jlong)-1) ? NULL : (CONST FILETIME *)&createTime,
 499         (lastAccessTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastAccessTime,
 500         (lastWriteTime == (jlong)-1) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0)
 501     {
 502         throwWindowsException(env, GetLastError());
 503     }
 504 }
 505 
 506 JNIEXPORT void JNICALL
 507 Java_sun_nio_fs_WindowsNativeDispatcher_SetEndOfFile(JNIEnv* env, jclass this,
 508     jlong handle)
 509 {
 510     HANDLE h = (HANDLE)jlong_to_ptr(handle);
 511 
 512     if (SetEndOfFile(h) == 0)
 513         throwWindowsException(env, GetLastError());
 514 }
 515 
 516 
 517 JNIEXPORT void JNICALL
 518 Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumeInformation0(JNIEnv* env, jclass this,
 519     jlong address, jobject obj)
 520 {
 521     WCHAR volumeName[MAX_PATH+1];
 522     DWORD volumeSerialNumber;
 523     DWORD maxComponentLength;
 524     DWORD flags;
 525     WCHAR fileSystemName[MAX_PATH+1];
 526     LPCWSTR lpFileName = jlong_to_ptr(address);
 527     jstring str;
 528 
 529     BOOL res = GetVolumeInformationW(lpFileName,
 530                                      &volumeName[0],
 531                                      MAX_PATH+1,
 532                                      &volumeSerialNumber,
 533                                      &maxComponentLength,
 534                                      &flags,
 535                                      &fileSystemName[0],
 536                                      MAX_PATH+1);
 537     if (res == 0) {
 538         throwWindowsException(env, GetLastError());
 539         return;
 540     }
 541 
 542     str = (*env)->NewString(env, (const jchar *)fileSystemName, (jsize)wcslen(fileSystemName));
 543     if (str == NULL) return;
 544     (*env)->SetObjectField(env, obj, volumeInfo_fsName, str);
 545 
 546     str = (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
 547     if (str == NULL) return;
 548     (*env)->SetObjectField(env, obj, volumeInfo_volName, str);
 549 
 550     (*env)->SetIntField(env, obj, volumeInfo_volSN, (jint)volumeSerialNumber);
 551     (*env)->SetIntField(env, obj, volumeInfo_flags, (jint)flags);
 552 }
 553 
 554 
 555 JNIEXPORT jint JNICALL
 556 Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0(JNIEnv* env, jclass this, jlong address) {
 557     LPCWSTR lpRootPathName = jlong_to_ptr(address);
 558     return (jint)GetDriveTypeW(lpRootPathName);
 559 }
 560 
 561 
 562 JNIEXPORT void JNICALL
 563 Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpaceEx0(JNIEnv* env, jclass this,
 564     jlong address, jobject obj)
 565 {
 566     ULARGE_INTEGER freeBytesAvailable;
 567     ULARGE_INTEGER totalNumberOfBytes;
 568     ULARGE_INTEGER totalNumberOfFreeBytes;
 569     LPCWSTR lpDirName = jlong_to_ptr(address);
 570 
 571 
 572     BOOL res = GetDiskFreeSpaceExW(lpDirName,
 573                                    &freeBytesAvailable,
 574                                    &totalNumberOfBytes,
 575                                    &totalNumberOfFreeBytes);
 576     if (res == 0) {
 577         throwWindowsException(env, GetLastError());
 578         return;
 579     }
 580 
 581     (*env)->SetLongField(env, obj, diskSpace_bytesAvailable,
 582         long_to_jlong(freeBytesAvailable.QuadPart));
 583     (*env)->SetLongField(env, obj, diskSpace_totalBytes,
 584         long_to_jlong(totalNumberOfBytes.QuadPart));
 585     (*env)->SetLongField(env, obj, diskSpace_totalFree,
 586         long_to_jlong(totalNumberOfFreeBytes.QuadPart));
 587 }
 588 
 589 JNIEXPORT void JNICALL
 590 Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpace0(JNIEnv* env, jclass this,
 591     jlong address, jobject obj)
 592 {
 593     DWORD sectorsPerCluster;
 594     DWORD bytesPerSector;
 595     DWORD numberOfFreeClusters;
 596     DWORD totalNumberOfClusters;
 597     LPCWSTR lpRootPathName = jlong_to_ptr(address);
 598 
 599 
 600     BOOL res = GetDiskFreeSpaceW(lpRootPathName,
 601                                  &sectorsPerCluster,
 602                                  &bytesPerSector,
 603                                  &numberOfFreeClusters,
 604                                  &totalNumberOfClusters);
 605     if (res == 0) {
 606         throwWindowsException(env, GetLastError());
 607         return;
 608     }
 609 
 610     (*env)->SetLongField(env, obj, diskSpace_bytesPerSector,
 611         long_to_jlong(bytesPerSector));
 612 }
 613 
 614 JNIEXPORT jstring JNICALL
 615 Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this,
 616     jlong address)
 617 {
 618     WCHAR volumeName[MAX_PATH+1];
 619     LPCWSTR lpFileName = jlong_to_ptr(address);
 620 
 621 
 622     BOOL res = GetVolumePathNameW(lpFileName,
 623                                   &volumeName[0],
 624                                   MAX_PATH+1);
 625     if (res == 0) {
 626         throwWindowsException(env, GetLastError());
 627         return NULL;
 628     } else {
 629         return (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName));
 630     }
 631 }
 632 
 633 JNIEXPORT void JNICALL
 634 Java_sun_nio_fs_WindowsNativeDispatcher_InitializeSecurityDescriptor(JNIEnv* env, jclass this,
 635     jlong address)
 636 {
 637     PSECURITY_DESCRIPTOR pSecurityDescriptor =
 638         (PSECURITY_DESCRIPTOR)jlong_to_ptr(address);
 639 
 640     if (InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) == 0) {
 641         throwWindowsException(env, GetLastError());
 642     }
 643 }
 644 
 645 JNIEXPORT void JNICALL
 646 Java_sun_nio_fs_WindowsNativeDispatcher_InitializeAcl(JNIEnv* env, jclass this,
 647     jlong address, jint size)
 648 {
 649     PACL pAcl = (PACL)jlong_to_ptr(address);
 650 
 651     if (InitializeAcl(pAcl, (DWORD)size, ACL_REVISION) == 0) {
 652         throwWindowsException(env, GetLastError());
 653     }
 654 }
 655 
 656 
 657 JNIEXPORT void JNICALL
 658 Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this,
 659     jlong pathAddress, jint requestedInformation, jlong descAddress)
 660 {
 661     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 662     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 663     DWORD lengthNeeded = 0;
 664 
 665     BOOL res = SetFileSecurityW(lpFileName,
 666                                 (SECURITY_INFORMATION)requestedInformation,
 667                                 pSecurityDescriptor);
 668 
 669     if (res == 0) {
 670         throwWindowsException(env, GetLastError());
 671     }
 672 }
 673 
 674 JNIEXPORT jint JNICALL
 675 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSecurity0(JNIEnv* env, jclass this,
 676     jlong pathAddress, jint requestedInformation, jlong descAddress, jint nLength)
 677 {
 678     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
 679     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 680     DWORD lengthNeeded = 0;
 681 
 682     BOOL res = GetFileSecurityW(lpFileName,
 683                                 (SECURITY_INFORMATION)requestedInformation,
 684                                 pSecurityDescriptor,
 685                                 (DWORD)nLength,
 686                                 &lengthNeeded);
 687 
 688     if (res == 0) {
 689         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 690             return (jint)lengthNeeded;
 691         } else {
 692             throwWindowsException(env, GetLastError());
 693             return 0;
 694         }
 695     } else {
 696         return (jint)nLength;
 697     }
 698 }
 699 
 700 JNIEXPORT jlong JNICALL
 701 Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorOwner(JNIEnv* env,
 702     jclass this, jlong address)
 703 {
 704     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
 705     PSID pOwner;
 706     BOOL bOwnerDefaulted;
 707 
 708 
 709     if (GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwner, &bOwnerDefaulted) == 0) {
 710         throwWindowsException(env, GetLastError());
 711     }
 712     return ptr_to_jlong(pOwner);
 713 }
 714 
 715 JNIEXPORT void JNICALL
 716 Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorOwner(JNIEnv* env,
 717     jclass this, jlong descAddress, jlong ownerAddress)
 718 {
 719     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
 720     PSID pOwner = jlong_to_ptr(ownerAddress);
 721 
 722     if (SetSecurityDescriptorOwner(pSecurityDescriptor, pOwner, FALSE) == 0) {
 723         throwWindowsException(env, GetLastError());
 724     }
 725 }
 726 
 727 
 728 JNIEXPORT jlong JNICALL
 729 Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorDacl(JNIEnv* env,
 730     jclass this, jlong address)
 731 {
 732     PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address);
 733     BOOL bDaclPresent;
 734     PACL pDacl;
 735     BOOL bDaclDefaulted;
 736 
 737     if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) == 0) {
 738         throwWindowsException(env, GetLastError());
 739         return (jlong)0;
 740     } else {
 741         return (bDaclPresent) ? ptr_to_jlong(pDacl) : (jlong)0;
 742     }
 743 }
 744 
 745 JNIEXPORT void JNICALL
 746 Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorDacl(JNIEnv* env,
 747     jclass this, jlong descAddress, jlong aclAddress)
 748 {
 749     PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR)jlong_to_ptr(descAddress);
 750     PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
 751 
 752     if (SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pAcl, FALSE) == 0) {
 753         throwWindowsException(env, GetLastError());
 754     }
 755 }
 756 
 757 
 758 JNIEXPORT void JNICALL
 759 Java_sun_nio_fs_WindowsNativeDispatcher_GetAclInformation0(JNIEnv* env,
 760     jclass this, jlong address, jobject obj)
 761 {
 762     PACL pAcl = (PACL)jlong_to_ptr(address);
 763     ACL_SIZE_INFORMATION acl_size_info;
 764 
 765     if (GetAclInformation(pAcl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation) == 0) {
 766         throwWindowsException(env, GetLastError());
 767     } else {
 768         (*env)->SetIntField(env, obj, aclInfo_aceCount, (jint)acl_size_info.AceCount);
 769     }
 770 }
 771 
 772 JNIEXPORT jlong JNICALL
 773 Java_sun_nio_fs_WindowsNativeDispatcher_GetAce(JNIEnv* env, jclass this, jlong address,
 774     jint aceIndex)
 775 {
 776     PACL pAcl = (PACL)jlong_to_ptr(address);
 777     LPVOID pAce;
 778 
 779     if (GetAce(pAcl, (DWORD)aceIndex, &pAce) == 0) {
 780         throwWindowsException(env, GetLastError());
 781         return (jlong)0;
 782     } else {
 783         return ptr_to_jlong(pAce);
 784     }
 785 }
 786 
 787 JNIEXPORT void JNICALL
 788 Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessAllowedAceEx(JNIEnv* env,
 789     jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress)
 790 {
 791     PACL pAcl = (PACL)jlong_to_ptr(aclAddress);
 792     PSID pSid = (PSID)jlong_to_ptr(sidAddress);
 793 
 794     if (AddAccessAllowedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
 795         throwWindowsException(env, GetLastError());
 796     }
 797 }
 798 
 799 JNIEXPORT void JNICALL
 800 Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessDeniedAceEx(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 (AddAccessDeniedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) {
 807         throwWindowsException(env, GetLastError());
 808     }
 809 }
 810 
 811 
 812 JNIEXPORT void JNICALL
 813 Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env,
 814     jclass this, jlong address, jobject obj)
 815 {
 816     WCHAR domain[255];
 817     WCHAR name[255];
 818     DWORD domainLen = sizeof(domain);
 819     DWORD nameLen = sizeof(name);
 820     SID_NAME_USE use;
 821     PSID sid = jlong_to_ptr(address);
 822     jstring s;
 823 
 824     if (LookupAccountSidW(NULL, sid, &name[0], &nameLen, &domain[0], &domainLen, &use) == 0) {
 825         throwWindowsException(env, GetLastError());
 826         return;
 827     }
 828 
 829     s = (*env)->NewString(env, (const jchar *)domain, (jsize)wcslen(domain));
 830     if (s == NULL)
 831         return;
 832     (*env)->SetObjectField(env, obj, account_domain, s);
 833 
 834     s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name));
 835     if (s == NULL)
 836         return;
 837     (*env)->SetObjectField(env, obj, account_name, s);
 838     (*env)->SetIntField(env, obj, account_use, (jint)use);
 839 }
 840 
 841 JNIEXPORT jint JNICALL
 842 Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env,
 843     jclass this, jlong nameAddress, jlong sidAddress, jint cbSid)
 844 {
 845 
 846     LPCWSTR accountName = jlong_to_ptr(nameAddress);
 847     PSID sid = jlong_to_ptr(sidAddress);
 848     WCHAR domain[255];
 849     DWORD domainLen = sizeof(domain);
 850     SID_NAME_USE use;
 851 
 852     if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid,
 853                            &domain[0], &domainLen, &use) == 0)
 854     {
 855         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 856             throwWindowsException(env, GetLastError());
 857         }
 858     }
 859 
 860     return cbSid;
 861 }
 862 
 863 JNIEXPORT jint JNICALL
 864 Java_sun_nio_fs_WindowsNativeDispatcher_GetLengthSid(JNIEnv* env,
 865     jclass this, jlong address)
 866 {
 867     PSID sid = jlong_to_ptr(address);
 868     return (jint)GetLengthSid(sid);
 869 }
 870 
 871 
 872 JNIEXPORT jstring JNICALL
 873 Java_sun_nio_fs_WindowsNativeDispatcher_ConvertSidToStringSid(JNIEnv* env,
 874     jclass this, jlong address)
 875 {
 876     PSID sid = jlong_to_ptr(address);
 877     LPWSTR string;
 878     if (ConvertSidToStringSidW(sid, &string) == 0) {
 879         throwWindowsException(env, GetLastError());
 880         return NULL;
 881     } else {
 882         jstring s = (*env)->NewString(env, (const jchar *)string,
 883             (jsize)wcslen(string));
 884         LocalFree(string);
 885         return s;
 886     }
 887 }
 888 
 889 JNIEXPORT jlong JNICALL
 890 Java_sun_nio_fs_WindowsNativeDispatcher_ConvertStringSidToSid0(JNIEnv* env,
 891     jclass this, jlong address)
 892 {
 893     LPWSTR lpStringSid = jlong_to_ptr(address);
 894     PSID pSid;
 895     if (ConvertStringSidToSidW(lpStringSid, &pSid) == 0)
 896         throwWindowsException(env, GetLastError());
 897     return ptr_to_jlong(pSid);
 898 }
 899 
 900 JNIEXPORT jlong JNICALL
 901 Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentProcess(JNIEnv* env, jclass this) {
 902     HANDLE hProcess = GetCurrentProcess();
 903     return ptr_to_jlong(hProcess);
 904 }
 905 
 906 JNIEXPORT jlong JNICALL
 907 Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentThread(JNIEnv* env, jclass this) {
 908     HANDLE hThread = GetCurrentThread();
 909     return ptr_to_jlong(hThread);
 910 }
 911 
 912 JNIEXPORT jlong JNICALL
 913 Java_sun_nio_fs_WindowsNativeDispatcher_OpenProcessToken(JNIEnv* env,
 914     jclass this, jlong process, jint desiredAccess)
 915 {
 916     HANDLE hProcess = (HANDLE)jlong_to_ptr(process);
 917     HANDLE hToken;
 918 
 919     if (OpenProcessToken(hProcess, (DWORD)desiredAccess, &hToken) == 0)
 920         throwWindowsException(env, GetLastError());
 921     return ptr_to_jlong(hToken);
 922 }
 923 
 924 JNIEXPORT jlong JNICALL
 925 Java_sun_nio_fs_WindowsNativeDispatcher_OpenThreadToken(JNIEnv* env,
 926     jclass this, jlong thread, jint desiredAccess, jboolean openAsSelf)
 927 {
 928     HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
 929     HANDLE hToken;
 930     BOOL bOpenAsSelf = (openAsSelf == JNI_TRUE) ? TRUE : FALSE;
 931 
 932     if (OpenThreadToken(hThread, (DWORD)desiredAccess, bOpenAsSelf, &hToken) == 0) {
 933         if (GetLastError() == ERROR_NO_TOKEN)
 934             return (jlong)0;
 935         throwWindowsException(env, GetLastError());
 936     }
 937     return ptr_to_jlong(hToken);
 938 }
 939 
 940 JNIEXPORT jlong JNICALL
 941 Java_sun_nio_fs_WindowsNativeDispatcher_DuplicateTokenEx(JNIEnv* env,
 942     jclass this, jlong token, jint desiredAccess)
 943 {
 944     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 945     HANDLE resultToken;
 946     BOOL res;
 947 
 948     res = DuplicateTokenEx(hToken,
 949                            (DWORD)desiredAccess,
 950                            NULL,
 951                            SecurityImpersonation,
 952                            TokenImpersonation,
 953                            &resultToken);
 954     if (res == 0)
 955         throwWindowsException(env, GetLastError());
 956     return ptr_to_jlong(resultToken);
 957 }
 958 
 959 JNIEXPORT void JNICALL
 960 Java_sun_nio_fs_WindowsNativeDispatcher_SetThreadToken(JNIEnv* env,
 961     jclass this, jlong thread, jlong token)
 962 {
 963     HANDLE hThread = (HANDLE)jlong_to_ptr(thread);
 964     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 965 
 966     if (SetThreadToken(hThread, hToken) == 0)
 967         throwWindowsException(env, GetLastError());
 968 }
 969 
 970 JNIEXPORT jint JNICALL
 971 Java_sun_nio_fs_WindowsNativeDispatcher_GetTokenInformation(JNIEnv* env,
 972     jclass this, jlong token, jint tokenInfoClass, jlong tokenInfo, jint tokenInfoLength)
 973 {
 974     BOOL res;
 975     DWORD lengthNeeded;
 976     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 977     LPVOID result = (LPVOID)jlong_to_ptr(tokenInfo);
 978 
 979     res = GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)tokenInfoClass, (LPVOID)result,
 980                               tokenInfoLength, &lengthNeeded);
 981     if (res == 0) {
 982         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 983             return (jint)lengthNeeded;
 984         } else {
 985             throwWindowsException(env, GetLastError());
 986             return 0;
 987         }
 988     } else {
 989         return tokenInfoLength;
 990     }
 991 }
 992 
 993 JNIEXPORT void JNICALL
 994 Java_sun_nio_fs_WindowsNativeDispatcher_AdjustTokenPrivileges(JNIEnv* env,
 995     jclass this, jlong token, jlong luid, jint attributes)
 996 {
 997     TOKEN_PRIVILEGES privs[1];
 998     HANDLE hToken = (HANDLE)jlong_to_ptr(token);
 999     PLUID pLuid = (PLUID)jlong_to_ptr(luid);
1000 
1001     privs[0].PrivilegeCount = 1;
1002     privs[0].Privileges[0].Luid = *pLuid;
1003     privs[0].Privileges[0].Attributes = (DWORD)attributes;
1004 
1005     if (AdjustTokenPrivileges(hToken, FALSE, &privs[0], 1, NULL, NULL) == 0)
1006         throwWindowsException(env, GetLastError());
1007 }
1008 
1009 JNIEXPORT jboolean JNICALL
1010 Java_sun_nio_fs_WindowsNativeDispatcher_AccessCheck(JNIEnv* env,
1011     jclass this, jlong token, jlong securityInfo, jint accessMask,
1012     jint genericRead, jint genericWrite, jint genericExecute, jint genericAll)
1013 {
1014     HANDLE hImpersonatedToken = (HANDLE)jlong_to_ptr(token);
1015     PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)jlong_to_ptr(securityInfo);
1016     DWORD checkAccessRights = (DWORD)accessMask;
1017     GENERIC_MAPPING mapping = {
1018         genericRead,
1019         genericWrite,
1020         genericExecute,
1021         genericAll};
1022     PRIVILEGE_SET privileges = {0};
1023     DWORD privilegesLength = sizeof(privileges);
1024     DWORD grantedAccess = 0;
1025     BOOL result = FALSE;
1026 
1027     /* checkAccessRights is in-out parameter */
1028     MapGenericMask(&checkAccessRights, &mapping);
1029     if (AccessCheck(security, hImpersonatedToken, checkAccessRights,
1030             &mapping, &privileges, &privilegesLength, &grantedAccess, &result) == 0)
1031         throwWindowsException(env, GetLastError());
1032 
1033     return (result == FALSE) ? JNI_FALSE : JNI_TRUE;
1034 }
1035 
1036 JNIEXPORT jlong JNICALL
1037 Java_sun_nio_fs_WindowsNativeDispatcher_LookupPrivilegeValue0(JNIEnv* env,
1038     jclass this, jlong name)
1039 {
1040     LPCWSTR lpName = (LPCWSTR)jlong_to_ptr(name);
1041     PLUID pLuid = LocalAlloc(0, sizeof(LUID));
1042 
1043     if (pLuid == NULL) {
1044         JNU_ThrowInternalError(env, "Unable to allocate LUID structure");
1045     } else {
1046         if (LookupPrivilegeValueW(NULL, lpName, pLuid) == 0)
1047             throwWindowsException(env, GetLastError());
1048     }
1049     return ptr_to_jlong(pLuid);
1050 }
1051 
1052 JNIEXPORT void JNICALL
1053 Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
1054     jclass this, jlong linkAddress, jlong targetAddress, jint flags)
1055 {
1056     LPCWSTR link = jlong_to_ptr(linkAddress);
1057     LPCWSTR target = jlong_to_ptr(targetAddress);
1058 
1059     /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */
1060     if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0)
1061         throwWindowsException(env, GetLastError());
1062 }
1063 
1064 JNIEXPORT void JNICALL
1065 Java_sun_nio_fs_WindowsNativeDispatcher_CreateHardLink0(JNIEnv* env,
1066     jclass this, jlong newFileAddress, jlong existingFileAddress)
1067 {
1068     LPCWSTR newFile = jlong_to_ptr(newFileAddress);
1069     LPCWSTR existingFile = jlong_to_ptr(existingFileAddress);
1070 
1071     if (CreateHardLinkW(newFile, existingFile, NULL) == 0)
1072         throwWindowsException(env, GetLastError());
1073 }
1074 
1075 JNIEXPORT jstring JNICALL
1076 Java_sun_nio_fs_WindowsNativeDispatcher_GetFullPathName0(JNIEnv *env,
1077                                                          jclass clz,
1078                                                          jlong pathAddress)
1079 {
1080     jstring rv = NULL;
1081     WCHAR *lpBuf = NULL;
1082     WCHAR buf[MAX_PATH];
1083     DWORD len;
1084     LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
1085 
1086     len = GetFullPathNameW(lpFileName, MAX_PATH, buf, NULL);
1087     if (len > 0) {
1088         if (len < MAX_PATH) {
1089             rv = (*env)->NewString(env, buf, len);
1090         } else {
1091             len += 1;  /* return length does not include terminator */
1092             lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
1093             if (lpBuf != NULL) {
1094                 len = GetFullPathNameW(lpFileName, len, lpBuf, NULL);
1095                 if (len > 0) {
1096                     rv = (*env)->NewString(env, lpBuf, len);
1097                 } else {
1098                     JNU_ThrowInternalError(env, "GetFullPathNameW failed");
1099                 }
1100                 free(lpBuf);
1101             } else {
1102                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
1103             }
1104         }
1105     } else {
1106         throwWindowsException(env, GetLastError());
1107     }
1108 
1109     return rv;
1110 }
1111 
1112 JNIEXPORT jstring JNICALL
1113 Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
1114     jclass this, jlong handle)
1115 {
1116     jstring rv = NULL;
1117     WCHAR *lpBuf = NULL;
1118     WCHAR path[MAX_PATH];
1119     HANDLE h = (HANDLE)jlong_to_ptr(handle);
1120     DWORD len;
1121 
1122     len = GetFinalPathNameByHandleW(h, path, MAX_PATH, 0);
1123     if (len > 0) {
1124         if (len < MAX_PATH) {
1125             rv = (*env)->NewString(env, (const jchar *)path, (jsize)len);
1126         } else {
1127             len += 1;  /* return length does not include terminator */
1128             lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
1129             if (lpBuf != NULL) {
1130                 len = GetFinalPathNameByHandleW(h, lpBuf, len, 0);
1131                 if (len > 0)  {
1132                     rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len);
1133                 } else {
1134                     JNU_ThrowInternalError(env, "GetFinalPathNameByHandleW failed");
1135                 }
1136                 free(lpBuf);
1137             } else {
1138                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failure");
1139             }
1140         }
1141     } else {
1142         throwWindowsException(env, GetLastError());
1143     }
1144     return rv;
1145 }
1146 
1147 JNIEXPORT jlong JNICALL
1148 Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
1149     jlong fileHandle, jlong existingPort, jlong completionKey)
1150 {
1151     HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
1152                                          (HANDLE)jlong_to_ptr(existingPort),
1153                                          (ULONG_PTR)completionKey,
1154                                          0);
1155     if (port == NULL) {
1156         throwWindowsException(env, GetLastError());
1157     }
1158     return ptr_to_jlong(port);
1159 }
1160 
1161 JNIEXPORT void JNICALL
1162 Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jclass this,
1163     jlong completionPort, jobject obj)
1164 {
1165     DWORD bytesTransferred;
1166     ULONG_PTR completionKey;
1167     OVERLAPPED *lpOverlapped;
1168     BOOL res;
1169 
1170     res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
1171                                   &bytesTransferred,
1172                                   &completionKey,
1173                                   &lpOverlapped,
1174                                   INFINITE);
1175     if (res == 0 && lpOverlapped == NULL) {
1176         throwWindowsException(env, GetLastError());
1177     } else {
1178         DWORD ioResult = (res == 0) ? GetLastError() : 0;
1179         (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
1180         (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
1181             (jint)bytesTransferred);
1182         (*env)->SetLongField(env, obj, completionStatus_completionKey,
1183             (jlong)completionKey);
1184     }
1185 }
1186 
1187 JNIEXPORT void JNICALL
1188 Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
1189     jlong completionPort, jlong completionKey)
1190 {
1191     BOOL res;
1192 
1193     res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
1194                                      (DWORD)0,  /* dwNumberOfBytesTransferred */
1195                                      (ULONG_PTR)completionKey,
1196                                      NULL);  /* lpOverlapped */
1197     if (res == 0) {
1198         throwWindowsException(env, GetLastError());
1199     }
1200 }
1201 
1202 JNIEXPORT void JNICALL
1203 Java_sun_nio_fs_WindowsNativeDispatcher_CancelIo(JNIEnv* env, jclass this, jlong hFile) {
1204     if (CancelIo((HANDLE)jlong_to_ptr(hFile)) == 0) {
1205         throwWindowsException(env, GetLastError());
1206     }
1207 }
1208 
1209 JNIEXPORT jint JNICALL
1210 Java_sun_nio_fs_WindowsNativeDispatcher_GetOverlappedResult(JNIEnv *env, jclass this,
1211     jlong hFile, jlong lpOverlapped)
1212 {
1213     BOOL res;
1214     DWORD bytesTransferred = -1;
1215 
1216     res = GetOverlappedResult((HANDLE)jlong_to_ptr(hFile),
1217                               (LPOVERLAPPED)jlong_to_ptr(lpOverlapped),
1218                               &bytesTransferred,
1219                               TRUE);
1220     if (res == 0) {
1221         throwWindowsException(env, GetLastError());
1222     }
1223 
1224     return (jint)bytesTransferred;
1225 }
1226 
1227 JNIEXPORT void JNICALL
1228 Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this,
1229     jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter,
1230     jlong bytesReturnedAddress, jlong pOverlapped)
1231 {
1232     BOOL res;
1233     BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
1234     LPOVERLAPPED ov = (LPOVERLAPPED)jlong_to_ptr(pOverlapped);
1235 
1236     res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
1237                                 (LPVOID)jlong_to_ptr(bufferAddress),
1238                                 (DWORD)bufferLength,
1239                                 subtree,
1240                                 (DWORD)filter,
1241                                 (LPDWORD)jlong_to_ptr(bytesReturnedAddress),
1242                                 (LPOVERLAPPED)jlong_to_ptr(pOverlapped),
1243                                 NULL);
1244     if (res == 0) {
1245         throwWindowsException(env, GetLastError());
1246     }
1247 }