diff --git a/CHANGES.md b/CHANGES.md index 8407152047..014fb5240b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -55,6 +55,8 @@ Features * [#654](https://github.com/java-native-access/jna/pull/654): Support named arguments for `com.sun.jna.platform.win32.COM.util.CallbackProxy` based callbacks - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#659](https://github.com/java-native-access/jna/issues/659): Enable LCID (locale) override for `com.sun.jna.platform.win32.COM.util.ProxyObject`-based COM calls - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#665](https://github.com/java-native-access/jna/pull/665): Added `XSetWMProtocols` and `XGetWMProtocols` to `com.sun.jna.platform.unix.X11` - [@zainab-ali](https://github.com/zainab-ali). +* [#667](https://github.com/java-native-access/jna/pull/667): Added SetFileSecurity, GetSecurityInfo and SetSecurityInfo to `com.sun.jna.platform.win32.Advapi32` - [@amarcionek](https://github.com/amarcionek). +* [#667](https://github.com/java-native-access/jna/pull/667): Added NtSetSecurityObject and NtQuerySecurityObject to `com.sun.jna.platform.win32.NtDll` - [@amarcionek](https://github.com/amarcionek). * [#680](https://github.com/java-native-access/jna/pull/680): Added `SetCurrentProcessExplicitAppUserModelID` and `GetCurrentProcessExplicitAppUserModelID` to `com.sun.jna.platform.win32.Shell32` for setting the [System.AppUserModel.ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569.aspx) of the host process - [@rednoah](https://github.com/rednoah). Bug Fixes diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java index 520d2ebb2d..a086bb2df9 100755 --- a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java @@ -1634,6 +1634,144 @@ boolean GetFileSecurity(String lpFileName, int RequestedInformation, Pointer pointer, int nLength, IntByReference lpnLengthNeeded); + /** + * The SetFileSecurity function sets the security of a file or directory object. + * This function is obsolete. Use the SetNamedSecurityInfo function instead. + * + * @param lpFileName + * A pointer to a null-terminated string that specifies the file or directory for which security is set. + * Note that security applied to a directory is not inherited by its children. + * @param SecurityInformation + * Specifies a SECURITY_INFORMATION structure that identifies the contents of the security descriptor + * pointed to by the pSecurityDescriptor parameter. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure. + * @return + * If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get + * extended error information, call GetLastError. + */ + boolean SetFileSecurity(String lpFileName, int SecurityInformation, Pointer pSecurityDescriptor); + + /** + * The GetSecurityInfo function retrieves a copy of the security descriptor for an object specified by a handle. + * + * @param handle [in] + * A handle to the object from which to retrieve security information. + * @param ObjectType [in] + * SE_OBJECT_TYPE enumeration value that indicates the type of object. + * @param SecurityInfo [in] + * A set of bit flags that indicate the type of security information to retrieve. See WinNT *_SECURITY_INFORMATION + * @param ppsidOwner [out, optional] + * A pointer to a variable that receives a pointer to the owner SID in the security descriptor returned + * in ppSecurityDescriptor. The returned pointer is valid only if you set the OWNER_SECURITY_INFORMATION flag. + * This parameter can be NULL if you do not need the owner SID. + * @param ppsidGroup [in, optional] + * A pointer to a variable that receives a pointer to the primary group SID in the returned security descriptor. + * The returned pointer is valid only if you set the GROUP_SECURITY_INFORMATION flag. This parameter can be NULL + * if you do not need the group SID. + * @param ppDacl [in, optional] + * A pointer to a variable that receives a pointer to the DACL in the returned security descriptor. The returned + * pointer is valid only if you set the DACL_SECURITY_INFORMATION flag. This parameter can be NULL if you do not + * need the DACL. + * @param ppSacl [in, optional] + * A pointer to a variable that receives a pointer to the SACL in the returned security descriptor. The returned + * pointer is valid only if you set the SACL_SECURITY_INFORMATION flag. This parameter can be NULL if you do not + * need the SACL. + * @param ppSecurityDescriptor + * A pointer to a variable that receives a pointer to the security descriptor of the object. When you have finished + * using the pointer, free the returned buffer by calling the LocalFree function. + * This parameter is required if any one of the ppsidOwner, ppsidGroup, ppDacl, or ppSacl parameters is not NULL. + * @return whether the call succeeded. A nonzero return is a failure. + * + *

NOTES:

+ *

1. If the ppsidOwner, ppsidGroup, ppDacl, and ppSacl parameters are non-NULL, and the SecurityInfo parameter specifies + * that they be retrieved from the object, those parameters will point to the corresponding parameters in the security descriptor + * returned in ppSecurityDescriptor.

+ *

2. To read the owner, group, or DACL from the object's security descriptor, the calling process must have been granted + * READ_CONTROL access when the handle was opened. To get READ_CONTROL access, the caller must be the owner of the object or + * the object's DACL must grant the access.

+ *

3. To read the SACL from the security descriptor, the calling process must have been granted ACCESS_SYSTEM_SECURITY access + * when the handle was opened. The proper way to get this access is to enable the SE_SECURITY_NAME privilege in the caller's + * current token, open the handle for ACCESS_SYSTEM_SECURITY access, and then disable the privilege.

+ *

4. If the supplied handle was opened with an ACCESS_MASK value of MAXIMUM_ALLOWED, + * then the SetSecurityInfo function will not propagate ACEs to children.

+ */ + int GetSecurityInfo(HANDLE handle, + int ObjectType, + int SecurityInfo, + PointerByReference ppsidOwner, + PointerByReference ppsidGroup, + PointerByReference ppDacl, + PointerByReference ppSacl, + PointerByReference ppSecurityDescriptor); + + /** + * The SetSecurityInfo function sets specified security information in + * the security descriptor of a specified object. The caller identifies the + * object by a handle. + * + * @param handle [in] + * A handle to the object for which to set security information. + * @param ObjectType [in] + * A value of the SE_OBJECT_TYPE enumeration that indicates the type + * of object named by the pObjectName parameter. + * @param SecurityInfo [in] + * A set of bit flags that indicate the type of security + * information to set. See WinNT *_SECURITY_INFORMATION + * @param ppsidOwner [in, optional] + * A pointer to a SID structure that identifies the owner of the object. + * If the caller does not have the SeRestorePrivilege constant + * (see Privilege Constants), this SID must be contained in the + * caller's token, and must have the SE_GROUP_OWNER permission enabled. + * The SecurityInfo parameter must include the OWNER_SECURITY_INFORMATION + * flag. To set the owner, the caller must have WRITE_OWNER access to + * the object or have the SE_TAKE_OWNERSHIP_NAME privilege enabled. + * If you are not setting the owner SID, this parameter can be NULL. + * @param ppsidGroup [in, optional] + * A pointer to a SID that identifies the primary group of the object. + * The SecurityInfo parameter must include the GROUP_SECURITY_INFORMATION + * flag. If you are not setting the primary group SID, this parameter + * can be NULL. + * @param ppDacl [in, optional] + * A pointer to the new DACL for the object. The SecurityInfo parameter + * must include the DACL_SECURITY_INFORMATION flag. The caller must have + * WRITE_DAC access to the object or be the owner of the object. If you + * are not setting the DACL, this parameter can be NULL. + * @param ppSacl [in, optional] + * A pointer to the new SACL for the object. The SecurityInfo parameter + * must include any of the following flags: SACL_SECURITY_INFORMATION, + * LABEL_SECURITY_INFORMATION, ATTRIBUTE_SECURITY_INFORMATION, + * SCOPE_SECURITY_INFORMATION, or BACKUP_SECURITY_INFORMATION. + * If setting SACL_SECURITY_INFORMATION or SCOPE_SECURITY_INFORMATION, + * the caller must have the SE_SECURITY_NAME privilege enabled. If + * you are not setting the SACL, this parameter can be NULL. + * @return whether the call succeeded. A nonzero return is a failure. + * + *

NOTES:

+ *

1. If you are setting the discretionary access control list (DACL) or any elements + * in the system access control list (SACL) of an object, the system automatically + * propagates any inheritable access control entries (ACEs) to existing child objects, + * according to the ACE inheritance rules.

+ *

2. The SetSecurityInfo function does not reorder access-allowed or access-denied + * ACEs based on the preferred order. When propagating inheritable ACEs to existing + * child objects, SetSecurityInfo puts inherited ACEs in order after all of the + * noninherited ACEs in the DACLs of the child objects.

+ *

3. If share access to the children of the object is not available, this function + * will not propagate unprotected ACEs to the children. For example, if a directory + * is opened with exclusive access, the operating system will not propagate unprotected + * ACEs to the subdirectories or files of that directory when the security on the + * directory is changed.

+ *

4. If the supplied handle was opened with an ACCESS_MASK value of MAXIMUM_ALLOWED, + * then the SetSecurityInfo function will not propagate ACEs to children.

+ */ + int SetSecurityInfo(HANDLE handle, + int ObjectType, + int SecurityInfo, + Pointer ppsidOwner, + Pointer ppsidGroup, + Pointer ppDacl, + Pointer ppSacl); + /** * The GetNamedSecurityInfo function retrieves a copy of the security * descriptor for an object specified by name diff --git a/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java b/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java index 26b74e1974..417f38b29b 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java @@ -13,6 +13,7 @@ package com.sun.jna.platform.win32; import com.sun.jna.Native; +import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.ptr.IntByReference; @@ -51,4 +52,56 @@ public interface NtDll extends StdCallLibrary { */ public int ZwQueryKey(HANDLE KeyHandle, int KeyInformationClass, Structure KeyInformation, int Length, IntByReference ResultLength); + + /** + * The NtSetSecurityObject routine sets an object's security state. + * @param handle [in] + * Handle for the object whose security state is to be set. This handle must have the access + * specified in the Meaning column of the table shown in the description of the + * SecurityInformation parameter. + * @param SecurityInformation [in] + * SECURITY_INFORMATION value specifying the information to be set. Can be a combination of + * one or more of the following: + * DACL_SECURITY_INFORMATION + * Indicates the discretionary access control list (DACL) of the object is to be set. Requires WRITE_DAC access. + * GROUP_SECURITY_INFORMATION + * Indicates the primary group identifier of the object is to be set. Requires WRITE_OWNER access. + * OWNER_SECURITY_INFORMATION + * Indicates the owner identifier of the object is to be set. Requires WRITE_OWNER access. + * SACL_SECURITY_INFORMATION + * Indicates the system ACL (SACL) of the object is to be set. Requires ACCESS_SYSTEM_SECURITY access. + * @param pSecurityDescriptor [in] + * Pointer to the security descriptor to be set for the object. + * @return + * NtSetSecurityObject returns STATUS_SUCCESS or an appropriate error status. + */ + public int NtSetSecurityObject(HANDLE handle, int SecurityInformation, Pointer pSecurityDescriptor); + + /** + * The NtQuerySecurityObject routine retrieves a copy of an object's security descriptor. + * + * @param handle [in] + * Handle for the object whose security descriptor is to be queried. This handle must have the access specified + * in the Meaning column of the table shown in the description of the SecurityInformation parameter. + * @param SecurityInformation [in] + * Pointer to a SECURITY_INFORMATION value specifying the information to be queried. Can be a combination of + * one or more of the following: + * DACL_SECURITY_INFORMATION + * Indicates the discretionary access control list (DACL) of the object is to be set. Requires WRITE_DAC access. + * GROUP_SECURITY_INFORMATION + * Indicates the primary group identifier of the object is to be set. Requires WRITE_OWNER access. + * OWNER_SECURITY_INFORMATION + * Indicates the owner identifier of the object is to be set. Requires WRITE_OWNER access. + * SACL_SECURITY_INFORMATION + * Indicates the system ACL (SACL) of the object is to be set. Requires ACCESS_SYSTEM_SECURITY access. + * @param SecurityDescriptor [out] + * Pointer to the security descriptor to be set for the object. + * @param Length [in] + * Size, in bytes, of the buffer pointed to by SecurityDescriptor. + * @param LengthNeeded [in] + * Pointer to a caller-allocated variable that receives the number of bytes required to store the copied security descriptor. + * @return + * NtQuerySecurityObject returns STATUS_SUCCESS or an appropriate error status. + */ + public int NtQuerySecurityObject(HANDLE handle, int SecurityInformation, Pointer SecurityDescriptor, int Length, IntByReference LengthNeeded); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java index 02bf2418f5..beaeef3c00 100755 --- a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java @@ -1005,6 +1005,200 @@ public void testImpersonateSelf() { assertTrue(Advapi32.INSTANCE.RevertToSelf()); } + public void testGetSetFileSecurityNoSACL() throws Exception { + int infoType = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + + int memSize = 64 * 1024; + Memory memorySecurity = new Memory(memSize); + IntByReference sizeNeeded = new IntByReference(0); + // create a temp file + File file = createTempFile(); + String filePath = file.getAbsolutePath(); + + try { + + assertEquals("GetFileSecurity(" + filePath + ")", true, + Advapi32.INSTANCE.GetFileSecurity( + filePath, + infoType, + memorySecurity, + memSize, + sizeNeeded)); + assertEquals("SetFileSecurity(" + filePath + ")", true, + Advapi32.INSTANCE.SetFileSecurity( + filePath, + infoType, + memorySecurity)); + } finally { + file.delete(); + } + } + + public void testGetSetSecurityInfoNoSACL() throws Exception { + int infoType = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + + PointerByReference ppsidOwner = new PointerByReference(); + PointerByReference ppsidGroup = new PointerByReference(); + PointerByReference ppDacl = new PointerByReference(); + PointerByReference ppSecurityDescriptor = new PointerByReference(); + // create a temp file + File file = createTempFile(); + String filePath = file.getAbsolutePath(); + + HANDLE hFile = Kernel32.INSTANCE.CreateFile( + filePath, + WinNT.GENERIC_ALL | WinNT.WRITE_OWNER | WinNT.WRITE_DAC, + WinNT.FILE_SHARE_READ, + new WinBase.SECURITY_ATTRIBUTES(), + WinNT.OPEN_EXISTING, + WinNT.FILE_ATTRIBUTE_NORMAL, + null); + assertFalse("Failed to create file handle: " + filePath, WinBase.INVALID_HANDLE_VALUE.equals(hFile)); + + try { + try { + + assertEquals("GetSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.GetSecurityInfo( + hFile, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + null, + ppSecurityDescriptor)); + + assertEquals("SetSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.SetSecurityInfo( + hFile, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner.getValue(), + ppsidGroup.getValue(), + ppDacl.getValue(), + null)); + } finally { + Kernel32.INSTANCE.CloseHandle(hFile); + file.delete(); + } + } finally { + Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue()); + } + } + + public void testGetSetSecurityInfoForFileWithSACL() throws Exception { + boolean impersontating = false; + + HANDLEByReference phToken = new HANDLEByReference(); + HANDLEByReference phTokenDuplicate = new HANDLEByReference(); + try { + // open thread or process token, elevate + if (!Advapi32.INSTANCE.OpenThreadToken( + Kernel32.INSTANCE.GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES, + false, + phToken)) + { + assertEquals(W32Errors.ERROR_NO_TOKEN, Kernel32.INSTANCE.GetLastError()); + // OpenThreadToken may fail with W32Errors.ERROR_NO_TOKEN if current thread is anonymous. When this happens, + // we need to open the process token to duplicate it, then set our thread token. + assertTrue(Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), TOKEN_DUPLICATE, phToken)); + // Process token opened, now duplicate + assertTrue(Advapi32.INSTANCE.DuplicateTokenEx( + phToken.getValue(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE, + null, + SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, + TOKEN_TYPE.TokenImpersonation, + phTokenDuplicate)); + // And set thread token. + assertTrue(Advapi32.INSTANCE.SetThreadToken(null, phTokenDuplicate.getValue())); + impersontating = true; + } + + // Which token to adjust depends on whether we had to impersonate or not. + HANDLE tokenAdjust = impersontating ? phTokenDuplicate.getValue() : phToken.getValue(); + + WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(1); + WinNT.LUID pLuid = new WinNT.LUID(); + + assertTrue(Advapi32.INSTANCE.LookupPrivilegeValue(null, SE_SECURITY_NAME, pLuid)); + tp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(pLuid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED)); + assertTrue(Advapi32.INSTANCE.AdjustTokenPrivileges(tokenAdjust, false, tp, 0, null, null)); + + assertTrue(Advapi32.INSTANCE.LookupPrivilegeValue(null, SE_RESTORE_NAME, pLuid)); + tp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(pLuid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED)); + assertTrue(Advapi32.INSTANCE.AdjustTokenPrivileges(tokenAdjust, false, tp, 0, null, null)); + + // create a temp file + File file = createTempFile(); + int infoType = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION + | SACL_SECURITY_INFORMATION; + + PointerByReference ppsidOwner = new PointerByReference(); + PointerByReference ppsidGroup = new PointerByReference(); + PointerByReference ppDacl = new PointerByReference(); + PointerByReference ppSacl = new PointerByReference(); + PointerByReference ppSecurityDescriptor = new PointerByReference(); + String filePath = file.getAbsolutePath(); + HANDLE hFile = WinBase.INVALID_HANDLE_VALUE; + + try { + try { + hFile = Kernel32.INSTANCE.CreateFile( + filePath, + WinNT.ACCESS_SYSTEM_SECURITY | WinNT.GENERIC_WRITE | WinNT.WRITE_OWNER | WinNT.WRITE_DAC, + WinNT.FILE_SHARE_READ, + new WinBase.SECURITY_ATTRIBUTES(), + WinNT.OPEN_EXISTING, + WinNT.FILE_ATTRIBUTE_NORMAL, + null); + assertEquals("GetSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.GetSecurityInfo( + hFile, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + ppSacl, + ppSecurityDescriptor)); + assertEquals("SetSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.SetSecurityInfo( + hFile, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner.getValue(), + ppsidGroup.getValue(), + ppDacl.getValue(), + ppSacl.getValue())); + } finally { + if (hFile != WinBase.INVALID_HANDLE_VALUE) + Kernel32.INSTANCE.CloseHandle(hFile); + file.delete(); + } + } finally { + Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue()); + } + + if (impersontating) { + assertTrue("SetThreadToken", Advapi32.INSTANCE.SetThreadToken(null, null)); + } + else { + tp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(pLuid, new DWORD(0)); + assertTrue("AdjustTokenPrivileges", Advapi32.INSTANCE.AdjustTokenPrivileges(tokenAdjust, false, tp, 0, null, null)); + } + } finally { + Kernel32Util.closeHandleRefs(phToken, phTokenDuplicate); + } + } public void testGetNamedSecurityInfoForFileNoSACL() throws Exception { int infoType = OWNER_SECURITY_INFORMATION diff --git a/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java b/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java index bf832a295a..378e77ad1c 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java @@ -12,13 +12,22 @@ */ package com.sun.jna.platform.win32; -import junit.framework.TestCase; +import static com.sun.jna.platform.win32.WinNT.DACL_SECURITY_INFORMATION; +import static com.sun.jna.platform.win32.WinNT.GROUP_SECURITY_INFORMATION; +import static com.sun.jna.platform.win32.WinNT.OWNER_SECURITY_INFORMATION; + +import java.io.File; +import java.io.FileWriter; +import com.sun.jna.Memory; import com.sun.jna.platform.win32.Wdm.KEY_BASIC_INFORMATION; import com.sun.jna.platform.win32.Wdm.KEY_INFORMATION_CLASS; +import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinReg.HKEYByReference; import com.sun.jna.ptr.IntByReference; +import junit.framework.TestCase; + /** * @author dblock[at]dblock[dot]org */ @@ -49,4 +58,63 @@ public void testZwQueryKey() { // close key assertEquals(W32Errors.ERROR_SUCCESS, Advapi32.INSTANCE.RegCloseKey(phKey.getValue())); } + + public void testNtQuerySetSecurityObjectNoSACL() throws Exception { + int infoType = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + + // create a temp file + File file = createTempFile(); + String filePath = file.getAbsolutePath(); + HANDLE hFile = WinBase.INVALID_HANDLE_VALUE; + + try { + hFile = Kernel32.INSTANCE.CreateFile( + filePath, + WinNT.GENERIC_WRITE | WinNT.WRITE_OWNER | WinNT.WRITE_DAC, + WinNT.FILE_SHARE_READ, + new WinBase.SECURITY_ATTRIBUTES(), + WinNT.OPEN_EXISTING, + WinNT.FILE_ATTRIBUTE_NORMAL, + null); + assertFalse("Failed to create file handle: " + filePath, WinBase.INVALID_HANDLE_VALUE.equals(hFile)); + + int Length = 64 * 1024; + Memory SecurityDescriptor = new Memory(Length); + IntByReference LengthNeeded = new IntByReference(); + + assertEquals("NtQuerySecurityObject(" + filePath + ")", 0, + NtDll.INSTANCE.NtQuerySecurityObject( + hFile, + infoType, + SecurityDescriptor, + Length, + LengthNeeded)); + assertTrue(LengthNeeded.getValue() > 0); + assertTrue(LengthNeeded.getValue() < 64 * 1024); + assertEquals("NtSetSecurityObject(" + filePath + ")", 0, + NtDll.INSTANCE.NtSetSecurityObject( + hFile, + infoType, + SecurityDescriptor)); + } finally { + if (hFile != WinBase.INVALID_HANDLE_VALUE) + Kernel32.INSTANCE.CloseHandle(hFile); + file.delete(); + } + } + + private File createTempFile() throws Exception { + String filePath = System.getProperty("java.io.tmpdir") + System.nanoTime() + + ".text"; + File file = new File(filePath); + file.createNewFile(); + FileWriter fileWriter = new FileWriter(file); + for (int i = 0; i < 1000; i++) { + fileWriter.write("Sample text " + i + System.getProperty("line.separator")); + } + fileWriter.close(); + return file; + } }