1

I am looking to use the GetEffectiveRightsFromAclW Win32 function in .NET Framework. One of the parameters is of type PTRUSTEE_W. Insofar as what I've come across, this is a rather complex C type:

typedef struct _TRUSTEE_W {
  struct _TRUSTEE_W          *pMultipleTrustee;
  MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
  TRUSTEE_FORM               TrusteeForm;
  TRUSTEE_TYPE               TrusteeType;
  union {
    LPWSTR             ptstrName;
    SID                *pSid;
    OBJECTS_AND_SID    *pObjectsAndSid;
    OBJECTS_AND_NAME_W *pObjectsAndName;
  };
  LPWCH                      ptstrName;
} TRUSTEE_W, *PTRUSTEE_W, TRUSTEEW, *PTRUSTEEW;

I'm stuck on 3 main fronts:

  • My understanding of a C union is that any of the parameters defined within a union may be used to populate the field at that position in the struct. Am I understanding that correctly?
  • The parameter name ptstrName appears twice, once within the union and once at the end. Each instance has a different type (LPSTR and LPCH). What does this mean, exactly?
  • I have absolutely no idea what the last line of this typedef (after the final closing brace) means
    TRUSTEE_W, *PTRUSTEE_W, TRUSTEEW, *PTRUSTEEW;

I did make an attempt, which did not work (this is assuming x64 architecture, so I'm incrementing the offset by 8 instead of 4; let me know if that's wrong):

struct Trustee {
    [FieldOffset(0)] IntPtr pMultipleTrustee;
    [FieldOffset(8)] int MultipleTrusteeOperation;
    [FieldOffset(16)] int TrusteeForm;
    [FieldOffset(24)] int TrusteeType;
    [FieldOffset(32)] string ptstrName;
    [FieldOffset(32)] IntPtr pSid;
    [FieldOffset(32)] IntPtr pObjectsAndSid;
    [FieldOffset(32)] IntPtr pObjectsAndName;
};
Mike Bruno
  • 600
  • 2
  • 9
  • 26
  • Are you using [TRUSTEE_A](https://learn.microsoft.com/en-us/windows/win32/api/accctrl/ns-accctrl-trustee_a) or [TRUSTEE_W](https://learn.microsoft.com/en-us/windows/win32/api/accctrl/ns-accctrl-trustee_w)? – thedemons Oct 27 '22 at 20:14
  • @thedemons Well, the documentation for [GetEffectiveRightsFromAclW](https://learn.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-geteffectiverightsfromaclw) links to [TRUSTEE_A](https://learn.microsoft.com/en-us/windows/win32/api/accctrl/ns-accctrl-trustee_a) however, in the function signature, they list the type for the parameter as `TRUSTEE_W`. So I'm honestly not sure – Mike Bruno Oct 27 '22 at 20:18
  • 1
    it uses the `TRUSTEE_W`, Microsoft has always been known for making poor documentation, the struct definition is also wrong – thedemons Oct 27 '22 at 20:20
  • @thedemons Awesome... Well feel free to edit the struct in this question. – Mike Bruno Oct 27 '22 at 20:21
  • 2
    I don't code in C# so I'm not really sure how to define a struct, but for x64, the offset of `TrusteeForm` should be 12, `TrusteeType` should be 16, and the union should be 24 (because of alignment). Note that the struct definition on microsoft docs is wrong. Only the union or `ptstrName` exists, not both, because they're in a if else preprocessor deriective. – thedemons Oct 27 '22 at 20:35
  • Also, I think `ptstrName` should be defined with [`MarshalAs(UnmanagedType.LPWStr)`](https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshalling-for-strings#strings-used-in-interfaces) – thedemons Oct 27 '22 at 20:37
  • Try to use [CsWin32](https://www.nuget.org/packages/Microsoft.Windows.CsWin32#readme-body-tab), maybe it will help you. – Kaneko Qt Oct 27 '22 at 21:20
  • @KanekoQt Thanks, this is a pretty cool package, but unfortunately, I can't use a 3rd party tool for this particular project. Plus, I'm stuck on .NET Framework 4.7.2 – Mike Bruno Oct 28 '22 at 02:13
  • 1
    What I would do is 1) remove all field offsets (so it will use default packing) 2) add [StructLayout(LayoutKind.Sequential)] attribute to struct and 2) just keep one IntPtr for the union/pstrName. – Simon Mourier Oct 28 '22 at 06:03
  • @MikeBruno, you can use this package to generate C# code and then see how it works. – Kaneko Qt Oct 28 '22 at 08:38
  • I looked and CsWin32 does not generate union, this is sad. Then, why you increment from MultipleTrusteeOperation to TrusteeForm by 8, int size is 4 bytes as I know, so offsets will be like: 0, 0 + PTR_SIZE, 0 + PTR_SIZE + sizeof(int), 0 + PTR_SIZE + sizeof(int) + sizeof(int), 0 + PTR_SIZE + sizeof(int) + sizeof(int) + sizeof(int), 0 + PTR_SIZE + sizeof(int) + sizeof(int) + sizeof(int) + PTR_SIZE, 0 + PTR_SIZE + sizeof(int) + sizeof(int) + sizeof(int) + PTR_SIZE, 0 + PTR_SIZE + sizeof(int) + sizeof(int) + sizeof(int) + PTR_SIZE; or just 0, 8, 12, 16, 20, 28, 28, 28 in your case. – Kaneko Qt Oct 28 '22 at 09:58

1 Answers1

-1

I was able to find what I needed on pinvoke.net

I'm not marking this as the authoritative answer since I don't have the function actually working yet. Return code is: (0x80004005): The parameter is incorrect

Mike Bruno
  • 600
  • 2
  • 9
  • 26