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