Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentbsite.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS Explorer 00003 * 00004 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <precomp.h> 00022 00023 /***************************************************************************** 00024 ** ITrayBandSite ************************************************************ 00025 *****************************************************************************/ 00026 00027 static const ITrayBandSiteVtbl ITrayBandSiteImpl_Vtbl; 00028 static const IBandSiteVtbl IBandSiteImpl_Vtbl; 00029 00030 typedef struct 00031 { 00032 const ITrayBandSiteVtbl *lpVtbl; 00033 const IBandSiteVtbl *lpBandSiteVtbl; 00034 LONG Ref; 00035 00036 ITrayWindow *Tray; 00037 00038 IUnknown *punkInner; 00039 IBandSite *BandSite; 00040 ITaskBand *TaskBand; 00041 IWinEventHandler *WindowEventHandler; 00042 IContextMenu *ContextMenu; 00043 00044 HWND hWndRebar; 00045 00046 union 00047 { 00048 DWORD dwFlags; 00049 struct 00050 { 00051 DWORD Locked : 1; 00052 }; 00053 }; 00054 } ITrayBandSiteImpl; 00055 00056 static HRESULT 00057 ITrayBandSiteImpl_Update(IN OUT ITrayBandSiteImpl *This); 00058 00059 static IUnknown * 00060 IUnknown_from_ITrayBandSiteImpl(ITrayBandSiteImpl *This) 00061 { 00062 return (IUnknown *)&This->lpVtbl; 00063 } 00064 00065 IMPL_CASTS(ITrayBandSite, ITrayBandSite, lpVtbl) 00066 IMPL_CASTS(IBandSite, ITrayBandSite, lpBandSiteVtbl) 00067 00068 static ULONG STDMETHODCALLTYPE 00069 ITrayBandSiteImpl_AddRef(IN OUT ITrayBandSite *iface) 00070 { 00071 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00072 00073 return InterlockedIncrement(&This->Ref); 00074 } 00075 00076 static VOID 00077 ITrayBandSiteImpl_Free(IN OUT ITrayBandSiteImpl *This) 00078 { 00079 if (This->BandSite != NULL) 00080 { 00081 IBandSite_Release(This->BandSite); 00082 This->BandSite = NULL; 00083 } 00084 00085 if (This->WindowEventHandler != NULL) 00086 { 00087 IWinEventHandler_Release(This->WindowEventHandler); 00088 This->WindowEventHandler = NULL; 00089 } 00090 00091 if (This->ContextMenu != NULL) 00092 { 00093 IContextMenu_Release(This->ContextMenu); 00094 This->ContextMenu = NULL; 00095 } 00096 00097 if (This->punkInner != NULL) 00098 { 00099 IUnknown_Release(This->punkInner); 00100 This->punkInner = NULL; 00101 } 00102 00103 HeapFree(hProcessHeap, 00104 0, 00105 This); 00106 } 00107 00108 static ULONG STDMETHODCALLTYPE 00109 ITrayBandSiteImpl_Release(IN OUT ITrayBandSite *iface) 00110 { 00111 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00112 ULONG Ret; 00113 00114 Ret = InterlockedDecrement(&This->Ref); 00115 00116 if (Ret == 0) 00117 ITrayBandSiteImpl_Free(This); 00118 00119 return Ret; 00120 } 00121 00122 static HRESULT STDMETHODCALLTYPE 00123 ITrayBandSiteImpl_QueryInterface(IN OUT ITrayBandSite *iface, 00124 IN REFIID riid, 00125 OUT LPVOID *ppvObj) 00126 { 00127 ITrayBandSiteImpl *This; 00128 00129 if (ppvObj == NULL) 00130 return E_POINTER; 00131 00132 This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00133 00134 if (IsEqualIID(riid, 00135 &IID_IUnknown) || 00136 IsEqualIID(riid, 00137 &IID_IBandSiteStreamCallback)) 00138 { 00139 /* NOTE: IID_IBandSiteStreamCallback is queried by the shell, we 00140 implement this interface directly */ 00141 *ppvObj = IUnknown_from_ITrayBandSiteImpl(This); 00142 } 00143 else if (IsEqualIID(riid, 00144 &IID_IBandSite)) 00145 { 00146 *ppvObj = IBandSite_from_ITrayBandSiteImpl(This); 00147 } 00148 else if (IsEqualIID(riid, 00149 &IID_IWinEventHandler)) 00150 { 00151 DbgPrint("ITaskBandSite: IWinEventHandler queried!\n"); 00152 *ppvObj = NULL; 00153 return E_NOINTERFACE; 00154 } 00155 else if (This->punkInner != NULL) 00156 { 00157 return IUnknown_QueryInterface(This->punkInner, 00158 riid, 00159 ppvObj); 00160 } 00161 else 00162 { 00163 *ppvObj = NULL; 00164 return E_NOINTERFACE; 00165 } 00166 00167 ITrayBandSiteImpl_AddRef(iface); 00168 return S_OK; 00169 } 00170 00171 static HRESULT STDMETHODCALLTYPE 00172 ITrayBandSiteImpl_OnLoad(IN OUT ITrayBandSite *iface, 00173 IN OUT IStream *pStm, 00174 IN REFIID riid, 00175 OUT PVOID *pvObj) 00176 { 00177 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00178 LARGE_INTEGER liPosZero; 00179 ULARGE_INTEGER liCurrent; 00180 CLSID clsid; 00181 ULONG ulRead; 00182 HRESULT hRet; 00183 00184 /* NOTE: Callback routine called by the shell while loading the task band 00185 stream. We use it to intercept the default behavior when the task 00186 band is loaded from the stream. 00187 00188 NOTE: riid always points to IID_IUnknown! This is because the shell hasn't 00189 read anything from the stream and therefore doesn't know what CLSID 00190 it's dealing with. We'll have to find it out ourselves by reading 00191 the GUID from the stream. */ 00192 00193 /* Read the current position of the stream, we'll have to reset it everytime 00194 we read a CLSID that's not the task band... */ 00195 ZeroMemory(&liPosZero, 00196 sizeof(liPosZero)); 00197 hRet = IStream_Seek(pStm, 00198 liPosZero, 00199 STREAM_SEEK_CUR, 00200 &liCurrent); 00201 00202 if (SUCCEEDED(hRet)) 00203 { 00204 /* Now let's read the CLSID from the stream and see if it's our task band */ 00205 #if defined(IStream_Read) 00206 hRet = IStream_Read(pStm, 00207 &clsid, 00208 sizeof(clsid), 00209 &ulRead); 00210 #else 00211 ulRead = sizeof(clsid); 00212 hRet = IStream_Read(pStm, 00213 &clsid, 00214 sizeof(clsid)); 00215 #endif 00216 if (SUCCEEDED(hRet) && ulRead == sizeof(clsid)) 00217 { 00218 if (IsEqualGUID(&clsid, 00219 &CLSID_ITaskBand)) 00220 { 00221 ASSERT(This->TaskBand != NULL); 00222 /* We're trying to load the task band! Let's create it... */ 00223 00224 hRet = ITaskBand_QueryInterface(This->TaskBand, 00225 riid, 00226 pvObj); 00227 if (SUCCEEDED(hRet)) 00228 { 00229 /* Load the stream */ 00230 DbgPrint("IBandSiteStreamCallback::OnLoad intercepted the task band CLSID!\n"); 00231 } 00232 00233 return hRet; 00234 } 00235 } 00236 } 00237 00238 /* Reset the position and let the shell do all the work for us */ 00239 hRet = IStream_Seek(pStm, 00240 *(LARGE_INTEGER*)&liCurrent, 00241 STREAM_SEEK_SET, 00242 NULL); 00243 if (SUCCEEDED(hRet)) 00244 { 00245 /* Let the shell handle everything else for us :) */ 00246 hRet = OleLoadFromStream(pStm, 00247 riid, 00248 pvObj); 00249 } 00250 00251 if (!SUCCEEDED(hRet)) 00252 { 00253 DbgPrint("IBandSiteStreamCallback::OnLoad(0x%p, 0x%p, 0x%p) returns 0x%x\n", pStm, riid, pvObj, hRet); 00254 } 00255 00256 return hRet; 00257 } 00258 00259 static HRESULT STDMETHODCALLTYPE 00260 ITrayBandSiteImpl_OnSave(IN OUT ITrayBandSite *iface, 00261 IN OUT IUnknown *pUnk, 00262 IN OUT IStream *pStm) 00263 { 00264 /* NOTE: Callback routine called by the shell while saving the task band 00265 stream. We use it to intercept the default behavior when the task 00266 band is saved to the stream */ 00267 /* FIXME: Implement */ 00268 DbgPrint("IBandSiteStreamCallback::OnSave(0x%p, 0x%p) returns E_NOTIMPL\n", pUnk, pStm); 00269 return E_NOTIMPL; 00270 } 00271 00272 static HRESULT 00273 IsSameObject(IN IUnknown *punk1, 00274 IN IUnknown *punk2) 00275 { 00276 HRESULT hRet; 00277 00278 hRet = IUnknown_QueryInterface(punk1, 00279 &IID_IUnknown, 00280 (PVOID*)&punk1); 00281 if (!SUCCEEDED(hRet)) 00282 return hRet; 00283 00284 hRet = IUnknown_QueryInterface(punk2, 00285 &IID_IUnknown, 00286 (PVOID*)&punk2); 00287 IUnknown_Release(punk1); 00288 00289 if (!SUCCEEDED(hRet)) 00290 return hRet; 00291 00292 IUnknown_Release(punk2); 00293 00294 /* We're dealing with the same object if the IUnknown pointers are equal */ 00295 return (punk1 == punk2) ? S_OK : S_FALSE; 00296 } 00297 00298 static HRESULT STDMETHODCALLTYPE 00299 ITrayBandSiteImpl_IsTaskBand(IN OUT ITrayBandSite *iface, 00300 IN IUnknown *punk) 00301 { 00302 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00303 return IsSameObject((IUnknown *)This->BandSite, 00304 punk); 00305 } 00306 00307 static HRESULT STDMETHODCALLTYPE 00308 ITrayBandSiteImpl_ProcessMessage(IN OUT ITrayBandSite *iface, 00309 IN HWND hWnd, 00310 IN UINT uMsg, 00311 IN WPARAM wParam, 00312 IN LPARAM lParam, 00313 OUT LRESULT *plResult) 00314 { 00315 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00316 HRESULT hRet; 00317 00318 ASSERT(This->hWndRebar != NULL); 00319 00320 /* Custom task band behavior */ 00321 switch (uMsg) 00322 { 00323 case WM_NOTIFY: 00324 { 00325 const NMHDR *nmh = (const NMHDR *)lParam; 00326 00327 if (nmh->hwndFrom == This->hWndRebar) 00328 { 00329 switch (nmh->code) 00330 { 00331 case NM_NCHITTEST: 00332 { 00333 LPNMMOUSE nmm = (LPNMMOUSE)lParam; 00334 00335 if (nmm->dwHitInfo == RBHT_CLIENT || nmm->dwHitInfo == RBHT_NOWHERE || 00336 nmm->dwItemSpec == (DWORD_PTR)-1) 00337 { 00338 /* Make the rebar control appear transparent so the user 00339 can drag the tray window */ 00340 *plResult = HTTRANSPARENT; 00341 } 00342 return S_OK; 00343 } 00344 00345 case RBN_MINMAX: 00346 /* Deny if an Administrator disabled this "feature" */ 00347 *plResult = (SHRestricted(REST_NOMOVINGBAND) != 0); 00348 return S_OK; 00349 } 00350 } 00351 00352 //DbgPrint("ITrayBandSite::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u...\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code); 00353 break; 00354 } 00355 }; 00356 00357 /* Forward to the shell's IWinEventHandler interface to get the default 00358 shell behavior! */ 00359 if (This->WindowEventHandler != NULL) 00360 { 00361 /*DbgPrint("Calling IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p) This->hWndRebar=0x%p\n", hWnd, uMsg, wParam, lParam, plResult, This->hWndRebar);*/ 00362 hRet = IWinEventHandler_OnWinEvent(This->WindowEventHandler, 00363 hWnd, 00364 uMsg, 00365 wParam, 00366 lParam, 00367 plResult); 00368 if (!SUCCEEDED(hRet)) 00369 { 00370 if (uMsg == WM_NOTIFY) 00371 { 00372 const NMHDR *nmh = (const NMHDR *)lParam; 00373 DbgPrint("ITrayBandSite->IWinEventHandler::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u returned 0x%x\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code, hRet); 00374 } 00375 else 00376 { 00377 DbgPrint("ITrayBandSite->IWinEventHandler::ProcessMessage(0x%p,0x%x,0x%p,0x%p,0x%p->0x%p) returned: 0x%x\n", hWnd, uMsg, wParam, lParam, plResult, *plResult, hRet); 00378 } 00379 } 00380 } 00381 else 00382 hRet = E_FAIL; 00383 00384 return hRet; 00385 } 00386 00387 static HRESULT STDMETHODCALLTYPE 00388 ITrayBandSiteImpl_AddContextMenus(IN OUT ITrayBandSite *iface, 00389 IN HMENU hmenu, 00390 IN UINT indexMenu, 00391 IN UINT idCmdFirst, 00392 IN UINT idCmdLast, 00393 IN UINT uFlags, 00394 OUT IContextMenu **ppcm) 00395 { 00396 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00397 IShellService *pSs; 00398 HRESULT hRet; 00399 00400 if (This->ContextMenu == NULL) 00401 { 00402 /* Cache the context menu so we don't need to CoCreateInstance all the time... */ 00403 hRet = CoCreateInstance(&CLSID_IShellBandSiteMenu, 00404 NULL, 00405 CLSCTX_INPROC_SERVER, 00406 &IID_IShellService, 00407 (PVOID*)&pSs); 00408 DbgPrint("CoCreateInstance(CLSID_IShellBandSiteMenu) for IShellService returned: 0x%x\n", hRet); 00409 if (!SUCCEEDED(hRet)) 00410 return hRet; 00411 00412 hRet = IShellService_SetOwner(pSs, 00413 IUnknown_from_ITrayBandSiteImpl(This)); 00414 if (!SUCCEEDED(hRet)) 00415 { 00416 IShellService_Release(pSs); 00417 return hRet; 00418 } 00419 00420 hRet = IShellService_QueryInterface(pSs, 00421 &IID_IContextMenu, 00422 (PVOID*)&This->ContextMenu); 00423 00424 IShellService_Release(pSs); 00425 00426 if (!SUCCEEDED(hRet)) 00427 return hRet; 00428 } 00429 00430 if (ppcm != NULL) 00431 { 00432 IContextMenu_AddRef(This->ContextMenu); 00433 *ppcm = This->ContextMenu; 00434 } 00435 00436 /* Add the menu items */ 00437 return IContextMenu_QueryContextMenu(This->ContextMenu, 00438 hmenu, 00439 indexMenu, 00440 idCmdFirst, 00441 idCmdLast, 00442 uFlags); 00443 } 00444 00445 static HRESULT STDMETHODCALLTYPE 00446 ITrayBandSiteImpl_Lock(IN OUT ITrayBandSite *iface, 00447 IN BOOL bLock) 00448 { 00449 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_ITrayBandSite(iface); 00450 BOOL bPrevLocked = This->Locked; 00451 BANDSITEINFO bsi; 00452 HRESULT hRet; 00453 00454 ASSERT(This->BandSite != NULL); 00455 00456 if (bPrevLocked != bLock) 00457 { 00458 This->Locked = bLock; 00459 00460 bsi.dwMask = BSIM_STYLE; 00461 bsi.dwStyle = (This->Locked ? BSIS_LOCKED | BSIS_NOGRIPPER : BSIS_AUTOGRIPPER); 00462 00463 hRet = IBandSite_SetBandSiteInfo(This->BandSite, 00464 &bsi); 00465 if (SUCCEEDED(hRet)) 00466 { 00467 hRet = ITrayBandSiteImpl_Update(This); 00468 } 00469 00470 return hRet; 00471 } 00472 00473 return S_FALSE; 00474 } 00475 00476 static const ITrayBandSiteVtbl ITrayBandSiteImpl_Vtbl = 00477 { 00478 /*** IUnknown methods ***/ 00479 ITrayBandSiteImpl_QueryInterface, 00480 ITrayBandSiteImpl_AddRef, 00481 ITrayBandSiteImpl_Release, 00482 /*** IBandSiteStreamCallback methods ***/ 00483 ITrayBandSiteImpl_OnLoad, 00484 ITrayBandSiteImpl_OnSave, 00485 /*** ITrayBandSite methods ***/ 00486 ITrayBandSiteImpl_IsTaskBand, 00487 ITrayBandSiteImpl_ProcessMessage, 00488 ITrayBandSiteImpl_AddContextMenus, 00489 ITrayBandSiteImpl_Lock 00490 }; 00491 00492 /*******************************************************************/ 00493 00494 METHOD_IUNKNOWN_INHERITED_ADDREF(IBandSite, ITrayBandSite) 00495 METHOD_IUNKNOWN_INHERITED_RELEASE(IBandSite, ITrayBandSite) 00496 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IBandSite, ITrayBandSite) 00497 00498 static HRESULT STDMETHODCALLTYPE 00499 ITrayBandSiteImpl_AddBand(IN OUT IBandSite *iface, 00500 IN IUnknown *punk) 00501 { 00502 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00503 IOleCommandTarget *pOct; 00504 HRESULT hRet; 00505 00506 hRet = IUnknown_QueryInterface(punk, 00507 &IID_IOleCommandTarget, 00508 (PVOID*)&pOct); 00509 if (SUCCEEDED(hRet)) 00510 { 00511 /* Send the DBID_DELAYINIT command to initialize the band to be added */ 00512 /* FIXME: Should be delayed */ 00513 IOleCommandTarget_Exec(pOct, 00514 &IID_IDeskBand, 00515 DBID_DELAYINIT, 00516 0, 00517 NULL, 00518 NULL); 00519 00520 IOleCommandTarget_Release(pOct); 00521 } 00522 00523 return IBandSite_AddBand(This->BandSite, 00524 punk); 00525 } 00526 00527 static HRESULT STDMETHODCALLTYPE 00528 ITrayBandSiteImpl_EnumBands(IN OUT IBandSite *iface, 00529 IN UINT uBand, 00530 OUT DWORD *pdwBandID) 00531 { 00532 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00533 return IBandSite_EnumBands(This->BandSite, 00534 uBand, 00535 pdwBandID); 00536 } 00537 00538 static HRESULT STDMETHODCALLTYPE 00539 ITrayBandSiteImpl_QueryBand(IN OUT IBandSite *iface, 00540 IN DWORD dwBandID, 00541 OUT IDeskBand **ppstb, 00542 OUT DWORD *pdwState, 00543 OUT LPWSTR pszName, 00544 IN int cchName) 00545 { 00546 HRESULT hRet; 00547 IDeskBand *pstb = NULL; 00548 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00549 00550 hRet = IBandSite_QueryBand(This->BandSite, 00551 dwBandID, 00552 &pstb, 00553 pdwState, 00554 pszName, 00555 cchName); 00556 00557 if (SUCCEEDED(hRet)) 00558 { 00559 hRet = IsSameObject((IUnknown *)pstb, 00560 (IUnknown *)This->TaskBand); 00561 if (hRet == S_OK) 00562 { 00563 /* Add the BSSF_UNDELETEABLE flag to pdwState because the task bar band shouldn't be deletable */ 00564 if (pdwState != NULL) 00565 *pdwState |= BSSF_UNDELETEABLE; 00566 } 00567 else if (!SUCCEEDED(hRet)) 00568 { 00569 IDeskBand_Release(pstb); 00570 pstb = NULL; 00571 } 00572 00573 if (ppstb != NULL) 00574 *ppstb = pstb; 00575 } 00576 else if (ppstb != NULL) 00577 *ppstb = NULL; 00578 00579 return hRet; 00580 } 00581 00582 static HRESULT STDMETHODCALLTYPE 00583 ITrayBandSiteImpl_SetBandState(IN OUT IBandSite *iface, 00584 IN DWORD dwBandID, 00585 IN DWORD dwMask, 00586 IN DWORD dwState) 00587 { 00588 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00589 return IBandSite_SetBandState(This->BandSite, 00590 dwBandID, 00591 dwMask, 00592 dwState); 00593 } 00594 00595 static HRESULT STDMETHODCALLTYPE 00596 ITrayBandSiteImpl_RemoveBand(IN OUT IBandSite *iface, 00597 IN DWORD dwBandID) 00598 { 00599 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00600 return IBandSite_RemoveBand(This->BandSite, 00601 dwBandID); 00602 } 00603 00604 static HRESULT STDMETHODCALLTYPE 00605 ITrayBandSiteImpl_GetBandObject(IN OUT IBandSite *iface, 00606 IN DWORD dwBandID, 00607 IN REFIID riid, 00608 OUT VOID **ppv) 00609 { 00610 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00611 return IBandSite_GetBandObject(This->BandSite, 00612 dwBandID, 00613 riid, 00614 ppv); 00615 } 00616 00617 static HRESULT STDMETHODCALLTYPE 00618 ITrayBandSiteImpl_SetBandSiteInfo(IN OUT IBandSite *iface, 00619 IN const BANDSITEINFO *pbsinfo) 00620 { 00621 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00622 return IBandSite_SetBandSiteInfo(This->BandSite, 00623 pbsinfo); 00624 } 00625 00626 static HRESULT STDMETHODCALLTYPE 00627 ITrayBandSiteImpl_GetBandSiteInfo(IN OUT IBandSite *iface, 00628 IN OUT BANDSITEINFO *pbsinfo) 00629 { 00630 ITrayBandSiteImpl *This = ITrayBandSiteImpl_from_IBandSite(iface); 00631 return IBandSite_GetBandSiteInfo(This->BandSite, 00632 pbsinfo); 00633 } 00634 00635 static const IBandSiteVtbl IBandSiteImpl_Vtbl = 00636 { 00637 /*** IUnknown methods ***/ 00638 METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IBandSite, ITrayBandSite), 00639 METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IBandSite, ITrayBandSite), 00640 METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IBandSite, ITrayBandSite), 00641 /*** IBandSite methods ***/ 00642 ITrayBandSiteImpl_AddBand, 00643 ITrayBandSiteImpl_EnumBands, 00644 ITrayBandSiteImpl_QueryBand, 00645 ITrayBandSiteImpl_SetBandState, 00646 ITrayBandSiteImpl_RemoveBand, 00647 ITrayBandSiteImpl_GetBandObject, 00648 ITrayBandSiteImpl_SetBandSiteInfo, 00649 ITrayBandSiteImpl_GetBandSiteInfo, 00650 }; 00651 00652 static BOOL 00653 ITrayBandSiteImpl_HasTaskBand(IN OUT ITrayBandSiteImpl *This) 00654 { 00655 ASSERT(This->TaskBand != NULL); 00656 00657 return SUCCEEDED(ITaskBand_GetRebarBandID(This->TaskBand, 00658 NULL)); 00659 } 00660 00661 static HRESULT 00662 ITrayBandSiteImpl_AddTaskBand(IN OUT ITrayBandSiteImpl *This) 00663 { 00664 #if 0 00665 /* FIXME: This is the code for the simple taskbar */ 00666 IObjectWithSite *pOws; 00667 HRESULT hRet; 00668 00669 hRet = ITaskBand_QueryInterface(This->TaskBand, 00670 &IID_IObjectWithSite, 00671 (PVOID*)&pOws); 00672 if (SUCCEEDED(hRet)) 00673 { 00674 hRet = IObjectWithSite_SetSite(pOws, 00675 (IUnknown *)This->TaskBand); 00676 00677 IObjectWithSite_Release(pOws); 00678 } 00679 00680 return hRet; 00681 #else 00682 if (!ITrayBandSiteImpl_HasTaskBand(This)) 00683 { 00684 return IBandSite_AddBand(This->BandSite, 00685 (IUnknown *)This->TaskBand); 00686 } 00687 00688 return S_OK; 00689 #endif 00690 } 00691 00692 static HRESULT 00693 ITrayBandSiteImpl_Update(IN OUT ITrayBandSiteImpl *This) 00694 { 00695 IOleCommandTarget *pOct; 00696 HRESULT hRet; 00697 00698 hRet = IUnknown_QueryInterface(This->punkInner, 00699 &IID_IOleCommandTarget, 00700 (PVOID*)&pOct); 00701 if (SUCCEEDED(hRet)) 00702 { 00703 /* Send the DBID_BANDINFOCHANGED command to update the band site */ 00704 hRet = IOleCommandTarget_Exec(pOct, 00705 &IID_IDeskBand, 00706 DBID_BANDINFOCHANGED, 00707 0, 00708 NULL, 00709 NULL); 00710 00711 IOleCommandTarget_Release(pOct); 00712 } 00713 00714 return hRet; 00715 } 00716 00717 static VOID 00718 ITrayBandSiteImpl_BroadcastOleCommandExec(IN OUT ITrayBandSiteImpl *This, 00719 const GUID *pguidCmdGroup, 00720 DWORD nCmdID, 00721 DWORD nCmdExecOpt, 00722 VARIANTARG *pvaIn, 00723 VARIANTARG *pvaOut) 00724 { 00725 IOleCommandTarget *pOct; 00726 DWORD dwBandID; 00727 UINT uBand = 0; 00728 00729 /* Enumerate all bands */ 00730 while (SUCCEEDED(IBandSite_EnumBands(This->BandSite, 00731 uBand, 00732 &dwBandID))) 00733 { 00734 if (SUCCEEDED(IBandSite_GetBandObject(This->BandSite, 00735 dwBandID, 00736 &IID_IOleCommandTarget, 00737 (PVOID*)&pOct))) 00738 { 00739 /* Execute the command */ 00740 IOleCommandTarget_Exec(pOct, 00741 pguidCmdGroup, 00742 nCmdID, 00743 nCmdExecOpt, 00744 pvaIn, 00745 pvaOut); 00746 00747 IOleCommandTarget_Release(pOct); 00748 } 00749 00750 uBand++; 00751 } 00752 } 00753 00754 static HRESULT 00755 ITrayBandSiteImpl_FinishInit(IN OUT ITrayBandSiteImpl *This) 00756 { 00757 /* Broadcast the DBID_FINISHINIT command */ 00758 ITrayBandSiteImpl_BroadcastOleCommandExec(This, 00759 &IID_IDeskBand, 00760 DBID_FINISHINIT, 00761 0, 00762 NULL, 00763 NULL); 00764 00765 return S_OK; 00766 } 00767 00768 static HRESULT 00769 ITrayBandSiteImpl_Show(IN OUT ITrayBandSiteImpl *This, 00770 IN BOOL bShow) 00771 { 00772 IDeskBarClient *pDbc; 00773 HRESULT hRet; 00774 00775 hRet = IBandSite_QueryInterface(This->BandSite, 00776 &IID_IDeskBarClient, 00777 (PVOID*)&pDbc); 00778 if (SUCCEEDED(hRet)) 00779 { 00780 hRet = IDeskBarClient_UIActivateDBC(pDbc, 00781 bShow ? DBC_SHOW : DBC_HIDE); 00782 IDeskBarClient_Release(pDbc); 00783 } 00784 00785 return hRet; 00786 } 00787 00788 static HRESULT 00789 ITrayBandSiteImpl_LoadFromStream(IN OUT ITrayBandSiteImpl *This, 00790 IN OUT IStream *pStm) 00791 { 00792 IPersistStream *pPStm; 00793 HRESULT hRet; 00794 00795 ASSERT(This->BandSite != NULL); 00796 00797 /* We implement the undocumented COM interface IBandSiteStreamCallback 00798 that the shell will query so that we can intercept and custom-load 00799 the task band when it finds the task band's CLSID (which is internal). 00800 This way we can prevent the shell from attempting to CoCreateInstance 00801 the (internal) task band, resulting in a failure... */ 00802 hRet = IBandSite_QueryInterface(This->BandSite, 00803 &IID_IPersistStream, 00804 (PVOID*)&pPStm); 00805 if (SUCCEEDED(hRet)) 00806 { 00807 hRet = IPersistStream_Load(pPStm, 00808 pStm); 00809 DbgPrint("IPersistStream_Load() returned 0x%x\n", hRet); 00810 IPersistStream_Release(pPStm); 00811 } 00812 00813 return hRet; 00814 } 00815 00816 static IStream * 00817 GetUserBandsStream(IN DWORD grfMode) 00818 { 00819 HKEY hkStreams; 00820 IStream *Stream = NULL; 00821 00822 if (RegCreateKey(hkExplorer, 00823 TEXT("Streams"), 00824 &hkStreams) == ERROR_SUCCESS) 00825 { 00826 Stream = SHOpenRegStream(hkStreams, 00827 TEXT("Desktop"), 00828 TEXT("TaskbarWinXP"), 00829 grfMode); 00830 00831 RegCloseKey(hkStreams); 00832 } 00833 00834 return Stream; 00835 } 00836 00837 static IStream * 00838 GetDefaultBandsStream(IN DWORD grfMode) 00839 { 00840 HKEY hkStreams; 00841 IStream *Stream = NULL; 00842 00843 if (RegCreateKey(HKEY_LOCAL_MACHINE, 00844 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Streams"), 00845 &hkStreams) == ERROR_SUCCESS) 00846 { 00847 Stream = SHOpenRegStream(hkStreams, 00848 TEXT("Desktop"), 00849 TEXT("Default Taskbar"), 00850 grfMode); 00851 00852 RegCloseKey(hkStreams); 00853 } 00854 00855 return Stream; 00856 } 00857 00858 static HRESULT 00859 ITrayBandSiteImpl_Load(IN OUT ITrayBandSiteImpl *This) 00860 { 00861 IStream *pStm; 00862 HRESULT hRet; 00863 00864 /* Try to load the user's settings */ 00865 pStm = GetUserBandsStream(STGM_READ); 00866 if (pStm != NULL) 00867 { 00868 hRet = ITrayBandSiteImpl_LoadFromStream(This, 00869 pStm); 00870 00871 DbgPrint("Loaded user bands settings: 0x%x\n", hRet); 00872 IStream_Release(pStm); 00873 } 00874 else 00875 hRet = E_FAIL; 00876 00877 /* If the user's settings couldn't be loaded, try with 00878 default settings (ie. when the user logs in for the 00879 first time! */ 00880 if (!SUCCEEDED(hRet)) 00881 { 00882 pStm = GetDefaultBandsStream(STGM_READ); 00883 if (pStm != NULL) 00884 { 00885 hRet = ITrayBandSiteImpl_LoadFromStream(This, 00886 pStm); 00887 00888 DbgPrint("Loaded default user bands settings: 0x%x\n", hRet); 00889 IStream_Release(pStm); 00890 } 00891 else 00892 hRet = E_FAIL; 00893 } 00894 00895 return hRet; 00896 } 00897 00898 static ITrayBandSiteImpl * 00899 ITrayBandSiteImpl_Construct(IN OUT ITrayWindow *Tray, 00900 OUT HWND *phWndRebar, 00901 OUT HWND *phwndTaskSwitch) 00902 { 00903 ITrayBandSiteImpl *This; 00904 IDeskBarClient *pDbc; 00905 IDeskBand *pDb; 00906 IOleWindow *pOw; 00907 HRESULT hRet; 00908 00909 *phWndRebar = NULL; 00910 *phwndTaskSwitch = NULL; 00911 00912 This = HeapAlloc(hProcessHeap, 00913 0, 00914 sizeof(*This)); 00915 if (This == NULL) 00916 return NULL; 00917 00918 ZeroMemory(This, 00919 sizeof(*This)); 00920 This->lpVtbl = &ITrayBandSiteImpl_Vtbl; 00921 This->lpBandSiteVtbl = &IBandSiteImpl_Vtbl; 00922 This->Ref = 1; 00923 This->Tray = Tray; 00924 00925 /* Create a RebarBandSite provided by the shell */ 00926 hRet = CoCreateInstance(&CLSID_RebarBandSite, 00927 (LPUNKNOWN)IBandSite_from_ITrayBandSiteImpl(This), 00928 CLSCTX_INPROC_SERVER, 00929 &IID_IUnknown, 00930 (LPVOID*)&This->punkInner); 00931 if (!SUCCEEDED(hRet)) 00932 { 00933 ITrayBandSiteImpl_Free(This); 00934 return NULL; 00935 } 00936 00937 hRet = IUnknown_QueryInterface(This->punkInner, 00938 &IID_IBandSite, 00939 (PVOID*)&This->BandSite); 00940 if (!SUCCEEDED(hRet)) 00941 { 00942 ITrayBandSiteImpl_Free(This); 00943 return NULL; 00944 } 00945 00946 hRet = IUnknown_QueryInterface(This->punkInner, 00947 &IID_IWinEventHandler, 00948 (PVOID*)&This->WindowEventHandler); 00949 if (!SUCCEEDED(hRet)) 00950 { 00951 ITrayBandSiteImpl_Free(This); 00952 return NULL; 00953 } 00954 00955 This->TaskBand = CreateTaskBand(Tray); 00956 if (This->TaskBand != NULL) 00957 { 00958 /* Add the task band to the site */ 00959 hRet = IBandSite_QueryInterface(This->BandSite, 00960 &IID_IDeskBarClient, 00961 (PVOID*)&pDbc); 00962 if (SUCCEEDED(hRet)) 00963 { 00964 hRet = ITaskBand_QueryInterface(This->TaskBand, 00965 &IID_IOleWindow, 00966 (PVOID*)&pOw); 00967 if (SUCCEEDED(hRet)) 00968 { 00969 /* We cause IDeskBarClient to create the rebar control by passing the new 00970 task band to it. The band reports the tray window handle as window handle 00971 so that IDeskBarClient knows the parent window of the Rebar control that 00972 it wants to create. */ 00973 hRet = IDeskBarClient_SetDeskBarSite(pDbc, 00974 (IUnknown *)pOw); 00975 00976 if (SUCCEEDED(hRet)) 00977 { 00978 /* The Rebar control is now created, we can query the window handle */ 00979 hRet = IDeskBarClient_GetWindow(pDbc, 00980 &This->hWndRebar); 00981 00982 if (SUCCEEDED(hRet)) 00983 { 00984 /* We need to manually remove the RBS_BANDBORDERS style! */ 00985 SetWindowStyle(This->hWndRebar, 00986 RBS_BANDBORDERS, 00987 0); 00988 } 00989 } 00990 00991 IOleWindow_Release(pOw); 00992 } 00993 00994 if (SUCCEEDED(hRet)) 00995 { 00996 DWORD dwMode = 0; 00997 00998 /* Set the Desk Bar mode to the current one */ 00999 01000 /* FIXME: We need to set the mode (and update) whenever the user docks 01001 the tray window to another monitor edge! */ 01002 01003 if (!ITrayWindow_IsHorizontal(This->Tray)) 01004 dwMode = DBIF_VIEWMODE_VERTICAL; 01005 01006 hRet = IDeskBarClient_SetModeDBC(pDbc, 01007 dwMode); 01008 } 01009 01010 IDeskBarClient_Release(pDbc); 01011 } 01012 01013 /* Load the saved state of the task band site */ 01014 /* FIXME: We should delay loading shell extensions, also see DBID_DELAYINIT */ 01015 ITrayBandSiteImpl_Load(This); 01016 01017 /* Add the task bar band if it hasn't been added already */ 01018 hRet = ITrayBandSiteImpl_AddTaskBand(This); 01019 if (SUCCEEDED(hRet)) 01020 { 01021 hRet = ITaskBand_QueryInterface(This->TaskBand, 01022 &IID_IDeskBand, 01023 (PVOID*)&pDb); 01024 if (SUCCEEDED(hRet)) 01025 { 01026 hRet = IDeskBand_GetWindow(pDb, 01027 phwndTaskSwitch); 01028 if (!SUCCEEDED(hRet)) 01029 *phwndTaskSwitch = NULL; 01030 01031 IDeskBand_Release(pDb); 01032 } 01033 } 01034 01035 /* Should we send this after showing it? */ 01036 ITrayBandSiteImpl_Update(This); 01037 01038 /* FIXME: When should we send this? Does anyone care anyway? */ 01039 ITrayBandSiteImpl_FinishInit(This); 01040 01041 /* Activate the band site */ 01042 ITrayBandSiteImpl_Show(This, 01043 TRUE); 01044 } 01045 01046 *phWndRebar = This->hWndRebar; 01047 01048 return This; 01049 } 01050 01051 /*******************************************************************/ 01052 01053 ITrayBandSite * 01054 CreateTrayBandSite(IN OUT ITrayWindow *Tray, 01055 OUT HWND *phWndRebar, 01056 OUT HWND *phWndTaskSwitch) 01057 { 01058 ITrayBandSiteImpl *This; 01059 01060 This = ITrayBandSiteImpl_Construct(Tray, 01061 phWndRebar, 01062 phWndTaskSwitch); 01063 if (This != NULL) 01064 { 01065 return ITrayBandSite_from_ITrayBandSiteImpl(This); 01066 } 01067 01068 return NULL; 01069 } Generated on Sat May 26 2012 04:17:24 for ReactOS by
1.7.6.1
|