diff --git a/CHANGES.md b/CHANGES.md index c4fa0863d2..1d80ac376a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -63,6 +63,8 @@ Features * [#689](https://github.com/java-native-access/jna/pull/689): Add `GetProcAddress(HMODULE, int)` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#723](https://github.com/java-native-access/jna/pull/723): Added `com.sun.jna.platform.win32.Wevtapi` and `com.sun.jna.platform.win32.Winevt` - [@sakamotodesu](https://github.com/sakamotodesu). * [#720](https://github.com/java-native-access/jna/issues/720): Added `SetThreadExecutionState` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing). +* [#738](https://github.com/java-native-access/jna/pull/738): Added `GetSecurityDescriptorOwner`, `SetSecurityDescriptorOwner`, `GetSecurityDescriptorGroup`, `SetSecurityDescriptorGroup`, `GetSecurityDescriptorControl`, `SetSecurityDescriptorControl`, `GetSecurityDescriptorDacl`, `SetSecurityDescriptorDacl`, `MakeSelfRelativeSD`, `MakeAbsoluteSD`, `EqualSid`, `InitializeSecurityDescriptor`, `InitializeAcl`, `AddAce`, `AddAccessAllowedAce`, `AddAccessAllowedAceEx`, and `GetAce` to `com.sun.jna.platform.win32.Advapi32 - [@amarcionek](https://github.com/amarcionek). +* [#738](https://github.com/java-native-access/jna/pull/738): Added `RtlNtStatusToDosError` to `com.sun.jna.platform.win32.NtDll - [@amarcionek](https://github.com/amarcionek). * [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.WinioctlUtil` for help in determining FSCTL_* codes - [@amarcionek](https://github.com/amarcionek). * [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.Ntifs` with Reparse Point structures and defines - [@amarcionek](https://github.com/amarcionek). * [#732](https://github.com/java-native-access/jna/pull/732): Added initialization of FILETIME from LARGE_INTEGER - [@amarcionek](https://github.com/amarcionek). 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 fcbbad8eb7..f28b15a97c 100755 --- a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java @@ -35,12 +35,16 @@ import com.sun.jna.platform.win32.WinDef.DWORD; import com.sun.jna.platform.win32.WinDef.DWORDByReference; import com.sun.jna.platform.win32.WinDef.ULONG; +import com.sun.jna.platform.win32.WinNT.ACL; import com.sun.jna.platform.win32.WinNT.GENERIC_MAPPING; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; +import com.sun.jna.platform.win32.WinNT.PACLByReference; import com.sun.jna.platform.win32.WinNT.PRIVILEGE_SET; import com.sun.jna.platform.win32.WinNT.PSID; import com.sun.jna.platform.win32.WinNT.PSIDByReference; +import com.sun.jna.platform.win32.WinNT.SECURITY_DESCRIPTOR; +import com.sun.jna.platform.win32.WinNT.SECURITY_DESCRIPTOR_RELATIVE; import com.sun.jna.platform.win32.WinReg.HKEY; import com.sun.jna.platform.win32.WinReg.HKEYByReference; import com.sun.jna.platform.win32.Winsvc.ChangeServiceConfig2Info; @@ -50,6 +54,7 @@ import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.LongByReference; import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.ptr.ShortByReference; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIOptions; @@ -248,6 +253,20 @@ boolean LookupAccountSid(String lpSystemName, PSID Sid, */ boolean IsValidSid(PSID pSid); + /** + * he EqualSid function tests two security identifier (SID) values for equality. + * Two SIDs must match exactly to be considered equal. + * @param pSid1 + * A pointer to the first SID structure to compare. This structure is assumed to be valid. + * @param pSid2 + * A pointer to the second SID structure to compare. This structure is assumed to be valid. + * @return If the SID structures are equal, the return value is nonzero. + * If the SID structures are not equal, the return value is zero. To get extended error + * information, call GetLastError. + * If either SID structure is not valid, the return value is undefined. + */ + boolean EqualSid(PSID pSid1, PSID pSid2); + /** * Compares a SID to a well known SID and returns TRUE if they match. * @@ -283,6 +302,292 @@ boolean LookupAccountSid(String lpSystemName, PSID Sid, boolean CreateWellKnownSid(int wellKnownSidType, PSID domainSid, PSID pSid, IntByReference cbSid); + /** + * The InitializeSecurityDescriptor function initializes a new security descriptor. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure that the function initializes. + * @param dwRevision + * The revision level to assign to the security descriptor. This parameter + * must be SECURITY_DESCRIPTOR_REVISION. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean InitializeSecurityDescriptor(SECURITY_DESCRIPTOR pSecurityDescriptor, int dwRevision); + + /** + * The GetSecurityDescriptorControl function retrieves a security descriptor control and revision information. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure whose control and revision + * information the function retrieves. + * @param pControl + * A pointer to a SECURITY_DESCRIPTOR_CONTROL structure that receives the security descriptor's + * control information. + * @param lpdwRevision + * A pointer to a variable that receives the security descriptor's revision value. + * This value is always set, even when GetSecurityDescriptorControl returns an error. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean GetSecurityDescriptorControl(SECURITY_DESCRIPTOR pSecurityDescriptor, ShortByReference pControl, IntByReference lpdwRevision); + + /** + * The SetSecurityDescriptorControl function sets the control bits of a security descriptor. The function can set only the control + * bits that relate to automatic inheritance of ACEs. To set the other control bits of a security descriptor, use the functions, + * such as SetSecurityDescriptorDacl, for modifying the components of a security descriptor. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure whose control and revision information are set. + * @param ControlBitsOfInterest + * A SECURITY_DESCRIPTOR_CONTROL mask that indicates the control bits to set. + * @param ControlBitsToSet + * SECURITY_DESCRIPTOR_CONTROL mask that indicates the new values for the control bits specified by the ControlBitsOfInterest mask. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean SetSecurityDescriptorControl(SECURITY_DESCRIPTOR pSecurityDescriptor, short ControlBitsOfInterest, short ControlBitsToSet); + + /** + * The GetSecurityDescriptorOwner function retrieves the owner information from a security descriptor. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure whose owner information the function retrieves. + * @param pOwner + * A pointer to a pointer to a security identifier (SID) that identifies the owner when the function returns. + * If the security descriptor does not contain an owner, the function sets the pointer pointed to by pOwner + * to NULL and ignores the remaining output parameter, lpbOwnerDefaulted. If the security descriptor contains an owner, + * the function sets the pointer pointed to by pOwner to the address of the security descriptor's owner SID + * and provides a valid value for the variable pointed to by lpbOwnerDefaulted. + * @param lpbOwnerDefaulted + * A pointer to a flag that is set to the value of the SE_OWNER_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL + * structure when the function returns. If the value stored in the variable pointed to by the pOwner parameter is + * NULL, no value is set. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean GetSecurityDescriptorOwner(SECURITY_DESCRIPTOR pSecurityDescriptor, PSIDByReference pOwner, BOOLByReference lpbOwnerDefaulted); + + /** + * The SetSecurityDescriptorOwner function sets the owner information of an absolute-format security descriptor. It replaces + * any owner information already present in the security descriptor. + * @param pSecurityDescriptor + * A pointer to the SECURITY_DESCRIPTOR structure whose owner is set by this function. The function replaces any existing + * owner with the new owner. + * @param pOwner + * A pointer to a SID structure for the security descriptor's new primary owner. The SID structure is referenced by, not + * copied into, the security descriptor. If this parameter is NULL, the function clears the security descriptor's owner + * information. This marks the security descriptor as having no owner. + * @param bOwnerDefaulted + * Indicates whether the owner information is derived from a default mechanism. If this value is TRUE, it is default information. + * The function stores this value as the SE_OWNER_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure. If this parameter + * is zero, the SE_OWNER_DEFAULTED flag is cleared. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean SetSecurityDescriptorOwner(SECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, boolean bOwnerDefaulted); + + /** + * The GetSecurityDescriptorGroup function retrieves the primary group information from a security descriptor. + * @param pSecurityDescriptor + * A pointer to a SECURITY_DESCRIPTOR structure whose primary group information the function retrieves. + * @param pGroup + * A pointer to a pointer to a security identifier (SID) that identifies the primary group when the function + * returns. If the security descriptor does not contain a primary group, the function sets the pointer + * pointed to by pGroup to NULL and ignores the remaining output parameter, lpbGroupDefaulted. If the + * security descriptor contains a primary group, the function sets the pointer pointed to by pGroup to the + * address of the security descriptor's group SID and provides a valid value for the variable pointed to + * by lpbGroupDefaulted. + * @param lpbGroupDefaulted + * A pointer to a flag that is set to the value of the SE_GROUP_DEFAULTED flag in the + * SECURITY_DESCRIPTOR_CONTROL structure when the function returns. If the value stored in the variable + * pointed to by the pGroup parameter is NULL, no value is set. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean GetSecurityDescriptorGroup(SECURITY_DESCRIPTOR pSecurityDescriptor, PSIDByReference pGroup, BOOLByReference lpbGroupDefaulted); + + /** + * The SetSecurityDescriptorGroup function sets the primary group information of an absolute-format security descriptor, replacing + * any primary group information already present in the security descriptor. + * @param pSecurityDescriptor + * A pointer to the SECURITY_DESCRIPTOR structure whose primary group is set by this function. The function replaces + * any existing primary group with the new primary group. + * @param pGroup + * A pointer to a SID structure for the security descriptor's new primary group. The SID structure is referenced by, not copied + * into, the security descriptor. If this parameter is NULL, the function clears the security descriptor's primary group + * information. This marks the security descriptor as having no primary group. + * @param bGroupDefaulted + * Indicates whether the primary group information was derived from a default mechanism. If this value is TRUE, it is default + * information, and the function stores this value as the SE_GROUP_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure. + * If this parameter is zero, the SE_GROUP_DEFAULTED flag is cleared. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean SetSecurityDescriptorGroup(SECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, boolean bGroupDefaulted); + + /** + * The GetSecurityDescriptorDacl function retrieves a pointer to the discretionary access control list (DACL) in + * a specified security descriptor. + * @param pSecurityDescriptor + * A pointer to the SECURITY_DESCRIPTOR structure that contains the DACL. The function retrieves a pointer to it. + * @param bDaclPresent + * A pointer to a value that indicates the presence of a DACL in the specified security descriptor. If + * lpbDaclPresent is TRUE, the security descriptor contains a DACL, and the remaining output parameters in this + * function receive valid values. If lpbDaclPresent is FALSE, the security descriptor does not contain a DACL, + * and the remaining output parameters do not receive valid values. A value of TRUE for lpbDaclPresent does not + * mean that pDacl is not NULL. That is, lpbDaclPresent can be TRUE while pDacl is NULL, meaning that a NULL + * DACL is in effect. A NULL DACL implicitly allows all access to an object and is not the same as an empty DACL. + * An empty DACL permits no access to an object. For information about creating a proper DACL, see Creating a DACL. + * @param pDacl + * A pointer to a pointer to an access control list (ACL). If a DACL exists, the function sets the pointer pointed + * to by pDacl to the address of the security descriptor's DACL. If a DACL does not exist, no value is stored. + * If the function stores a NULL value in the pointer pointed to by pDacl, the security descriptor has a NULL DACL. + * A NULL DACL implicitly allows all access to an object. + * If an application expects a non-NULL DACL but encounters a NULL DACL, the application should fail securely and + * not allow access. + * @param bDaclDefaulted + * A pointer to a flag set to the value of the SE_DACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure + * if a DACL exists for the security descriptor. If this flag is TRUE, the DACL was retrieved by a default mechanism; + * if FALSE, the DACL was explicitly specified by a user. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean GetSecurityDescriptorDacl(SECURITY_DESCRIPTOR pSecurityDescriptor, BOOLByReference bDaclPresent, PACLByReference pDacl, BOOLByReference bDaclDefaulted); + + /** + * The SetSecurityDescriptorDacl function sets information in a discretionary access control list (DACL). + * If a DACL is already present in the security descriptor, the DACL is replaced. + * @param pSecurityDescriptor + * A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the DACL. This + * security descriptor must be in absolute format, meaning that its members must be pointers + * to other structures, rather than offsets to contiguous data. + * @param bDaclPresent + * A flag that indicates the presence of a DACL in the security descriptor. If this parameter + * is TRUE, the function sets the SE_DACL_PRESENT flag in the SECURITY_DESCRIPTOR_CONTROL + * structure and uses the values in the pDacl and bDaclDefaulted parameters. If this parameter + * is FALSE, the function clears the SE_DACL_PRESENT flag, and pDacl and bDaclDefaulted are ignored. + * @param pDacl + * A pointer to an ACL structure that specifies the DACL for the security descriptor. If this + * parameter is NULL, a NULL DACL is assigned to the security descriptor, which allows all access + * to the object. The DACL is referenced by, not copied into, the security descriptor. + * @param bDaclDefaulted + * A flag that indicates the source of the DACL. If this flag is TRUE, the DACL has been retrieved + * by some default mechanism. If FALSE, the DACL has been explicitly specified by a user. The function + * stores this value in the SE_DACL_DEFAULTED flag of the SECURITY_DESCRIPTOR_CONTROL structure. If + * this parameter is not specified, the SE_DACL_DEFAULTED flag is cleared. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean SetSecurityDescriptorDacl(SECURITY_DESCRIPTOR pSecurityDescriptor, boolean bDaclPresent, ACL pDacl, boolean bDaclDefaulted); + + /** + * The InitializeAcl function initializes a new ACL structure. + * @param pAcl + * A pointer to an ACL structure to be initialized by this function. + * Allocate memory for pAcl before calling this function. + * @param nAclLength + * The length, in bytes, of the buffer pointed to by the pAcl parameter. This value + * must be large enough to contain the ACL header and all of the access control + * entries (ACEs) to be stored in the ACL. In addition, this value must be + * DWORD-aligned. For more information about calculating the size of an ACL, + * see Remarks. + * @param dwAclRevision + * The revision level of the ACL structure being created. This value can be ACL_REVISION + * or ACL_REVISION_DS. Use ACL_REVISION_DS if the access control list (ACL) supports + * object-specific ACEs. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean InitializeAcl(ACL pAcl, int nAclLength, int dwAclRevision); + + /** + * The AddAce function adds one or more access control entries (ACEs) to a specified access control list (ACL). + * @param pAcl + * A pointer to an ACL. This function adds an ACE to this ACL. + * @param dwAceRevision + * Specifies the revision level of the ACL being modified. This value can be ACL_REVISION or + * ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. This value + * must be compatible with the AceType field of all ACEs in pAceList. Otherwise, the function + * will fail and set the last error to ERROR_INVALID_PARAMETER. + * @param dwStartingAceIndex + * Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero + * inserts the ACEs at the beginning of the list. A value of MAXDWORD appends the ACEs to the end + * of the list. + * @param pAceList + * A pointer to a list of one or more ACEs to be added to the specified ACL. The ACEs in the list + * must be stored contiguously. + * @param nAceListLength + * Specifies the size, in bytes, of the input buffer pointed to by the pAceList parameter. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean AddAce(ACL pAcl, int dwAceRevision, int dwStartingAceIndex, Pointer pAceList, int nAceListLength); + + /** + * The AddAce function adds one or more access control entries (ACEs) to a specified access control list (ACL). + * @param pAcl + * A pointer to an ACL. This function adds an access-allowed ACE to the end of this ACL. + * The ACE is in the form of an ACCESS_ALLOWED_ACE structure. + * @param dwAceRevision + * Specifies the revision level of the ACL being modified. This value can be ACL_REVISION or + * ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. + * @param AccessMask + * Specifies the mask of access rights to be granted to the specified SID. + * @param pSid + * A pointer to the SID representing a user, group, or logon account being granted access. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean AddAccessAllowedAce(ACL pAcl, int dwAceRevision, int AccessMask, PSID pSid); + + /** + * The AddAce function adds one or more access control entries (ACEs) to a specified access control list (ACL). + * @param pAcl + * A pointer to an ACL. This function adds an access-allowed ACE to the end of this ACL. + * The ACE is in the form of an ACCESS_ALLOWED_ACE structure. + * @param dwAceRevision + * Specifies the revision level of the ACL being modified. This value can be ACL_REVISION or + * ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. + * @param AceFlags + * A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags + * member of the ACE_HEADER structure of the new ACE. This parameter can be a combination + * of the following values: CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE, INHERITED_ACE, + * NO_PROPAGATE_INHERIT_ACE, and OBJECT_INHERIT_ACE + * @param AccessMask + * Specifies the mask of access rights to be granted to the specified SID. + * @param pSid + * A pointer to the SID representing a user, group, or logon account being granted access. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean AddAccessAllowedAceEx(ACL pAcl, int dwAceRevision, int AceFlags, int AccessMask, PSID pSid); + + /** + * The GetAce function obtains a pointer to an access control entry (ACE) in an access + * control list (ACL). + * @param pAcl + * A pointer to an ACL that contains the ACE to be retrieved. + * @param dwAceIndex + * The index of the ACE to be retrieved. A value of zero corresponds to the first ACE in + * the ACL, a value of one to the second ACE, and so on. + * @param pAce + * A pointer to a pointer that the function sets to the address of the ACE. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. For extended error + * information, call GetLastError. + */ + boolean GetAce(ACL pAcl, int dwAceIndex, PointerByReference pAce); + /** * The LogonUser function attempts to log a user on to the local computer. * The local computer is the computer from which LogonUser was called. You @@ -1941,6 +2246,85 @@ int SetNamedSecurityInfo( */ boolean IsValidSecurityDescriptor(Pointer ppSecurityDescriptor); + /** + * A pointer to a SECURITY_DESCRIPTOR structure in absolute format. The function creates a version of this security + * descriptor in self-relative format without modifying the original. + * @param pAbsoluteSD + * A pointer to a SECURITY_DESCRIPTOR structure in absolute format. The function creates a version of this + * security descriptor in self-relative format without modifying the original. + * @param pSelfRelativeSD + * A pointer to a buffer the function fills with a security descriptor in self-relative format. + * @param lpdwBufferLength + * A pointer to a variable specifying the size of the buffer pointed to by the pSelfRelativeSD parameter. + * If the buffer is not large enough for the security descriptor, the function fails and sets this variable + * to the minimum required size. + * @return If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get + * extended error information, call GetLastError. Possible return codes include, but are not limited to, the following: + * ERROR_INSUFFICIENT_BUFFER - One or more of the buffers is too small. + */ + boolean MakeSelfRelativeSD(SECURITY_DESCRIPTOR pAbsoluteSD, + SECURITY_DESCRIPTOR_RELATIVE pSelfRelativeSD, + IntByReference lpdwBufferLength); + + /** + * The MakeAbsoluteSD function creates a security descriptor in absolute format by using a + * security descriptor in self-relative format as a template. + * @param pSelfRelativeSD + * A pointer to a SECURITY_DESCRIPTOR structure in self-relative format. The function creates an + * absolute-format version of this security descriptor without modifying the original security descriptor. + * @param pAbsoluteSD + * A pointer to a buffer that the function fills with the main body of an absolute-format security + * descriptor. This information is formatted as a SECURITY_DESCRIPTOR structure. + * @param lpdwAbsoluteSDSize + * A pointer to a variable that specifies the size of the buffer pointed to by the pAbsoluteSD parameter. + * If the buffer is not large enough for the security descriptor, the function fails and sets this variable + * to the minimum required size. + * @param pDacl + * A pointer to a buffer the function fills with the discretionary access control list (DACL) of the + * absolute-format security descriptor. The main body of the absolute-format security descriptor references + * this pointer. + * @param lpdwDaclSize + * A pointer to a variable that specifies the size of the buffer pointed to by the pDacl parameter. If + * the buffer is not large enough for the access control list (ACL), the function fails and sets this + * variable to the minimum required size. + * @param pSacl + * A pointer to a buffer the function fills with the system access control list (SACL) of the absolute-format + * security descriptor. The main body of the absolute-format security descriptor references this pointer. + * @param lpdwSaclSize + * A pointer to a variable that specifies the size of the buffer pointed to by the pSacl parameter. If the + * buffer is not large enough for the ACL, the function fails and sets this variable to the minimum required + * size. + * @param pOwner + * A pointer to a buffer the function fills with the security identifier (SID) of the owner of the + * absolute-format security descriptor. The main body of the absolute-format security descriptor references + * this pointer. + * @param lpdwOwnerSize + * A pointer to a variable that specifies the size of the buffer pointed to by the pOwner parameter. + * If the buffer is not large enough for the SID, the function fails and sets this variable to the minimum + * required size. + * @param pPrimaryGroup + * A pointer to a buffer the function fills with the SID of the absolute-format security descriptor's + * primary group. The main body of the absolute-format security descriptor references this pointer. + * @param lpdwPrimaryGroupSize + * A pointer to a variable that specifies the size of the buffer pointed to by the pPrimaryGroup parameter. + * If the buffer is not large enough for the SID, the function fails and sets this variable to the minimum + * required size. + * @return If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get + * extended error information, call GetLastError. Possible return codes include, but are not limited to, the following: + * ERROR_INSUFFICIENT_BUFFER - One or more of the buffers is too small. + */ + boolean MakeAbsoluteSD(SECURITY_DESCRIPTOR_RELATIVE pSelfRelativeSD, + SECURITY_DESCRIPTOR pAbsoluteSD, + IntByReference lpdwAbsoluteSDSize, + ACL pDacl, + IntByReference lpdwDaclSize, + ACL pSacl, + IntByReference lpdwSaclSize, + PSID pOwner, + IntByReference lpdwOwnerSize, + PSID pPrimaryGroup, + IntByReference lpdwPrimaryGroupSize); + /** * The IsValidAcl function validates an access control list (ACL). * diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java index ecb23c5120..a405890d88 100755 --- a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java @@ -71,6 +71,7 @@ import com.sun.jna.platform.win32.WinDef.ULONG; import com.sun.jna.platform.win32.WinDef.ULONGByReference; import com.sun.jna.platform.win32.WinNT.ACCESS_ACEStructure; +import com.sun.jna.platform.win32.WinNT.ACCESS_ALLOWED_ACE; import com.sun.jna.platform.win32.WinNT.ACL; import com.sun.jna.platform.win32.WinNT.EVENTLOGRECORD; import com.sun.jna.platform.win32.WinNT.GENERIC_MAPPING; @@ -380,7 +381,27 @@ public static boolean isWellKnownSid(byte[] sidBytes, int wellKnownSidType) { return Advapi32.INSTANCE.IsWellKnownSid(pSID, wellKnownSidType); } + /** + * Align cbAcl on a DWORD + * @param cbAcl size to align + * @return the aligned size + */ + public static int alignOnDWORD(int cbAcl) { + return (cbAcl + (DWORD.SIZE - 1)) & 0xfffffffc; + } + /** + * Helper function to calculate the size of an ACE for a given PSID size + * @param sidLength length of the sid + * @return size of the ACE + */ + public static int getAceSize(int sidLength) { + return Native.getNativeSize(ACCESS_ALLOWED_ACE.class, null) + + sidLength + - DWORD.SIZE; + } + + /** * Get an account name from a string SID on the local machine. * * @param sidString diff --git a/contrib/platform/src/com/sun/jna/platform/win32/NTStatus.java b/contrib/platform/src/com/sun/jna/platform/win32/NTStatus.java index d2bb81d1de..37111794ea 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/NTStatus.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/NTStatus.java @@ -96,5 +96,14 @@ public interface NTStatus { // STATUS_ABANDONED_WAIT_63 // int STATUS_ABANDONED_WAIT_63 = 0x000000BF; + + // + // MessageId: STATUS_INVALID_OWNER + // + // MessageText: + // + // Indicates a particular Security ID may not be assigned as the owner of an object. + // + int STATUS_INVALID_OWNER = 0xC000005A; } 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 e51ef8dffa..0caf2dfe06 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/NtDll.java @@ -115,4 +115,13 @@ public int ZwQueryKey(HANDLE KeyHandle, int KeyInformationClass, * NtQuerySecurityObject returns STATUS_SUCCESS or an appropriate error status. */ public int NtQuerySecurityObject(HANDLE handle, int SecurityInformation, Pointer SecurityDescriptor, int Length, IntByReference LengthNeeded); + + /** + * Converts the specified NTSTATUS code to its equivalent system error code. + * @param Status [in] + * The NTSTATUS code to be converted. + * @return The function returns the corresponding system error code. ERROR_MR_MID_NOT_FOUND is returned when the specified NTSTATUS code + * does not have a corresponding system error code. + */ + public int RtlNtStatusToDosError(int Status); } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java b/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java index 5dcf09bf07..26f432a30d 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import com.sun.jna.FromNativeContext; import com.sun.jna.IntegerType; @@ -50,6 +49,15 @@ @SuppressWarnings("serial") public interface WinNT extends WinError, WinDef, WinBase, BaseTSD { + int MINCHAR = 0x80; + int MAXCHAR = 0x7f; + int MINSHORT = 0x8000; + int MAXSHORT = 0x7fff; + int MINLONG = 0x80000000; + int MAXLONG = 0x7fffffff; + int MAXBYTE = 0xff; + int MAXWORD = 0xffff; + int MAXDWORD = 0xffffffff; // // The following are masks for the predefined standard access types // @@ -2481,6 +2489,7 @@ protected List getFieldOrder() { int SE_RM_CONTROL_VALID = 0x00004000; int SE_SELF_RELATIVE = 0x00008000; + int SECURITY_DESCRIPTOR_REVISION = 0x00000001; public static class SECURITY_DESCRIPTOR extends Structure { public static class ByReference extends SECURITY_DESCRIPTOR implements @@ -2495,10 +2504,17 @@ public SECURITY_DESCRIPTOR() { } public SECURITY_DESCRIPTOR(byte[] data) { + super(); this.data = data; useMemory(new Memory(data.length)); } + public SECURITY_DESCRIPTOR(int size) { + super(); + useMemory(new Memory(size)); + data = new byte[size]; + } + public SECURITY_DESCRIPTOR(Pointer memory) { super(memory); read(); @@ -2510,9 +2526,27 @@ protected List getFieldOrder() { } } + int ACL_REVISION = 2; + int ACL_REVISION_DS = 4; + + // This is the history of ACL revisions. Add a new one whenever + // ACL_REVISION is updated + int ACL_REVISION1 = 1; + int ACL_REVISION2 = 2; + int ACL_REVISION3 = 3; + int ACL_REVISION4 = 4; + int MIN_ACL_REVISION = ACL_REVISION2; + int MAX_ACL_REVISION = ACL_REVISION4; + public static class ACL extends Structure { public static final List FIELDS = createFieldsOrder("AclRevision", "Sbz1", "AclSize", "AceCount", "Sbz2"); + /* + * Maximum size chosen based on technet article: + * https://technet.microsoft.com/en-us/library/cc781716.aspx + */ + public static int MAX_ACL_SIZE = 64 * 1024; + public byte AclRevision; public byte Sbz1; public short AclSize; @@ -2525,6 +2559,11 @@ public ACL() { super(); } + public ACL(int size) { + super(); + useMemory(new Memory(size)); + } + public ACL(Pointer pointer) { super(pointer); read(); @@ -2560,6 +2599,31 @@ protected List getFieldOrder() { } } + public static class PACLByReference extends ByReference { + public PACLByReference() { + this(null); + } + + public PACLByReference(ACL h) { + super(Pointer.SIZE); + setValue(h); + } + + public void setValue(ACL h) { + getPointer().setPointer(0, h != null ? h.getPointer() : null); + } + + public ACL getValue() { + Pointer p = getPointer().getPointer(0); + if (p == null) { + return null; + } + else { + return new ACL(p); + } + } + } + public static class SECURITY_DESCRIPTOR_RELATIVE extends Structure { public static class ByReference extends SECURITY_DESCRIPTOR_RELATIVE implements Structure.ByReference { @@ -2575,10 +2639,10 @@ public static class ByReference extends SECURITY_DESCRIPTOR_RELATIVE public int Sacl; public int Dacl; - private ACL DACL; private PSID OWNER; private PSID GROUP; private ACL SACL; + private ACL DACL; public SECURITY_DESCRIPTOR_RELATIVE() { super(); @@ -2590,6 +2654,10 @@ public SECURITY_DESCRIPTOR_RELATIVE(byte[] data) { setMembers(); } + public SECURITY_DESCRIPTOR_RELATIVE(int length) { + super(new Memory(length)); + } + public SECURITY_DESCRIPTOR_RELATIVE(Pointer p) { super(p); setMembers(); @@ -2650,6 +2718,15 @@ public ACEStructure(Pointer p) { super(p); } + public ACEStructure(byte AceType, byte AceFlags, short AceSize, PSID psid) { + super(); + this.AceType = AceType; + this.AceFlags = AceFlags; + this.AceSize = AceSize; + this.psid = psid; + write(); + } + public String getSidString() { return Advapi32Util.convertSidToStringSid(psid); } @@ -2680,46 +2757,69 @@ public ACE_HEADER(Pointer p) { * ACCESS_ALLOWED_ACE and ACCESS_DENIED_ACE have the same structure layout */ public static abstract class ACCESS_ACEStructure extends ACEStructure { - public static final List EXTRA_ABSTRACT_FIELDS = createFieldsOrder("Mask", "SidStart"); - private static final AtomicReference> fieldsHolder = new AtomicReference>(null); - private static List resolveEffectiveFields(List baseFields) { - List fields; - synchronized (fieldsHolder) { - fields = fieldsHolder.get(); - if (fields == null) { - fields = createFieldsOrder(baseFields, EXTRA_ABSTRACT_FIELDS); - fieldsHolder.set(fields); - } - } - - return fields; - } + public static final List FIELDS = createFieldsOrder(ACEStructure.FIELDS, "Mask", "SidStart"); public int Mask; /** - * first 4 bytes of the SID + * First 4 bytes of the SID + * Only used to have a valid field defined - use sid! */ - public DWORD SidStart; + public byte[] SidStart = new byte[4]; public ACCESS_ACEStructure() { super(); } + public ACCESS_ACEStructure(int Mask, byte AceType, byte AceFlags, PSID psid) { + super(); + this.calculateSize(true); + this.AceType = AceType; + this.AceFlags = AceFlags; + this.AceSize = (short) (super.fieldOffset("SidStart") + psid.getBytes().length); + this.psid = psid; + this.Mask = Mask; + this.SidStart = psid.getPointer().getByteArray(0, SidStart.length); + this.allocateMemory(AceSize); + write(); + } + public ACCESS_ACEStructure(Pointer p) { super(p); read(); - // AceSize - size of public members of the structure + size of DWORD - // (SidStart) - int sizeOfSID = super.AceSize - size() + 4; - // ACE_HEADER + size of int (Mask) - int offsetOfSID = 4 + 4; - byte[] data = p.getByteArray(offsetOfSID, sizeOfSID); - psid = new PSID(data); + } + + /** + * Write override due to psid not being a managed field + */ + @Override + public void write() { + super.write(); + int offsetOfSID = super.fieldOffset("SidStart"); + int sizeOfSID = super.AceSize - super.fieldOffset("SidStart"); + if(psid != null) { + // Get bytes from the PSID + byte[] psidWrite = psid.getBytes(); + assert psidWrite.length <= sizeOfSID; + // Write those bytes to native memory + getPointer().write(offsetOfSID, psidWrite, 0, sizeOfSID); + } + } + + @Override + public void read() { + super.read(); + int offsetOfSID = super.fieldOffset("SidStart"); + int sizeOfSID = super.AceSize - super.fieldOffset("SidStart"); + if(sizeOfSID > 0) { + psid = new PSID(getPointer().getByteArray(offsetOfSID, sizeOfSID)); + } else { + psid = new PSID(); + } } @Override protected List getFieldOrder() { - return resolveEffectiveFields(super.getFieldOrder()); + return FIELDS; } } @@ -2732,6 +2832,10 @@ public ACCESS_ALLOWED_ACE() { public ACCESS_ALLOWED_ACE(Pointer p) { super(p); } + + public ACCESS_ALLOWED_ACE(int Mask, byte AceFlags, PSID psid) { + super(Mask, ACCESS_ALLOWED_ACE_TYPE, AceFlags, psid); + } } /* Access denied ACE */ @@ -2743,6 +2847,10 @@ public ACCESS_DENIED_ACE() { public ACCESS_DENIED_ACE(Pointer p) { super(p); } + + public ACCESS_DENIED_ACE(int Mask, byte AceFlags, PSID psid) { + super(Mask, ACCESS_DENIED_ACE_TYPE, AceFlags, psid); + } } /* ACE types */ 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 beaeef3c00..4a422858bc 100755 --- a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java @@ -50,18 +50,24 @@ import com.sun.jna.platform.win32.WinBase.FILETIME; import com.sun.jna.platform.win32.WinBase.PROCESS_INFORMATION; import com.sun.jna.platform.win32.WinBase.STARTUPINFO; +import com.sun.jna.platform.win32.WinDef.BOOL; import com.sun.jna.platform.win32.WinDef.BOOLByReference; import com.sun.jna.platform.win32.WinDef.DWORD; import com.sun.jna.platform.win32.WinDef.DWORDByReference; import com.sun.jna.platform.win32.WinDef.ULONG; import com.sun.jna.platform.win32.WinDef.ULONGByReference; +import com.sun.jna.platform.win32.WinNT.ACCESS_ALLOWED_ACE; +import com.sun.jna.platform.win32.WinNT.ACL; import com.sun.jna.platform.win32.WinNT.EVENTLOGRECORD; import com.sun.jna.platform.win32.WinNT.GENERIC_MAPPING; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; +import com.sun.jna.platform.win32.WinNT.PACLByReference; import com.sun.jna.platform.win32.WinNT.PRIVILEGE_SET; import com.sun.jna.platform.win32.WinNT.PSID; import com.sun.jna.platform.win32.WinNT.PSIDByReference; +import com.sun.jna.platform.win32.WinNT.SECURITY_DESCRIPTOR; +import com.sun.jna.platform.win32.WinNT.SECURITY_DESCRIPTOR_RELATIVE; import com.sun.jna.platform.win32.WinNT.SECURITY_IMPERSONATION_LEVEL; import com.sun.jna.platform.win32.WinNT.SID_AND_ATTRIBUTES; import com.sun.jna.platform.win32.WinNT.SID_NAME_USE; @@ -74,6 +80,7 @@ import com.sun.jna.platform.win32.Winsvc.SERVICE_STATUS_PROCESS; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.ptr.ShortByReference; import junit.framework.TestCase; @@ -149,6 +156,23 @@ public void testIsValidSid() { } } + public void testEqualSid() { + String sidString = EVERYONE; + PSIDByReference sid1 = new PSIDByReference(); + PSIDByReference sid2 = new PSIDByReference(); + assertTrue("SID1 conversion failed", Advapi32.INSTANCE.ConvertStringSidToSid(sidString, sid1)); + assertTrue("SID2 conversion failed", Advapi32.INSTANCE.ConvertStringSidToSid(sidString, sid2)); + + try { + assertTrue("Converted SID1 not valid", Advapi32.INSTANCE.IsValidSid(sid1.getValue())); + assertTrue("Converted SID2 not valid", Advapi32.INSTANCE.IsValidSid(sid2.getValue())); + assertTrue("Invalid sid", Advapi32.INSTANCE.EqualSid(sid1.getValue(), sid2.getValue())); + } finally { + Kernel32Util.freeLocalMemory(sid1.getValue().getPointer()); + Kernel32Util.freeLocalMemory(sid2.getValue().getPointer()); + } + } + public void testGetSidLength() { String sidString = EVERYONE; PSIDByReference sid = new PSIDByReference(); @@ -674,6 +698,205 @@ public void testCreateWellKnownSid() { } } + public void testInitializeSecurityDescriptor() { + SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(sd, WinNT.SECURITY_DESCRIPTOR_REVISION)); + } + + public void testSetGetSecurityDescriptorControl() { + SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(sd, WinNT.SECURITY_DESCRIPTOR_REVISION)); + assertTrue(Advapi32.INSTANCE.SetSecurityDescriptorControl(sd, (short)WinNT.SE_DACL_PROTECTED, (short)WinNT.SE_DACL_PROTECTED)); + ShortByReference pControl = new ShortByReference(); + IntByReference lpdwRevision = new IntByReference(); + assertTrue(Advapi32.INSTANCE.GetSecurityDescriptorControl(sd, pControl, lpdwRevision)); + assertTrue(pControl.getValue() == WinNT.SE_DACL_PROTECTED); + assertTrue(lpdwRevision.getValue() == WinNT.SECURITY_DESCRIPTOR_REVISION); + } + + public void testSetGetSecurityDescriptorOwner() { + SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(sd, WinNT.SECURITY_DESCRIPTOR_REVISION)); + + PSID pSidPut = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSidPut, cbSid)); + + assertTrue(Advapi32.INSTANCE.SetSecurityDescriptorOwner(sd, pSidPut, true)); + + BOOLByReference lpbOwnerDefaulted = new BOOLByReference(); + PSIDByReference prSd = new PSIDByReference(); + assertTrue(Advapi32.INSTANCE.GetSecurityDescriptorOwner(sd, prSd, lpbOwnerDefaulted)); + + PSID pSidGet = prSd.getValue(); + assertTrue(Advapi32.INSTANCE.EqualSid(pSidPut, pSidGet)); + } + + public void testSetGetSecurityDescriptorGroup() { + SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(sd, WinNT.SECURITY_DESCRIPTOR_REVISION)); + + PSID pSidPut = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSidPut, cbSid)); + + assertTrue(Advapi32.INSTANCE.SetSecurityDescriptorGroup(sd, pSidPut, true)); + + BOOLByReference lpbOwnerDefaulted = new BOOLByReference(); + PSIDByReference prSd = new PSIDByReference(); + assertTrue(Advapi32.INSTANCE.GetSecurityDescriptorGroup(sd, prSd, lpbOwnerDefaulted)); + + PSID pSidGet = prSd.getValue(); + assertTrue(Advapi32.INSTANCE.EqualSid(pSidPut, pSidGet)); + } + + public void testSetGetSecurityDescriptorDacl() throws IOException { + SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(sd, WinNT.SECURITY_DESCRIPTOR_REVISION)); + + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Native.getNativeSize(ACCESS_ALLOWED_ACE.class, null); + cbAcl += (sidLength - DWORD.SIZE); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + assertTrue(Advapi32.INSTANCE.AddAccessAllowedAce(pAcl, WinNT.ACL_REVISION, WinNT.STANDARD_RIGHTS_ALL, pSid)); + assertTrue(Advapi32.INSTANCE.SetSecurityDescriptorDacl(sd, true, pAcl, false)); + BOOLByReference lpbDaclPresent = new BOOLByReference(); + BOOLByReference lpbDaclDefaulted = new BOOLByReference(); + PACLByReference pDacl = new PACLByReference(); + assertTrue(Advapi32.INSTANCE.GetSecurityDescriptorDacl(sd, lpbDaclPresent, pDacl, lpbDaclDefaulted)); + ACL pAclGet = pDacl.getValue(); + assertEquals(new BOOL(true), lpbDaclPresent.getValue()); + assertEquals(new BOOL(false), lpbDaclDefaulted.getValue()); + assertEquals(1, pAclGet.AceCount); + assertEquals(WinNT.ACL_REVISION, pAclGet.AclRevision); + } + + public void testInitializeAcl() throws IOException { + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Native.getNativeSize(ACCESS_ALLOWED_ACE.class, null); + cbAcl += (sidLength - DWORD.SIZE); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + } + + public void testGetAce() throws IOException { + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Native.getNativeSize(ACCESS_ALLOWED_ACE.class, null); + cbAcl += (sidLength - DWORD.SIZE); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + assertTrue(Advapi32.INSTANCE.AddAccessAllowedAce(pAcl, WinNT.ACL_REVISION, WinNT.STANDARD_RIGHTS_ALL, pSid)); + + PointerByReference pAce = new PointerByReference(new Memory(16)); + assertTrue(Advapi32.INSTANCE.GetAce(pAcl, 0, pAce)); + ACCESS_ALLOWED_ACE pAceGet = new ACCESS_ALLOWED_ACE(pAce.getValue()); + assertTrue(pAceGet.Mask == WinNT.STANDARD_RIGHTS_ALL); + assertTrue(Advapi32.INSTANCE.EqualSid(pAceGet.psid, pSid)); + } + + public void testAddAce() throws IOException { + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Advapi32Util.getAceSize(sidLength); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + ACCESS_ALLOWED_ACE pace = new ACCESS_ALLOWED_ACE(WinNT.STANDARD_RIGHTS_ALL, + WinNT.INHERITED_ACE, + pSid); + + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + assertTrue(Advapi32.INSTANCE.AddAce(pAcl, WinNT.ACL_REVISION, WinNT.MAXDWORD, pace.getPointer(), pace.size())); + + PointerByReference pAce = new PointerByReference(new Memory(16)); + assertTrue(Advapi32.INSTANCE.GetAce(pAcl, 0, pAce)); + ACCESS_ALLOWED_ACE pAceGet = new ACCESS_ALLOWED_ACE(pAce.getValue()); + assertTrue(pAceGet.Mask == WinNT.STANDARD_RIGHTS_ALL); + assertTrue(Advapi32.INSTANCE.EqualSid(pAceGet.psid, pSid)); + } + + public void testAddAccessAllowedAce() throws IOException { + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Advapi32Util.getAceSize(sidLength); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + assertTrue(Advapi32.INSTANCE.AddAccessAllowedAce(pAcl, WinNT.ACL_REVISION, WinNT.STANDARD_RIGHTS_ALL, pSid)); + + PointerByReference pAce = new PointerByReference(new Memory(16)); + assertTrue(Advapi32.INSTANCE.GetAce(pAcl, 0, pAce)); + ACCESS_ALLOWED_ACE pAceGet = new ACCESS_ALLOWED_ACE(pAce.getValue()); + assertTrue(pAceGet.Mask == WinNT.STANDARD_RIGHTS_ALL); + assertTrue(Advapi32.INSTANCE.EqualSid(pAceGet.psid, pSid)); + } + + public void testAddAccessAllowedAceEx() throws IOException { + ACL pAcl; + int cbAcl = 0; + PSID pSid = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference cbSid = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + assertTrue("Failed to create well-known SID", + Advapi32.INSTANCE.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, null, pSid, cbSid)); + + int sidLength = Advapi32.INSTANCE.GetLengthSid(pSid); + cbAcl = Native.getNativeSize(ACL.class, null); + cbAcl += Advapi32Util.getAceSize(sidLength); + cbAcl = Advapi32Util.alignOnDWORD(cbAcl); + pAcl = new ACL(cbAcl); + assertTrue(Advapi32.INSTANCE.InitializeAcl(pAcl, cbAcl, WinNT.ACL_REVISION)); + assertTrue(Advapi32.INSTANCE.AddAccessAllowedAceEx(pAcl, WinNT.ACL_REVISION, WinNT.INHERIT_ONLY_ACE, WinNT.STANDARD_RIGHTS_ALL, pSid)); + + PointerByReference pAce = new PointerByReference(new Memory(16)); + assertTrue(Advapi32.INSTANCE.GetAce(pAcl, 0, pAce)); + ACCESS_ALLOWED_ACE pAceGet = new ACCESS_ALLOWED_ACE(pAce.getValue()); + assertTrue(pAceGet.Mask == WinNT.STANDARD_RIGHTS_ALL); + assertTrue(Advapi32.INSTANCE.EqualSid(pAceGet.psid, pSid)); + } + public void testOpenEventLog() { HANDLE h = Advapi32.INSTANCE.OpenEventLog(null, "Application"); assertNotNull(h); @@ -1513,6 +1736,60 @@ public void testIsValidSecurityDescriptor() throws Exception { } } + public void testMakeSelfRelativeSD() { + SECURITY_DESCRIPTOR absolute = new SECURITY_DESCRIPTOR(64 * 1024); + assertTrue(Advapi32.INSTANCE.InitializeSecurityDescriptor(absolute, WinNT.SECURITY_DESCRIPTOR_REVISION)); + SECURITY_DESCRIPTOR_RELATIVE relative = new SECURITY_DESCRIPTOR_RELATIVE(64 * 1024); + IntByReference lpdwBufferLength = new IntByReference(64 * 1024); + assertTrue(Advapi32.INSTANCE.MakeSelfRelativeSD(absolute, relative, lpdwBufferLength)); + assertEquals(WinNT.SECURITY_DESCRIPTOR_REVISION, relative.Revision); + } + + public void testMakeAbsoluteSD() throws Exception { + SECURITY_DESCRIPTOR absolute = new SECURITY_DESCRIPTOR(64 * 1024); + + // Get a SD in self relative form + int infoType = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + + PointerByReference relativeByReference = new PointerByReference(); + File file = createTempFile(); + try { + try { + assertEquals("GetNamedSecurityInfo(" + file + ")", + Advapi32.INSTANCE.GetNamedSecurityInfo( + file.getAbsolutePath(), + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + null, + null, + null, + null, + relativeByReference), 0); + + SECURITY_DESCRIPTOR_RELATIVE relative = new SECURITY_DESCRIPTOR_RELATIVE(relativeByReference.getValue()); + + PSID pOwner = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + PSID pGroup = new PSID(WinNT.SECURITY_MAX_SID_SIZE); + ACL pDacl = new ACL(ACL.MAX_ACL_SIZE); + ACL pSacl = new ACL(ACL.MAX_ACL_SIZE); + + IntByReference lpdwBufferLength = new IntByReference(absolute.size()); + IntByReference lpdwDaclSize = new IntByReference(ACL.MAX_ACL_SIZE); + IntByReference lpdwSaclSize= new IntByReference(ACL.MAX_ACL_SIZE); + IntByReference lpdwOwnerSize= new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + IntByReference lpdwPrimaryGroupSize = new IntByReference(WinNT.SECURITY_MAX_SID_SIZE); + + assertTrue(Advapi32.INSTANCE.MakeAbsoluteSD(relative, absolute, lpdwBufferLength, pDacl, lpdwDaclSize, pSacl, lpdwSaclSize, pOwner, lpdwOwnerSize, pGroup, lpdwPrimaryGroupSize)); + } finally { + file.delete(); + } + } finally { + Kernel32Util.freeLocalMemory(relativeByReference.getValue()); + } + } + public void testMapGenericReadMask() { final GENERIC_MAPPING mapping = new GENERIC_MAPPING(); mapping.genericRead = new DWORD(FILE_GENERIC_READ); 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 378e77ad1c..f37b2febdd 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/NtDllTest.java @@ -105,6 +105,12 @@ public void testNtQuerySetSecurityObjectNoSACL() throws Exception { } } + public void testRtlNtStatusToDosError() { + int status = NTStatus.STATUS_INVALID_OWNER; + int error = NtDll.INSTANCE.RtlNtStatusToDosError(status); + assertEquals(W32Errors.ERROR_INVALID_OWNER, error); + } + private File createTempFile() throws Exception { String filePath = System.getProperty("java.io.tmpdir") + System.nanoTime() + ".text";