1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
5 * Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /*
23 This class handles the combo box of the address band.
24 */
25
26 #include "precomp.h"
27
28 /*
29 TODO:
30 Add drag and drop of icon in edit box
31 Handle change notifies to update appropriately
32 */
33
CAddressEditBox()34 CAddressEditBox::CAddressEditBox() :
35 fCombobox(WC_COMBOBOXEXW, this),
36 fEditWindow(WC_EDITW, this),
37 fSite(NULL),
38 pidlLastParsed(NULL)
39 {
40 }
41
~CAddressEditBox()42 CAddressEditBox::~CAddressEditBox()
43 {
44 if (pidlLastParsed)
45 ILFree(pidlLastParsed);
46 }
47
SetOwner(IUnknown * pOwner)48 HRESULT STDMETHODCALLTYPE CAddressEditBox::SetOwner(IUnknown *pOwner)
49 {
50 if (!pOwner)
51 {
52 CComPtr<IBrowserService> browserService;
53 HRESULT hResult = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
54 if (SUCCEEDED(hResult))
55 AtlUnadvise(browserService, DIID_DWebBrowserEvents, fAdviseCookie);
56 fSite = NULL;
57 }
58 // connect to browser connection point
59 return 0;
60 }
61
FileSysChange(long param8,long paramC)62 HRESULT STDMETHODCALLTYPE CAddressEditBox::FileSysChange(long param8, long paramC)
63 {
64 return E_NOTIMPL;
65 }
66
Refresh(long param8)67 HRESULT STDMETHODCALLTYPE CAddressEditBox::Refresh(long param8)
68 {
69 return E_NOTIMPL;
70 }
71
Init(HWND comboboxEx,HWND editControl,long param14,IUnknown * param18)72 HRESULT STDMETHODCALLTYPE CAddressEditBox::Init(HWND comboboxEx, HWND editControl, long param14, IUnknown *param18)
73 {
74 CComPtr<IBrowserService> browserService;
75
76 fCombobox.SubclassWindow(comboboxEx);
77 fEditWindow.SubclassWindow(editControl);
78 fSite = param18;
79 hComboBoxEx = comboboxEx;
80
81 SHAutoComplete(fEditWindow.m_hWnd, SHACF_FILESYSTEM | SHACF_URLALL | SHACF_USETAB);
82
83 // take advice to watch events
84 HRESULT hResult = IUnknown_QueryService(param18, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
85 if (SUCCEEDED(hResult))
86 {
87 hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
88 }
89
90 return hResult;
91 }
92
SetCurrentDir(long paramC)93 HRESULT STDMETHODCALLTYPE CAddressEditBox::SetCurrentDir(long paramC)
94 {
95 return E_NOTIMPL;
96 }
97
GetComboBoxText(CComHeapPtr<WCHAR> & pszText)98 BOOL CAddressEditBox::GetComboBoxText(CComHeapPtr<WCHAR>& pszText)
99 {
100 pszText.Free();
101 INT cchMax = fCombobox.GetWindowTextLength() + sizeof(UNICODE_NULL);
102 if (!pszText.Allocate(cchMax))
103 return FALSE;
104 return fCombobox.GetWindowText(pszText, cchMax);
105 }
106
RefreshAddress()107 HRESULT CAddressEditBox::RefreshAddress()
108 {
109 /* Get the current pidl of the browser */
110 CComHeapPtr<ITEMIDLIST> absolutePIDL;
111 HRESULT hr = GetAbsolutePidl(&absolutePIDL);
112 if (FAILED_UNEXPECTEDLY(hr))
113 return hr;
114
115 /* Fill the combobox */
116 ATLASSERT(absolutePIDL != NULL);
117 PopulateComboBox(absolutePIDL);
118
119 /* Get pShellFolder and pidlChild */
120 CComPtr<IShellFolder> pShellFolder;
121 PCITEMID_CHILD pidlChild;
122 hr = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &pShellFolder), &pidlChild);
123 if (FAILED_UNEXPECTEDLY(hr))
124 return hr;
125
126 /* Get ready to set the displayed item */
127 COMBOBOXEXITEMW item = { CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM };
128 item.iItem = -1; /* -1 to specify the displayed item */
129 item.iImage = SHMapPIDLToSystemImageListIndex(pShellFolder, pidlChild, &item.iSelectedImage);
130
131 /* Set the path if filesystem; otherwise use the name */
132 WCHAR szPathOrName[MAX_PATH];
133 SHGDNF flags = SHGDN_FORADDRESSBAR;
134 if (gCabinetState.fFullPathAddress)
135 flags |= SHGDN_FORPARSING;
136
137 if (SUCCEEDED(IEGetNameAndFlags(absolutePIDL, flags, szPathOrName, _countof(szPathOrName), NULL)))
138 item.pszText = szPathOrName;
139
140 /* Ownership of absolutePIDL will be moved to fCombobox. See CBEN_DELETEITEM */
141 item.lParam = reinterpret_cast<LPARAM>(absolutePIDL.Detach());
142
143 fCombobox.SendMessage(CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item)); /* Set it! */
144 return S_OK;
145 }
146
GetAbsolutePidl(PIDLIST_ABSOLUTE * pAbsolutePIDL)147 HRESULT CAddressEditBox::GetAbsolutePidl(PIDLIST_ABSOLUTE *pAbsolutePIDL)
148 {
149 CComPtr<IBrowserService> isb;
150 HRESULT hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb));
151 if (FAILED_UNEXPECTEDLY(hr))
152 return hr;
153
154 hr = isb->GetPidl(pAbsolutePIDL);
155 if (FAILED_UNEXPECTEDLY(hr))
156 return hr;
157
158 return S_OK;
159 }
160
161 /* Execute command line from address bar */
ExecuteCommandLine()162 BOOL CAddressEditBox::ExecuteCommandLine()
163 {
164 /* Get command line */
165 CComHeapPtr<WCHAR> pszCmdLine;
166 if (!GetComboBoxText(pszCmdLine))
167 return FALSE;
168
169 /* Split 1st parameter from trailing arguments */
170 PWCHAR args = PathGetArgsW(pszCmdLine);
171 PathRemoveArgsW(pszCmdLine);
172
173 PathUnquoteSpacesW(pszCmdLine); /* Unquote the 1st parameter */
174
175 /* Get ready for execution */
176 SHELLEXECUTEINFOW info = { sizeof(info), SEE_MASK_FLAG_NO_UI, m_hWnd };
177 info.lpFile = pszCmdLine;
178 info.lpParameters = args;
179 info.nShow = SW_SHOWNORMAL;
180
181 /* Set current directory */
182 WCHAR dir[MAX_PATH] = L"";
183 CComHeapPtr<ITEMIDLIST> pidl;
184 if (SUCCEEDED(GetAbsolutePidl(&pidl)))
185 {
186 if (SHGetPathFromIDListW(pidl, dir) && PathIsDirectoryW(dir))
187 info.lpDirectory = dir;
188 }
189
190 if (!::ShellExecuteExW(&info)) /* Execute! */
191 return FALSE;
192
193 RefreshAddress();
194 return TRUE;
195 }
196
ParseNow(long paramC)197 HRESULT STDMETHODCALLTYPE CAddressEditBox::ParseNow(long paramC)
198 {
199 ULONG eaten;
200 ULONG attributes;
201 HRESULT hr;
202 HWND topLevelWindow;
203 PIDLIST_ABSOLUTE pidlCurrent= NULL;
204 PIDLIST_RELATIVE pidlRelative = NULL;
205 CComPtr<IShellFolder> psfCurrent;
206
207 CComPtr<IBrowserService> pbs;
208 hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &pbs));
209 if (FAILED_UNEXPECTEDLY(hr))
210 return hr;
211
212 hr = IUnknown_GetWindow(pbs, &topLevelWindow);
213 if (FAILED_UNEXPECTEDLY(hr))
214 return hr;
215
216 /* Get the path to browse and expand it if needed */
217 CComHeapPtr<WCHAR> input, address;
218 if (!GetComboBoxText(input))
219 return E_FAIL;
220
221 INT addressLength = (wcschr(input, L'%') ? ::SHExpandEnvironmentStringsW(input, NULL, 0) : 0);
222 if (addressLength <= 0 ||
223 !address.Allocate(addressLength + 1) ||
224 !::SHExpandEnvironmentStringsW(input, address, addressLength))
225 {
226 address.Free();
227 address.Attach(input.Detach());
228 }
229
230 /* Try to parse a relative path and if it fails, try to browse an absolute path */
231 CComPtr<IShellFolder> psfDesktop;
232 hr = SHGetDesktopFolder(&psfDesktop);
233 if (FAILED_UNEXPECTEDLY(hr))
234 goto cleanup;
235
236 hr = pbs->GetPidl(&pidlCurrent);
237 if (FAILED_UNEXPECTEDLY(hr))
238 goto parseabsolute;
239
240 hr = psfDesktop->BindToObject(pidlCurrent, NULL, IID_PPV_ARG(IShellFolder, &psfCurrent));
241 if (FAILED_UNEXPECTEDLY(hr))
242 goto parseabsolute;
243
244 hr = psfCurrent->ParseDisplayName(topLevelWindow, NULL, address, &eaten, &pidlRelative, &attributes);
245 if (SUCCEEDED(hr))
246 {
247 pidlLastParsed = ILCombine(pidlCurrent, pidlRelative);
248 ILFree(pidlRelative);
249 goto cleanup;
250 }
251
252 parseabsolute:
253 /* We couldn't parse a relative path, attempt to parse an absolute path */
254 hr = psfDesktop->ParseDisplayName(topLevelWindow, NULL, address, &eaten, &pidlLastParsed, &attributes);
255
256 cleanup:
257 if (pidlCurrent)
258 ILFree(pidlCurrent);
259 return hr;
260 }
261
ShowFileNotFoundError(HRESULT hRet)262 HRESULT STDMETHODCALLTYPE CAddressEditBox::ShowFileNotFoundError(HRESULT hRet)
263 {
264 CComHeapPtr<WCHAR> input;
265 if (!GetComboBoxText(input))
266 return E_FAIL;
267
268 ShellMessageBoxW(_AtlBaseModule.GetResourceInstance(), fCombobox.m_hWnd, MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TEXT), MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TITLE), MB_OK | MB_ICONERROR, input.m_pData);
269
270 return hRet;
271 }
272
Execute(long paramC)273 HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC)
274 {
275 HRESULT hr;
276
277 /*
278 * Parse the path if it wasn't parsed
279 */
280 if (!pidlLastParsed)
281 {
282 hr = ParseNow(0);
283
284 /* If the destination path doesn't exist then display an error message */
285 if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
286 {
287 if (ExecuteCommandLine())
288 return S_OK;
289
290 return ShowFileNotFoundError(hr);
291 }
292
293 if (!pidlLastParsed)
294 return E_FAIL;
295 }
296
297 /*
298 * Get the IShellBrowser and IBrowserService interfaces of the shell browser
299 */
300 CComPtr<IShellBrowser> pisb;
301 hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pisb));
302 if (FAILED(hr))
303 return hr;
304
305 /*
306 * Get the current pidl of the shellbrowser and check if it is the same with the parsed one
307 */
308 PIDLIST_ABSOLUTE pidl;
309 hr = GetAbsolutePidl(&pidl);
310 if (FAILED(hr))
311 return hr;
312
313 CComPtr<IShellFolder> psf;
314 hr = SHGetDesktopFolder(&psf);
315 if (FAILED(hr))
316 return hr;
317
318 hr = psf->CompareIDs(0, pidl, pidlLastParsed);
319
320 SHFree(pidl);
321
322 if (hr == 0)
323 {
324 if (pidlLastParsed)
325 {
326 ILFree(pidlLastParsed);
327 pidlLastParsed = NULL;
328 }
329 return S_OK;
330 }
331
332 /*
333 * Attempt to browse to the parsed pidl
334 */
335 hr = pisb->BrowseObject(pidlLastParsed, 0);
336 if (SUCCEEDED(hr))
337 return hr;
338
339 /*
340 * Browsing to the pidl failed so it's not a folder. So invoke its defaule command.
341 */
342 HWND topLevelWindow;
343 hr = IUnknown_GetWindow(pisb, &topLevelWindow);
344 if (FAILED(hr))
345 return hr;
346
347 LPCITEMIDLIST pidlChild;
348 CComPtr<IShellFolder> sf;
349 hr = SHBindToParent(pidlLastParsed, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
350 if (FAILED(hr))
351 return hr;
352
353 hr = SHInvokeDefaultCommand(topLevelWindow, sf, pidlChild);
354 if (FAILED(hr))
355 return hr;
356
357 return hr;
358 }
359
Save(long paramC)360 HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(long paramC)
361 {
362 return E_NOTIMPL;
363 }
364
OnWinEvent(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * theResult)365 HRESULT STDMETHODCALLTYPE CAddressEditBox::OnWinEvent(
366 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
367 {
368 LPNMHDR hdr;
369
370 if (theResult)
371 *theResult = 0;
372
373 switch (uMsg)
374 {
375 case WM_COMMAND:
376 {
377 if (HIWORD(wParam) == CBN_SELCHANGE)
378 {
379 UINT selectedIndex = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
380 pidlLastParsed = ILClone((LPITEMIDLIST)SendMessageW((HWND)lParam, CB_GETITEMDATA, selectedIndex, 0));
381 Execute(0);
382 }
383 break;
384 }
385 case WM_NOTIFY:
386 {
387 hdr = (LPNMHDR) lParam;
388 if (hdr->code == CBEN_ENDEDIT)
389 {
390 NMCBEENDEDITW *endEdit = (NMCBEENDEDITW*) lParam;
391 if (endEdit->iWhy == CBENF_RETURN)
392 {
393 Execute(0);
394 }
395 else if (endEdit->iWhy == CBENF_ESCAPE)
396 {
397 /* Reset the contents of the combo box */
398 RefreshAddress();
399 }
400 }
401 else if (hdr->code == CBEN_DELETEITEM)
402 {
403 PNMCOMBOBOXEX pCBEx = (PNMCOMBOBOXEX) lParam;
404 LPITEMIDLIST itemPidl = (LPITEMIDLIST)pCBEx->ceItem.lParam;
405 if (itemPidl)
406 {
407 ILFree(itemPidl);
408 }
409 }
410 break;
411 }
412 }
413 return S_OK;
414 }
415
IsWindowOwner(HWND hWnd)416 HRESULT STDMETHODCALLTYPE CAddressEditBox::IsWindowOwner(HWND hWnd)
417 {
418 if (fCombobox.m_hWnd == hWnd)
419 return S_OK;
420 if (fEditWindow.m_hWnd == hWnd)
421 return S_OK;
422 return S_FALSE;
423 }
424
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)425 HRESULT STDMETHODCALLTYPE CAddressEditBox::QueryStatus(
426 const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
427 {
428 return E_NOTIMPL;
429 }
430
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)431 HRESULT STDMETHODCALLTYPE CAddressEditBox::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
432 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
433 {
434 return E_NOTIMPL;
435 }
436
GetTypeInfoCount(UINT * pctinfo)437 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetTypeInfoCount(UINT *pctinfo)
438 {
439 return E_NOTIMPL;
440 }
441
GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)442 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
443 {
444 return E_NOTIMPL;
445 }
446
GetIDsOfNames(REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)447 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetIDsOfNames(
448 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
449 {
450 return E_NOTIMPL;
451 }
452
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)453 HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
454 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
455 {
456 if (pDispParams == NULL)
457 return E_INVALIDARG;
458
459 switch (dispIdMember)
460 {
461 case DISPID_NAVIGATECOMPLETE2:
462 case DISPID_DOCUMENTCOMPLETE:
463 if (pidlLastParsed)
464 {
465 ILFree(pidlLastParsed);
466 pidlLastParsed = NULL;
467 }
468
469 RefreshAddress();
470 break;
471 }
472 return S_OK;
473 }
474
GetClassID(CLSID * pClassID)475 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetClassID(CLSID *pClassID)
476 {
477 if (pClassID == NULL)
478 return E_POINTER;
479 *pClassID = CLSID_AddressEditBox;
480 return S_OK;
481 }
482
IsDirty()483 HRESULT STDMETHODCALLTYPE CAddressEditBox::IsDirty()
484 {
485 return E_NOTIMPL;
486 }
487
Load(IStream * pStm)488 HRESULT STDMETHODCALLTYPE CAddressEditBox::Load(IStream *pStm)
489 {
490 return E_NOTIMPL;
491 }
492
Save(IStream * pStm,BOOL fClearDirty)493 HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(IStream *pStm, BOOL fClearDirty)
494 {
495 return E_NOTIMPL;
496 }
497
GetSizeMax(ULARGE_INTEGER * pcbSize)498 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetSizeMax(ULARGE_INTEGER *pcbSize)
499 {
500 return E_NOTIMPL;
501 }
502
PopulateComboBox(LPITEMIDLIST pidlCurrent)503 void CAddressEditBox::PopulateComboBox(LPITEMIDLIST pidlCurrent)
504 {
505 HRESULT hr;
506 LPITEMIDLIST pidl;
507 int indent = 0;
508 int index;
509
510 index = SendMessageW(hComboBoxEx, CB_GETCOUNT, 0, 0);
511 for (int i = 0; i < index; i++)
512 SendMessageW(hComboBoxEx, CBEM_DELETEITEM, i, 0);
513 SendMessageW(hComboBoxEx, CB_RESETCONTENT, 0, 0);
514
515 /* Calculate the indent level. No need to clone the pidl */
516 pidl = pidlCurrent;
517 do
518 {
519 if(!pidl->mkid.cb)
520 break;
521 pidl = ILGetNext(pidl);
522 indent++;
523 } while (pidl);
524 index = indent;
525
526 /* Add every id from the pidl in the combo box */
527 pidl = ILClone(pidlCurrent);
528 do
529 {
530 AddComboBoxItem(pidl, 0, index);
531 ILRemoveLastID(pidl);
532 index--;
533 } while (index >= 0);
534 ILFree(pidl);
535
536 /* Add the items of the desktop */
537 FillOneLevel(0, 1, indent);
538
539 /* Add the items of My Computer */
540 hr = SHGetSpecialFolderLocation(0, CSIDL_DRIVES, &pidl);
541 if (FAILED_UNEXPECTEDLY(hr))
542 return;
543
544 for(LPITEMIDLIST i = GetItemData(0); i; i = GetItemData(index))
545 {
546 if (ILIsEqual(i, pidl))
547 {
548 FillOneLevel(index, 2, indent);
549 break;
550 }
551 index++;
552 }
553 ILFree(pidl);
554 }
555
AddComboBoxItem(LPITEMIDLIST pidl,int index,int indent)556 void CAddressEditBox::AddComboBoxItem(LPITEMIDLIST pidl, int index, int indent)
557 {
558 HRESULT hr;
559 WCHAR buf[4096];
560
561 LPCITEMIDLIST pidlChild;
562 CComPtr<IShellFolder> sf;
563 hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
564 if (FAILED_UNEXPECTEDLY(hr))
565 return;
566
567 STRRET strret;
568 hr = sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR, &strret);
569 if (FAILED_UNEXPECTEDLY(hr))
570 return;
571
572 hr = StrRetToBufW(&strret, pidlChild, buf, 4095);
573 if (FAILED_UNEXPECTEDLY(hr))
574 return;
575
576 COMBOBOXEXITEMW item = {0};
577 item.mask = CBEIF_LPARAM | CBEIF_INDENT | CBEIF_SELECTEDIMAGE | CBEIF_IMAGE | CBEIF_TEXT;
578 item.iImage = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &item.iSelectedImage);
579 item.pszText = buf;
580 item.lParam = (LPARAM)(ILClone(pidl));
581 item.iIndent = indent;
582 item.iItem = index;
583 SendMessageW(hComboBoxEx, CBEM_INSERTITEMW, 0, (LPARAM)&item);
584 }
585
FillOneLevel(int index,int levelIndent,int indent)586 void CAddressEditBox::FillOneLevel(int index, int levelIndent, int indent)
587 {
588 HRESULT hr;
589 ULONG numObj;
590 int count;
591 LPITEMIDLIST pidl, pidl2, pidl3, pidl4;
592
593 count = index + 1;
594 pidl = GetItemData(index);
595 pidl2 = GetItemData(count);
596 if(pidl)
597 {
598 CComPtr<IShellFolder> psfDesktop;
599 CComPtr<IShellFolder> psfItem;
600
601 hr = SHGetDesktopFolder(&psfDesktop);
602 if (FAILED_UNEXPECTEDLY(hr))
603 return;
604
605 if (!pidl->mkid.cb)
606 {
607 psfItem = psfDesktop;
608 }
609 else
610 {
611 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfItem));
612 if (FAILED_UNEXPECTEDLY(hr))
613 return;
614 }
615
616 CComPtr<IEnumIDList> pEnumIDList;
617 hr = psfItem->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnumIDList);
618 if (FAILED_UNEXPECTEDLY(hr))
619 return;
620
621 do
622 {
623 hr = pEnumIDList->Next(1, &pidl3, &numObj);
624 if(hr != S_OK || !numObj)
625 break;
626
627 pidl4 = ILCombine(pidl, pidl3);
628 if (pidl2 && ILIsEqual(pidl4, pidl2))
629 count += (indent - levelIndent);
630 else
631 AddComboBoxItem(pidl4, count, levelIndent);
632 count++;
633 ILFree(pidl3);
634 ILFree(pidl4);
635 } while (true);
636 }
637 }
638
GetItemData(int index)639 LPITEMIDLIST CAddressEditBox::GetItemData(int index)
640 {
641 COMBOBOXEXITEMW item;
642
643 memset(&item, 0, sizeof(COMBOBOXEXITEMW));
644 item.mask = CBEIF_LPARAM;
645 item.iItem = index;
646 SendMessageW(hComboBoxEx, CBEM_GETITEMW, 0, (LPARAM)&item);
647 return (LPITEMIDLIST)item.lParam;
648 }
649
OnSettingChange(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)650 LRESULT CAddressEditBox::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
651 {
652 RefreshAddress();
653 return NO_ERROR;
654 }
655