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