Hi @Chris Terrell ,
I tested class 46 on Windows 11 build 10.0.26200, x64, and I went back through the Microsoft pages you listed plus the related native and SDK material. I will separate what the documentation states, what it does not state, and what I observed.
On whether the ntifs.h description applies to GetTokenInformation, I could not find any Microsoft source that says it does. The winnt.h entry for TokenIsLessPrivilegedAppContainer only describes what an LPAC is and ends with "You can create an LPAC only imperatively via APIs; not declaratively via appxmanifest.xml". It gives no output type, size, version, or error. The ntifs.h entry ("Returns a DWORD value that is nonzero if the token is for a less privileged app container") is written for SeQueryInformationToken and ZwQueryInformationToken. The only documented bridge between the two surfaces is the note on the ZwQueryInformationToken page that user mode should use the name NtQueryInformationToken, and that page's per-class table does not include class 46. So the applicability you asked about is not established by any cited source.
On your four points, based on my test run:
- Support and prerequisites: No Microsoft page gives a minimum version or build for class 46 (the winnt.h Requirements table covers the whole enum and says Windows XP). On build 26200 the query failed identically for a normal token, an AppContainer token, an impersonation token at both Identification and Impersonation level, elevated and non-elevated, and for a genuine LPAC token whose security attributes (class 39) included
WIN://NOALLAPPPKG. A handle opened with onlyTOKEN_QUERY_SOURCEreturned the same error rather thanERROR_ACCESS_DENIED, which suggests the class is rejected before the access check. I did not find any documented architecture or token-context requirement. - Output representation: Only the ntifs.h text describes the payload (DWORD, nonzero means LPAC). No source promises normalization to 0 or 1, and no source defines zero beyond "not LPAC". I could not observe the payload because no call succeeded. For comparison,
TokenIsAppContainer(29) andTokenIsSandboxed(47) succeeded on the same tokens withReturnLength4 and values of exactly 0 or 1, but that is data from other classes, not evidence for class 46. Alignment is documented on the ZwQueryInformationToken page ("All structures must be aligned on a 32-bit boundary"), and I observed that a 4-byte buffer at a misaligned address failed withSTATUS_DATATYPE_MISALIGNMENT(error 998) for every class, including 46, before the class itself was validated. - Retrieval procedure: The general GetTokenInformation contract (NULL buffer with zero length,
ERROR_INSUFFICIENT_BUFFER,ReturnLengthset) has no documented exception for class 46. In my test the NULL/0 sizing call for class 46 returned FALSE with error 87 and leftReturnLengthunwritten. The same sizing call for class 29 returned error 122 withReturnLength4, as the general contract describes. - Output validity and the error 87: This is the part I can tie to documentation. The ZwQueryInformationToken page lists
STATUS_INVALID_INFO_CLASSwith the description "TokenInformationClass was not a valid token information class", andRtlNtStatusToDosErrormaps that status to 87, ERROR_INVALID_PARAMETER (I confirmed the mapping on this build). In my runs,NtQueryInformationTokenwith class 46 returned0xC0000003for every buffer size (0, 4, 8, 16 bytes) and every token, withReturnLengthuntouched and the buffer untouched, which is the same behavior I got from a deliberately invalid class value. A buffer that is too small for a valid class producesSTATUS_BUFFER_TOO_SMALL(error 122) instead. I agree that 87 alone does not establish anything, but 87 that is independent of buffer size, leavesReturnLengthunwritten, and corresponds toSTATUS_INVALID_INFO_CLASSwhile neighboring classes succeed in the same call pattern does point to the class being rejected on this build rather than to a parameter problem on your side. The documentation does not list any class-specific failure condition for 46, and the general page says no data is stored when the call fails.
Two limitations: I only tested build 26200, so I cannot say whether class 46 was accepted from user mode on earlier builds. And the WIN://NOALLAPPPKG attribute I used to confirm the LPAC token is not documented on Microsoft Learn or in the SDK headers, and class 39 is marked reserved in the Win32 documentation, so I would treat that as an observed technique only. The fully documented alternative remains TokenIsAppContainer, as shown in AppContainer for legacy apps.
Since this forum has no access to the Windows source, telemetry, or the product team, so the above is capability guidance from the public documentation and my own verification. If you need a formal ruling on whether class 46 is a supported user-mode query and on which builds, a Windows developer support case is the right channel.
I hope these information help. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.
Thank you.