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

oleobj.c
Go to the documentation of this file.
00001 /*
00002  *  OLE2 COM objects
00003  *
00004  *  Copyright 1998 Eric Kohl
00005  *      Copyright 1999 Francis Beaudet
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 
00023 #include <stdarg.h>
00024 #include <string.h>
00025 
00026 #define COBJMACROS
00027 #define NONAMELESSUNION
00028 #define NONAMELESSSTRUCT
00029 
00030 #include "windef.h"
00031 #include "winbase.h"
00032 #include "winuser.h"
00033 #include "winerror.h"
00034 #include "wine/debug.h"
00035 #include "ole2.h"
00036 
00037 #include "compobj_private.h"
00038 
00039 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00040 
00041 #define INITIAL_SINKS 10
00042 
00043 static void release_statdata(STATDATA *data)
00044 {
00045     if(data->formatetc.ptd)
00046     {
00047         CoTaskMemFree(data->formatetc.ptd);
00048         data->formatetc.ptd = NULL;
00049     }
00050 
00051     if(data->pAdvSink)
00052     {
00053         IAdviseSink_Release(data->pAdvSink);
00054         data->pAdvSink = NULL;
00055     }
00056 }
00057 
00058 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
00059 {
00060     *dst = *src;
00061     if(src->formatetc.ptd)
00062     {
00063         dst->formatetc.ptd = CoTaskMemAlloc(src->formatetc.ptd->tdSize);
00064         if(!dst->formatetc.ptd) return E_OUTOFMEMORY;
00065         memcpy(dst->formatetc.ptd, src->formatetc.ptd, src->formatetc.ptd->tdSize);
00066     }
00067     if(dst->pAdvSink) IAdviseSink_AddRef(dst->pAdvSink);
00068     return S_OK;
00069 }
00070 
00071 /**************************************************************************
00072  *  EnumSTATDATA Implementation
00073  */
00074 
00075 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, IEnumSTATDATA **ppenum);
00076 
00077 typedef struct
00078 {
00079     IEnumSTATDATA IEnumSTATDATA_iface;
00080     LONG ref;
00081 
00082     ULONG index;
00083     DWORD num_of_elems;
00084     STATDATA *statdata;
00085     IUnknown *holder;
00086 } EnumSTATDATA;
00087 
00088 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
00089 {
00090     return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
00091 }
00092 
00093 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
00094 {
00095     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
00096     if (IsEqualIID(riid, &IID_IUnknown) ||
00097         IsEqualIID(riid, &IID_IEnumSTATDATA))
00098     {
00099         IUnknown_AddRef(iface);
00100         *ppv = iface;
00101         return S_OK;
00102     }
00103     return E_NOINTERFACE;
00104 }
00105 
00106 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
00107 {
00108     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00109     TRACE("()\n");
00110     return InterlockedIncrement(&This->ref);
00111 }
00112 
00113 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
00114 {
00115     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00116     LONG refs = InterlockedDecrement(&This->ref);
00117     TRACE("()\n");
00118     if (!refs)
00119     {
00120         DWORD i;
00121         for(i = 0; i < This->num_of_elems; i++)
00122             release_statdata(This->statdata + i);
00123         HeapFree(GetProcessHeap(), 0, This->statdata);
00124         IUnknown_Release(This->holder);
00125         HeapFree(GetProcessHeap(), 0, This);
00126     }
00127     return refs;
00128 }
00129 
00130 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
00131                                         ULONG *fetched)
00132 {
00133     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00134     DWORD count = 0;
00135     HRESULT hr = S_OK;
00136 
00137     TRACE("(%d, %p, %p)\n", num, data, fetched);
00138 
00139     while(num--)
00140     {
00141         if (This->index >= This->num_of_elems)
00142         {
00143             hr = S_FALSE;
00144             break;
00145         }
00146 
00147         copy_statdata(data + count, This->statdata + This->index);
00148 
00149         count++;
00150         This->index++;
00151     }
00152 
00153     if (fetched) *fetched = count;
00154 
00155     return hr;
00156 }
00157 
00158 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
00159 {
00160     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00161 
00162     TRACE("(%d)\n", num);
00163 
00164     if(This->index + num >= This->num_of_elems)
00165     {
00166         This->index = This->num_of_elems;
00167         return S_FALSE;
00168     }
00169 
00170     This->index += num;
00171     return S_OK;
00172 }
00173 
00174 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
00175 {
00176     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00177 
00178     TRACE("()\n");
00179 
00180     This->index = 0;
00181     return S_OK;
00182 }
00183 
00184 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
00185 {
00186     EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
00187 
00188     return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata, ppenum);
00189 }
00190 
00191 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
00192 {
00193     EnumSTATDATA_QueryInterface,
00194     EnumSTATDATA_AddRef,
00195     EnumSTATDATA_Release,
00196     EnumSTATDATA_Next,
00197     EnumSTATDATA_Skip,
00198     EnumSTATDATA_Reset,
00199     EnumSTATDATA_Clone
00200 };
00201 
00202 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
00203                                       IEnumSTATDATA **ppenum)
00204 {
00205     EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
00206     DWORD i, count;
00207 
00208     if (!This) return E_OUTOFMEMORY;
00209 
00210     This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
00211     This->ref = 1;
00212     This->index = index;
00213 
00214     This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
00215     if(!This->statdata)
00216     {
00217         HeapFree(GetProcessHeap(), 0, This);
00218         return E_OUTOFMEMORY;
00219     }
00220 
00221     for(i = 0, count = 0; i < array_len; i++)
00222     {
00223         if(data[i].pAdvSink)
00224         {
00225             copy_statdata(This->statdata + count, data + i);
00226             count++;
00227         }
00228     }
00229 
00230     This->num_of_elems = count;
00231     This->holder = holder;
00232     IUnknown_AddRef(holder);
00233     *ppenum = &This->IEnumSTATDATA_iface;
00234     return S_OK;
00235 }
00236 
00237 /**************************************************************************
00238  *  OleAdviseHolder Implementation
00239  */
00240 typedef struct
00241 {
00242     IOleAdviseHolder IOleAdviseHolder_iface;
00243 
00244     LONG ref;
00245 
00246     DWORD max_cons;
00247     STATDATA *connections;
00248 } OleAdviseHolderImpl;
00249 
00250 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
00251 {
00252     return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
00253 }
00254 
00255 /**************************************************************************
00256  *  OleAdviseHolderImpl_Destructor
00257  */
00258 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
00259 {
00260     DWORD index;
00261     TRACE("%p\n", This);
00262 
00263     for (index = 0; index < This->max_cons; index++)
00264     {
00265         if (This->connections[index].pAdvSink != NULL)
00266             release_statdata(This->connections + index);
00267     }
00268 
00269     HeapFree(GetProcessHeap(), 0, This->connections);
00270     HeapFree(GetProcessHeap(), 0, This);
00271 }
00272 
00273 /**************************************************************************
00274  *  OleAdviseHolderImpl_QueryInterface
00275  */
00276 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
00277                                                          REFIID iid, void **obj)
00278 {
00279   OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00280   TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
00281 
00282   if (obj == NULL)
00283     return E_POINTER;
00284 
00285   *obj = NULL;
00286 
00287   if (IsEqualIID(iid, &IID_IUnknown) ||
00288       IsEqualIID(iid, &IID_IOleAdviseHolder))
00289   {
00290     *obj = &This->IOleAdviseHolder_iface;
00291   }
00292 
00293   if(*obj == NULL)
00294     return E_NOINTERFACE;
00295 
00296   IUnknown_AddRef((IUnknown*)*obj);
00297 
00298   return S_OK;
00299 }
00300 
00301 /******************************************************************************
00302  * OleAdviseHolderImpl_AddRef
00303  */
00304 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
00305 {
00306   OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00307   ULONG ref = InterlockedIncrement(&This->ref);
00308 
00309   TRACE("(%p)->(ref=%d)\n", This, ref - 1);
00310 
00311   return ref;
00312 }
00313 
00314 /******************************************************************************
00315  * OleAdviseHolderImpl_Release
00316  */
00317 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
00318 {
00319   OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00320   ULONG ref;
00321   TRACE("(%p)->(ref=%d)\n", This, This->ref);
00322   ref = InterlockedDecrement(&This->ref);
00323 
00324   if (ref == 0) OleAdviseHolderImpl_Destructor(This);
00325 
00326   return ref;
00327 }
00328 
00329 /******************************************************************************
00330  * OleAdviseHolderImpl_Advise
00331  */
00332 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
00333                                                  IAdviseSink *pAdvise,
00334                                                  DWORD *pdwConnection)
00335 {
00336   DWORD index;
00337   OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00338   STATDATA new_conn;
00339   static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
00340 
00341   TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
00342 
00343   if (pdwConnection==NULL)
00344     return E_POINTER;
00345 
00346   *pdwConnection = 0;
00347 
00348   for (index = 0; index < This->max_cons; index++)
00349   {
00350     if (This->connections[index].pAdvSink == NULL)
00351       break;
00352   }
00353 
00354   if (index == This->max_cons)
00355   {
00356     This->max_cons += INITIAL_SINKS;
00357     This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
00358                                     This->max_cons * sizeof(*This->connections));
00359   }
00360 
00361   new_conn.pAdvSink = pAdvise;
00362   new_conn.advf = 0;
00363   new_conn.formatetc = empty_fmtetc;
00364   new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
00365 
00366   copy_statdata(This->connections + index, &new_conn);
00367 
00368   *pdwConnection = new_conn.dwConnection;
00369 
00370   return S_OK;
00371 }
00372 
00373 /******************************************************************************
00374  * OleAdviseHolderImpl_Unadvise
00375  */
00376 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
00377                                                    DWORD dwConnection)
00378 {
00379   OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00380   DWORD index;
00381 
00382   TRACE("(%p)->(%u)\n", This, dwConnection);
00383 
00384   /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
00385   index = dwConnection - 1;
00386 
00387   if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
00388      return OLE_E_NOCONNECTION;
00389 
00390   release_statdata(This->connections + index);
00391 
00392   return S_OK;
00393 }
00394 
00395 /******************************************************************************
00396  * OleAdviseHolderImpl_EnumAdvise
00397  */
00398 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
00399 {
00400     OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
00401     IUnknown *unk;
00402     HRESULT hr;
00403 
00404     TRACE("(%p)->(%p)\n", This, enum_advise);
00405 
00406     IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
00407     hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, enum_advise);
00408     IUnknown_Release(unk);
00409     return hr;
00410 }
00411 
00412 /******************************************************************************
00413  * OleAdviseHolderImpl_SendOnRename
00414  */
00415 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
00416 {
00417     IEnumSTATDATA *pEnum;
00418     HRESULT hr;
00419 
00420     TRACE("(%p)->(%p)\n", iface, pmk);
00421 
00422     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
00423     if (SUCCEEDED(hr))
00424     {
00425         STATDATA statdata;
00426         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
00427         {
00428             IAdviseSink_OnRename(statdata.pAdvSink, pmk);
00429 
00430             IAdviseSink_Release(statdata.pAdvSink);
00431         }
00432         IEnumSTATDATA_Release(pEnum);
00433     }
00434 
00435     return hr;
00436 }
00437 
00438 /******************************************************************************
00439  * OleAdviseHolderImpl_SendOnSave
00440  */
00441 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
00442 {
00443     IEnumSTATDATA *pEnum;
00444     HRESULT hr;
00445 
00446     TRACE("(%p)->()\n", iface);
00447 
00448     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
00449     if (SUCCEEDED(hr))
00450     {
00451         STATDATA statdata;
00452         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
00453         {
00454             IAdviseSink_OnSave(statdata.pAdvSink);
00455 
00456             IAdviseSink_Release(statdata.pAdvSink);
00457         }
00458         IEnumSTATDATA_Release(pEnum);
00459     }
00460 
00461     return hr;
00462 }
00463 
00464 /******************************************************************************
00465  * OleAdviseHolderImpl_SendOnClose
00466  */
00467 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
00468 {
00469     IEnumSTATDATA *pEnum;
00470     HRESULT hr;
00471 
00472     TRACE("(%p)->()\n", iface);
00473 
00474     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
00475     if (SUCCEEDED(hr))
00476     {
00477         STATDATA statdata;
00478         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
00479         {
00480             IAdviseSink_OnClose(statdata.pAdvSink);
00481 
00482             IAdviseSink_Release(statdata.pAdvSink);
00483         }
00484         IEnumSTATDATA_Release(pEnum);
00485     }
00486 
00487     return hr;
00488 }
00489 
00490 /**************************************************************************
00491  *  OleAdviseHolderImpl_VTable
00492  */
00493 static const IOleAdviseHolderVtbl oahvt =
00494 {
00495     OleAdviseHolderImpl_QueryInterface,
00496     OleAdviseHolderImpl_AddRef,
00497     OleAdviseHolderImpl_Release,
00498     OleAdviseHolderImpl_Advise,
00499     OleAdviseHolderImpl_Unadvise,
00500     OleAdviseHolderImpl_EnumAdvise,
00501     OleAdviseHolderImpl_SendOnRename,
00502     OleAdviseHolderImpl_SendOnSave,
00503     OleAdviseHolderImpl_SendOnClose
00504 };
00505 
00506 /**************************************************************************
00507  *  OleAdviseHolderImpl_Constructor
00508  */
00509 
00510 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
00511 {
00512   OleAdviseHolderImpl* lpoah;
00513 
00514   lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
00515 
00516   lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
00517   lpoah->ref = 1;
00518   lpoah->max_cons = INITIAL_SINKS;
00519   lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00520                                  lpoah->max_cons * sizeof(*lpoah->connections));
00521 
00522   TRACE("returning %p\n",  &lpoah->IOleAdviseHolder_iface);
00523   return &lpoah->IOleAdviseHolder_iface;
00524 }
00525 
00526 /**************************************************************************
00527  *  DataAdviseHolder Implementation
00528  */
00529 typedef struct
00530 {
00531   IDataAdviseHolder     IDataAdviseHolder_iface;
00532 
00533   LONG                  ref;
00534   DWORD                 maxCons;
00535   STATDATA*             connections;
00536   DWORD*                remote_connections;
00537   IDataObject*          delegate;
00538 } DataAdviseHolder;
00539 
00540 /* this connection has also has been advised to the delegate data object */
00541 #define WINE_ADVF_REMOTE 0x80000000
00542 
00543 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
00544 {
00545     return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
00546 }
00547 
00548 /******************************************************************************
00549  * DataAdviseHolder_Destructor
00550  */
00551 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
00552 {
00553   DWORD index;
00554   TRACE("%p\n", ptrToDestroy);
00555 
00556   for (index = 0; index < ptrToDestroy->maxCons; index++)
00557   {
00558     if (ptrToDestroy->connections[index].pAdvSink != NULL)
00559     {
00560       if (ptrToDestroy->delegate && 
00561           (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
00562         IDataObject_DUnadvise(ptrToDestroy->delegate,
00563           ptrToDestroy->remote_connections[index]);
00564 
00565       release_statdata(ptrToDestroy->connections + index);
00566     }
00567   }
00568 
00569   HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
00570   HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
00571   HeapFree(GetProcessHeap(), 0, ptrToDestroy);
00572 }
00573 
00574 /************************************************************************
00575  * DataAdviseHolder_QueryInterface (IUnknown)
00576  */
00577 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
00578                                                       REFIID riid, void **ppvObject)
00579 {
00580   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00581   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
00582 
00583   if ( (This==0) || (ppvObject==0) )
00584     return E_INVALIDARG;
00585 
00586   *ppvObject = 0;
00587 
00588   if ( IsEqualIID(&IID_IUnknown, riid) ||
00589        IsEqualIID(&IID_IDataAdviseHolder, riid)  )
00590   {
00591     *ppvObject = iface;
00592   }
00593 
00594   if ((*ppvObject)==0)
00595   {
00596     return E_NOINTERFACE;
00597   }
00598 
00599   IUnknown_AddRef((IUnknown*)*ppvObject);
00600   return S_OK;
00601 }
00602 
00603 /************************************************************************
00604  * DataAdviseHolder_AddRef (IUnknown)
00605  */
00606 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
00607 {
00608   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00609   TRACE("(%p) (ref=%d)\n", This, This->ref);
00610   return InterlockedIncrement(&This->ref);
00611 }
00612 
00613 /************************************************************************
00614  * DataAdviseHolder_Release (IUnknown)
00615  */
00616 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
00617 {
00618   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00619   ULONG ref;
00620   TRACE("(%p) (ref=%d)\n", This, This->ref);
00621 
00622   ref = InterlockedDecrement(&This->ref);
00623   if (ref==0) DataAdviseHolder_Destructor(This);
00624 
00625   return ref;
00626 }
00627 
00628 /************************************************************************
00629  * DataAdviseHolder_Advise
00630  *
00631  */
00632 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
00633                                               IDataObject *pDataObject, FORMATETC *pFetc,
00634                                               DWORD advf, IAdviseSink *pAdvise,
00635                                               DWORD *pdwConnection)
00636 {
00637   DWORD index;
00638   STATDATA new_conn;
00639   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00640 
00641   TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
00642     pAdvise, pdwConnection);
00643 
00644   if (pdwConnection==NULL)
00645     return E_POINTER;
00646 
00647   *pdwConnection = 0;
00648 
00649   for (index = 0; index < This->maxCons; index++)
00650   {
00651     if (This->connections[index].pAdvSink == NULL)
00652       break;
00653   }
00654 
00655   if (index == This->maxCons)
00656   {
00657     This->maxCons+=INITIAL_SINKS;
00658     This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00659                                     This->connections,
00660                                     This->maxCons * sizeof(*This->connections));
00661     This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00662                                            This->remote_connections,
00663                                            This->maxCons * sizeof(*This->remote_connections));
00664   }
00665 
00666   new_conn.pAdvSink = pAdvise;
00667   new_conn.advf = advf & ~WINE_ADVF_REMOTE;
00668   new_conn.formatetc = *pFetc;
00669   new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
00670 
00671   copy_statdata(This->connections + index, &new_conn);
00672 
00673   if (This->connections[index].pAdvSink != NULL)
00674   {
00675     /* if we are already connected advise the remote object */
00676     if (This->delegate)
00677     {
00678         HRESULT hr;
00679 
00680         hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
00681                                  new_conn.advf, new_conn.pAdvSink,
00682                                  &This->remote_connections[index]);
00683         if (FAILED(hr))
00684         {
00685             IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
00686             return hr;
00687         }
00688         This->connections[index].advf |= WINE_ADVF_REMOTE;
00689     }
00690     else if(advf & ADVF_PRIMEFIRST)
00691       /* only do this if we have no delegate, since in the above case the
00692        * delegate will do the priming for us */
00693       IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
00694   }
00695 
00696   *pdwConnection = new_conn.dwConnection;
00697 
00698   return S_OK;
00699 }
00700 
00701 /******************************************************************************
00702  * DataAdviseHolder_Unadvise
00703  */
00704 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
00705                                                 DWORD dwConnection)
00706 {
00707   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00708   DWORD index;
00709   TRACE("(%p)->(%u)\n", This, dwConnection);
00710 
00711   /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
00712   index = dwConnection - 1;
00713 
00714   if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
00715      return OLE_E_NOCONNECTION;
00716 
00717   if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
00718   {
00719     IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
00720     This->remote_connections[index] = 0;
00721   }
00722 
00723   release_statdata(This->connections + index);
00724 
00725   return S_OK;
00726 }
00727 
00728 /******************************************************************************
00729  * DataAdviseHolder_EnumAdvise
00730  */
00731 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
00732                                                   IEnumSTATDATA **enum_advise)
00733 {
00734     DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00735     IUnknown *unk;
00736     HRESULT hr;
00737 
00738     TRACE("(%p)->(%p)\n", This, enum_advise);
00739 
00740     IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
00741     hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, enum_advise);
00742     IUnknown_Release(unk);
00743     return hr;
00744 }
00745 
00746 /******************************************************************************
00747  * DataAdviseHolder_SendOnDataChange
00748  */
00749 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
00750                                                         IDataObject *data_obj,
00751                                                         DWORD dwReserved, DWORD advf)
00752 {
00753     IEnumSTATDATA *pEnum;
00754     HRESULT hr;
00755 
00756     TRACE("(%p)->(%p, %08x, %08x)\n", iface, data_obj, dwReserved, advf);
00757 
00758     hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
00759     if (SUCCEEDED(hr))
00760     {
00761         STATDATA statdata;
00762         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
00763         {
00764             STGMEDIUM stg;
00765             stg.tymed = TYMED_NULL;
00766             stg.u.pstg = NULL;
00767             stg.pUnkForRelease = NULL;
00768 
00769             if(!(statdata.advf & ADVF_NODATA))
00770             {
00771                 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
00772             }
00773 
00774             IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
00775 
00776             if(statdata.advf & ADVF_ONLYONCE)
00777             {
00778                 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
00779             }
00780 
00781             release_statdata(&statdata);
00782         }
00783         IEnumSTATDATA_Release(pEnum);
00784     }
00785 
00786     return S_OK;
00787 }
00788 
00789 /**************************************************************************
00790  *  DataAdviseHolderImpl_VTable
00791  */
00792 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
00793 {
00794   DataAdviseHolder_QueryInterface,
00795   DataAdviseHolder_AddRef,
00796   DataAdviseHolder_Release,
00797   DataAdviseHolder_Advise,
00798   DataAdviseHolder_Unadvise,
00799   DataAdviseHolder_EnumAdvise,
00800   DataAdviseHolder_SendOnDataChange
00801 };
00802 
00803 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
00804 {
00805   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00806   DWORD index;
00807   HRESULT hr = S_OK;
00808 
00809   for(index = 0; index < This->maxCons; index++)
00810   {
00811     if(This->connections[index].pAdvSink != NULL)
00812     {
00813       hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
00814                                This->connections[index].advf,
00815                                This->connections[index].pAdvSink,
00816                                &This->remote_connections[index]);
00817       if (FAILED(hr)) break;
00818       This->connections[index].advf |= WINE_ADVF_REMOTE;
00819     }
00820   }
00821   This->delegate = pDelegate;
00822   return hr;
00823 }
00824 
00825 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
00826 {
00827   DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
00828   DWORD index;
00829 
00830   for(index = 0; index < This->maxCons; index++)
00831   {
00832     if((This->connections[index].pAdvSink != NULL) &&
00833        (This->connections[index].advf & WINE_ADVF_REMOTE))
00834     {
00835       IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
00836       This->remote_connections[index] = 0;
00837       This->connections[index].advf &= ~WINE_ADVF_REMOTE;
00838     }
00839   }
00840   This->delegate = NULL;
00841 }
00842 
00843 /******************************************************************************
00844  * DataAdviseHolder_Constructor
00845  */
00846 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
00847 {
00848   DataAdviseHolder* newHolder;
00849 
00850   newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
00851 
00852   newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
00853   newHolder->ref = 1;
00854   newHolder->maxCons = INITIAL_SINKS;
00855   newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00856                                      newHolder->maxCons * sizeof(*newHolder->connections));
00857   newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00858                                             newHolder->maxCons * sizeof(*newHolder->remote_connections));
00859   newHolder->delegate = NULL;
00860 
00861   TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
00862   return &newHolder->IDataAdviseHolder_iface;
00863 }
00864 
00865 /***********************************************************************
00866  * API functions
00867  */
00868 
00869 /***********************************************************************
00870  * CreateOleAdviseHolder [OLE32.@]
00871  */
00872 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
00873 {
00874   TRACE("(%p)\n", ppOAHolder);
00875 
00876   if (ppOAHolder==NULL)
00877     return E_POINTER;
00878 
00879   *ppOAHolder = OleAdviseHolderImpl_Constructor ();
00880 
00881   if (*ppOAHolder != NULL)
00882     return S_OK;
00883 
00884   return E_OUTOFMEMORY;
00885 }
00886 
00887 /******************************************************************************
00888  *              CreateDataAdviseHolder        [OLE32.@]
00889  */
00890 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
00891 {
00892   TRACE("(%p)\n", ppDAHolder);
00893 
00894   if (ppDAHolder==NULL)
00895     return E_POINTER;
00896 
00897   *ppDAHolder = DataAdviseHolder_Constructor();
00898 
00899   if (*ppDAHolder != NULL)
00900     return S_OK;
00901 
00902   return E_OUTOFMEMORY;
00903 }

Generated on Sun May 27 2012 04:25:06 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.