Why would the PIDL for the control panel be different?

拟墨画扇 提交于 2021-02-07 14:55:28

问题


I see that one should do this to compare PIDLs: IShellFolder::CompareIDs().

In particular, I'm trying to detect if a given absolute PIDL (or relative) is that of the Control Panel.

However, in practice I end up with two PIDLs which IShellFolder::CompareIDs() claims are not equal, when they should be (looking at the GetDisplayName() for each, I can see that we're indeed looking at the Control Panel).

Basically, I'm obtaining the absolute PIDL for the Control panel by:

PIDL iidControlPanel = nullptr;
SHGetSpecialFolderLocation(hwnd, CSIDL_CONTROLS, &iidControlPanel);

And then comparing the incoming enumerated shell object like so (see here for context - in a nutshell this is looking at the results of enumerating the desktop shell namespace inside of CMFCShellTreeCtrl):

bool bIsControlPanel = CompareAbsolutePIDLs(iidControlPanel, pItem->pidlFQ);

For reference, here's the comparison function:

bool CompareAbsolutePIDLs(PIDLIST_ABSOLUTE pidl1, PIDLIST_ABSOLUTE pidl2)
{
    CComPtr<IShellFolder> ishDesk;
    SHGetDesktopFolder(&ishDesk);
    HRESULT hr = ishDesk->CompareIDs(SHCIDS_CANONICALONLY, pidl1, pidl2);
    return SUCCEEDED(hr) && HRESULT_CODE(hr) == 0;
}

In the debugger, I can see that GetDisplayName() for each returns:

"::{26EE0668-A00A-44D7-9371-BEB064C98683}\0"
"::{26EE0668-A00A-44D7-9371-BEB064C98683}"

Here you can see the hex dump of the PIDLs:

1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *0c* 00
1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *00* 00

The underlying PIDLS are also binary identical excepting the penultimate value (00 vs. 0c). I'm currently at a loss as to why they're different, or what I can do to resolve this issue?!

Questions

  1. Is there another way to obtain the PIDL of the control it in a way that doesn't include that seemingly spurious extra null byte?
  2. Alternately, is there a better way to obtain the PIDL of the enumeration item (Is there something insufficient in the way that CMFCShellTreeCtrol obtains the absolute PIDL such that it fails to include the final null byte?)
  3. Is there a way to obtain the control panel as a relative PIDL and then compare that to the relative enumeration PIDL (which I also have)?
  4. ???

回答1:


These really are different shell objects. You can pass the PIDLs you got to SHGetNameFromIDList() with the SIGDN_NORMALDISPLAY option to convert them to readable strings. The long PIDL (with 0x0c) converts to "All Control Panel Items", the short one converts to "Control Panel".

This problem got started by using SHGetSpecialFolderLocation() to retrieve the virtual folder for the Control Panel controls. Distinct from the Control Panel object off the desktop root. I think you need to fix this by obtaining the PIDL for Control Panel and ignore the virtual folder. One way to do so is by using ILCloneFirst to convert the virtual folder to the root object:

 PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);

Or you can hard-code the control panel CLSID, "::{26EE0668-A00A-44D7-9371-BEB064C98683}", and convert it to a PIDL with SHParseDisplayName().



来源:https://stackoverflow.com/questions/14325953/why-would-the-pidl-for-the-control-panel-be-different

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!