ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tbsite.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.