idlist.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 26k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*----------------------------------------------------------------------------
  2. / Title;
  3. /   idlist.cpp
  4. /
  5. / Authors;
  6. /   Rick Turner (ricktu)
  7. /
  8. / Notes;
  9. /----------------------------------------------------------------------------*/
  10. #include "precomp.hxx"
  11. #include "stddef.h"
  12. #pragma hdrstop
  13. /*-----------------------------------------------------------------------------
  14. / IDLISTs are opaque structures, they can be stored at any aligment, ours
  15. / contain the following data.  However this should not be treated as the
  16. / public version.  The pack and unpack functions below are responsible for
  17. / generating this structure, use those.
  18. /----------------------------------------------------------------------------*/
  19. #pragma pack(1)
  20. struct _myiconinfo {
  21.     UINT    uIndex;
  22.     TCHAR   szPath[1];
  23. };
  24. struct _myidlist {
  25.     WORD    cbSize;         // size of the idlist
  26.     DWORD   dwMagic;        // gaurd word
  27.     DWORD   dwFlags;        // idlist flags
  28.     DWORD   dwIconOffset;   // offset to icon info (present if MDIDL_HASICONINFO)
  29.     DWORD   dwNameOffset;   // offset to name info (present if MDIDL_SPECIALITEM)
  30.     DWORD   dwPathOffset;   // offset to path info (present if MDIDL_HASPATH)
  31.     DWORD   dwReserved;
  32.     ITEMIDLIST idl;         // shell's idlist (if present)
  33. };
  34. #pragma pack()
  35. typedef struct _myiconinfo MYICONINFO;
  36. typedef UNALIGNED MYICONINFO* LPMYICONINFO;
  37. typedef struct _myidlist    MYIDLIST;
  38. typedef UNALIGNED MYIDLIST* LPMYIDLIST;
  39. /*-----------------------------------------------------------------------------
  40. / IsIDLRootOfNameSpace
  41. / ---------------------
  42. /   Given an idlist, checks to see if it is one that points to the root
  43. /   our namespace (a regitem pidl w/our class id in it)
  44. /
  45. / In:
  46. /   pidl   = one of our pidls
  47. /
  48. / Out:
  49. /   TRUE or FALSE
  50. /----------------------------------------------------------------------------*/
  51. BOOL
  52. IsIDLRootOfNameSpace( LPITEMIDLIST pidlIN )
  53. {
  54.     LPIDREGITEM pidl = (LPIDREGITEM)pidlIN;
  55.     if ( (pidl->cb == (sizeof(IDREGITEM) - sizeof(WORD)))     &&
  56.          (pidl->bFlags == SHID_ROOT_REGITEM) &&
  57.          IsEqualGUID( pidl->clsid, CLSID_MyDocumentsExt)
  58.         )
  59.     {
  60.         return TRUE;
  61.     }
  62.     return FALSE;
  63. }
  64. /*-----------------------------------------------------------------------------
  65. / IsIDLFSJunction
  66. / ---------------
  67. /   Given an idlist & attributes of item, checks to see if the item
  68. /   is a junction point (i.e., a folder w/a desktop.ini in it).
  69. /
  70. / In:
  71. /   pidl
  72. /   dwAttrb
  73. /
  74. / Out:
  75. /   TRUE or FALSE
  76. /----------------------------------------------------------------------------*/
  77. BOOL
  78. IsIDLFSJunction( LPCITEMIDLIST pidlIN, DWORD dwAttrb )
  79. {
  80.     LPIDFSITEM pidl = (LPIDFSITEM)pidlIN;
  81.     if ( (!(dwAttrb & SFGAO_FILESYSTEM)) ||
  82.          (!(dwAttrb & SFGAO_FOLDER))     ||
  83.          (!pidlIN)                       ||
  84.          ILIsEmpty(pidlIN)
  85.         )
  86.     {
  87.         return FALSE;
  88.     }
  89.     if ( (pidl->bFlags & (SHID_JUNCTION)) &&
  90.          ((pidl->bFlags & SHID_FS_DIRECTORY) || (pidl->bFlags & SHID_FS_DIRUNICODE))
  91.         )
  92.     {
  93.         return TRUE;
  94.     }
  95.     return FALSE;
  96. }
  97. /*-----------------------------------------------------------------------------
  98. / MDGetPathFromIDL
  99. / ---------------------
  100. /   Given one of our IDLIST, return the relative path to the item...
  101. /
  102. / In:
  103. /   pidl   = one of our pidls
  104. /   pPath  = buffer of where to store path
  105. /
  106. / Out:
  107. /   pointer to the path (should NOT be freed)
  108. /----------------------------------------------------------------------------*/
  109. BOOL
  110. MDGetPathFromIDL( LPITEMIDLIST pidl, LPTSTR pPath, LPTSTR pRootPath )
  111. {
  112.     LPMYIDLIST pIDL = (LPMYIDLIST)pidl;
  113.     LPITEMIDLIST pidlTmp;
  114.     BOOL fRes = FALSE;
  115.     TCHAR szPath[ MAX_PATH ];
  116.     if (pIDL->dwMagic == MDIDL_MAGIC)
  117.     {
  118.         if ( (pIDL->dwFlags & MDIDL_HASNOSHELLPIDL) &&
  119.              (pIDL->dwFlags & MDIDL_HASPATHINFO)
  120.             )
  121.         {
  122.             UINT cch = MAX_PATH;
  123.             if (SUCCEEDED(MDGetPathInfoFromIDL( pidl, pPath, &cch )))
  124.                 return TRUE;
  125.             else
  126.                 return FALSE;
  127.         }
  128.         pidlTmp = &pIDL->idl;
  129.     }
  130.     else
  131.     {
  132.         pidlTmp = pidl;
  133.     }
  134.     if (SHGetPathFromIDList( pidlTmp, szPath ))
  135.     {
  136.         if (MDIsSpecialIDL(pidl) || (!pRootPath))
  137.         {
  138.             lstrcpy( pPath, szPath );
  139.         }
  140.         else
  141.         {
  142.             LPTSTR pFileName;
  143.             pFileName = PathFindFileName( szPath );
  144.             if (pRootPath && *pRootPath)
  145.             {
  146.                 lstrcpy( pPath, pRootPath );
  147.                 if (pPath[lstrlen(pPath)-1] != TEXT('\'))
  148.                 {
  149.                     lstrcat( pPath, TEXT("\") );
  150.                 }
  151.                 lstrcat( pPath, pFileName );
  152.             }
  153.             else
  154.             {
  155.                 lstrcpy( pPath, pFileName );
  156.             }
  157.         }
  158.         fRes = TRUE;
  159.     }
  160.     return fRes;
  161. }
  162. /*-----------------------------------------------------------------------------
  163. / MDGetFullPathFromIDL
  164. / ---------------------
  165. /   Given one of our IDLIST, return the path to the item walking down the
  166. /   idlist...
  167. /
  168. / In:
  169. /   pidl   = one of our pidls
  170. /   pPath  = buffer of where to store path
  171. /
  172. / Out:
  173. /   pointer to the path (should NOT be freed)
  174. /----------------------------------------------------------------------------*/
  175. BOOL
  176. MDGetFullPathFromIDL( LPITEMIDLIST pidl, LPTSTR pPath, LPTSTR pRootPath )
  177. {
  178.     LPITEMIDLIST pidlClone, pidlTmp;
  179.     LPTSTR pTmpPath = pPath, pRoot;
  180.     TCHAR szNull = 0, chLast;
  181.     pidlClone = ILClone( pidl );
  182.     if (pRootPath)
  183.         pRoot = pRootPath;
  184.     else
  185.         pRoot = &szNull;
  186.     if (!pidlClone)
  187.         return FALSE;
  188.     for ( pidlTmp = pidlClone;
  189.           pidlTmp && !ILIsEmpty(pidlTmp);
  190.           pidlTmp = ILGetNext( pidlTmp )
  191.          )
  192.     {
  193.         LPITEMIDLIST pidlNext = ILGetNext(pidlTmp);
  194.         WORD cbNext = pidlNext->mkid.cb;
  195.         pidlNext->mkid.cb = 0;
  196.         // get the path for this item
  197.         if (!MDGetPathFromIDL( pidlTmp, pTmpPath, pRoot ))
  198.             return FALSE;
  199.         // if there are more items, then tack on a '' to the end of the path
  200.         if (cbNext)
  201.         {
  202.             for( ; (chLast = *pTmpPath) && chLast; pTmpPath++ )
  203.                 ;
  204.             //
  205.             // only add '' to end if it isn't already there (as is the case
  206.             // with a drive --> c:
  207.             //
  208.             if (chLast != TEXT('\'))
  209.             {
  210.                 *pTmpPath++ = TEXT('\');
  211.                 *pTmpPath = 0;
  212.             }
  213.         }
  214.         pidlNext->mkid.cb = cbNext;
  215.         pRoot = &szNull;
  216.     }
  217.     ILFree( pidlClone );
  218.     return TRUE;
  219. }
  220. /*-----------------------------------------------------------------------------
  221. / _WrapSHIDL
  222. / ---------------------
  223. /   Given one of the shell's IDLISTs, return it wrapped in one of our own...
  224. /
  225. / In:
  226. /   pidlShell   = one of the shell's pidls
  227. /
  228. / Out:
  229. /   pidl (one of ours)
  230. /----------------------------------------------------------------------------*/
  231. LPMYIDLIST _WrapSHIDL( LPITEMIDLIST pidlRoot, LPITEMIDLIST pidlShell, LPTSTR pPath )
  232. {
  233.     LPMYIDLIST pidl;
  234.     LPITEMIDLIST pidlCombine;
  235.     UINT cb;
  236.     DWORD dw;
  237.     TCHAR szPath[ MAX_PATH ];
  238.     MDTraceEnter( TRACE_IDLIST, "_WrapSHIDL" );
  239. //    MDTrace(TEXT("Incoming: pidlRoot = %08X, pidl = %08X"), pidlRoot, pidlShell );
  240.     if (pidlRoot)
  241.     {
  242.         pidlCombine = ILCombine( pidlRoot, pidlShell );
  243.     }
  244.     else
  245.     {
  246.         pidlCombine = pidlShell;
  247.     }
  248.     cb  = ILGetSize( pidlCombine );
  249.     pidl = (LPMYIDLIST)SHAlloc( cb + sizeof(MYIDLIST) );
  250.     if (pidl)
  251.     {
  252.         memset( pidl, 0, cb + sizeof(MYIDLIST) );
  253.         pidl->cbSize = cb + sizeof(MYIDLIST) - sizeof(WORD);
  254.         pidl->dwMagic = MDIDL_MAGIC;
  255.         memcpy( (LPVOID)&(pidl->idl), pidlCombine, cb );
  256.     }
  257.     if (!pPath)
  258.     {
  259.         SHGetPathFromIDList( pidlCombine, szPath );
  260.         pPath = szPath;
  261.     }
  262.     //
  263.     // If this item is directory, mark it is a junction...
  264.     //
  265.     dw = GetFileAttributes( pPath );
  266.     if (dw!=0xFFFFFFFF)
  267.     {
  268.         if (dw & FILE_ATTRIBUTE_DIRECTORY)
  269.         {
  270.             pidl->dwFlags |= MDIDL_ISJUNCTION;
  271.         }
  272.     }
  273. //    MDTrace(TEXT("Outgoing pidl is %08X"), pidl );
  274.     MDTraceLeave();
  275.     return pidl;
  276. }
  277. /*-----------------------------------------------------------------------------
  278. / _UnWrapMDIDL
  279. / ---------------------
  280. /   Given one of our IDLISTs, return a copy of the embedded shell idlist...
  281. /
  282. / In:
  283. /   pidlShell   = one of the shell's pidls
  284. /
  285. / Out:
  286. /   pidl (one of ours)
  287. /----------------------------------------------------------------------------*/
  288. LPITEMIDLIST _UnWrapMDIDL( LPMYIDLIST pidl )
  289. {
  290.     LPITEMIDLIST pidlOut = (LPITEMIDLIST)pidl;
  291.     MDTraceEnter( TRACE_IDLIST, "_UnWrapMDIDL" );
  292. //    MDTrace(TEXT("Incoming pidl is %08X"), pidl );
  293.     if (pidl->dwMagic == MDIDL_MAGIC)
  294.     {
  295.         if (pidl->dwFlags & MDIDL_HASNOSHELLPIDL)
  296.         {
  297.             pidlOut = NULL;
  298.         }
  299.         else
  300.         {
  301.             pidlOut = &pidl->idl;
  302.         }
  303.     }
  304. //    MDTrace(TEXT("Outgoing pidl is %08X"), pidlOut );
  305.     MDTraceLeave();
  306.     return pidlOut;
  307. }
  308. /*-----------------------------------------------------------------------------
  309. / MDCreateIDLFromPath
  310. / ---------------------
  311. /   Given a pointer to filename (or UNC path), create an IDLIST from that.
  312. /   that.
  313. /
  314. / In:
  315. /   ppidl = receives a pointer to new IDLIST
  316. /   pPath = filesystem (or UNC) path to object
  317. /
  318. / Out:
  319. /   HRESULT
  320. /----------------------------------------------------------------------------*/
  321. HRESULT
  322. MDCreateIDLFromPath( LPITEMIDLIST* ppidl,
  323.                      LPTSTR pPath
  324.                      )
  325. {
  326.     HRESULT hr = S_OK;
  327.     LPMYIDLIST pidl = NULL;
  328.     LPITEMIDLIST pidlShell = NULL;
  329.     MDTraceEnter(TRACE_IDLIST, "MDCreateIDLFromPath");
  330.     MDTraceAssert(ppidl);
  331.     MDTraceAssert(pPath);
  332.     *ppidl = NULL;                      // incase we fail
  333.     //
  334.     // Get pidl from shell
  335.     //
  336.     hr = SHILCreateFromPath( pPath, &pidlShell, NULL );
  337.     FailGracefully( hr, "SHILCreateFromPath failed" );
  338.     //
  339.     // Now wrap it...
  340.     //
  341.     pidl = _WrapSHIDL( NULL, pidlShell, pPath );
  342.     if (!pidl)
  343.         ExitGracefully( hr, E_FAIL, "_WrapSHIDL failed" );
  344.     *ppidl = (LPITEMIDLIST)pidl;
  345. //    MDTrace( TEXT("returning pidl of %08X"), pidl );
  346. exit_gracefully:
  347.     DoILFree( pidlShell );
  348.     MDTraceLeaveResult(hr);
  349. }
  350. /*-----------------------------------------------------------------------------
  351. / MDWrapShellIDList
  352. / ---------------------
  353. /   Given an array of shell idlists, return an array of MyDocuments idlists
  354. /   that wrap the shell's idlists.
  355. /
  356. / In:
  357. /   celt  = number of IDLISTs in array
  358. /   rgelt = array of IDLISTs
  359. /
  360. / Out:
  361. /   HRESULT
  362. /----------------------------------------------------------------------------*/
  363. HRESULT
  364. MDWrapShellIDLists( LPITEMIDLIST pidlRoot,
  365.                     UINT celtIN,
  366.                     LPITEMIDLIST * rgeltIN,
  367.                     LPITEMIDLIST * rgeltOUT
  368.                    )
  369. {
  370.     HRESULT hr = S_OK;
  371.     UINT i;
  372.     MDTraceEnter( TRACE_IDLIST, "MDWrapShellIDLists" );
  373.     if (!celtIN || !rgeltIN || !rgeltOUT)
  374.         ExitGracefully( hr, E_INVALIDARG, "either bad incoming or outgoing parameters" );
  375.     //
  376.     // Set up prgeltOUT to hold the results...
  377.     //
  378.     i = 0;
  379.     while( i < celtIN )
  380.     {
  381.         rgeltOUT[i] = (LPITEMIDLIST)_WrapSHIDL( pidlRoot, rgeltIN[i], NULL );
  382.         if (!rgeltOUT[i])
  383.             ExitGracefully( hr, E_FAIL, "Failure to wrap an IDLIST" );
  384.         i++;
  385.     }
  386. exit_gracefully:
  387.     MDTraceLeaveResult(hr);
  388. }
  389. /*-----------------------------------------------------------------------------
  390. / MDUnWrapMDIDList
  391. / ---------------------
  392. /   Given an array of our idlists, return an array of shell idlists.
  393. /
  394. / In:
  395. /   celt  = number of IDLISTs in array
  396. /   rgelt = array of IDLISTs
  397. /
  398. / Out:
  399. /   HRESULT
  400. /----------------------------------------------------------------------------*/
  401. HRESULT
  402. MDUnWrapMDIDLists( UINT celtIN,
  403.                    LPITEMIDLIST * rgeltIN,
  404.                    LPITEMIDLIST * rgeltOUT
  405.                   )
  406. {
  407.     HRESULT hr = S_OK;
  408.     UINT i;
  409.     MDTraceEnter( TRACE_IDLIST, "MDUnWrapMDIDLists" );
  410.     if (!celtIN || !rgeltIN || !rgeltOUT)
  411.         ExitGracefully( hr, E_INVALIDARG, "either bad incoming or outgoing parameters" );
  412.     //
  413.     // Set up prgeltOUT to hold the results...
  414.     //
  415.     i = 0;
  416.     while( i < celtIN )
  417.     {
  418.         LPITEMIDLIST pidl = _UnWrapMDIDL( (LPMYIDLIST)rgeltIN[i] );
  419.         if (pidl)
  420.         {
  421.             rgeltOUT[i] = ILFindLastID(pidl);
  422.         }
  423.         else
  424.         {
  425.             rgeltOUT[i] = NULL;
  426.         }
  427.         if (!rgeltOUT[i])
  428.             ExitGracefully( hr, E_FAIL, "Failure to unwrap an IDLIST" );
  429.         i++;
  430.     }
  431. exit_gracefully:
  432.     MDTraceLeaveResult(hr);
  433. }
  434. /*-----------------------------------------------------------------------------
  435. / SHIDLFromMDIDL
  436. / ---------------------
  437. /   If it's one of our pidls, return the embedded shell IDLIST
  438. /
  439. / In:
  440. /   pidl = one of our pidls
  441. /
  442. / Out:
  443. /   pidl that is shell's embedded pidl
  444. /----------------------------------------------------------------------------*/
  445. LPITEMIDLIST
  446. SHIDLFromMDIDL( LPCITEMIDLIST pidl )
  447. {
  448.     LPITEMIDLIST pidlOut = (LPITEMIDLIST)pidl;
  449.     LPMYIDLIST pIDL = (LPMYIDLIST)pidl;
  450.     MDTraceEnter( TRACE_IDLIST, "SHIDLFroMDIDL" );
  451.     if ( pIDL
  452.          && (pIDL->dwMagic == MDIDL_MAGIC)
  453.         )
  454.     {
  455.         if ( ( pIDL->dwFlags & MDIDL_HASNOSHELLPIDL ) )
  456.         {
  457.             pidlOut = NULL;
  458.         }
  459.         else
  460.         {
  461.             pidlOut = &((LPMYIDLIST)pidl)->idl;
  462.         }
  463.     }
  464.     MDTraceLeave();
  465.     return pidlOut;
  466. }
  467. /*-----------------------------------------------------------------------------
  468. / MDCreateSpecialIDL
  469. / ---------------------
  470. /   Return an IDL for the Published Documents folder
  471. /
  472. / In:
  473. /   pidl = one of our pidls
  474. /
  475. / Out:
  476. /   pidl that is shell's embedded pidl
  477. /----------------------------------------------------------------------------*/
  478. LPITEMIDLIST
  479. MDCreateSpecialIDL( LPTSTR pPath,
  480.                     LPTSTR pName,
  481.                     LPTSTR pIconPath,
  482.                     UINT   uIconIndex
  483.                    )
  484. {
  485.     HRESULT hr = S_OK;
  486.     LPMYIDLIST pidl = NULL;
  487.     UINT cbSize = 0, cbName = 0, cbIconInfo = 0, cbPath = 0;
  488.     DWORD dwFlags = 0;
  489.     MDTraceEnter(TRACE_IDLIST, "MDCreateSpecialIDL");
  490.     MDTraceAssert(pPath);
  491. //#ifdef WINNT
  492. //    DebugBreak();
  493. //#else
  494. //    _asm {
  495. //        int 3;
  496. //    }
  497. //#endif
  498.     if ((pPath && *pPath))
  499.     {
  500. #ifdef TRY_TO_STORE_PIDL
  501.         if (PathFileExists(pPath))
  502.         {
  503.             //
  504.             // Create a pidl
  505.             //
  506.             hr = MDCreateIDLFromPath( (LPITEMIDLIST *)&pidl, pPath );
  507.             FailGracefully( hr, "MDCreateIDLFromPath failed" );
  508.         }
  509.         else
  510. #endif
  511.         {
  512.             cbPath = ((lstrlen(pPath) + 1) * sizeof(TCHAR));
  513.             dwFlags |= MDIDL_HASPATHINFO;
  514.         }
  515.     }
  516.     dwFlags |= MDIDL_ISSPECIALITEM;
  517.     if (pidl)
  518.     {
  519.         cbSize = ILGetSize( (LPITEMIDLIST)pidl ) + sizeof(WORD);
  520.     }
  521.     else
  522.     {
  523.         cbSize = sizeof(MYIDLIST);
  524.     }
  525.     //
  526.     // If there's a display name, make room for it...
  527.     //
  528.     if (pName && *pName)
  529.     {
  530.         cbName = ((lstrlen(pName) + 1) * sizeof(TCHAR));
  531.         dwFlags |= MDIDL_HASNAME;
  532.     }
  533.     //
  534.     // If there's icon information, make room for it...
  535.     //
  536.     if (pIconPath && *pIconPath)
  537.     {
  538.         // NULL terminator is already in MYICONINFO
  539.         cbIconInfo = ( sizeof(MYICONINFO) + (lstrlen(pIconPath) * sizeof(TCHAR)) );
  540.         dwFlags |= MDIDL_HASICONINFO;
  541.     }
  542.     //
  543.     // Now, combine all the info into one place...
  544.     //
  545.     if (cbName || cbIconInfo || cbPath)
  546.     {
  547.         UINT cbTotal = cbSize + cbName + cbIconInfo + cbPath;
  548.         LPITEMIDLIST pidlTemp =
  549.                 (LPITEMIDLIST)SHAlloc( cbTotal );
  550.         if (pidlTemp)
  551.         {
  552.             memset( pidlTemp, 0, cbTotal );
  553.             //
  554.             // Copy the old stuff and adjust the size field...
  555.             //
  556.             if (pidl)
  557.             {
  558.                 pidl->dwFlags = dwFlags;
  559.                 cbSize -= sizeof(WORD);
  560.                 memcpy( (LPVOID)pidlTemp, (LPVOID)pidl, cbSize );
  561.                 DoILFree( pidl );
  562.                 pidlTemp->mkid.cb += sizeof(WORD);
  563.             }
  564.             else
  565.             {
  566.                 ((LPMYIDLIST)pidlTemp)->dwMagic = MDIDL_MAGIC;
  567.                 ((LPMYIDLIST)pidlTemp)->dwFlags = (dwFlags | MDIDL_HASNOSHELLPIDL);
  568.                 cbSize -= sizeof(WORD);
  569.                 ((LPMYIDLIST)pidlTemp)->cbSize  = cbSize;
  570.             }
  571.             pidl = (LPMYIDLIST)pidlTemp;
  572.             pidl->cbSize += (cbName + cbIconInfo + cbPath);
  573.             //
  574.             // Now insert the new stuff...
  575.             //
  576.             if (cbName)
  577.             {
  578.                 LPTSTR pTmp;
  579.                 pidl->dwNameOffset = cbSize;
  580.                 pTmp = (LPTSTR)((LPBYTE)pidl + pidl->dwNameOffset);
  581.                 lstrcpy( pTmp, pName );
  582.             }
  583.             if (cbIconInfo)
  584.             {
  585.                 LPMYICONINFO pii;
  586.                 pidl->dwIconOffset = cbSize + cbName;
  587.                 pii = (LPMYICONINFO)((LPBYTE)pidl + pidl->dwIconOffset);
  588.                 pii->uIndex = uIconIndex;
  589.                 lstrcpy( pii->szPath, pIconPath );
  590.             }
  591.             if (cbPath)
  592.             {
  593.                 LPTSTR pTmp;
  594.                 pidl->dwPathOffset = cbSize + cbName + cbIconInfo;
  595.                 pTmp = (LPTSTR)((LPBYTE)pidl + pidl->dwPathOffset);
  596.                 lstrcpy( pTmp, pPath );
  597.             }
  598.         }
  599.         else
  600.         {
  601.             DoILFree( pidl )
  602.             pidl = NULL;
  603.         }
  604.     }
  605. #if 0
  606.     MDTrace(TEXT("pidl->cbSize = %d"), pidl->cbSize );
  607.     MDTrace(TEXT("pidl->dwFlags = %08X"), pidl->dwFlags );
  608.     if (cbName)
  609.         MDTrace(TEXT("Name is: -%s-"), (LPTSTR)((LPBYTE)pidl + pidl->dwNameOffset) );
  610.     if (cbIconInfo)
  611.     {
  612.         LPMYICONINFO pii = (LPMYICONINFO)((LPBYTE)pidl + pidl->dwIconOffset);
  613.         MDTrace(TEXT("Icon info: %s,%d"), pii->szPath, pii->uIndex );
  614.     }
  615.     MDTrace(TEXT("ILNext(pidl) is %04X"), *((WORD *)((LPBYTE)pidl + pidl->cbSize)));
  616. #endif
  617. #ifdef TRY_TO_STORE_PIDL
  618. exit_gracefully:
  619. #endif
  620. //    MDTrace(TEXT("returning pidl of %08X"), pidl );
  621.     MDTraceLeave();
  622.     return (LPITEMIDLIST)pidl;
  623. }
  624. /*-----------------------------------------------------------------------------
  625. / MDIsSepcialIDL
  626. / ---------------------
  627. /   Check if this pidl is a special item (ie: PUBLISHED DOCUMENTS) pidl
  628. /
  629. / In:
  630. /   pidl
  631. /
  632. / Out:
  633. /   TRUE or FALSE
  634. /----------------------------------------------------------------------------*/
  635. BOOL
  636. MDIsSpecialIDL( LPITEMIDLIST pidl )
  637. {
  638.     
  639.     if (pidl && ((sizeof(MYIDLIST) - sizeof(WORD)) <= (pidl->mkid).cb)) {
  640.         if ( ( ((LPMYIDLIST)pidl)->dwMagic == MDIDL_MAGIC ) &&
  641.              ( ((LPMYIDLIST)pidl)->dwFlags & MDIDL_ISSPECIALITEM )
  642.             )
  643.             return TRUE;
  644.     }
  645.     return FALSE;
  646. }
  647. /*-----------------------------------------------------------------------------
  648. / MDIsJunctionIDL
  649. / ---------------------
  650. /   Check if this pidl represents a junction to a folder
  651. /
  652. / In:
  653. /   pidl
  654. /
  655. / Out:
  656. /   TRUE or FALSE
  657. /----------------------------------------------------------------------------*/
  658. BOOL
  659. MDIsJunctionIDL( LPITEMIDLIST pidl )
  660. {
  661.     if (pidl && ((sizeof(MYIDLIST) - sizeof(WORD)) <= (pidl->mkid).cb)) {
  662.         if ( ( ((LPMYIDLIST)pidl)->dwMagic == MDIDL_MAGIC ) &&
  663.              ( ((LPMYIDLIST)pidl)->dwFlags & MDIDL_ISJUNCTION )
  664.             )
  665.             return TRUE;
  666.     
  667.         //
  668.         // HACK: 0x31 is the SHITEMID flags for a folder and
  669.         //       0x35 is the SHITEMID flags for a unicode folder...
  670.         //
  671.     
  672.         if ( (((_idregitem *)pidl)->bFlags == 0x31) ||
  673.              (((_idregitem *)pidl)->bFlags == 0x35) )
  674.         {
  675.             return TRUE;
  676.         }
  677.     }
  678.     return FALSE;
  679. }
  680. /*-----------------------------------------------------------------------------
  681. / MDGetIconInfoFromIDL
  682. / ---------------------
  683. /   Check if this pidl is a special pidl, and then returns the icon
  684. /   information if present...
  685. /
  686. / In:
  687. /   pidl -> pidl in question
  688. /   pIconPath -> pointer to buffer to contain path (assumed to be MAX_PATH long)
  689. /   pwIndex -> index of icon within pIconPath
  690. /
  691. / Out:
  692. /   HRESULT
  693. /----------------------------------------------------------------------------*/
  694. HRESULT
  695. MDGetIconInfoFromIDL( LPITEMIDLIST pidl,
  696.                       LPTSTR pIconPath,
  697.                       UINT cch,
  698.                       UINT * pIndex
  699.                      )
  700. {
  701.     HRESULT hr = S_OK;
  702.     LPMYIDLIST pIDL = (LPMYIDLIST)pidl;
  703.     LPMYICONINFO pii;
  704.     MDTraceEnter(TRACE_IDLIST, "MDGetIconInfoFromIDL");
  705.     if (!pIconPath)
  706.         ExitGracefully( hr, E_INVALIDARG, "pIconPath is invalid" );
  707.     if (!pIndex)
  708.         ExitGracefully( hr, E_INVALIDARG, "pIndex is invalid" );
  709.     *pIconPath = 0;
  710.     *pIndex = 0;
  711.     if (!MDIsSpecialIDL(pidl))
  712.         ExitGracefully( hr, E_FAIL, "Not a special idlist" );
  713.     if (!(pIDL->dwFlags & MDIDL_HASICONINFO))
  714.         ExitGracefully( hr, E_FAIL, "No icon info to return..." );
  715.     pii = (LPMYICONINFO)( (LPBYTE)pIDL + pIDL->dwIconOffset );
  716.     lstrcpyn( pIconPath, pii->szPath, cch );
  717.     *pIndex = pii->uIndex;
  718. exit_gracefully:
  719.     MDTraceLeaveResult(hr);
  720. }
  721. /*-----------------------------------------------------------------------------
  722. / MDGetNameFromIDL
  723. / ---------------------
  724. /   Check if this pidl is a special pidl, and then returns the name
  725. /   information if present...
  726. /
  727. / In:
  728. /   pidl -> pidl in question
  729. /   pName -> pointer to buffer to contain name
  730. /   cchName -> size of name buffer, in characters
  731. /   fFullPath -> if TRUE, then walk down the IDLIST building up a path.  If
  732. /                FALSE, just return the display name for the first item in the
  733. /                ID List...
  734. /
  735. /
  736. / Out:
  737. /   HRESULT
  738. /       E_INVALIDARG --> buffer is to small, *pcch hold required size
  739. /----------------------------------------------------------------------------*/
  740. HRESULT
  741. MDGetNameFromIDL( LPITEMIDLIST pidl,
  742.                   LPTSTR pName,
  743.                   UINT *  pcch,
  744.                   BOOL fFullPath
  745.                  )
  746. {
  747.     HRESULT hr = S_OK;
  748.     LPITEMIDLIST pidlTemp = pidl;
  749.     LPMYIDLIST pIDL;
  750.     LPTSTR pNAME;
  751.     UINT cch;
  752.     TCHAR szPath[ MAX_PATH ];
  753.     MDTraceEnter(TRACE_IDLIST, "MDGetNameFromIDL");
  754.     if (!pName)
  755.         ExitGracefully( hr, E_FAIL, "pName is invalid" );
  756.     if (!pcch)
  757.         ExitGracefully( hr, E_FAIL, "cch is invalid" );
  758.     *pName = 0;
  759.     cch = *pcch;
  760.     *pcch = 0;
  761.     while( pidlTemp && !ILIsEmpty(pidlTemp) )
  762.     {
  763.         pIDL = (LPMYIDLIST)pidlTemp;
  764.         if (MDIsSpecialIDL(pidlTemp) && (pIDL->dwFlags & MDIDL_HASNAME))
  765.         {
  766.             pNAME = (LPTSTR)( (LPBYTE)pIDL + pIDL->dwNameOffset );
  767.         }
  768.         else
  769.         {
  770.             if (fFullPath)
  771.             {
  772.                 pName = szPath;
  773.                 MDGetPathFromIDL( pidlTemp, szPath, NULL );
  774.             }
  775.             else
  776.             {
  777.                 ExitGracefully( hr, E_INVALIDARG, "fFullPath is FALSE and encountered a non-special IDL" );
  778.             }
  779.         }
  780.         if ((*pcch += (lstrlen(pNAME)+2)) <= cch)
  781.         {
  782.             lstrcat( pName, pNAME );
  783.         }
  784.         else
  785.         {
  786.             hr = E_INVALIDARG;
  787.             break;
  788.         }
  789.         pidlTemp = ILGetNext( pidlTemp );
  790.         if (pidlTemp && !ILIsEmpty( pidlTemp ))
  791.         {
  792.             lstrcat( pName, TEXT("\") );
  793.         }
  794.     }
  795. exit_gracefully:
  796.     MDTraceLeaveResult(hr);
  797. }
  798. /*-----------------------------------------------------------------------------
  799. / MDGetPathInfoIDL
  800. / ---------------------
  801. /   Check if this pidl is a special pidl, and then if it has a path stored
  802. /   int he pidl, and if so, it returns that path...
  803. /
  804. / In:
  805. /   pidl -> pidl in question
  806. /   pName -> pointer to buffer to contain name
  807. /   cchName -> size of name buffer, in characters
  808. /
  809. / Out:
  810. /   HRESULT
  811. /       E_INVALIDARG --> buffer is to small, *pcch hold required size
  812. /----------------------------------------------------------------------------*/
  813. HRESULT
  814. MDGetPathInfoFromIDL( LPITEMIDLIST pidl,
  815.                       LPTSTR pPath,
  816.                       UINT *  pcch
  817.                      )
  818. {
  819.     HRESULT hr = S_OK;
  820.     LPMYIDLIST pIDL = (LPMYIDLIST)pidl;
  821.     LPTSTR pPATH = NULL;
  822.     UINT cch;
  823.     MDTraceEnter(TRACE_IDLIST, "MDGetPathInfoIDL");
  824.     if (!pPath)
  825.         ExitGracefully( hr, E_FAIL, "pName is invalid" );
  826.     if (!pcch)
  827.         ExitGracefully( hr, E_FAIL, "cch is invalid" );
  828.     if (!pIDL || (!(pIDL->dwFlags & MDIDL_HASPATHINFO)))
  829.     {
  830.         ExitGracefully( hr, E_FAIL, "pidl is NULL or doesn't have a path!" );
  831.     }
  832.     *pPath = 0;
  833.     cch = *pcch;
  834.     *pcch = 0;
  835.     pPATH = (LPTSTR)((LPBYTE)pIDL + pIDL->dwPathOffset);
  836.     if (cch < (UINT)((lstrlen(pPATH)+1)))
  837.     {
  838.         *pcch = (UINT)(lstrlen(pPATH)+1);
  839.         ExitGracefully( hr, E_INVALIDARG, "*pcch wasn't big enough" );
  840.     }
  841.     if (0==ExpandEnvironmentStrings( pPATH, pPath, cch ))
  842.     {
  843.         lstrcpy( pPath, pPATH );
  844.     }
  845. exit_gracefully:
  846.     MDTraceLeaveResult(hr);
  847. }