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 package sun.nio.fs;
  27 
  28 import jdk.internal.misc.Blocker;
  29 import jdk.internal.misc.Unsafe;
  30 
  31 import static sun.nio.fs.WindowsConstants.*;
  32 
  33 /**
  34  * Win32 and library calls.
  35  */
  36 
  37 class WindowsNativeDispatcher {
  38     private WindowsNativeDispatcher() { }
  39 
  40     /**
  41      * HANDLE CreateEvent(
  42      *   LPSECURITY_ATTRIBUTES lpEventAttributes,
  43      *   BOOL bManualReset,
  44      *   BOOL bInitialState,
  45      *   PCTSTR lpName
  46      * );
  47      */
  48     static native long CreateEvent(boolean bManualReset, boolean bInitialState)
  49         throws WindowsException;
  50 
  51     /**
  52      * HANDLE CreateFile(
  53      *   LPCTSTR lpFileName,
  54      *   DWORD dwDesiredAccess,
  55      *   DWORD dwShareMode,
  56      *   LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  57      *   DWORD dwCreationDisposition,
  58      *   DWORD dwFlagsAndAttributes,
  59      *   HANDLE hTemplateFile
  60      * )
  61      */
  62     static long CreateFile(String path,
  63                            int dwDesiredAccess,
  64                            int dwShareMode,
  65                            long lpSecurityAttributes,
  66                            int dwCreationDisposition,
  67                            int dwFlagsAndAttributes)
  68         throws WindowsException
  69     {
  70         try (NativeBuffer buffer = asNativeBuffer(path)) {
  71             if (Thread.currentThread().isVirtual()) {
  72                 return Blocker.managedBlock(() ->
  73                         CreateFile0(buffer.address(),
  74                                     dwDesiredAccess,
  75                                     dwShareMode,
  76                                     lpSecurityAttributes,
  77                                     dwCreationDisposition,
  78                                     dwFlagsAndAttributes));
  79             } else {
  80                 return CreateFile0(buffer.address(),
  81                                    dwDesiredAccess,
  82                                    dwShareMode,
  83                                    lpSecurityAttributes,
  84                                    dwCreationDisposition,
  85                                    dwFlagsAndAttributes);
  86             }
  87         }
  88     }
  89     static long CreateFile(String path,
  90                            int dwDesiredAccess,
  91                            int dwShareMode,
  92                            int dwCreationDisposition,
  93                            int dwFlagsAndAttributes)
  94         throws WindowsException
  95     {
  96         return CreateFile(path, dwDesiredAccess, dwShareMode, 0L,
  97                           dwCreationDisposition, dwFlagsAndAttributes);
  98     }
  99     private static native long CreateFile0(long lpFileName,
 100                                            int dwDesiredAccess,
 101                                            int dwShareMode,
 102                                            long lpSecurityAttributes,
 103                                            int dwCreationDisposition,
 104                                            int dwFlagsAndAttributes)
 105         throws WindowsException;
 106 
 107     /**
 108      * CloseHandle(
 109      *   HANDLE hObject
 110      * )
 111      */
 112     static native void CloseHandle(long handle);
 113 
 114     /**
 115      * DeleteFile(
 116      *   LPCTSTR lpFileName
 117      * )
 118      */
 119     static void DeleteFile(String path) throws WindowsException {
 120         try (NativeBuffer buffer = asNativeBuffer(path)) {
 121             if (Thread.currentThread().isVirtual()) {
 122                 Blocker.managedBlock(() -> DeleteFile0(buffer.address()));
 123             } else {
 124                 DeleteFile0(buffer.address());
 125             }
 126         }
 127     }
 128     private static native void DeleteFile0(long lpFileName)
 129         throws WindowsException;
 130 
 131     /**
 132      * CreateDirectory(
 133      *   LPCTSTR lpPathName,
 134      *   LPSECURITY_ATTRIBUTES lpSecurityAttributes
 135      * )
 136      */
 137     static void CreateDirectory(String path, long lpSecurityAttributes) throws WindowsException {
 138         try (NativeBuffer buffer = asNativeBuffer(path)) {
 139             if (Thread.currentThread().isVirtual()) {
 140                 Blocker.managedBlock(() -> CreateDirectory0(buffer.address(), lpSecurityAttributes));
 141             } else {
 142                 CreateDirectory0(buffer.address(), lpSecurityAttributes);
 143             }
 144         }
 145     }
 146     private static native void CreateDirectory0(long lpFileName, long lpSecurityAttributes)
 147         throws WindowsException;
 148 
 149     /**
 150      * RemoveDirectory(
 151      *   LPCTSTR lpPathName
 152      * )
 153      */
 154     static void RemoveDirectory(String path) throws WindowsException {
 155         try (NativeBuffer buffer = asNativeBuffer(path)) {
 156             if (Thread.currentThread().isVirtual()) {
 157                 Blocker.managedBlock(() -> RemoveDirectory0(buffer.address()));
 158             } else {
 159                 RemoveDirectory0(buffer.address());
 160             }
 161         }
 162     }
 163     private static native void RemoveDirectory0(long lpFileName)
 164         throws WindowsException;
 165 
 166     /**
 167      * Marks a file as a sparse file.
 168      *
 169      * DeviceIoControl(
 170      *   FSCTL_SET_SPARSE
 171      * )
 172      */
 173     static native void DeviceIoControlSetSparse(long handle)
 174         throws WindowsException;
 175 
 176     /**
 177      * Retrieves the reparse point data associated with the file or directory.
 178      *
 179      * DeviceIoControl(
 180      *   FSCTL_GET_REPARSE_POINT
 181      * )
 182      */
 183     static native void DeviceIoControlGetReparsePoint(long handle,
 184         long bufferAddress, int bufferSize) throws WindowsException;
 185 
 186     /**
 187      * Retrieves the size of the specified file.
 188      *
 189      * BOOL GetFileSizeEx(
 190      *   HANDLE hFile,
 191      *   PLARGE_INTEGER lpFileSize
 192      * )
 193      */
 194     static native long GetFileSizeEx(long handle) throws WindowsException;
 195 
 196     /**
 197      * HANDLE FindFirstFile(
 198      *   LPCTSTR lpFileName,
 199      *   LPWIN32_FIND_DATA lpFindFileData
 200      * )
 201      */
 202     static FirstFile FindFirstFile(String path) throws WindowsException {
 203         try (NativeBuffer buffer = asNativeBuffer(path)) {
 204             FirstFile data = new FirstFile();
 205             if (Thread.currentThread().isVirtual()) {
 206                 Blocker.managedBlock(() -> FindFirstFile0(buffer.address(), data));
 207             } else {
 208                 FindFirstFile0(buffer.address(), data);
 209             }
 210             return data;
 211         }
 212     }
 213     static class FirstFile {
 214         private long handle;
 215         private String name;
 216         private int attributes;
 217 
 218         private FirstFile() { }
 219         public long handle()    { return handle; }
 220         public String name()    { return name; }
 221         public int attributes() { return attributes; }
 222     }
 223     private static native void FindFirstFile0(long lpFileName, FirstFile obj)
 224         throws WindowsException;
 225 
 226     /**
 227      * HANDLE FindFirstFile(
 228      *   LPCTSTR lpFileName,
 229      *   LPWIN32_FIND_DATA lpFindFileData
 230      * )
 231      */
 232     static long FindFirstFile(String path, long address) throws WindowsException {
 233         try (NativeBuffer buffer = asNativeBuffer(path)) {
 234             if (Thread.currentThread().isVirtual()) {
 235                 return Blocker.managedBlock(() -> FindFirstFile1(buffer.address(), address));
 236             } else {
 237                 return FindFirstFile1(buffer.address(), address);
 238             }
 239         }
 240     }
 241     private static native long FindFirstFile1(long lpFileName, long address)
 242         throws WindowsException;
 243 
 244     /**
 245      * FindNextFile(
 246      *   HANDLE hFindFile,
 247      *   LPWIN32_FIND_DATA lpFindFileData
 248      * )
 249      *
 250      * @return  lpFindFileData->cFileName or null
 251      */
 252     static String FindNextFile(long handle, long address) throws WindowsException {
 253         if (Thread.currentThread().isVirtual()) {
 254             return Blocker.managedBlock(() -> FindNextFile0(handle, address));
 255         } else {
 256             return FindNextFile0(handle, address);
 257         }
 258     }
 259     private static native String FindNextFile0(long handle, long address)
 260         throws WindowsException;
 261 
 262     /**
 263      * HANDLE FindFirstStreamW(
 264      *   LPCWSTR lpFileName,
 265      *   STREAM_INFO_LEVELS InfoLevel,
 266      *   LPVOID lpFindStreamData,
 267      *   DWORD dwFlags
 268      * )
 269      */
 270     static FirstStream FindFirstStream(String path) throws WindowsException {
 271         try (NativeBuffer buffer = asNativeBuffer(path)) {
 272             FirstStream data = new FirstStream();
 273             if (Thread.currentThread().isVirtual()) {
 274                 Blocker.managedBlock(() -> FindFirstStream0(buffer.address(), data));
 275             } else {
 276                 FindFirstStream0(buffer.address(), data);
 277             }
 278             if (data.handle() == WindowsConstants.INVALID_HANDLE_VALUE)
 279                 return null;
 280             return data;
 281         }
 282     }
 283     static class FirstStream {
 284         private long handle;
 285         private String name;
 286 
 287         private FirstStream() { }
 288         public long handle()    { return handle; }
 289         public String name()    { return name; }
 290     }
 291     private static native void FindFirstStream0(long lpFileName, FirstStream obj)
 292         throws WindowsException;
 293 
 294     /*
 295      * FindNextStreamW(
 296      *   HANDLE hFindStream,
 297      *   LPVOID lpFindStreamData
 298      * )
 299      */
 300     static String FindNextStream(long handle) throws WindowsException {
 301         if (Thread.currentThread().isVirtual()) {
 302             return Blocker.managedBlock(() -> FindNextStream0(handle));
 303         } else {
 304             return FindNextStream0(handle);
 305         }
 306     }
 307     private static native String FindNextStream0(long handle) throws WindowsException;
 308 
 309     /**
 310      * FindClose(
 311      *   HANDLE hFindFile
 312      * )
 313      */
 314     static native void FindClose(long handle) throws WindowsException;
 315 
 316     /**
 317      * GetFileInformationByHandle(
 318      *   HANDLE hFile,
 319      *   LPBY_HANDLE_FILE_INFORMATION lpFileInformation
 320      * )
 321      */
 322     static void GetFileInformationByHandle(long handle, long address)
 323         throws WindowsException
 324     {
 325         if (Thread.currentThread().isVirtual()) {
 326             Blocker.managedBlock(() -> GetFileInformationByHandle0(handle, address));
 327         } else {
 328             GetFileInformationByHandle0(handle, address);
 329         }
 330     }
 331     private static native void GetFileInformationByHandle0(long handle, long address)
 332         throws WindowsException;
 333 
 334     /**
 335      * CopyFileEx(
 336      *   LPCWSTR lpExistingFileName
 337      *   LPCWSTR lpNewFileName,
 338      *   LPPROGRESS_ROUTINE lpProgressRoutine
 339      *   LPVOID lpData,
 340      *   LPBOOL pbCancel,
 341      *   DWORD dwCopyFlags
 342      * )
 343      */
 344     static void CopyFileEx(String source, String target, int flags,
 345                            long addressToPollForCancel)
 346         throws WindowsException
 347     {
 348         try (NativeBuffer sourceBuffer = asNativeBuffer(source);
 349              NativeBuffer targetBuffer = asNativeBuffer(target)) {
 350             if (Thread.currentThread().isVirtual()) {
 351                 Blocker.managedBlock(() ->
 352                     CopyFileEx0(sourceBuffer.address(), targetBuffer.address(), flags,
 353                                 addressToPollForCancel));
 354             } else {
 355                 CopyFileEx0(sourceBuffer.address(), targetBuffer.address(), flags,
 356                             addressToPollForCancel);
 357             }
 358         }
 359     }
 360     private static native void CopyFileEx0(long existingAddress, long newAddress,
 361         int flags, long addressToPollForCancel) throws WindowsException;
 362 
 363     /**
 364      * MoveFileEx(
 365      *   LPCTSTR lpExistingFileName,
 366      *   LPCTSTR lpNewFileName,
 367      *   DWORD dwFlags
 368      * )
 369      */
 370     static void MoveFileEx(String source, String target, int flags)
 371         throws WindowsException
 372     {
 373         try (NativeBuffer sourceBuffer = asNativeBuffer(source);
 374              NativeBuffer targetBuffer = asNativeBuffer(target)) {
 375             if (Thread.currentThread().isVirtual()) {
 376                 Blocker.managedBlock(() ->
 377                     MoveFileEx0(sourceBuffer.address(), targetBuffer.address(), flags));
 378             } else {
 379                 MoveFileEx0(sourceBuffer.address(), targetBuffer.address(), flags);
 380             }
 381         }
 382     }
 383     private static native void MoveFileEx0(long existingAddress, long newAddress,
 384         int flags) throws WindowsException;
 385 
 386     /**
 387      * DWORD GetFileAttributes(
 388      *   LPCTSTR lpFileName
 389      * )
 390      */
 391     static int GetFileAttributes(String path) throws WindowsException {
 392         try (NativeBuffer buffer = asNativeBuffer(path)) {
 393             if (Thread.currentThread().isVirtual()) {
 394                 return Blocker.managedBlock(() -> GetFileAttributes0(buffer.address()));
 395             } else {
 396                 return GetFileAttributes0(buffer.address());
 397             }
 398         }
 399     }
 400     private static native int GetFileAttributes0(long lpFileName)
 401         throws WindowsException;
 402 
 403     /**
 404      * SetFileAttributes(
 405      *   LPCTSTR lpFileName,
 406      *   DWORD dwFileAttributes
 407      */
 408     static void SetFileAttributes(String path, int dwFileAttributes)
 409         throws WindowsException
 410     {
 411         try (NativeBuffer buffer = asNativeBuffer(path)) {
 412             if (Thread.currentThread().isVirtual()) {
 413                 Blocker.managedBlock(() -> SetFileAttributes0(buffer.address(), dwFileAttributes));
 414             } else {
 415                 SetFileAttributes0(buffer.address(), dwFileAttributes);
 416             }
 417         }
 418     }
 419     private static native void SetFileAttributes0(long lpFileName,
 420         int dwFileAttributes) throws WindowsException;
 421 
 422     /**
 423      * GetFileAttributesEx(
 424      *   LPCTSTR lpFileName,
 425      *   GET_FILEEX_INFO_LEVELS fInfoLevelId,
 426      *   LPVOID lpFileInformation
 427      * );
 428      */
 429     static void GetFileAttributesEx(String path, long address) throws WindowsException {
 430         try (NativeBuffer buffer = asNativeBuffer(path)) {
 431             if (Thread.currentThread().isVirtual()) {
 432                 Blocker.managedBlock(() -> GetFileAttributesEx0(buffer.address(), address));
 433             } else {
 434                 GetFileAttributesEx0(buffer.address(), address);
 435             }
 436         }
 437     }
 438     private static native void GetFileAttributesEx0(long lpFileName, long address)
 439         throws WindowsException;
 440 
 441     /**
 442      * SetFileTime(
 443      *   HANDLE hFile,
 444      *   CONST FILETIME *lpCreationTime,
 445      *   CONST FILETIME *lpLastAccessTime,
 446      *   CONST FILETIME *lpLastWriteTime
 447      * )
 448      */
 449     static void SetFileTime(long handle, long createTime, long lastAccessTime, long lastWriteTime)
 450         throws WindowsException
 451     {
 452         if (Thread.currentThread().isVirtual()) {
 453             Blocker.managedBlock(() -> SetFileTime0(handle, createTime, lastAccessTime, lastWriteTime));
 454         } else {
 455             SetFileTime0(handle, createTime, lastAccessTime, lastWriteTime);
 456         }
 457     }
 458     private static native void SetFileTime0(long handle,
 459                                             long createTime,
 460                                             long lastAccessTime,
 461                                             long lastWriteTime)
 462         throws WindowsException;
 463 
 464     /**
 465      * SetEndOfFile(
 466      *   HANDLE hFile
 467      * )
 468      */
 469     static native void SetEndOfFile(long handle) throws WindowsException;
 470 
 471     /**
 472      * DWORD GetLogicalDrives(VOID)
 473      */
 474     static native int GetLogicalDrives() throws WindowsException;
 475 
 476     /**
 477      * GetVolumeInformation(
 478      *   LPCTSTR lpRootPathName,
 479      *   LPTSTR lpVolumeNameBuffer,
 480      *   DWORD nVolumeNameSize,
 481      *   LPDWORD lpVolumeSerialNumber,
 482      *   LPDWORD lpMaximumComponentLength,
 483      *   LPDWORD lpFileSystemFlags,
 484      *   LPTSTR lpFileSystemNameBuffer,
 485      *   DWORD nFileSystemNameSize
 486      * )
 487      */
 488     static VolumeInformation GetVolumeInformation(String root)
 489         throws WindowsException
 490     {
 491         NativeBuffer buffer = asNativeBuffer(root);
 492         try {
 493             VolumeInformation info = new VolumeInformation();
 494             GetVolumeInformation0(buffer.address(), info);
 495             return info;
 496         } finally {
 497             buffer.release();
 498         }
 499     }
 500     static class VolumeInformation {
 501         private String fileSystemName;
 502         private String volumeName;
 503         private int volumeSerialNumber;
 504         private int flags;
 505         private VolumeInformation() { }
 506 
 507         public String fileSystemName()      { return fileSystemName; }
 508         public String volumeName()          { return volumeName; }
 509         public int volumeSerialNumber()     { return volumeSerialNumber; }
 510         public int flags()                  { return flags; }
 511     }
 512     private static native void GetVolumeInformation0(long lpRoot,
 513                                                      VolumeInformation obj)
 514         throws WindowsException;
 515 
 516     /**
 517      * UINT GetDriveType(
 518      *   LPCTSTR lpRootPathName
 519      * )
 520      */
 521     static int GetDriveType(String root) throws WindowsException {
 522         NativeBuffer buffer = asNativeBuffer(root);
 523         try {
 524             return GetDriveType0(buffer.address());
 525         } finally {
 526             buffer.release();
 527         }
 528     }
 529     private static native int GetDriveType0(long lpRoot) throws WindowsException;
 530 
 531     /**
 532      * GetDiskFreeSpaceEx(
 533      *   LPCTSTR lpDirectoryName,
 534      *   PULARGE_INTEGER lpFreeBytesAvailableToCaller,
 535      *   PULARGE_INTEGER lpTotalNumberOfBytes,
 536      *   PULARGE_INTEGER lpTotalNumberOfFreeBytes
 537      * )
 538      */
 539     static DiskFreeSpace GetDiskFreeSpaceEx(String path)
 540         throws WindowsException
 541     {
 542         NativeBuffer buffer = asNativeBuffer(path);
 543         try {
 544             DiskFreeSpace space = new DiskFreeSpace();
 545             GetDiskFreeSpaceEx0(buffer.address(), space);
 546             return space;
 547         } finally {
 548             buffer.release();
 549         }
 550     }
 551 
 552     /**
 553      * GetDiskFreeSpace(
 554      *   LPCTSTR lpRootPathName,
 555      *   LPDWORD lpSectorsPerCluster,
 556      *   LPDWORD lpBytesPerSector,
 557      *   LPDWORD lpNumberOfFreeClusters,
 558      *   LPDWORD lpTotalNumberOfClusters
 559      * )
 560      */
 561     static DiskFreeSpace GetDiskFreeSpace(String path)
 562         throws WindowsException
 563     {
 564         NativeBuffer buffer = asNativeBuffer(path);
 565         try {
 566             DiskFreeSpace space = new DiskFreeSpace();
 567             GetDiskFreeSpace0(buffer.address(), space);
 568             return space;
 569         } finally {
 570             buffer.release();
 571         }
 572     }
 573 
 574     static class DiskFreeSpace {
 575         private long freeBytesAvailable;
 576         private long totalNumberOfBytes;
 577         private long totalNumberOfFreeBytes;
 578         private long bytesPerSector;
 579         private DiskFreeSpace() { }
 580 
 581         public long freeBytesAvailable()      { return freeBytesAvailable; }
 582         public long totalNumberOfBytes()      { return totalNumberOfBytes; }
 583         public long totalNumberOfFreeBytes()  { return totalNumberOfFreeBytes; }
 584         public long bytesPerSector()          { return bytesPerSector; }
 585     }
 586     private static native void GetDiskFreeSpaceEx0(long lpDirectoryName,
 587                                                    DiskFreeSpace obj)
 588         throws WindowsException;
 589 
 590 
 591     private static native void GetDiskFreeSpace0(long lpRootPathName,
 592                                                  DiskFreeSpace obj)
 593         throws WindowsException;
 594 
 595     /**
 596      * GetVolumePathName(
 597      *   LPCTSTR lpszFileName,
 598      *   LPTSTR lpszVolumePathName,
 599      *   DWORD cchBufferLength
 600      * )
 601      *
 602      * @return  lpFileName
 603      */
 604     static String GetVolumePathName(String path) throws WindowsException {
 605         NativeBuffer buffer = asNativeBuffer(path);
 606         try {
 607             return GetVolumePathName0(buffer.address());
 608         } finally {
 609             buffer.release();
 610         }
 611     }
 612     private static native String GetVolumePathName0(long lpFileName)
 613         throws WindowsException;
 614 
 615 
 616     /**
 617      * InitializeSecurityDescriptor(
 618      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 619      *   DWORD dwRevision
 620      * )
 621      */
 622     static native void InitializeSecurityDescriptor(long sdAddress)
 623         throws WindowsException;
 624 
 625     /**
 626      * InitializeAcl(
 627      *   PACL pAcl,
 628      *   DWORD nAclLength,
 629      *   DWORD dwAclRevision
 630      * )
 631      */
 632     static native void InitializeAcl(long aclAddress, int size)
 633          throws WindowsException;
 634 
 635     /**
 636      * GetFileSecurity(
 637      *   LPCTSTR lpFileName,
 638      *   SECURITY_INFORMATION RequestedInformation,
 639      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 640      *   DWORD nLength,
 641      *   LPDWORD lpnLengthNeeded
 642      * )
 643      */
 644     static int GetFileSecurity(String path,
 645                                int requestedInformation,
 646                                long pSecurityDescriptor,
 647                                int nLength) throws WindowsException
 648     {
 649         NativeBuffer buffer = asNativeBuffer(path);
 650         try {
 651             return GetFileSecurity0(buffer.address(), requestedInformation,
 652                 pSecurityDescriptor, nLength);
 653         } finally {
 654             buffer.release();
 655         }
 656     }
 657     private static native int GetFileSecurity0(long lpFileName,
 658                                                int requestedInformation,
 659                                                long pSecurityDescriptor,
 660                                                int nLength) throws WindowsException;
 661 
 662     /**
 663      * SetFileSecurity(
 664      *   LPCTSTR lpFileName,
 665      *   SECURITY_INFORMATION SecurityInformation,
 666      *   PSECURITY_DESCRIPTOR pSecurityDescriptor
 667      * )
 668      */
 669     static void SetFileSecurity(String path,
 670                                 int securityInformation,
 671                                 long pSecurityDescriptor)
 672         throws WindowsException
 673     {
 674         NativeBuffer buffer = asNativeBuffer(path);
 675         try {
 676             // may be called with elevated privileges so always run on current thread
 677             SetFileSecurity0(buffer.address(), securityInformation, pSecurityDescriptor);
 678         } finally {
 679             buffer.release();
 680         }
 681     }
 682     static native void SetFileSecurity0(long lpFileName, int securityInformation,
 683         long pSecurityDescriptor) throws WindowsException;
 684 
 685     /**
 686      * GetSecurityDescriptorOwner(
 687      *   PSECURITY_DESCRIPTOR pSecurityDescriptor
 688      *   PSID *pOwner,
 689      *   LPBOOL lpbOwnerDefaulted
 690      * )
 691      *
 692      * @return  pOwner
 693      */
 694     static native long GetSecurityDescriptorOwner(long pSecurityDescriptor)
 695         throws WindowsException;
 696 
 697     /**
 698      * SetSecurityDescriptorOwner(
 699      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 700      *   PSID pOwner,
 701      *   BOOL bOwnerDefaulted
 702      * )
 703      */
 704     static native void SetSecurityDescriptorOwner(long pSecurityDescriptor,
 705                                                   long pOwner)
 706         throws WindowsException;
 707 
 708     /**
 709      * GetSecurityDescriptorDacl(
 710      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 711      *   LPBOOL lpbDaclPresent,
 712      *   PACL *pDacl,
 713      *   LPBOOL lpbDaclDefaulted
 714      * )
 715      */
 716     static native long GetSecurityDescriptorDacl(long pSecurityDescriptor);
 717 
 718     /**
 719      * SetSecurityDescriptorDacl(
 720      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 721      *   BOOL bDaclPresent,
 722      *   PACL pDacl,
 723      *   BOOL bDaclDefaulted
 724      * )
 725      */
 726     static native void SetSecurityDescriptorDacl(long pSecurityDescriptor, long pAcl)
 727         throws WindowsException;
 728 
 729 
 730     /**
 731      * GetAclInformation(
 732      *   PACL pAcl,
 733      *   LPVOID pAclInformation,
 734      *   DWORD nAclInformationLength,
 735      *   ACL_INFORMATION_CLASS dwAclInformationClass
 736      * )
 737      */
 738     static AclInformation GetAclInformation(long aclAddress) {
 739         AclInformation info = new AclInformation();
 740         GetAclInformation0(aclAddress, info);
 741         return info;
 742     }
 743     static class AclInformation {
 744         private int aceCount;
 745         private AclInformation() { }
 746 
 747         public int aceCount()   { return aceCount; }
 748     }
 749     private static native void GetAclInformation0(long aclAddress,
 750         AclInformation obj);
 751 
 752     /**
 753      * GetAce(
 754      *   PACL pAcl,
 755      *   DWORD dwAceIndex,
 756      *   LPVOID *pAce
 757      * )
 758      */
 759     static native long GetAce(long aclAddress, int aceIndex);
 760 
 761     /**
 762      * AddAccessAllowedAceEx(
 763      *   PACL pAcl,
 764      *   DWORD dwAceRevision,
 765      *   DWORD AceFlags,
 766      *   DWORD AccessMask,
 767      *   PSID pSid
 768      * )
 769      */
 770     static native void AddAccessAllowedAceEx(long aclAddress, int flags,
 771         int mask, long sidAddress) throws WindowsException;
 772 
 773     /**
 774      * AddAccessDeniedAceEx(
 775      *   PACL pAcl,
 776      *   DWORD dwAceRevision,
 777      *   DWORD AceFlags,
 778      *   DWORD AccessMask,
 779      *   PSID pSid
 780      * )
 781      */
 782     static native void AddAccessDeniedAceEx(long aclAddress, int flags,
 783         int mask, long sidAddress) throws WindowsException;
 784 
 785     /**
 786      * LookupAccountSid(
 787      *   LPCTSTR lpSystemName,
 788      *   PSID Sid,
 789      *   LPTSTR Name,
 790      *   LPDWORD cbName,
 791      *   LPTSTR ReferencedDomainName,
 792      *   LPDWORD cbReferencedDomainName,
 793      *   PSID_NAME_USE peUse
 794      * )
 795      */
 796     static Account LookupAccountSid(long sidAddress) throws WindowsException {
 797         Account acc = new Account();
 798         LookupAccountSid0(sidAddress, acc);
 799         return acc;
 800     }
 801     static class Account {
 802         private String domain;
 803         private String name;
 804         private int use;
 805         private Account() { }
 806 
 807         public String domain()  { return domain; }
 808         public String name()    { return name; }
 809         public int use()        { return use; }
 810     }
 811     private static native void LookupAccountSid0(long sidAddress, Account obj)
 812         throws WindowsException;
 813 
 814     /**
 815      * LookupAccountName(
 816      *   LPCTSTR lpSystemName,
 817      *   LPCTSTR lpAccountName,
 818      *   PSID Sid,
 819      *   LPDWORD cbSid,
 820      *   LPTSTR ReferencedDomainName,
 821      *   LPDWORD cbReferencedDomainName,
 822      *   PSID_NAME_USE peUse
 823      * )
 824      *
 825      * @return  cbSid
 826      */
 827     static int LookupAccountName(String accountName,
 828                                  long pSid,
 829                                  int cbSid) throws WindowsException
 830     {
 831         NativeBuffer buffer = asNativeBuffer(accountName);
 832         try {
 833             return LookupAccountName0(buffer.address(), pSid, cbSid);
 834         } finally {
 835             buffer.release();
 836         }
 837     }
 838     private static native int LookupAccountName0(long lpAccountName, long pSid,
 839         int cbSid) throws WindowsException;
 840 
 841     /**
 842      * DWORD GetLengthSid(
 843      *   PSID pSid
 844      * )
 845      */
 846     static native int GetLengthSid(long sidAddress);
 847 
 848     /**
 849      * ConvertSidToStringSid(
 850      *   PSID Sid,
 851      *   LPTSTR* StringSid
 852      * )
 853      *
 854      * @return  StringSid
 855      */
 856     static native String ConvertSidToStringSid(long sidAddress)
 857         throws WindowsException;
 858 
 859     /**
 860      * ConvertStringSidToSid(
 861      *   LPCTSTR StringSid,
 862      *   PSID* pSid
 863      * )
 864      *
 865      * @return  pSid
 866      */
 867     static long ConvertStringSidToSid(String sidString)
 868         throws WindowsException
 869     {
 870         NativeBuffer buffer = asNativeBuffer(sidString);
 871         try {
 872             return ConvertStringSidToSid0(buffer.address());
 873         } finally {
 874             buffer.release();
 875         }
 876     }
 877     private static native long ConvertStringSidToSid0(long lpStringSid)
 878         throws WindowsException;
 879 
 880     /**
 881      * HANDLE GetCurrentProcess(VOID)
 882      */
 883     static native long GetCurrentProcess();
 884 
 885     /**
 886      * HANDLE GetCurrentThread(VOID)
 887      */
 888     static native long GetCurrentThread();
 889 
 890     /**
 891      * OpenProcessToken(
 892      *   HANDLE ProcessHandle,
 893      *   DWORD DesiredAccess,
 894      *   PHANDLE TokenHandle
 895      * )
 896      */
 897     static native long OpenProcessToken(long hProcess, int desiredAccess)
 898         throws WindowsException;
 899 
 900     /**
 901      * OpenThreadToken(
 902      *   HANDLE ThreadHandle,
 903      *   DWORD DesiredAccess,
 904      *   BOOL OpenAsSelf,
 905      *   PHANDLE TokenHandle
 906      * )
 907      */
 908     static native long OpenThreadToken(long hThread, int desiredAccess,
 909         boolean openAsSelf) throws WindowsException;
 910 
 911     /**
 912      */
 913     static native long DuplicateTokenEx(long hThread, int desiredAccess)
 914         throws WindowsException;
 915 
 916     /**
 917      * SetThreadToken(
 918      *   PHANDLE Thread,
 919      *   HANDLE Token
 920      * )
 921      */
 922     static native void SetThreadToken(long thread, long hToken)
 923         throws WindowsException;
 924 
 925     /**
 926      * GetTokenInformation(
 927      *   HANDLE TokenHandle,
 928      *   TOKEN_INFORMATION_CLASS TokenInformationClass,
 929      *   LPVOID TokenInformation,
 930      *   DWORD TokenInformationLength,
 931      *   PDWORD ReturnLength
 932      * )
 933      */
 934     static native int GetTokenInformation(long token, int tokenInfoClass,
 935         long pTokenInfo, int tokenInfoLength) throws WindowsException;
 936 
 937     /**
 938      * AdjustTokenPrivileges(
 939      *   HANDLE TokenHandle,
 940      *   BOOL DisableAllPrivileges
 941      *   PTOKEN_PRIVILEGES NewState
 942      *   DWORD BufferLength
 943      *   PTOKEN_PRIVILEGES
 944      *   PDWORD ReturnLength
 945      * )
 946      */
 947     static native void AdjustTokenPrivileges(long token, long luid, int attributes)
 948         throws WindowsException;
 949 
 950 
 951     /**
 952      * AccessCheck(
 953      *   PSECURITY_DESCRIPTOR pSecurityDescriptor,
 954      *   HANDLE ClientToken,
 955      *   DWORD DesiredAccess,
 956      *   PGENERIC_MAPPING GenericMapping,
 957      *   PPRIVILEGE_SET PrivilegeSet,
 958      *   LPDWORD PrivilegeSetLength,
 959      *   LPDWORD GrantedAccess,
 960      *   LPBOOL AccessStatus
 961      * )
 962      */
 963     static native boolean AccessCheck(long token, long securityInfo, int accessMask,
 964         int genericRead, int genericWrite, int genericExecute, int genericAll)
 965         throws WindowsException;
 966 
 967     /**
 968      */
 969     static long LookupPrivilegeValue(String name) throws WindowsException {
 970         NativeBuffer buffer = asNativeBuffer(name);
 971         try {
 972             return LookupPrivilegeValue0(buffer.address());
 973         } finally {
 974             buffer.release();
 975         }
 976     }
 977     private static native long LookupPrivilegeValue0(long lpName)
 978         throws WindowsException;
 979 
 980     /**
 981      * CreateSymbolicLink(
 982      *   LPCWSTR lpSymlinkFileName,
 983      *   LPCWSTR lpTargetFileName,
 984      *   DWORD dwFlags
 985      * )
 986      *
 987      * Creates a symbolic link, conditionally retrying with the addition of
 988      * the flag SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE if the initial
 989      * attempt fails with ERROR_PRIVILEGE_NOT_HELD. If the retry fails, throw
 990      * the original exception due to ERROR_PRIVILEGE_NOT_HELD. The retry will
 991      * succeed only on Windows build 14972 or later if Developer Mode is on.
 992      */
 993     static void CreateSymbolicLink(String link, String target, int flags)
 994         throws WindowsException
 995     {
 996         NativeBuffer linkBuffer = asNativeBuffer(link);
 997         NativeBuffer targetBuffer = asNativeBuffer(target);
 998         try {
 999             CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(),
1000                                 flags);
1001         } catch (WindowsException x) {
1002             if (x.lastError() == ERROR_PRIVILEGE_NOT_HELD) {
1003                 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1004                 try {
1005                     CreateSymbolicLink0(linkBuffer.address(),
1006                                         targetBuffer.address(), flags);
1007                     return;
1008                 } catch (WindowsException ignored) {
1009                     // Will fail with ERROR_INVALID_PARAMETER for Windows
1010                     // builds older than 14972.
1011                 }
1012             }
1013             throw x;
1014         } finally {
1015             targetBuffer.release();
1016             linkBuffer.release();
1017         }
1018     }
1019     private static native void CreateSymbolicLink0(long linkAddress,
1020         long targetAddress, int flags) throws WindowsException;
1021 
1022     /**
1023      * CreateHardLink(
1024      *    LPCTSTR lpFileName,
1025      *    LPCTSTR lpExistingFileName,
1026      *    LPSECURITY_ATTRIBUTES lpSecurityAttributes
1027      * )
1028      */
1029     static void CreateHardLink(String newFile, String existingFile)
1030         throws WindowsException
1031     {
1032         NativeBuffer newFileBuffer = asNativeBuffer(newFile);
1033         NativeBuffer existingFileBuffer = asNativeBuffer(existingFile);
1034         try {
1035             CreateHardLink0(newFileBuffer.address(), existingFileBuffer.address());
1036         } finally {
1037             existingFileBuffer.release();
1038             newFileBuffer.release();
1039         }
1040     }
1041     private static native void CreateHardLink0(long newFileBuffer,
1042         long existingFileBuffer) throws WindowsException;
1043 
1044     /**
1045      * GetFullPathName(
1046      *   LPCTSTR lpFileName,
1047      *   DWORD nBufferLength,
1048      *   LPTSTR lpBuffer,
1049      *   LPTSTR *lpFilePart
1050      * )
1051      */
1052     static String GetFullPathName(String path) throws WindowsException {
1053         NativeBuffer buffer = asNativeBuffer(path);
1054         try {
1055             return GetFullPathName0(buffer.address());
1056         } finally {
1057             buffer.release();
1058         }
1059     }
1060     private static native String GetFullPathName0(long pathAddress)
1061         throws WindowsException;
1062 
1063     /**
1064      * GetFinalPathNameByHandle(
1065      *   HANDLE hFile,
1066      *   LPTSTR lpszFilePath,
1067      *   DWORD cchFilePath,
1068      *   DWORD dwFlags
1069      * )
1070      */
1071     static native String GetFinalPathNameByHandle(long handle)
1072         throws WindowsException;
1073 
1074     /**
1075      * FormatMessage(
1076      *   DWORD dwFlags,
1077      *   LPCVOID lpSource,
1078      *   DWORD dwMessageId,
1079      *   DWORD dwLanguageId,
1080      *   LPTSTR lpBuffer,
1081      *   DWORD nSize,
1082      *   va_list *Arguments
1083      * )
1084      */
1085     static native String FormatMessage(int errorCode);
1086 
1087     /**
1088      * LocalFree(
1089      *   HLOCAL hMem
1090      * )
1091      */
1092     static native void LocalFree(long address);
1093 
1094     /**
1095      * HANDLE CreateIoCompletionPort (
1096      *   HANDLE FileHandle,
1097      *   HANDLE ExistingCompletionPort,
1098      *   ULONG_PTR CompletionKey,
1099      *   DWORD NumberOfConcurrentThreads
1100      * )
1101      */
1102     static native long CreateIoCompletionPort(long fileHandle, long existingPort,
1103         long completionKey) throws WindowsException;
1104 
1105 
1106     /**
1107      * GetQueuedCompletionStatus(
1108      *   HANDLE CompletionPort,
1109      *   LPDWORD lpNumberOfBytesTransferred,
1110      *   PULONG_PTR lpCompletionKey,
1111      *   LPOVERLAPPED *lpOverlapped,
1112      *   DWORD dwMilliseconds
1113      */
1114     static CompletionStatus GetQueuedCompletionStatus(long completionPort)
1115         throws WindowsException
1116     {
1117         CompletionStatus status = new CompletionStatus();
1118         GetQueuedCompletionStatus0(completionPort, status);
1119         return status;
1120     }
1121     static class CompletionStatus {
1122         private int error;
1123         private int bytesTransferred;
1124         private long completionKey;
1125         private CompletionStatus() { }
1126 
1127         int error() { return error; }
1128         int bytesTransferred() { return bytesTransferred; }
1129         long completionKey() { return completionKey; }
1130     }
1131     private static native void GetQueuedCompletionStatus0(long completionPort,
1132         CompletionStatus status) throws WindowsException;
1133 
1134     /**
1135      * PostQueuedCompletionStatus(
1136      *   HANDLE CompletionPort,
1137      *   DWORD dwNumberOfBytesTransferred,
1138      *   ULONG_PTR dwCompletionKey,
1139      *   LPOVERLAPPED lpOverlapped
1140      * )
1141      */
1142     static native void PostQueuedCompletionStatus(long completionPort,
1143         long completionKey) throws WindowsException;
1144 
1145     /**
1146      * ReadDirectoryChangesW(
1147      *   HANDLE hDirectory,
1148      *   LPVOID lpBuffer,
1149      *   DWORD nBufferLength,
1150      *   BOOL bWatchSubtree,
1151      *   DWORD dwNotifyFilter,
1152      *   LPDWORD lpBytesReturned,
1153      *   LPOVERLAPPED lpOverlapped,
1154      *   LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
1155      * )
1156      */
1157     static native void ReadDirectoryChangesW(long hDirectory,
1158                                              long bufferAddress,
1159                                              int bufferLength,
1160                                              boolean watchSubTree,
1161                                              int filter,
1162                                              long bytesReturnedAddress,
1163                                              long pOverlapped)
1164         throws WindowsException;
1165 
1166 
1167     /**
1168      * CancelIo(
1169      *   HANDLE hFile
1170      * )
1171      */
1172     static native void CancelIo(long hFile) throws WindowsException;
1173 
1174     /**
1175      * GetOverlappedResult(
1176      *   HANDLE hFile,
1177      *   LPOVERLAPPED lpOverlapped,
1178      *   LPDWORD lpNumberOfBytesTransferred,
1179      *   BOOL bWait
1180      * );
1181      */
1182     static native int GetOverlappedResult(long hFile, long lpOverlapped)
1183         throws WindowsException;
1184 
1185     // -- support for copying String with a NativeBuffer --
1186 
1187     private static final Unsafe unsafe = Unsafe.getUnsafe();
1188 
1189     static NativeBuffer asNativeBuffer(String s) throws WindowsException {
1190         if (s.length() > (Integer.MAX_VALUE - 2)/2) {
1191             throw new WindowsException
1192                 ("String too long to convert to native buffer");
1193         }
1194 
1195         int stringLengthInBytes = s.length() << 1;
1196         int sizeInBytes = stringLengthInBytes + 2;  // char terminator
1197 
1198         // get a native buffer of sufficient size
1199         NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(sizeInBytes);
1200         if (buffer == null) {
1201             buffer = NativeBuffers.allocNativeBuffer(sizeInBytes);
1202         } else {
1203             // buffer already contains the string contents
1204             if (buffer.owner() == s)
1205                 return buffer;
1206         }
1207 
1208         // copy into buffer and zero terminate
1209         char[] chars = s.toCharArray();
1210         unsafe.copyMemory(chars, Unsafe.ARRAY_CHAR_BASE_OFFSET, null,
1211             buffer.address(), (long)stringLengthInBytes);
1212         unsafe.putChar(buffer.address() + stringLengthInBytes, (char)0);
1213         buffer.setOwner(s);
1214         return buffer;
1215     }
1216 
1217     // -- native library initialization --
1218 
1219     private static native void initIDs();
1220 
1221     static {
1222         // nio.dll has dependency on net.dll
1223         jdk.internal.loader.BootLoader.loadLibrary("net");
1224         jdk.internal.loader.BootLoader.loadLibrary("nio");
1225         initIDs();
1226     }
1227 
1228 }