{"id":3173,"date":"2013-09-20T07:00:00","date_gmt":"2013-09-20T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/09\/20\/how-can-i-tell-that-i-have-a-shell-folder-that-represents-my-computer\/"},"modified":"2020-12-22T06:56:59","modified_gmt":"2020-12-22T14:56:59","slug":"how-can-i-tell-that-i-have-a-shell-folder-that-represents-my-computer","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130920-00\/?p=3173","title":{"rendered":"How can I tell that I have a shell folder that represents My Computer?"},"content":{"rendered":"<p>You have in your hands an <code>IShell\u00adFolder<\/code>, and you want to know whether this is an <code>IShell\u00adFolder<\/code> that represents <i>My Computer<\/i>. There are a few ideas that may occur to you.<\/p>\n<p>One is to ask the folder for its current location and compare it to <code>CSIDL_DRIVES<\/code>.<\/p>\n<pre>#define <a href=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/01\/24\/10387757.aspx\">STRICT_TYPED_ITEMIDS<\/a>\r\n#include &lt;shlobj.h&gt;\r\nPIDLIST_ABSOLUTE GetIDListViaPersistFolder(IUnknown *punk)\r\n{\r\n  PIDLIST_ABSOLUTE pidl = NULL;\r\n  IPersistFolder2 *ppf;\r\n  if (SUCCEEDED(punk-&gt;QueryInterface(IID_PPV_ARGS(&amp;ppf)))) {\r\n    ppf-&gt;GetCurFolder(&amp;pidl);\r\n    ppf-&gt;Release();\r\n  }\r\n  return pidl;\r\n}\r\nHRESULT CompareAbsoluteIDLists(\r\n    LPARAM lParam,\r\n    PCUIDLIST_ABSOLUTE pidl1,\r\n    PCUIDLIST_ABSOLUTE pidl2,\r\n    int *piResult)\r\n{\r\n  *piResult = 0;\r\n  IShellFolder *psfDesktop;\r\n  HRESULT hr = SHGetDesktopFolder(&amp;psfDesktop);\r\n  if (SUCCEEDED(hr)) {\r\n    hr = psfDesktop-&gt;CompareIDs(lParam,\r\n    reinterpret_cast&lt;PCUIDLIST_RELATIVE&gt;(pidl1),\r\n    reinterpret_cast&lt;PCUIDLIST_RELATIVE&gt;(pidl2));\r\n    if (SUCCEEDED(hr)) {\r\n     *piResult = (short)HRESULT_CODE(hr);\r\n    }\r\n    psfDesktop-&gt;Release();\r\n  }\r\n  return hr;\r\n}\r\nBOOL IsMyComputerFolder(IUnknown *punk)\r\n{\r\n  BOOL fIsMyComputer = FALSE;\r\n  PIDLIST_ABSOLUTE pidl = GetIDListViaPersistFolder(punk);\r\n  if (pidl) {\r\n    PIDLIST_ABSOLUTE pidlMyComputer;\r\n    if (SUCCEEDED(SHGetSpecialFolderLocation(NULL,\r\n                                 CSIDL_DRIVES, &amp;pidlMyComputer)))\r\n    {\r\n      int iCompare;\r\n      fIsMyComputer = SUCCEEDED(CompareAbsoluteIDLists(\r\n                               SHCIDS_CANONICALONLY,\r\n                               pidl, pidlMyComputer, &amp;iCompare)) &amp;&amp;\r\n                      iCompare == 0;\r\n      CoTaskMemFree(pidlMyComputer);\r\n    }\r\n    CoTaskMemFree(pidl);\r\n  }\r\n  return fIsMyComputer;\r\n}\r\n<\/pre>\n<p>Okay, we have a lot of moving parts here. Let&#8217;s look at them one at a time.<\/p>\n<p>The <code>Get\u00adIDList\u00adVia\u00adPersist\u00adFolder<\/code> function takes an object and asks <code>IPersist\u00adFolder2::Get\u00adCur\u00adFolder<\/code> what folder it represents. Since we don&#8217;t actually use any methods on the object beyond what is provided by <code>IUnknown<\/code>, we weaken the parameter requirement to simply <code>IUnknown<\/code>.<\/p>\n<p>The <code>Compare\u00adAbsolute\u00adIDLists<\/code> function compares two absolute ID lists according to the criteria specified by the <code>lParam<\/code>.<\/p>\n<p>The <code>Is\u00adMy\u00adComputer\u00adFolder<\/code> combines these two function: It takes the object you pass in and gets the ID list it represents. It then gets the ID list for the My Computer folder. And then it compares the two via <code>SHCIDS_CANONICAL\u00adONLY<\/code>, which means &#8220;I just want to see if they represent the same object. Don&#8217;t worry about getting the sort order absolutely right.&#8221; And again, since we don&#8217;t use any methods on the object other than <code>IUnknown::Query\u00adInterface<\/code>, we weaken the parameter requirements to simply <code>IUnknown<\/code>.<\/p>\n<p>Now, this code could be simplified or at least tweaked to take advantage of <code>IShell\u00adItem<\/code>. For example, we could use <code>SHGet\u00adKnown\u00adFolder\u00adItem<\/code> to get the <code>FOLDERID_Computer\u00adFolder<\/code> and then use <code>IShell\u00adItem::Compare<\/code>.<\/p>\n<p>But I&#8217;m not going to bother, because there is an underlying algorithmic problem with this technique: It is checking whether you have a folder to <i>My Computer<\/i> specifically at its default location. If somebody creates a <i>My Computer<\/i> folder at a custom location, say via a folder shortcut, or a folder with <a href=\"http:\/\/www.pctools.com\/guides\/registry\/detail\/38\/\"> a magic name<\/a>, then this code will not recognize it as <i>My Computer<\/i> because these alternate locations for <i>My Computer<\/i> will not match the standard location.<\/p>\n<p>If you want to identify <i>My Computer<\/i> no matter where it winds up, then instead of checking the path, you can check its class.<\/p>\n<pre>HRESULT GetObjectCLSID(IUnknown *punk, CLSID *pclsid)\r\n{\r\n  *pclsid = CLSID_NULL;\r\n  IPersist *pp;\r\n  HRESULT hr = punk-&gt;QueryInterface(IID_PPV_ARGS(&amp;pp));\r\n  if (SUCCEEDED(hr)) {\r\n    hr = pp-&gt;GetClassID(pclsid);\r\n    pp-&gt;Release();\r\n  }\r\n  return hr;\r\n}\r\nBOOL IsMyComputerFolder(IUnknown *punk)\r\n{\r\n  CLSID clsid;\r\n  GetObjectCLSID(punk, &amp;clsid);\r\n  return clsid == CLSID_MyComputer;\r\n}\r\n<\/pre>\n<p>We ask the object directly, &#8220;Hey, what&#8217;s your CLSID?&#8221; and if it replies, &#8220;I am <code>CLSID_My\u00adComputer<\/code>,&#8221; then we say, &#8220;Pleased to meet you, <i>My Computer<\/i>.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You have in your hands an IShell\u00adFolder, and you want to know whether this is an IShell\u00adFolder that represents My Computer. There are a few ideas that may occur to you. One is to ask the folder for its current location and compare it to CSIDL_DRIVES. #define STRICT_TYPED_ITEMIDS #include &lt;shlobj.h&gt; PIDLIST_ABSOLUTE GetIDListViaPersistFolder(IUnknown *punk) { PIDLIST_ABSOLUTE [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-3173","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You have in your hands an IShell\u00adFolder, and you want to know whether this is an IShell\u00adFolder that represents My Computer. There are a few ideas that may occur to you. One is to ask the folder for its current location and compare it to CSIDL_DRIVES. #define STRICT_TYPED_ITEMIDS #include &lt;shlobj.h&gt; PIDLIST_ABSOLUTE GetIDListViaPersistFolder(IUnknown *punk) { PIDLIST_ABSOLUTE [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=3173"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3173\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=3173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=3173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=3173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}