Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / dll / win32 / comdlg32 / filedlgbrowser.c
1 /*
2 * Implementation of IShellBrowser for the File Open common dialog
3 *
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #include <stdarg.h>
27 //#include <stdio.h>
28 //#include <string.h>
29
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33
34 #include <windef.h>
35 #include <winbase.h>
36 //#include "winnls.h"
37 #include <wingdi.h>
38 #include <winuser.h>
39 #include <winreg.h>
40 #include <commdlg.h>
41
42 #define NO_SHLWAPI_STREAM
43 #include <shlwapi.h>
44 #include <filedlgbrowser.h>
45 #include "cdlg.h"
46 //#include "shlguid.h"
47 //#include "servprov.h"
48 #include <wine/debug.h>
49
50 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
51
52 typedef struct
53 {
54
55 IShellBrowser IShellBrowser_iface;
56 ICommDlgBrowser ICommDlgBrowser_iface;
57 IServiceProvider IServiceProvider_iface;
58 LONG ref; /* Reference counter */
59 HWND hwndOwner; /* Owner dialog of the interface */
60
61 } IShellBrowserImpl;
62
63 static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
64 {
65 return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
66 }
67
68 static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface )
69 {
70 return CONTAINING_RECORD(iface, IShellBrowserImpl, ICommDlgBrowser_iface);
71 }
72
73 static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface )
74 {
75 return CONTAINING_RECORD(iface, IShellBrowserImpl, IServiceProvider_iface);
76 }
77
78 /**************************************************************************
79 * vtable
80 */
81 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
82 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl;
83 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl;
84
85 /*
86 * Helper functions
87 */
88
89 #define add_flag(a) if (flags & a) {strcat(str, #a );strcat(str," ");}
90 static void COMDLG32_DumpSBSPFlags(UINT uflags)
91 {
92 if (TRACE_ON(commdlg))
93 {
94 unsigned int i;
95 static const struct {
96 DWORD mask;
97 const char *name;
98 } flags[] = {
99 #define FE(x) { x, #x}
100 /* SBSP_DEFBROWSER == 0 */
101 FE(SBSP_SAMEBROWSER),
102 FE(SBSP_NEWBROWSER),
103
104 /* SBSP_DEFMODE == 0 */
105 FE(SBSP_OPENMODE),
106 FE(SBSP_EXPLOREMODE),
107 FE(SBSP_HELPMODE),
108 FE(SBSP_NOTRANSFERHIST),
109
110 /* SBSP_ABSOLUTE == 0 */
111 FE(SBSP_RELATIVE),
112 FE(SBSP_PARENT),
113 FE(SBSP_NAVIGATEBACK),
114 FE(SBSP_NAVIGATEFORWARD),
115 FE(SBSP_ALLOW_AUTONAVIGATE),
116
117 FE(SBSP_NOAUTOSELECT),
118 FE(SBSP_WRITENOHISTORY),
119
120 FE(SBSP_REDIRECT),
121 FE(SBSP_INITIATEDBYHLINKFRAME),
122 };
123 #undef FE
124 TRACE("SBSP Flags: %08x =", uflags);
125 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
126 if (flags[i].mask & uflags)
127 TRACE("%s ", flags[i].name);
128 TRACE("\n");
129 }
130 }
131
132 static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos)
133 {
134 LPSHELLFOLDER psfDesktop;
135 STRRET strret;
136 HRESULT res;
137
138 res = SHGetDesktopFolder(&psfDesktop);
139 if (FAILED(res))
140 return;
141
142 res = IShellFolder_GetDisplayNameOf(psfDesktop, fodInfos->ShellInfos.pidlAbsCurrent,
143 SHGDN_FORPARSING, &strret);
144 if (SUCCEEDED(res)) {
145 WCHAR wszCurrentDir[MAX_PATH];
146
147 res = StrRetToBufW(&strret, fodInfos->ShellInfos.pidlAbsCurrent, wszCurrentDir, MAX_PATH);
148 if (SUCCEEDED(res))
149 SetCurrentDirectoryW(wszCurrentDir);
150 }
151
152 IShellFolder_Release(psfDesktop);
153 }
154
155 /* copied from shell32 to avoid linking to it */
156 static BOOL COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl)
157 {
158 TRACE("dest=%p len=0x%x strret=%p pidl=%p stub\n",dest,len,src,pidl);
159
160 switch (src->uType)
161 {
162 case STRRET_WSTR:
163 lstrcpynW(dest, src->u.pOleStr, len);
164 COMDLG32_SHFree(src->u.pOleStr);
165 break;
166
167 case STRRET_CSTR:
168 if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
169 ((LPWSTR)dest)[len-1] = 0;
170 break;
171
172 case STRRET_OFFSET:
173 if (pidl)
174 {
175 if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset,
176 -1, dest, len ))
177 ((LPWSTR)dest)[len-1] = 0;
178 }
179 break;
180
181 default:
182 FIXME("unknown type!\n");
183 if (len)
184 { *(LPWSTR)dest = '\0';
185 }
186 return(FALSE);
187 }
188 return TRUE;
189 }
190
191 /*
192 * IShellBrowser
193 */
194
195 /**************************************************************************
196 * IShellBrowserImpl_Construct
197 */
198 IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
199 {
200 IShellBrowserImpl *sb;
201 FileOpenDlgInfos *fodInfos = GetPropA(hwndOwner,FileOpenDlgInfosStr);
202
203 sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl));
204
205 /* Initialisation of the member variables */
206 sb->ref=1;
207 sb->hwndOwner = hwndOwner;
208
209 /* Initialisation of the vTables */
210 sb->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
211 sb->ICommDlgBrowser_iface.lpVtbl = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
212 sb->IServiceProvider_iface.lpVtbl = &IShellBrowserImpl_IServiceProvider_Vtbl;
213 SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP,
214 &fodInfos->ShellInfos.pidlAbsCurrent);
215
216 TRACE("%p\n", sb);
217
218 return &sb->IShellBrowser_iface;
219 }
220
221 /***************************************************************************
222 * IShellBrowserImpl_QueryInterface
223 */
224 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
225 REFIID riid,
226 LPVOID *ppvObj)
227 {
228 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
229
230 TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid));
231
232 *ppvObj = NULL;
233
234 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
235 { *ppvObj = This;
236 }
237 else if(IsEqualIID(riid, &IID_IOleWindow)) /*IOleWindow*/
238 { *ppvObj = This;
239 }
240
241 else if(IsEqualIID(riid, &IID_IShellBrowser)) /*IShellBrowser*/
242 { *ppvObj = This;
243 }
244
245 else if(IsEqualIID(riid, &IID_ICommDlgBrowser)) /*ICommDlgBrowser*/
246 *ppvObj = &This->ICommDlgBrowser_iface;
247 else if(IsEqualIID(riid, &IID_IServiceProvider)) /* IServiceProvider */
248 *ppvObj = &This->IServiceProvider_iface;
249
250 if(*ppvObj)
251 { IUnknown_AddRef( (IShellBrowser*) *ppvObj);
252 return S_OK;
253 }
254 FIXME("Unknown interface requested\n");
255 return E_NOINTERFACE;
256 }
257
258 /**************************************************************************
259 * IShellBrowser::AddRef
260 */
261 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
262 {
263 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
264 ULONG ref = InterlockedIncrement(&This->ref);
265
266 TRACE("(%p,%u)\n", This, ref - 1);
267
268 return ref;
269 }
270
271 /**************************************************************************
272 * IShellBrowserImpl_Release
273 */
274 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
275 {
276 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
277 ULONG ref = InterlockedDecrement(&This->ref);
278
279 TRACE("(%p,%u)\n", This, ref + 1);
280
281 if (!ref)
282 {
283 COMDLG32_SHFree(This);
284 TRACE("-- destroyed\n");
285 return 0;
286 }
287 return ref;
288 }
289
290 /*
291 * IOleWindow
292 */
293
294 /**************************************************************************
295 * IShellBrowserImpl_GetWindow (IOleWindow)
296 *
297 * Inherited from IOleWindow::GetWindow
298 *
299 * See Windows documentation for more details
300 *
301 * Note : We will never be window less in the File Open dialog
302 *
303 */
304 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
305 HWND * phwnd)
306 {
307 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
308
309 TRACE("(%p)\n", This);
310
311 if(!This->hwndOwner)
312 return E_FAIL;
313
314 *phwnd = This->hwndOwner;
315
316 return (*phwnd) ? S_OK : E_UNEXPECTED;
317
318 }
319
320 /**************************************************************************
321 * IShellBrowserImpl_ContextSensitiveHelp
322 */
323 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
324 BOOL fEnterMode)
325 {
326 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
327
328 TRACE("(%p)\n", This);
329
330 /* Feature not implemented */
331 return E_NOTIMPL;
332 }
333
334 /*
335 * IShellBrowser
336 */
337
338 /**************************************************************************
339 * IShellBrowserImpl_BrowseObject
340 *
341 * See Windows documentation on IShellBrowser::BrowseObject for more details
342 *
343 * This function will override user specified flags and will always
344 * use SBSP_DEFBROWSER and SBSP_DEFMODE.
345 */
346 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
347 LPCITEMIDLIST pidl,
348 UINT wFlags)
349 {
350 HRESULT hRes;
351 IShellFolder *psfTmp;
352 IShellView *psvTmp;
353 FileOpenDlgInfos *fodInfos;
354 LPITEMIDLIST pidlTmp;
355 HWND hwndView;
356 HWND hDlgWnd;
357 BOOL bViewHasFocus;
358 RECT rectView;
359
360 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
361
362 TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
363 COMDLG32_DumpSBSPFlags(wFlags);
364
365 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
366
367 /* Format the pidl according to its parameter's category */
368 if(wFlags & SBSP_RELATIVE)
369 {
370
371 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */
372 if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
373 pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
374 {
375 ERR("bind to object failed\n");
376 return hRes;
377 }
378 /* create an absolute pidl */
379 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl);
380 }
381 else if(wFlags & SBSP_PARENT)
382 {
383 /* Browse the parent folder (ignores the pidl) */
384 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
385 psfTmp = GetShellFolderFromPidl(pidlTmp);
386
387 }
388 else /* SBSP_ABSOLUTE is 0x0000 */
389 {
390 /* An absolute pidl (relative from the desktop) */
391 pidlTmp = COMDLG32_PIDL_ILClone(pidl);
392 psfTmp = GetShellFolderFromPidl(pidlTmp);
393 }
394
395 if(!psfTmp)
396 {
397 ERR("could not browse to folder\n");
398 return E_FAIL;
399 }
400
401 /* If the pidl to browse to is equal to the actual pidl ...
402 do nothing and pretend you did it*/
403 if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
404 {
405 IShellFolder_Release(psfTmp);
406 COMDLG32_SHFree(pidlTmp);
407 TRACE("keep current folder\n");
408 return NOERROR;
409 }
410
411 /* Release the current DataObject */
412 if (fodInfos->Shell.FOIDataObject)
413 {
414 IDataObject_Release(fodInfos->Shell.FOIDataObject);
415 fodInfos->Shell.FOIDataObject = NULL;
416 }
417
418 /* Create the associated view */
419 TRACE("create view object\n");
420 if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner,
421 &IID_IShellView, (LPVOID *)&psvTmp))) goto error;
422
423 /* Check if listview has focus */
424 bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus());
425
426 /* Get the foldersettings from the old view */
427 if(fodInfos->Shell.FOIShellView)
428 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings);
429
430 /* Release the old fodInfos->Shell.FOIShellView and update its value.
431 We have to update this early since ShellView_CreateViewWindow of native
432 shell32 calls OnStateChange and needs the correct view here.*/
433 if(fodInfos->Shell.FOIShellView)
434 {
435 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
436 IShellView_Release(fodInfos->Shell.FOIShellView);
437 }
438 fodInfos->Shell.FOIShellView = psvTmp;
439
440 /* Release old FOIShellFolder and update its value */
441 if (fodInfos->Shell.FOIShellFolder)
442 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
443 fodInfos->Shell.FOIShellFolder = psfTmp;
444
445 /* Release old pidlAbsCurrent and update its value */
446 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
447 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
448
449 COMDLG32_UpdateCurrentDir(fodInfos);
450
451 GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
452 MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);
453
454 /* Create the window */
455 TRACE("create view window\n");
456 if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
457 &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
458 &rectView, &hwndView))) goto error;
459
460 fodInfos->ShellInfos.hwndView = hwndView;
461
462 /* Set view window control id to 5002 */
463 SetWindowLongPtrW(hwndView, GWLP_ID, lst2);
464
465 /* Select the new folder in the Look In combo box of the Open file dialog */
466 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent);
467
468 /* changes the tab order of the ListView to reflect the window's File Dialog */
469 hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN);
470 SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
471
472 /* Since we destroyed the old view if it had focus set focus to the newly created view */
473 if (bViewHasFocus)
474 SetFocus(fodInfos->ShellInfos.hwndView);
475
476 return hRes;
477 error:
478 ERR("Failed with error 0x%08x\n", hRes);
479 return hRes;
480 }
481
482 /**************************************************************************
483 * IShellBrowserImpl_EnableModelessSB
484 */
485 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
486 BOOL fEnable)
487
488 {
489 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
490
491 TRACE("(%p)\n", This);
492
493 /* Feature not implemented */
494 return E_NOTIMPL;
495 }
496
497 /**************************************************************************
498 * IShellBrowserImpl_GetControlWindow
499 */
500 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
501 UINT id,
502 HWND *lphwnd)
503
504 {
505 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
506
507 TRACE("(%p)\n", This);
508
509 /* Feature not implemented */
510 return E_NOTIMPL;
511 }
512
513 /**************************************************************************
514 * IShellBrowserImpl_GetViewStateStream
515 */
516 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
517 DWORD grfMode,
518 LPSTREAM *ppStrm)
519
520 {
521 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
522
523 FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm);
524
525 /* Feature not implemented */
526 return E_NOTIMPL;
527 }
528
529 /**************************************************************************
530 * IShellBrowserImpl_InsertMenusSB
531 */
532 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
533 HMENU hmenuShared,
534 LPOLEMENUGROUPWIDTHS lpMenuWidths)
535
536 {
537 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
538
539 TRACE("(%p)\n", This);
540
541 /* Feature not implemented */
542 return E_NOTIMPL;
543 }
544
545 /**************************************************************************
546 * IShellBrowserImpl_OnViewWindowActive
547 */
548 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
549 IShellView *ppshv)
550
551 {
552 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
553
554 TRACE("(%p)\n", This);
555
556 /* Feature not implemented */
557 return E_NOTIMPL;
558 }
559
560 /**************************************************************************
561 * IShellBrowserImpl_QueryActiveShellView
562 */
563 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
564 IShellView **ppshv)
565
566 {
567 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
568
569 FileOpenDlgInfos *fodInfos;
570
571 TRACE("(%p)\n", This);
572
573 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
574
575 if(!(*ppshv = fodInfos->Shell.FOIShellView))
576 {
577 return E_FAIL;
578 }
579 IShellView_AddRef(fodInfos->Shell.FOIShellView);
580 return NOERROR;
581 }
582
583 /**************************************************************************
584 * IShellBrowserImpl_RemoveMenusSB
585 */
586 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
587 HMENU hmenuShared)
588
589 {
590 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
591
592 TRACE("(%p)\n", This);
593
594 /* Feature not implemented */
595 return E_NOTIMPL;
596 }
597
598 /**************************************************************************
599 * IShellBrowserImpl_SendControlMsg
600 */
601 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
602 UINT id,
603 UINT uMsg,
604 WPARAM wParam,
605 LPARAM lParam,
606 LRESULT *pret)
607
608 {
609 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
610 LRESULT lres;
611
612 TRACE("(%p)->(0x%08x 0x%08x 0x%08lx 0x%08lx %p)\n", This, id, uMsg, wParam, lParam, pret);
613
614 switch (id)
615 {
616 case FCW_TOOLBAR:
617 lres = SendDlgItemMessageA( This->hwndOwner, IDC_TOOLBAR, uMsg, wParam, lParam);
618 break;
619 default:
620 FIXME("ctrl id: %x\n", id);
621 return E_NOTIMPL;
622 }
623 if (pret) *pret = lres;
624 return S_OK;
625 }
626
627 /**************************************************************************
628 * IShellBrowserImpl_SetMenuSB
629 */
630 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
631 HMENU hmenuShared,
632 HOLEMENU holemenuReserved,
633 HWND hwndActiveObject)
634
635 {
636 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
637
638 TRACE("(%p)\n", This);
639
640 /* Feature not implemented */
641 return E_NOTIMPL;
642 }
643
644 /**************************************************************************
645 * IShellBrowserImpl_SetStatusTextSB
646 */
647 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
648 LPCOLESTR lpszStatusText)
649
650 {
651 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
652
653 TRACE("(%p)\n", This);
654
655 /* Feature not implemented */
656 return E_NOTIMPL;
657 }
658
659 /**************************************************************************
660 * IShellBrowserImpl_SetToolbarItems
661 */
662 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
663 LPTBBUTTON lpButtons,
664 UINT nButtons,
665 UINT uFlags)
666
667 {
668 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
669
670 TRACE("(%p)\n", This);
671
672 /* Feature not implemented */
673 return E_NOTIMPL;
674 }
675
676 /**************************************************************************
677 * IShellBrowserImpl_TranslateAcceleratorSB
678 */
679 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
680 LPMSG lpmsg,
681 WORD wID)
682
683 {
684 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
685
686 TRACE("(%p)\n", This);
687
688 /* Feature not implemented */
689 return E_NOTIMPL;
690 }
691
692 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
693 {
694 /* IUnknown */
695 IShellBrowserImpl_QueryInterface,
696 IShellBrowserImpl_AddRef,
697 IShellBrowserImpl_Release,
698 /* IOleWindow */
699 IShellBrowserImpl_GetWindow,
700 IShellBrowserImpl_ContextSensitiveHelp,
701 /* IShellBrowser */
702 IShellBrowserImpl_InsertMenusSB,
703 IShellBrowserImpl_SetMenuSB,
704 IShellBrowserImpl_RemoveMenusSB,
705 IShellBrowserImpl_SetStatusTextSB,
706 IShellBrowserImpl_EnableModelessSB,
707 IShellBrowserImpl_TranslateAcceleratorSB,
708 IShellBrowserImpl_BrowseObject,
709 IShellBrowserImpl_GetViewStateStream,
710 IShellBrowserImpl_GetControlWindow,
711 IShellBrowserImpl_SendControlMsg,
712 IShellBrowserImpl_QueryActiveShellView,
713 IShellBrowserImpl_OnViewWindowActive,
714 IShellBrowserImpl_SetToolbarItems
715 };
716
717
718
719 /*
720 * ICommDlgBrowser
721 */
722
723 /***************************************************************************
724 * IShellBrowserImpl_ICommDlgBrowser_QueryInterface
725 */
726 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(
727 ICommDlgBrowser *iface,
728 REFIID riid,
729 LPVOID *ppvObj)
730 {
731 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
732
733 TRACE("(%p)\n", This);
734
735 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
736 }
737
738 /**************************************************************************
739 * IShellBrowserImpl_ICommDlgBrowser_AddRef
740 */
741 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
742 {
743 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
744
745 TRACE("(%p)\n", This);
746
747 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
748 }
749
750 /**************************************************************************
751 * IShellBrowserImpl_ICommDlgBrowser_Release
752 */
753 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
754 {
755 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
756
757 TRACE("(%p)\n", This);
758
759 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
760 }
761
762 /**************************************************************************
763 * IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
764 *
765 * Called when a user double-clicks in the view or presses the ENTER key
766 */
767 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
768 IShellView *ppshv)
769 {
770 LPITEMIDLIST pidl;
771 FileOpenDlgInfos *fodInfos;
772
773 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
774
775 TRACE("(%p)\n", This);
776
777 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
778
779 /* If the selected object is not a folder, send an IDOK command to parent window */
780 if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1)))
781 {
782 HRESULT hRes;
783
784 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
785 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
786 if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
787 {
788 hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE);
789 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
790 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
791 }
792 else
793 {
794 /* Tell the dialog that the user selected a file */
795 PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
796 hRes = S_OK;
797 }
798
799 /* Free memory used by pidl */
800 COMDLG32_SHFree(pidl);
801
802 return hRes;
803 }
804
805 return E_FAIL;
806 }
807
808 /**************************************************************************
809 * IShellBrowserImpl_OnSelChange
810 */
811 static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv)
812 {
813 FileOpenDlgInfos *fodInfos;
814
815 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
816 TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView);
817
818 /* release old selections */
819 if (fodInfos->Shell.FOIDataObject)
820 IDataObject_Release(fodInfos->Shell.FOIDataObject);
821
822 /* get a new DataObject from the ShellView */
823 if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION,
824 &IID_IDataObject, (void**)&fodInfos->Shell.FOIDataObject)))
825 return E_FAIL;
826
827 FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);
828
829 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
830 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
831 return S_OK;
832 }
833
834 /**************************************************************************
835 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange
836 */
837 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
838 IShellView *ppshv,
839 ULONG uChange)
840 {
841
842 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
843
844 TRACE("(%p shv=%p)\n", This, ppshv);
845
846 switch (uChange)
847 {
848 case CDBOSC_SETFOCUS:
849 /* FIXME: Reset the default button.
850 This should be taken care of by defdlg. If control
851 other than button receives focus the default button
852 should be restored. */
853 SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0);
854
855 break;
856 case CDBOSC_KILLFOCUS:
857 {
858 FileOpenDlgInfos *fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
859 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
860 {
861 WCHAR szSave[16];
862 LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR));
863 SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave);
864 }
865 }
866 break;
867 case CDBOSC_SELCHANGE:
868 return IShellBrowserImpl_OnSelChange(This, ppshv);
869 case CDBOSC_RENAME:
870 /* nothing to do */
871 break;
872 }
873
874 return NOERROR;
875 }
876
877 /* send_includeitem_notification
878 *
879 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg
880 */
881 static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl)
882 {
883 LRESULT hook_result = 0;
884 FileOpenDlgInfos *fodInfos = GetPropA(hwndParentDlg, FileOpenDlgInfosStr);
885
886 if(!fodInfos) return 0;
887
888 if(fodInfos->DlgInfos.hwndCustomDlg)
889 {
890 TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl);
891 if(fodInfos->unicode)
892 {
893 OFNOTIFYEXW ofnNotify;
894 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
895 ofnNotify.pidl = (LPITEMIDLIST)pidl;
896 ofnNotify.hdr.hwndFrom = hwndParentDlg;
897 ofnNotify.hdr.idFrom = 0;
898 ofnNotify.hdr.code = CDN_INCLUDEITEM;
899 ofnNotify.lpOFN = fodInfos->ofnInfos;
900 hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
901 }
902 else
903 {
904 OFNOTIFYEXA ofnNotify;
905 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
906 ofnNotify.pidl = (LPITEMIDLIST)pidl;
907 ofnNotify.hdr.hwndFrom = hwndParentDlg;
908 ofnNotify.hdr.idFrom = 0;
909 ofnNotify.hdr.code = CDN_INCLUDEITEM;
910 ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos;
911 hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
912 }
913 }
914 TRACE("Retval: 0x%08lx\n", hook_result);
915 return hook_result;
916 }
917
918 /**************************************************************************
919 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject
920 */
921 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
922 IShellView * ppshv,
923 LPCITEMIDLIST pidl)
924 {
925 FileOpenDlgInfos *fodInfos;
926 ULONG ulAttr;
927 STRRET str;
928 WCHAR szPathW[MAX_PATH];
929
930 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
931
932 TRACE("(%p)\n", This);
933
934 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
935
936 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK;
937 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
938
939 if( (ulAttr & SFGAO_HIDDEN) || /* hidden */
940 !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
941 return S_FALSE;
942
943 /* always include directories and links */
944 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
945 return S_OK;
946
947 /* if the application takes care of including the item we are done */
948 if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY &&
949 send_includeitem_notification(This->hwndOwner, pidl))
950 return S_OK;
951
952 /* Check if there is a mask to apply if not */
953 if(!fodInfos->ShellInfos.lpstrCurrentFilter || !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter))
954 return S_OK;
955
956 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
957 {
958 if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl))
959 {
960 if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
961 return S_OK;
962 }
963 }
964 return S_FALSE;
965
966 }
967
968 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
969 {
970 /* IUnknown */
971 IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
972 IShellBrowserImpl_ICommDlgBrowser_AddRef,
973 IShellBrowserImpl_ICommDlgBrowser_Release,
974 /* ICommDlgBrowser */
975 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
976 IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
977 IShellBrowserImpl_ICommDlgBrowser_IncludeObject
978 };
979
980
981
982
983 /*
984 * IServiceProvider
985 */
986
987 /***************************************************************************
988 * IShellBrowserImpl_IServiceProvider_QueryInterface
989 */
990 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
991 IServiceProvider *iface,
992 REFIID riid,
993 LPVOID *ppvObj)
994 {
995 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
996
997 FIXME("(%p)\n", This);
998
999 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
1000 }
1001
1002 /**************************************************************************
1003 * IShellBrowserImpl_IServiceProvider_AddRef
1004 */
1005 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
1006 {
1007 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1008
1009 FIXME("(%p)\n", This);
1010
1011 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
1012 }
1013
1014 /**************************************************************************
1015 * IShellBrowserImpl_IServiceProvider_Release
1016 */
1017 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
1018 {
1019 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1020
1021 FIXME("(%p)\n", This);
1022
1023 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
1024 }
1025
1026 /**************************************************************************
1027 * IShellBrowserImpl_IServiceProvider_Release
1028 *
1029 * NOTES
1030 * the w2k shellview asks for (guidService = SID_STopLevelBrowser,
1031 * riid = IShellBrowser) to call SendControlMsg ().
1032 *
1033 * FIXME
1034 * this is a hack!
1035 */
1036
1037 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
1038 IServiceProvider * iface,
1039 REFGUID guidService,
1040 REFIID riid,
1041 void** ppv)
1042 {
1043 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1044
1045 FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) );
1046
1047 *ppv = NULL;
1048 if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
1049 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppv);
1050
1051 FIXME("(%p) unknown interface requested\n", This);
1052 return E_NOINTERFACE;
1053
1054 }
1055
1056 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1057 {
1058 /* IUnknown */
1059 IShellBrowserImpl_IServiceProvider_QueryInterface,
1060 IShellBrowserImpl_IServiceProvider_AddRef,
1061 IShellBrowserImpl_IServiceProvider_Release,
1062 /* IServiceProvider */
1063 IShellBrowserImpl_IServiceProvider_QueryService
1064 };