Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
6.3 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Silicon Prairie Software, 1996
  4. //
  5. // File: pidl.cpp
  6. //
  7. // Contents: CIDList
  8. //
  9. // History: 9-26-95 Davepl Created
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "shtl.h"
  13. #include "cidl.h"
  14. #include "shellapi.h"
  15. //
  16. // CombineWith - Adds another pidl with this one, puts the result at
  17. // a new pidl ptr passed in
  18. //
  19. __DATL_INLINE HRESULT CIDList::CombineWith(const CIDList * pidlwith, CIDList ** ppidlto)
  20. {
  21. UINT cb1 = this->GetSize() - CB_IDLIST_TERMINATOR;
  22. UINT cb2 = pidlwith->GetSize();
  23. *ppidlto = (CIDList *) g_SHAlloc.Alloc(cb1 + cb2);
  24. if (NULL == *ppidlto)
  25. {
  26. return E_OUTOFMEMORY;
  27. }
  28. CopyMemory(*ppidlto, this, cb1);
  29. CopyMemory((((LPBYTE)*ppidlto) + cb1), pidlwith, cb2);
  30. return S_OK;
  31. }
  32. //+-------------------------------------------------------------------------
  33. //
  34. // Member: CIDList::IsParent
  35. //
  36. // Synopsis: Tests whether or not _this_ pidl is a parent of some
  37. // other pidl
  38. //
  39. // Returns: BOOL - TRUE if we are a child of the other pidl
  40. //
  41. // History: 5-15-95 DavePl Created
  42. //
  43. //--------------------------------------------------------------------------
  44. __DATL_INLINE BOOL CIDList::IsParentOf(const CIDList * pidlother, BOOL fImmediate) const
  45. {
  46. ptrdiff_t cb;
  47. if (NULL == pidlother)
  48. {
  49. return FALSE;
  50. }
  51. const CIDList * pidlthisT = this;
  52. const CIDList * pidlotherT = pidlother;
  53. //
  54. // Walk to the end of _this_ pidl. If we run out of hops on the other
  55. // pidl, its shorter than us so we can't be its parent
  56. while(FALSE == pidlthisT->IsEmpty())
  57. {
  58. if (pidlotherT->IsEmpty())
  59. {
  60. return FALSE;
  61. }
  62. pidlthisT = pidlthisT->Next();
  63. pidlotherT = pidlotherT->Next();
  64. }
  65. //
  66. // If caller wants to know if we're the _immediate_ parent, we should
  67. // be empty at this point and the other pidl should have exactly
  68. // one entry left
  69. //
  70. if (fImmediate)
  71. {
  72. if (pidlotherT->IsEmpty() || FALSE == pidlotherT->Next()->IsEmpty())
  73. {
  74. return FALSE;
  75. }
  76. }
  77. //
  78. // Create a new IDList from a portion of pidl2, which contains the
  79. // same number of IDs as pidl1.
  80. //
  81. cb = pidlotherT - pidlother;
  82. //
  83. // BUGBUG It's probably not valid to binary compare the pidls up to this point,
  84. // but since the shell doesn't expose a better mechanism for us to use...
  85. //
  86. if (0 == memcmp(pidlother, this, cb))
  87. {
  88. return TRUE;
  89. }
  90. else
  91. {
  92. return FALSE;
  93. }
  94. }
  95. //+-------------------------------------------------------------------------
  96. //
  97. // Member: CIDList::FindChild
  98. //
  99. // Synopsis: Given _this_ as a parent pidl, and some pidlchild which is
  100. // a child of it, returns the portion of the child not found
  101. // in the parent.
  102. //
  103. // ie: this == c:\foo\bar
  104. // child == c:\foo\bar\etc
  105. // return == \etc
  106. //
  107. // Returns: Uncommon child portion. NULL if child is not really our child.
  108. //
  109. // History: 5-15-95 DavePl Created
  110. //
  111. // Notes: Does _not_ allocate a new pidl, just returns a ptr into the
  112. // child.
  113. //
  114. //--------------------------------------------------------------------------
  115. __DATL_INLINE const CIDList * CIDList::FindChild(const CIDList * pidlchild) const
  116. {
  117. const CIDList * pidlparent = this;
  118. if (IsParentOf(pidlchild, FALSE))
  119. {
  120. while (FALSE == pidlparent->IsEmpty())
  121. {
  122. pidlchild = pidlchild->Next();
  123. pidlparent = pidlparent->Next();
  124. }
  125. return pidlchild;
  126. }
  127. return NULL;
  128. }
  129. // CIDList::GetIShellFolder
  130. //
  131. // Returns the IShellFolder implementation for this idlist
  132. __DATL_INLINE HRESULT CIDList::GetIShellFolder(IShellFolder ** ppFolder)
  133. {
  134. IShellFolder * pDesktop = NULL;
  135. HRESULT hr = SHGetDesktopFolder(&pDesktop);
  136. if (SUCCEEDED(hr))
  137. hr = pDesktop->BindToObject(this, NULL, IID_IShellFolder, (void **)ppFolder);
  138. if (pDesktop)
  139. pDesktop->Release();
  140. return hr;
  141. }
  142. // CIDList::AppendPath
  143. //
  144. // Given an idlist, which must be a folder, adds a text path to it
  145. __DATL_INLINE HRESULT CIDList::AppendPath(LPCTSTR pszPath, CIDList ** ppidlResult)
  146. {
  147. IShellFolder * pFolder = NULL;
  148. HRESULT hr = GetIShellFolder(&pFolder);
  149. if (SUCCEEDED(hr))
  150. {
  151. CIDList * pidlNew = NULL;
  152. #if defined(UNICODE) || defined(_UNICODE)
  153. LPCWSTR pwszPath = pszPath;
  154. #else
  155. WCHAR pwszPath[MAX_PATH];
  156. VERIFY( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPath, -1, pwszPath, MAX_PATH) );
  157. #endif
  158. ULONG chEaten;
  159. hr = pFolder->ParseDisplayName(NULL, NULL, const_cast<LPWSTR>(pwszPath), &chEaten, (LPITEMIDLIST *)&pidlNew, NULL);
  160. if (SUCCEEDED(hr))
  161. {
  162. CIDList * pidlResult = NULL;
  163. hr = CombineWith(pidlNew, ppidlResult);
  164. }
  165. g_SHAlloc.Free(pidlNew);
  166. }
  167. if (pFolder)
  168. pFolder->Release();
  169. return hr;
  170. }
  171. //
  172. // StrRetToTString - Gets a TString from a strret structure
  173. //
  174. // PrintStrRet - prints the contents of a STRRET structure.
  175. // pidl - PIDL containing the display name if STRRET_OFFSET
  176. // lpStr - address of the STRRET structure
  177. //
  178. /*
  179. __DATL_INLINE void StrRetToCString(CIDList * pCidl, LPSTRRET lpStr, tstring &str)
  180. {
  181. LPSTR lpsz;
  182. int cch;
  183. switch (lpStr->uType)
  184. {
  185. case STRRET_WSTR:
  186. cch = WideCharToMultiByte(CP_ACP, 0,
  187. lpStr->pOleStr, -1, NULL, 0, NULL, NULL);
  188. lpsz = new char[cch];
  189. if (lpsz != NULL) {
  190. WideCharToMultiByte(CP_ACP, 0,
  191. lpStr->pOleStr, -1, lpsz, cch, NULL, NULL);
  192. str = lpsz;
  193. delete [] lpsz;
  194. }
  195. break;
  196. case STRRET_OFFSET:
  197. str = (((char *) pCidl) + lpStr->uOffset);
  198. break;
  199. case STRRET_CSTR:
  200. str = lpStr->cStr;
  201. break;
  202. }
  203. }
  204. */
  205. __DATL_INLINE tstring CIDList::GetPath() const
  206. {
  207. tstring strPath;
  208. if (FALSE == SHGetPathFromIDList(this, strPath.GetBuffer(MAX_PATH)))
  209. throw new dexception(E_OUTOFMEMORY);
  210. strPath.ReleaseBuffer(-1);
  211. return strPath;
  212. }