1 ////////////////////////////////////////////////////////////////////
2 // PIDL.cpp: implementation of the CPIDL class.
4 // By Oz Solomonovich (osolo@bigfoot.com)
10 LPSHELLFOLDER CPIDL::m_sfDesktop = NULL; // cached destkop folder
11 LPMALLOC CPIDL::m_pAllocator = NULL; // cached system allocator
13 CPIDL::pidl_initializer CPIDL::m_initializer; // automatic init. obj
16 ////////////////////////////////////////////////////////////////////
17 // Initialization object
18 ////////////////////////////////////////////////////////////////////
20 // pidl_initializer is used to initialize the static data. The
21 // constructor and destructor are automatically called for us when
22 // the program starts/ends.
24 CPIDL::pidl_initializer::pidl_initializer()
26 SHGetDesktopFolder(&m_sfDesktop); // cache d'top folder obj ptr
27 SHGetMalloc(&m_pAllocator); // cache sys allocator obj ptr
30 CPIDL::pidl_initializer::~pidl_initializer()
32 m_sfDesktop->Release();
33 m_pAllocator->Release();
37 ////////////////////////////////////////////////////////////////////
38 // CPIDL Implementation
39 ////////////////////////////////////////////////////////////////////
40 CPIDL::CPIDL(LPCTSTR szPath, LPSHELLFOLDER psf) :
49 Free(); // just free used memory
53 ////////////////////////////////////////////////////////////////////
54 // Assignment Functions
56 HRESULT CPIDL::Set(const CPIDL& cpidl)
58 return MakeCopyOf(cpidl.m_pidl);
61 HRESULT CPIDL::Set(LPITEMIDLIST pidl)
68 HRESULT CPIDL::Set(LPCTSTR szPath, LPSHELLFOLDER psf)
70 OLECHAR olePath[MAX_PATH];
76 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1,
79 lstrcpy(olePath,szPath);
81 return psf->ParseDisplayName(NULL, NULL, olePath, &chEaten,
82 &m_pidl, &dwAttributes);
85 HRESULT CPIDL::MakeCopyOf(LPITEMIDLIST pidl)
89 UINT sz = m_pAllocator->GetSize((LPVOID)pidl);
91 CopyMemory((LPVOID)m_pidl, (LPVOID)pidl, sz);
96 HRESULT CPIDL::MakeAbsPIDLOf(LPSHELLFOLDER psf, LPITEMIDLIST pidl)
100 HRESULT hr = psf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &str);
103 hr = Set(A2T(str.cStr));
109 ////////////////////////////////////////////////////////////////////
115 m_pAllocator->Free(m_pidl);
120 #define CB_SIZE (sizeof(piid->cb)) // size of termination item
122 UINT CPIDL::GetSize() const
125 LPSHITEMID piid = GetFirstItemID();
132 cbTotal += CB_SIZE; // count the terminator
138 void CPIDL::Split(CPIDL& parent, CPIDL& obj) const
141 SHITEMID *piid, *piidLast;
143 // find last item-id and calculate total size of pidl
144 piid = piidLast = &m_pidl->mkid;
149 piid = (SHITEMID *)((LPBYTE)piid + (piid->cb));
152 // copy parent folder portion
153 size -= piidLast->cb; // don't count "object" item-id
156 parent.AllocMem(size + CB_SIZE);
157 CopyMemory(parent.m_pidl, m_pidl, size);
158 ZeroMemory((LPBYTE)parent.m_pidl + size, CB_SIZE); // terminator
160 // copy "object" portion
161 size = piidLast->cb + CB_SIZE;
165 CopyMemory(obj.m_pidl, piidLast, size);
169 CPIDL CPIDL::operator + (CPIDL& pidl) const
172 Concat(*this, pidl, ret);
176 void CPIDL::Concat(const CPIDL &a, const CPIDL& b, CPIDL& result)
180 // both empty->empty | a empty->return b | b empty->return a
181 if (a.m_pidl == NULL && b.m_pidl == NULL) return;
182 if (a.m_pidl == NULL) { result.Set(b); return; }
183 if (a.m_pidl == NULL) { result.Set(a); return; }
185 UINT cb1 = a.GetSize() - sizeof(a.m_pidl->mkid.cb);
186 UINT cb2 = b.GetSize();
187 result.AllocMem(cb1 + cb2); // allocate enough memory
188 CopyMemory(result.m_pidl, a.m_pidl, cb1); // 1st
189 CopyMemory(((LPBYTE)result.m_pidl) + cb1, b.m_pidl, cb2); // 2nd
192 HRESULT CPIDL::GetUIObjectOf(REFIID riid, LPVOID *ppvOut,
193 HWND hWnd /*= NULL*/, LPSHELLFOLDER psf /*= m_sfDesktop*/)
196 LPSHELLFOLDER psfParent;
200 // if no idl the use desktop folder
201 if (parent.m_pidl == NULL || parent.m_pidl->mkid.cb == 0)
208 // otherwise get the parent
209 hr = psf->BindToObject(parent, NULL, IID_IShellFolder,
210 (LPVOID *)&psfParent); // get the IShellFolder of the parent
214 hr = psfParent->GetUIObjectOf(hWnd, 1, obj, riid, 0, ppvOut);
215 psfParent->Release();
220 void CPIDL::ExtractCStr(STRRET& strRet) const
222 switch (strRet.uType)
226 // pOleStr points to a WCHAR string - convert it to ANSI
227 LPWSTR pOleStr = strRet.pOleStr;
228 WideCharToMultiByte(CP_ACP, 0, pOleStr, -1,
229 strRet.cStr, MAX_PATH, NULL, NULL);
230 m_pAllocator->Free(pOleStr);
235 // The string lives inside the pidl, so copy it out.
236 strncpy(strRet.cStr, (LPSTR)
237 ((LPBYTE)m_pidl + strRet.uOffset), MAX_PATH);
243 ////////////////////////////////////////////////////////////////////
244 // CPIDL Private Operations
246 void CPIDL::AllocMem(int iAllocSize)
249 m_pidl = (LPITEMIDLIST)m_pAllocator->Alloc(iAllocSize);