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