[BROWSEUI] CISFBand: Handle DBID_SETWINDOWTHEME. CORE-14176
[reactos.git] / dll / win32 / browseui / shellbars / CISFBand.cpp
1 /*
2 * PROJECT: ReactOS shell extensions
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/shellext/qcklnch/CISFBand.cpp
5 * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension)
6 * PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
7 */
8
9 #include "shellbars.h"
10
11 #include <commoncontrols.h>
12 #include <shellapi.h>
13 #include <wingdi.h>
14 #include <uxtheme.h>
15
16 /*
17 TODO:
18 ** drag and drop support
19 ** tooltips
20 ** handle change notifications
21 ** Fix position of the items context menu
22 ** Implement responding to theme change
23 */
24
25 //*****************************************************************************************
26 // *** CISFBand ***
27
28 CISFBand::CISFBand() :
29 m_BandID(0),
30 m_pidl(NULL),
31 m_textFlag(true),
32 m_iconFlag(true),
33 m_QLaunch(false)
34 {
35 }
36
37 CISFBand::~CISFBand()
38 {
39 CloseDW(0);
40 }
41
42 // Toolbar
43 /*++
44 * @name CreateSimpleToolbar
45 *
46 * Creates a toolbar and fills it up with buttons for enumerated objects.
47 *
48 * @param hWndParent
49 * Handle to the parent window, which receives the appropriate messages from child toolbar.
50 *
51 * @return The error code.
52 *
53 *--*/
54 HRESULT CISFBand::CreateSimpleToolbar(HWND hWndParent)
55 {
56 // Declare and initialize local constants.
57 const DWORD buttonStyles = BTNS_AUTOSIZE;
58
59 // Create the toolbar.
60 m_hWnd = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
61 WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NORESIZE | CCS_NODIVIDER, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
62 hWndParent, NULL, 0, NULL);
63 if (m_hWnd == NULL)
64 return E_FAIL;
65
66 if (!m_textFlag)
67 SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
68
69 // Set the image list.
70 HIMAGELIST* piml;
71 HRESULT hr = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml);
72 if (FAILED_UNEXPECTEDLY(hr))
73 {
74 DestroyWindow();
75 return hr;
76 }
77 SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml);
78
79 // Enumerate objects
80 CComPtr<IEnumIDList> pEndl;
81 LPITEMIDLIST pidl;
82 STRRET stret;
83 hr = m_pISF->EnumObjects(0, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS, &pEndl);
84 if (FAILED_UNEXPECTEDLY(hr))
85 {
86 DestroyWindow();
87 return hr;
88 }
89
90 for (int i=0; pEndl->Next(1, &pidl, NULL) != S_FALSE; i++)
91 {
92 WCHAR sz[MAX_PATH];
93 int index = SHMapPIDLToSystemImageListIndex(m_pISF, pidl, NULL);
94 hr = m_pISF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &stret);
95 if (FAILED_UNEXPECTEDLY(hr))
96 {
97 StringCchCopyW(sz, MAX_PATH, L"<Unknown-Name>");
98 }
99 else
100 StrRetToBuf(&stret, pidl, sz, _countof(sz));
101
102 TBBUTTON tb = { MAKELONG(index, 0), i, TBSTATE_ENABLED, buttonStyles,{ 0 }, (DWORD_PTR)pidl, (INT_PTR)sz };
103 SendMessage(m_hWnd, TB_INSERTBUTTONW, i, (LPARAM)&tb);
104 }
105
106 // Resize the toolbar, and then show it.
107 SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0);
108
109 return hr;
110 }
111
112 /*****************************************************************************/
113
114 // *** IObjectWithSite ***
115 STDMETHODIMP CISFBand::SetSite(IUnknown *pUnkSite)
116 {
117 HRESULT hr;
118 HWND hwndParent;
119
120 TRACE("CISFBand::SetSite(0x%p)\n", pUnkSite);
121
122 hr = IUnknown_GetWindow(pUnkSite, &hwndParent);
123 if (FAILED(hr))
124 {
125 TRACE("Querying site window failed: 0x%x\n", hr);
126 return hr;
127 }
128 m_Site = pUnkSite;
129
130 hr = CreateSimpleToolbar(hwndParent);
131 if (FAILED_UNEXPECTEDLY(hr))
132 return hr;
133
134 return S_OK;
135 }
136
137 STDMETHODIMP CISFBand::GetSite(IN REFIID riid, OUT VOID **ppvSite)
138 {
139 TRACE("CISFBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
140
141 HRESULT hr;
142 if (m_Site != NULL)
143 {
144 hr = m_Site->QueryInterface(riid, ppvSite);
145 if (FAILED(hr)) return hr;
146 }
147
148 *ppvSite = NULL;
149 return E_FAIL;
150 }
151
152 /*****************************************************************************/
153 // *** IDeskBand ***
154 STDMETHODIMP CISFBand::GetWindow(OUT HWND *phwnd)
155 {
156 if (!m_hWnd)
157 return E_FAIL;
158 if (!phwnd)
159 return E_POINTER;
160 *phwnd = m_hWnd;
161
162 return S_OK;
163 }
164
165 STDMETHODIMP CISFBand::ContextSensitiveHelp(IN BOOL fEnterMode)
166 {
167 /* FIXME: Implement */
168 return E_NOTIMPL;
169 }
170
171 STDMETHODIMP CISFBand::ShowDW(IN BOOL bShow)
172 {
173 if (m_hWnd)
174 {
175 ShowWindow(bShow ? SW_SHOW : SW_HIDE);
176 return S_OK;
177 }
178
179 return E_FAIL;
180 }
181
182 STDMETHODIMP CISFBand::CloseDW(IN DWORD dwReserved)
183 {
184 if (m_hWnd)
185 {
186 ShowWindow(SW_HIDE);
187
188 TBBUTTON tb;
189 for (int i = 0; SendMessage(m_hWnd, TB_GETBUTTON, i, (LPARAM)&tb); i++)
190 {
191 CoTaskMemFree((LPITEMIDLIST)tb.dwData);
192 }
193
194 DestroyWindow();
195 m_hWnd = NULL;
196 return S_OK;
197 }
198
199 return E_FAIL;
200 }
201
202 STDMETHODIMP CISFBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
203 {
204 /* No need to implement this method */
205
206 return E_NOTIMPL;
207 }
208
209 STDMETHODIMP CISFBand::GetBandInfo(IN DWORD dwBandID, IN DWORD dwViewMode, IN OUT DESKBANDINFO *pdbi)
210 {
211 TRACE("CTaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, m_hWnd);
212
213 if (m_hWnd && pdbi)
214 {
215 m_BandID = dwBandID;
216
217 RECT actualRect;
218 POINTL actualSize;
219 POINTL idealSize;
220 POINTL maxSize;
221 POINTL itemSize;
222
223 GetWindowRect(&actualRect);
224 actualSize.x = actualRect.right - actualRect.left;
225 actualSize.y = actualRect.bottom - actualRect.top;
226
227 // Obtain the ideal size, to be used as min and max
228 SendMessageW(m_hWnd, TB_AUTOSIZE, 0, 0);
229 SendMessageW(m_hWnd, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&maxSize));
230
231 idealSize = maxSize;
232 SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&idealSize));
233
234 // Obtain the button size, to be used as the integral size
235 DWORD size = SendMessageW(m_hWnd, TB_GETBUTTONSIZE, 0, 0);
236 itemSize.x = GET_X_LPARAM(size);
237 itemSize.y = GET_Y_LPARAM(size);
238
239 if (pdbi->dwMask & DBIM_MINSIZE)
240 {
241 if (m_QLaunch)
242 pdbi->ptMinSize.x = idealSize.x;
243 else
244 pdbi->ptMinSize.x = -1;
245 pdbi->ptMinSize.y = idealSize.y;
246 }
247 if (pdbi->dwMask & DBIM_MAXSIZE)
248 {
249 pdbi->ptMaxSize = maxSize;
250 }
251 if (pdbi->dwMask & DBIM_INTEGRAL)
252 {
253 pdbi->ptIntegral = itemSize;
254 }
255 if (pdbi->dwMask & DBIM_ACTUAL)
256 {
257 pdbi->ptActual = actualSize;
258 }
259 if (pdbi->dwMask & DBIM_TITLE)
260 {
261 if (m_QLaunch || !ILGetDisplayNameEx(NULL, m_pidl, pdbi->wszTitle, ILGDN_INFOLDER))
262 {
263 pdbi->dwMask &= ~DBIM_TITLE;
264 }
265 }
266 if (pdbi->dwMask & DBIM_MODEFLAGS)
267 {
268 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT | DBIMF_USECHEVRON | DBIMF_NOMARGINS | DBIMF_BKCOLOR;
269 if (m_QLaunch)
270 {
271 pdbi->dwModeFlags |= DBIMF_ADDTOFRONT;
272 }
273 }
274 if (pdbi->dwMask & DBIM_BKCOLOR)
275 pdbi->dwMask &= ~DBIM_BKCOLOR;
276
277 return S_OK;
278 }
279
280 return E_FAIL;
281 }
282
283 /*****************************************************************************/
284 // *** IPersistStream ***
285 STDMETHODIMP CISFBand::GetClassID(OUT CLSID *pClassID)
286 {
287 *pClassID = CLSID_ISFBand;
288
289 return S_OK;
290 }
291
292 STDMETHODIMP CISFBand::IsDirty()
293 {
294 /* The object hasn't changed since the last save! */
295
296 return S_FALSE;
297 }
298
299 STDMETHODIMP CISFBand::Load(IN IStream *pStm)
300 {
301 TRACE("CISFBand::Load called\n");
302 /* Nothing to do */
303
304 return S_OK;
305 }
306
307 STDMETHODIMP CISFBand::Save(IN IStream *pStm, IN BOOL fClearDirty)
308 {
309 /* Nothing to do */
310
311 return S_OK;
312 }
313
314 STDMETHODIMP CISFBand::GetSizeMax(OUT ULARGE_INTEGER *pcbSize)
315 {
316 TRACE("CISFBand::GetSizeMax called\n");
317
318 return S_OK;
319 }
320
321 /*****************************************************************************/
322 // *** IWinEventHandler ***
323 STDMETHODIMP CISFBand::ContainsWindow(IN HWND hWnd)
324 {
325 if (hWnd == m_hWnd || IsChild(hWnd))
326 {
327 TRACE("CISFBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
328 return S_OK;
329 }
330
331 return S_FALSE;
332 }
333
334 STDMETHODIMP CISFBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
335 {
336 switch (uMsg)
337 {
338 case WM_COMMAND:
339 {
340 TBBUTTON tb;
341 bool chk = SendMessage(m_hWnd, TB_GETBUTTON, LOWORD(wParam), (LPARAM)&tb);
342 if (chk)
343 SHInvokeDefaultCommand(m_hWnd, m_pISF, (LPITEMIDLIST)tb.dwData);
344
345 *theResult = TRUE;
346 break;
347 }
348 case WM_NOTIFY:
349 {
350 switch (((LPNMHDR)lParam)->code)
351 {
352 case NM_RCLICK:
353 {
354 HRESULT hr;
355 POINT pt = ((LPNMMOUSE)lParam)->pt;
356 CComPtr<IContextMenu> picm;
357 HMENU fmenu = CreatePopupMenu();
358 TBBUTTON tb;
359
360 bool chk = SendMessage(m_hWnd, TB_GETBUTTON, ((LPNMMOUSE)lParam)->dwItemSpec, (LPARAM)&tb);
361 LPITEMIDLIST pidl = (LPITEMIDLIST)tb.dwData;
362
363 if (chk)
364 {
365 ClientToScreen(&pt);
366 hr = m_pISF->GetUIObjectOf(m_hWnd, 1, &pidl, IID_NULL_PPV_ARG(IContextMenu, &picm));
367 if (FAILED_UNEXPECTEDLY(hr))
368 return hr;
369
370 hr = picm->QueryContextMenu(fmenu, 0, 1, 0x7FFF, CMF_DEFAULTONLY);
371 if (FAILED_UNEXPECTEDLY(hr))
372 return hr;
373
374 int id = TrackPopupMenuEx(fmenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RETURNCMD, pt.x, pt.y, m_hWnd, 0);
375 if (id > 0)
376 {
377 CMINVOKECOMMANDINFOEX info = { 0 };
378 info.cbSize = sizeof(info);
379 info.fMask = CMIC_MASK_PTINVOKE;
380 if (GetKeyState(VK_CONTROL) < 0)
381 {
382 info.fMask |= CMIC_MASK_CONTROL_DOWN;
383 }
384 if (GetKeyState(VK_SHIFT) < 0)
385 {
386 info.fMask |= CMIC_MASK_SHIFT_DOWN;
387 }
388 info.hwnd = m_hWnd;
389 info.lpVerb = MAKEINTRESOURCEA(id - 1);
390 info.nShow = SW_SHOWNORMAL;
391 info.ptInvoke = pt;
392 picm->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
393 }
394 }
395 DestroyMenu(fmenu);
396
397 *theResult = TRUE;
398 break;
399 }
400 default:
401 *theResult = FALSE;
402 }
403
404 break;
405 }
406 default:
407 *theResult = FALSE;
408 }
409
410 return S_OK;
411 }
412
413 STDMETHODIMP CISFBand::IsWindowOwner(HWND hWnd)
414 {
415 return (hWnd == m_hWnd) ? S_OK : S_FALSE;
416 }
417
418 /*****************************************************************************/
419 // *** IOleCommandTarget methods ***
420 STDMETHODIMP CISFBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
421 {
422 UNIMPLEMENTED;
423
424 return E_NOTIMPL;
425 }
426
427 STDMETHODIMP CISFBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
428 {
429 if (IsEqualIID(*pguidCmdGroup, IID_IBandSite))
430 {
431 return S_OK;
432 }
433
434 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand))
435 {
436 if (nCmdID == DBID_SETWINDOWTHEME)
437 {
438 if (pvaIn && V_VT(pvaIn) == VT_BSTR && V_BSTR(pvaIn))
439 {
440 SetWindowTheme(m_hWnd, V_BSTR(pvaIn), NULL);
441 }
442 }
443 return S_OK;
444 }
445
446 UNIMPLEMENTED;
447
448 return E_NOTIMPL;
449 }
450
451 /*****************************************************************************/
452 // *** IShellFolderBand ***
453 STDMETHODIMP CISFBand::GetBandInfoSFB(PBANDINFOSFB pbi)
454 {
455 if (pbi->dwMask == ISFB_MASK_IDLIST)
456 {
457 pbi->pidl = ILClone(m_pidl);
458 if (!pbi->pidl)
459 return E_OUTOFMEMORY;
460 return S_OK;
461 }
462
463 return E_NOTIMPL;
464 }
465
466 STDMETHODIMP CISFBand::InitializeSFB(IShellFolder *psf, PCIDLIST_ABSOLUTE pidl)
467 {
468 HRESULT hr;
469
470 if (!psf && !pidl)
471 return E_INVALIDARG;
472
473 if (psf && pidl)
474 return E_INVALIDARG;
475
476 if (pidl != NULL)
477 {
478 CComPtr<IShellFolder> psfDesktop;
479 hr = SHGetDesktopFolder(&psfDesktop);
480 if (FAILED_UNEXPECTEDLY(hr))
481 return hr;
482
483 if (_ILIsDesktop(pidl))
484 {
485 m_pISF = psfDesktop;
486 }
487 else
488 {
489 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &m_pISF));
490 if (FAILED_UNEXPECTEDLY(hr))
491 return hr;
492 }
493
494 m_pidl = ILClone(pidl);
495 }
496
497 if (psf != NULL)
498 {
499 CComPtr<IPersistFolder2> ppf2;
500 hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
501 if (FAILED_UNEXPECTEDLY(hr))
502 return hr;
503
504 hr = ppf2->GetCurFolder(&m_pidl);
505 if (FAILED_UNEXPECTEDLY(hr))
506 return hr;
507
508 m_pISF = psf;
509 }
510
511 return S_OK;
512 }
513
514 STDMETHODIMP CISFBand::SetBandInfoSFB( PBANDINFOSFB pbi)
515 {
516 if ((pbi->dwMask & ISFB_MASK_STATE) &&
517 (pbi->dwState & ISFB_STATE_QLINKSMODE) &&
518 (pbi->dwStateMask & ISFB_STATE_QLINKSMODE))
519 {
520 m_QLaunch = true;
521 m_textFlag = false;
522 if (m_hWnd)
523 SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
524 }
525
526 return E_NOTIMPL;
527 }
528
529 /*****************************************************************************/
530 // *** IContextMenu ***
531 STDMETHODIMP CISFBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
532 {
533 /*HRESULT hr = E_INVALIDARG;
534
535 if (idCmd == IDM_DISPLAY)
536 {
537 switch (uFlags)
538 {
539 case GCS_HELPTEXTW:
540 // Only useful for pre-Vista versions of Windows that
541 // have a Status bar.
542 hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName),
543 cchMax,
544 L"Display File Name");
545 break;
546
547 case GCS_VERBW:
548 // GCS_VERBW is an optional feature that enables a caller
549 // to discover the canonical name for the verb that is passed in
550 // through idCommand.
551 hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName),
552 cchMax,
553 L"DisplayFileName");
554 break;
555 }
556 }
557 return hr; */
558
559 return S_OK;
560 }
561
562 STDMETHODIMP CISFBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
563 {
564 if (!HIWORD(pici->lpVerb))
565 {
566 switch (LOWORD(pici->lpVerb))
567 {
568 case IDM_LARGE_ICONS:
569 {
570 m_iconFlag = false;
571
572 HIMAGELIST* piml = (HIMAGELIST*) SendMessage(m_hWnd, TB_GETIMAGELIST, 0, 0);
573 HRESULT hr = SHGetImageList(SHIL_LARGE, IID_IImageList, (void**)&piml);
574 if (FAILED_UNEXPECTEDLY(hr)) return hr;
575 SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml);
576 hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL);
577 if (FAILED_UNEXPECTEDLY(hr)) return hr;
578 break;
579 }
580 case IDM_SMALL_ICONS:
581 {
582 m_iconFlag = true;
583
584 HIMAGELIST* piml = (HIMAGELIST*)SendMessage(m_hWnd, TB_GETIMAGELIST, 0, 0);
585 HRESULT hr = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml);
586 if (FAILED_UNEXPECTEDLY(hr)) return hr;
587 SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml);
588 hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL);
589 if (FAILED_UNEXPECTEDLY(hr)) return hr;
590 break;
591 }
592 case IDM_OPEN_FOLDER:
593 {
594 SHELLEXECUTEINFO shexinfo;
595
596 memset(&shexinfo, 0x0, sizeof(shexinfo));
597
598 shexinfo.cbSize = sizeof(shexinfo);
599 shexinfo.fMask = SEE_MASK_IDLIST;
600 shexinfo.lpVerb = _T("open");
601 shexinfo.lpIDList = m_pidl;
602 shexinfo.nShow = SW_SHOW;
603
604 if (!ShellExecuteEx(&shexinfo))
605 return E_FAIL;
606
607 break;
608 }
609 case IDM_SHOW_TEXT:
610 {
611 if (m_textFlag)
612 {
613 m_textFlag = false;
614 SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
615 HRESULT hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL);
616 if (FAILED_UNEXPECTEDLY(hr)) return hr;
617 }
618 else
619 {
620 m_textFlag = true;
621 SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, 0);
622 HRESULT hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL);
623 if (FAILED_UNEXPECTEDLY(hr)) return hr;
624 }
625 break;
626 }
627 default:
628 return E_FAIL;
629 }
630 }
631
632 return S_OK;
633 }
634
635 STDMETHODIMP CISFBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
636 {
637 HMENU qMenu = LoadMenu(GetModuleHandleW(L"browseui.dll"), MAKEINTRESOURCE(IDM_POPUPMENU));
638
639 if(m_textFlag)
640 CheckMenuItem(qMenu, IDM_SHOW_TEXT, MF_CHECKED);
641 else
642 CheckMenuItem(qMenu, IDM_SHOW_TEXT, MF_UNCHECKED);
643
644 if (m_iconFlag)
645 {
646 CheckMenuItem(qMenu, IDM_SMALL_ICONS, MF_CHECKED);
647 CheckMenuItem(qMenu, IDM_LARGE_ICONS, MF_UNCHECKED);
648 }
649 else
650 {
651 CheckMenuItem(qMenu, IDM_LARGE_ICONS, MF_CHECKED);
652 CheckMenuItem(qMenu, IDM_SMALL_ICONS, MF_UNCHECKED);
653 }
654
655 if (_ILIsDesktop(m_pidl))
656 DeleteMenu(qMenu, IDM_OPEN_FOLDER, MF_BYCOMMAND);
657
658 UINT idMax = Shell_MergeMenus(hmenu, GetSubMenu(qMenu, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
659 DestroyMenu(qMenu);
660 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idMax - idCmdFirst +1));
661 }
662
663 /*****************************************************************************/
664 // C Constructor
665 extern "C"
666 HRESULT WINAPI RSHELL_CISFBand_CreateInstance(REFIID riid, void** ppv)
667 {
668 return ShellObjectCreator<CISFBand>(riid, ppv);
669 }
670