Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencompartmentmgr.c
Go to the documentation of this file.
00001 /* 00002 * ITfCompartmentMgr implementation 00003 * 00004 * Copyright 2009 Aric Stewart, CodeWeavers 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 St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <stdarg.h> 00024 00025 #define COBJMACROS 00026 00027 #include "wine/debug.h" 00028 #include "windef.h" 00029 #include "winbase.h" 00030 #include "winreg.h" 00031 #include "winuser.h" 00032 #include "shlwapi.h" 00033 #include "winerror.h" 00034 #include "objbase.h" 00035 #include "oleauto.h" 00036 #include "olectl.h" 00037 00038 #include "wine/unicode.h" 00039 #include "wine/list.h" 00040 00041 #include "msctf.h" 00042 #include "msctf_internal.h" 00043 00044 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 00045 00046 typedef struct tagCompartmentValue { 00047 struct list entry; 00048 GUID guid; 00049 TfClientId owner; 00050 ITfCompartment *compartment; 00051 } CompartmentValue; 00052 00053 typedef struct tagCompartmentMgr { 00054 const ITfCompartmentMgrVtbl *CompartmentMgrVtbl; 00055 LONG refCount; 00056 00057 IUnknown *pUnkOuter; 00058 00059 struct list values; 00060 } CompartmentMgr; 00061 00062 typedef struct tagCompartmentEnumGuid { 00063 const IEnumGUIDVtbl *Vtbl; 00064 LONG refCount; 00065 00066 struct list *values; 00067 struct list *cursor; 00068 } CompartmentEnumGuid; 00069 00070 00071 typedef struct tagCompartmentSink { 00072 struct list entry; 00073 union { 00074 IUnknown *pIUnknown; 00075 ITfCompartmentEventSink *pITfCompartmentEventSink; 00076 } interfaces; 00077 } CompartmentSink; 00078 00079 typedef struct tagCompartment { 00080 const ITfCompartmentVtbl *Vtbl; 00081 const ITfSourceVtbl *SourceVtbl; 00082 LONG refCount; 00083 00084 /* Only VT_I4, VT_UNKNOWN and VT_BSTR data types are allowed */ 00085 VARIANT variant; 00086 CompartmentValue *valueData; 00087 struct list CompartmentEventSink; 00088 } Compartment; 00089 00090 static HRESULT CompartmentEnumGuid_Constructor(struct list* values, IEnumGUID **ppOut); 00091 static HRESULT Compartment_Constructor(CompartmentValue *value, ITfCompartment **ppOut); 00092 00093 static inline Compartment *impl_from_ITfSourceVtbl(ITfSource *iface) 00094 { 00095 return (Compartment *)((char *)iface - FIELD_OFFSET(Compartment,SourceVtbl)); 00096 } 00097 00098 HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface) 00099 { 00100 CompartmentMgr *This = (CompartmentMgr *)iface; 00101 struct list *cursor, *cursor2; 00102 00103 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->values) 00104 { 00105 CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry); 00106 list_remove(cursor); 00107 ITfCompartment_Release(value->compartment); 00108 HeapFree(GetProcessHeap(),0,value); 00109 } 00110 00111 HeapFree(GetProcessHeap(),0,This); 00112 return S_OK; 00113 } 00114 00115 /***************************************************** 00116 * ITfCompartmentMgr functions 00117 *****************************************************/ 00118 static HRESULT WINAPI CompartmentMgr_QueryInterface(ITfCompartmentMgr *iface, REFIID iid, LPVOID *ppvOut) 00119 { 00120 CompartmentMgr *This = (CompartmentMgr *)iface; 00121 if (This->pUnkOuter) 00122 return IUnknown_QueryInterface(This->pUnkOuter, iid, *ppvOut); 00123 else 00124 { 00125 *ppvOut = NULL; 00126 00127 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartmentMgr)) 00128 { 00129 *ppvOut = This; 00130 } 00131 00132 if (*ppvOut) 00133 { 00134 IUnknown_AddRef(iface); 00135 return S_OK; 00136 } 00137 00138 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 00139 return E_NOINTERFACE; 00140 } 00141 } 00142 00143 static ULONG WINAPI CompartmentMgr_AddRef(ITfCompartmentMgr *iface) 00144 { 00145 CompartmentMgr *This = (CompartmentMgr *)iface; 00146 if (This->pUnkOuter) 00147 return IUnknown_AddRef(This->pUnkOuter); 00148 else 00149 return InterlockedIncrement(&This->refCount); 00150 } 00151 00152 static ULONG WINAPI CompartmentMgr_Release(ITfCompartmentMgr *iface) 00153 { 00154 CompartmentMgr *This = (CompartmentMgr *)iface; 00155 if (This->pUnkOuter) 00156 return IUnknown_Release(This->pUnkOuter); 00157 else 00158 { 00159 ULONG ret; 00160 00161 ret = InterlockedDecrement(&This->refCount); 00162 if (ret == 0) 00163 CompartmentMgr_Destructor(iface); 00164 return ret; 00165 } 00166 } 00167 00168 static HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface, 00169 REFGUID rguid, ITfCompartment **ppcomp) 00170 { 00171 CompartmentMgr *This = (CompartmentMgr *)iface; 00172 CompartmentValue* value; 00173 struct list *cursor; 00174 HRESULT hr; 00175 00176 TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),ppcomp); 00177 00178 LIST_FOR_EACH(cursor, &This->values) 00179 { 00180 value = LIST_ENTRY(cursor,CompartmentValue,entry); 00181 if (IsEqualGUID(rguid,&value->guid)) 00182 { 00183 ITfCompartment_AddRef(value->compartment); 00184 *ppcomp = value->compartment; 00185 return S_OK; 00186 } 00187 } 00188 00189 value = HeapAlloc(GetProcessHeap(),0,sizeof(CompartmentValue)); 00190 value->guid = *rguid; 00191 value->owner = 0; 00192 hr = Compartment_Constructor(value,&value->compartment); 00193 if (SUCCEEDED(hr)) 00194 { 00195 list_add_head(&This->values,&value->entry); 00196 ITfCompartment_AddRef(value->compartment); 00197 *ppcomp = value->compartment; 00198 } 00199 else 00200 { 00201 HeapFree(GetProcessHeap(),0,value); 00202 *ppcomp = NULL; 00203 } 00204 return hr; 00205 } 00206 00207 static HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface, 00208 TfClientId tid, REFGUID rguid) 00209 { 00210 struct list *cursor; 00211 CompartmentMgr *This = (CompartmentMgr *)iface; 00212 TRACE("(%p) %i %s\n",This,tid,debugstr_guid(rguid)); 00213 00214 LIST_FOR_EACH(cursor, &This->values) 00215 { 00216 CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry); 00217 if (IsEqualGUID(rguid,&value->guid)) 00218 { 00219 if (value->owner && tid != value->owner) 00220 return E_UNEXPECTED; 00221 list_remove(cursor); 00222 ITfCompartment_Release(value->compartment); 00223 HeapFree(GetProcessHeap(),0,value); 00224 return S_OK; 00225 } 00226 } 00227 00228 return CONNECT_E_NOCONNECTION; 00229 } 00230 00231 static HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface, 00232 IEnumGUID **ppEnum) 00233 { 00234 CompartmentMgr *This = (CompartmentMgr *)iface; 00235 TRACE("(%p) %p\n",This,ppEnum); 00236 if (!ppEnum) 00237 return E_INVALIDARG; 00238 return CompartmentEnumGuid_Constructor(&This->values, ppEnum); 00239 } 00240 00241 static const ITfCompartmentMgrVtbl CompartmentMgr_CompartmentMgrVtbl = 00242 { 00243 CompartmentMgr_QueryInterface, 00244 CompartmentMgr_AddRef, 00245 CompartmentMgr_Release, 00246 00247 CompartmentMgr_GetCompartment, 00248 CompartmentMgr_ClearCompartment, 00249 CompartmentMgr_EnumCompartments 00250 }; 00251 00252 HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut) 00253 { 00254 CompartmentMgr *This; 00255 00256 if (!ppOut) 00257 return E_POINTER; 00258 00259 if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) 00260 return CLASS_E_NOAGGREGATION; 00261 00262 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentMgr)); 00263 if (This == NULL) 00264 return E_OUTOFMEMORY; 00265 00266 This->CompartmentMgrVtbl = &CompartmentMgr_CompartmentMgrVtbl; 00267 This->pUnkOuter = pUnkOuter; 00268 list_init(&This->values); 00269 00270 if (pUnkOuter) 00271 { 00272 TRACE("returning %p\n", This); 00273 *ppOut = (IUnknown*)This; 00274 return S_OK; 00275 } 00276 else 00277 { 00278 HRESULT hr; 00279 hr = IUnknown_QueryInterface((IUnknown*)This, riid, (LPVOID*)ppOut); 00280 if (FAILED(hr)) 00281 HeapFree(GetProcessHeap(),0,This); 00282 return hr; 00283 } 00284 } 00285 00286 /************************************************** 00287 * IEnumGUID implementation for ITfCompartmentMgr::EnumCompartments 00288 **************************************************/ 00289 static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid *This) 00290 { 00291 TRACE("destroying %p\n", This); 00292 HeapFree(GetProcessHeap(),0,This); 00293 } 00294 00295 static HRESULT WINAPI CompartmentEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut) 00296 { 00297 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00298 *ppvOut = NULL; 00299 00300 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID)) 00301 { 00302 *ppvOut = This; 00303 } 00304 00305 if (*ppvOut) 00306 { 00307 IUnknown_AddRef(iface); 00308 return S_OK; 00309 } 00310 00311 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 00312 return E_NOINTERFACE; 00313 } 00314 00315 static ULONG WINAPI CompartmentEnumGuid_AddRef(IEnumGUID *iface) 00316 { 00317 CompartmentEnumGuid *This = (CompartmentEnumGuid*)iface; 00318 return InterlockedIncrement(&This->refCount); 00319 } 00320 00321 static ULONG WINAPI CompartmentEnumGuid_Release(IEnumGUID *iface) 00322 { 00323 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00324 ULONG ret; 00325 00326 ret = InterlockedDecrement(&This->refCount); 00327 if (ret == 0) 00328 CompartmentEnumGuid_Destructor(This); 00329 return ret; 00330 } 00331 00332 /***************************************************** 00333 * IEnumGuid functions 00334 *****************************************************/ 00335 static HRESULT WINAPI CompartmentEnumGuid_Next( LPENUMGUID iface, 00336 ULONG celt, GUID *rgelt, ULONG *pceltFetched) 00337 { 00338 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00339 ULONG fetched = 0; 00340 00341 TRACE("(%p)\n",This); 00342 00343 if (rgelt == NULL) return E_POINTER; 00344 00345 while (fetched < celt && This->cursor) 00346 { 00347 CompartmentValue* value = LIST_ENTRY(This->cursor,CompartmentValue,entry); 00348 if (!value) 00349 break; 00350 00351 This->cursor = list_next(This->values,This->cursor); 00352 *rgelt = value->guid; 00353 00354 ++fetched; 00355 ++rgelt; 00356 } 00357 00358 if (pceltFetched) *pceltFetched = fetched; 00359 return fetched == celt ? S_OK : S_FALSE; 00360 } 00361 00362 static HRESULT WINAPI CompartmentEnumGuid_Skip( LPENUMGUID iface, ULONG celt) 00363 { 00364 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00365 TRACE("(%p)\n",This); 00366 00367 This->cursor = list_next(This->values,This->cursor); 00368 return S_OK; 00369 } 00370 00371 static HRESULT WINAPI CompartmentEnumGuid_Reset( LPENUMGUID iface) 00372 { 00373 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00374 TRACE("(%p)\n",This); 00375 This->cursor = list_head(This->values); 00376 return S_OK; 00377 } 00378 00379 static HRESULT WINAPI CompartmentEnumGuid_Clone( LPENUMGUID iface, 00380 IEnumGUID **ppenum) 00381 { 00382 CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; 00383 HRESULT res; 00384 00385 TRACE("(%p)\n",This); 00386 00387 if (ppenum == NULL) return E_POINTER; 00388 00389 res = CompartmentEnumGuid_Constructor(This->values, ppenum); 00390 if (SUCCEEDED(res)) 00391 { 00392 CompartmentEnumGuid *new_This = (CompartmentEnumGuid *)*ppenum; 00393 new_This->cursor = This->cursor; 00394 } 00395 return res; 00396 } 00397 00398 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={ 00399 CompartmentEnumGuid_QueryInterface, 00400 CompartmentEnumGuid_AddRef, 00401 CompartmentEnumGuid_Release, 00402 00403 CompartmentEnumGuid_Next, 00404 CompartmentEnumGuid_Skip, 00405 CompartmentEnumGuid_Reset, 00406 CompartmentEnumGuid_Clone 00407 }; 00408 00409 static HRESULT CompartmentEnumGuid_Constructor(struct list *values, IEnumGUID **ppOut) 00410 { 00411 CompartmentEnumGuid *This; 00412 00413 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentEnumGuid)); 00414 if (This == NULL) 00415 return E_OUTOFMEMORY; 00416 00417 This->Vtbl= &IEnumGUID_Vtbl; 00418 This->refCount = 1; 00419 00420 This->values = values; 00421 This->cursor = list_head(values); 00422 00423 TRACE("returning %p\n", This); 00424 *ppOut = (IEnumGUID*)This; 00425 return S_OK; 00426 } 00427 00428 /************************************************** 00429 * ITfCompartment 00430 **************************************************/ 00431 static void free_sink(CompartmentSink *sink) 00432 { 00433 IUnknown_Release(sink->interfaces.pIUnknown); 00434 HeapFree(GetProcessHeap(),0,sink); 00435 } 00436 00437 static void Compartment_Destructor(Compartment *This) 00438 { 00439 struct list *cursor, *cursor2; 00440 TRACE("destroying %p\n", This); 00441 VariantClear(&This->variant); 00442 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CompartmentEventSink) 00443 { 00444 CompartmentSink* sink = LIST_ENTRY(cursor,CompartmentSink,entry); 00445 list_remove(cursor); 00446 free_sink(sink); 00447 } 00448 HeapFree(GetProcessHeap(),0,This); 00449 } 00450 00451 static HRESULT WINAPI Compartment_QueryInterface(ITfCompartment *iface, REFIID iid, LPVOID *ppvOut) 00452 { 00453 Compartment *This = (Compartment *)iface; 00454 *ppvOut = NULL; 00455 00456 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartment)) 00457 { 00458 *ppvOut = This; 00459 } 00460 else if (IsEqualIID(iid, &IID_ITfSource)) 00461 { 00462 *ppvOut = &This->SourceVtbl; 00463 } 00464 00465 if (*ppvOut) 00466 { 00467 IUnknown_AddRef(iface); 00468 return S_OK; 00469 } 00470 00471 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 00472 return E_NOINTERFACE; 00473 } 00474 00475 static ULONG WINAPI Compartment_AddRef(ITfCompartment *iface) 00476 { 00477 Compartment *This = (Compartment*)iface; 00478 return InterlockedIncrement(&This->refCount); 00479 } 00480 00481 static ULONG WINAPI Compartment_Release(ITfCompartment *iface) 00482 { 00483 Compartment *This = (Compartment *)iface; 00484 ULONG ret; 00485 00486 ret = InterlockedDecrement(&This->refCount); 00487 if (ret == 0) 00488 Compartment_Destructor(This); 00489 return ret; 00490 } 00491 00492 static HRESULT WINAPI Compartment_SetValue(ITfCompartment *iface, 00493 TfClientId tid, const VARIANT *pvarValue) 00494 { 00495 Compartment *This = (Compartment *)iface; 00496 struct list *cursor; 00497 00498 TRACE("(%p) %i %p\n",This,tid,pvarValue); 00499 00500 if (!pvarValue) 00501 return E_INVALIDARG; 00502 00503 if (!(V_VT(pvarValue) == VT_BSTR || V_VT(pvarValue) == VT_I4 || 00504 V_VT(pvarValue) == VT_UNKNOWN)) 00505 return E_INVALIDARG; 00506 00507 if (!This->valueData->owner) 00508 This->valueData->owner = tid; 00509 00510 VariantClear(&This->variant); 00511 00512 /* Shallow copy of value and type */ 00513 This->variant = *pvarValue; 00514 00515 if (V_VT(pvarValue) == VT_BSTR) 00516 V_BSTR(&This->variant) = SysAllocStringByteLen((char*)V_BSTR(pvarValue), 00517 SysStringByteLen(V_BSTR(pvarValue))); 00518 else if (V_VT(pvarValue) == VT_UNKNOWN) 00519 IUnknown_AddRef(V_UNKNOWN(&This->variant)); 00520 00521 LIST_FOR_EACH(cursor, &This->CompartmentEventSink) 00522 { 00523 CompartmentSink* sink = LIST_ENTRY(cursor,CompartmentSink,entry); 00524 ITfCompartmentEventSink_OnChange(sink->interfaces.pITfCompartmentEventSink,&This->valueData->guid); 00525 } 00526 00527 return S_OK; 00528 } 00529 00530 static HRESULT WINAPI Compartment_GetValue(ITfCompartment *iface, 00531 VARIANT *pvarValue) 00532 { 00533 Compartment *This = (Compartment *)iface; 00534 TRACE("(%p) %p\n",This, pvarValue); 00535 00536 if (!pvarValue) 00537 return E_INVALIDARG; 00538 00539 VariantInit(pvarValue); 00540 if (V_VT(&This->variant) == VT_EMPTY) return S_FALSE; 00541 return VariantCopy(pvarValue,&This->variant); 00542 } 00543 00544 static const ITfCompartmentVtbl ITfCompartment_Vtbl ={ 00545 Compartment_QueryInterface, 00546 Compartment_AddRef, 00547 Compartment_Release, 00548 00549 Compartment_SetValue, 00550 Compartment_GetValue 00551 }; 00552 00553 /***************************************************** 00554 * ITfSource functions 00555 *****************************************************/ 00556 00557 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) 00558 { 00559 Compartment *This = impl_from_ITfSourceVtbl(iface); 00560 return Compartment_QueryInterface((ITfCompartment *)This, iid, *ppvOut); 00561 } 00562 00563 static ULONG WINAPI Source_AddRef(ITfSource *iface) 00564 { 00565 Compartment *This = impl_from_ITfSourceVtbl(iface); 00566 return Compartment_AddRef((ITfCompartment*)This); 00567 } 00568 00569 static ULONG WINAPI Source_Release(ITfSource *iface) 00570 { 00571 Compartment *This = impl_from_ITfSourceVtbl(iface); 00572 return Compartment_Release((ITfCompartment *)This); 00573 } 00574 00575 static HRESULT WINAPI CompartmentSource_AdviseSink(ITfSource *iface, 00576 REFIID riid, IUnknown *punk, DWORD *pdwCookie) 00577 { 00578 CompartmentSink *cs; 00579 Compartment *This = impl_from_ITfSourceVtbl(iface); 00580 00581 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); 00582 00583 if (!riid || !punk || !pdwCookie) 00584 return E_INVALIDARG; 00585 00586 if (IsEqualIID(riid, &IID_ITfCompartmentEventSink)) 00587 { 00588 cs = HeapAlloc(GetProcessHeap(),0,sizeof(CompartmentSink)); 00589 if (!cs) 00590 return E_OUTOFMEMORY; 00591 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&cs->interfaces.pITfCompartmentEventSink))) 00592 { 00593 HeapFree(GetProcessHeap(),0,cs); 00594 return CONNECT_E_CANNOTCONNECT; 00595 } 00596 list_add_head(&This->CompartmentEventSink,&cs->entry); 00597 *pdwCookie = generate_Cookie(COOKIE_MAGIC_COMPARTMENTSINK , cs); 00598 } 00599 else 00600 { 00601 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); 00602 return E_NOTIMPL; 00603 } 00604 00605 TRACE("cookie %x\n",*pdwCookie); 00606 00607 return S_OK; 00608 } 00609 00610 static HRESULT WINAPI CompartmentSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) 00611 { 00612 CompartmentSink *sink; 00613 Compartment *This = impl_from_ITfSourceVtbl(iface); 00614 00615 TRACE("(%p) %x\n",This,pdwCookie); 00616 00617 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_COMPARTMENTSINK) 00618 return E_INVALIDARG; 00619 00620 sink = (CompartmentSink*)remove_Cookie(pdwCookie); 00621 if (!sink) 00622 return CONNECT_E_NOCONNECTION; 00623 00624 list_remove(&sink->entry); 00625 free_sink(sink); 00626 00627 return S_OK; 00628 } 00629 00630 static const ITfSourceVtbl Compartment_SourceVtbl = 00631 { 00632 Source_QueryInterface, 00633 Source_AddRef, 00634 Source_Release, 00635 00636 CompartmentSource_AdviseSink, 00637 CompartmentSource_UnadviseSink, 00638 }; 00639 00640 static HRESULT Compartment_Constructor(CompartmentValue *valueData, ITfCompartment **ppOut) 00641 { 00642 Compartment *This; 00643 00644 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Compartment)); 00645 if (This == NULL) 00646 return E_OUTOFMEMORY; 00647 00648 This->Vtbl= &ITfCompartment_Vtbl; 00649 This->SourceVtbl = &Compartment_SourceVtbl; 00650 This->refCount = 1; 00651 00652 This->valueData = valueData; 00653 VariantInit(&This->variant); 00654 00655 list_init(&This->CompartmentEventSink); 00656 00657 TRACE("returning %p\n", This); 00658 *ppOut = (ITfCompartment*)This; 00659 return S_OK; 00660 } Generated on Sun May 27 2012 04:24:49 for ReactOS by
1.7.6.1
|