Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenoleobj.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
1.7.6.1
|