Skip to content

SHGetFileInfoW needs a binary-PIDL input overload for SHGFI_PIDL #1832

Open

Description

@jevansaks

SHGetFileInfoW needs a binary-PIDL input overload for SHGFI_PIDL

Summary

When SHGFI_PIDL is set, the first argument of SHGetFileInfoW is a binary
ITEMIDLIST pointer, not a UTF-16 path. CsWin32 projects that argument as
PCWSTR and offers friendly string overloads, but no overload that accepts
binary PIDL bytes (for example, ReadOnlySpan<byte>).

The generated overload taking Span<byte> uses it for the third, output
SHFILEINFOW parameter; it does not solve the binary first parameter.
See the Win32 SHGetFileInfoW documentation.

Reproduction

With CsWin32 0.3.335, request SHGetFileInfo in NativeMethods.txt and use
an absolute PIDL such as the two-byte Desktop/root PIDL:

using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Shell;

byte[] desktopPidl = [0, 0];
unsafe
{
    fixed (byte* pidl = desktopPidl)
    {
        SHFILEINFOW info = default;
        nuint result = PInvoke.SHGetFileInfo(
            (PCWSTR)(char*)pidl,
            0,
            &info,
            (uint)sizeof(SHFILEINFOW),
            SHGFI_FLAGS.SHGFI_PIDL | SHGFI_FLAGS.SHGFI_DISPLAYNAME);
    }
}

The explicit byte* -> char* -> PCWSTR reinterpretation is required to
compile. Replacing the first argument with desktopPidl, desktopPidl.AsSpan(),
or a string is not an equivalent safe option: the PIDL is binary data with
embedded zero bytes, not a text path.

The generated method shapes observed in the consuming assembly are:

SHGetFileInfo(string, FILE_FLAGS_AND_ATTRIBUTES, Span<byte>, SHGFI_FLAGS)
SHGetFileInfo(string, FILE_FLAGS_AND_ATTRIBUTES, ref SHFILEINFOW, SHGFI_FLAGS)
SHGetFileInfo(PCWSTR, FILE_FLAGS_AND_ATTRIBUTES, SHFILEINFOW*, uint, SHGFI_FLAGS)

Expected behavior

Please provide a friendly overload accepting a binary PIDL input such as
ReadOnlySpan<byte> (also usable from Span<byte>), pinning it for the call
and forwarding it as the first argument when SHGFI_PIDL is specified.
The overload should keep the existing path/string behavior for calls without
SHGFI_PIDL; no conversion of the PIDL bytes to text is appropriate.

This would let callers of the dual-purpose API use the correct representation
without hand-writing an unsafe pointer reinterpretation or suppressing
native-interop analyzer warnings.

Activity

  1. jevansaks commented on Sep 29, 2026

    @jevansaks
    MemberAuthor

    Follow-up research: this appears to be one instance of a broader Win32 metadata problem where a parameter is declared as a string pointer for ABI purposes but can conditionally carry some other value or pointer type.

    API/surface Declared type Alternate interpretation
    SHGetFileInfo with SHGFI_PIDL PCWSTR ITEMIDLIST*
    GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS PCWSTR An arbitrary address within the module
    CreateWindowEx.lpClassName PCWSTR ATOM
    Resource APIs and fields PCWSTR A MAKEINTRESOURCE identifier
    TaskDialog.pszIcon PCWSTR A predefined icon identifier
    OPENFILENAME.lpTemplateName PCWSTR A resource identifier

    Relevant Win32Metadata history:

    • microsoft/win32metadata#69 handled MAKEINTRESOURCE from the constant/value side. Constants are emitted as ushort with [NativeTypeName("LPCWSTR")] or LPCSTR, but this does not identify which parameters or fields accept such values.
    • microsoft/win32metadata#623 discussed this exact shape for CreateWindowEx accepting either a string or an ATOM. A native union was rejected because wrapping a pointer may alter ABI behavior. Possible annotations such as an opaque union or unaligned pointer were discussed, but the information was ultimately left to individual projections.
    • microsoft/win32metadata#2160 confirms that Win32Metadata currently has no mechanism to model the alternate interpretations of SHGetFileInfo.pszPath.
    • [AssociatedEnum] is the nearest existing metadata pattern: it retains the header/ABI type while identifying another logical type that projections may expose. There is no corresponding general [AssociatedType]/[AcceptsType] annotation today.

    A potential general solution would be a repeatable parameter/field annotation such as [AcceptsType("ITEMIDLIST*")], preserving the original ABI type while allowing projections to generate appropriate alternatives. APIs whose interpretation is flag-dependent may additionally need a way to associate the alternate type with SHGFI_PIDL, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, etc.

    For this particular API, metadata should probably express the alternate native type as ITEMIDLIST*; projecting that as a friendly ReadOnlySpan<byte> overload would then be CsWin32 policy.

  2. E021ntox commented on Oct 3, 2026

    @E021ntox

    Another issue is that &info triggers a warning: CS9123: The '&' operator should not be used on parameters or local variables in async methods.

  3. jevansaks commented on Oct 5, 2026

    @jevansaks
    MemberAuthor

    That's easy to handle in these cases by lifting the unsafe block into a sync method.

  4. E021ntox commented on Oct 15, 2026

    @E021ntox

    Jevan Saks (@jevansaks) I reported this issue in win32metadata about a month ago, but haven't received a response yet, so I'm following up here.

    IImageList::GetIcon should also use IMAGE_LIST_DRAW_STYLE
    https://learn.microsoft.com/en-us/windows/win32/api/commoncontrols/nf-commoncontrols-iimagelist-geticon

  5. jevansaks commented on Oct 15, 2026

    @jevansaks
    MemberAuthor

    E021ntox You commented on a closed issue, that makes it easier to miss. If you have a specific request, please file a new issue on win32metadata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions