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