[CRT] Massively improve performance of rand_s
[reactos.git] / dll / win32 / ole32 / antimoniker.c
1 /*
2 * AntiMonikers implementation
3 *
4 * Copyright 1999 Noomen Hamza
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
24
25 #define COBJMACROS
26 #define NONAMELESSUNION
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "wine/debug.h"
33 #include "moniker.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
36
37 /* AntiMoniker data structure */
38 typedef struct AntiMonikerImpl{
39 IMoniker IMoniker_iface;
40 IROTData IROTData_iface;
41 LONG ref;
42 IUnknown *pMarshal; /* custom marshaler */
43 } AntiMonikerImpl;
44
45 static inline AntiMonikerImpl *impl_from_IMoniker(IMoniker *iface)
46 {
47 return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
48 }
49
50 static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface)
51 {
52 return CONTAINING_RECORD(iface, AntiMonikerImpl, IROTData_iface);
53 }
54
55
56 /*******************************************************************************
57 * AntiMoniker_QueryInterface
58 *******************************************************************************/
59 static HRESULT WINAPI
60 AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
61 {
62 AntiMonikerImpl *This = impl_from_IMoniker(iface);
63
64 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
65
66 /* Perform a sanity check on the parameters.*/
67 if ( ppvObject==0 )
68 return E_INVALIDARG;
69
70 /* Initialize the return parameter */
71 *ppvObject = 0;
72
73 /* Compare the riid with the interface IDs implemented by this object.*/
74 if (IsEqualIID(&IID_IUnknown, riid) ||
75 IsEqualIID(&IID_IPersist, riid) ||
76 IsEqualIID(&IID_IPersistStream, riid) ||
77 IsEqualIID(&IID_IMoniker, riid))
78 *ppvObject = iface;
79 else if (IsEqualIID(&IID_IROTData, riid))
80 *ppvObject = &This->IROTData_iface;
81 else if (IsEqualIID(&IID_IMarshal, riid))
82 {
83 HRESULT hr = S_OK;
84 if (!This->pMarshal)
85 hr = MonikerMarshal_Create(iface, &This->pMarshal);
86 if (hr != S_OK)
87 return hr;
88 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
89 }
90
91 /* Check that we obtained an interface.*/
92 if ((*ppvObject)==0)
93 return E_NOINTERFACE;
94
95 /* always increase the reference count by one when it is successful */
96 IMoniker_AddRef(iface);
97
98 return S_OK;
99 }
100
101 /******************************************************************************
102 * AntiMoniker_AddRef
103 ******************************************************************************/
104 static ULONG WINAPI
105 AntiMonikerImpl_AddRef(IMoniker* iface)
106 {
107 AntiMonikerImpl *This = impl_from_IMoniker(iface);
108
109 TRACE("(%p)\n",This);
110
111 return InterlockedIncrement(&This->ref);
112 }
113
114 /******************************************************************************
115 * AntiMoniker_Release
116 ******************************************************************************/
117 static ULONG WINAPI
118 AntiMonikerImpl_Release(IMoniker* iface)
119 {
120 AntiMonikerImpl *This = impl_from_IMoniker(iface);
121 ULONG ref;
122
123 TRACE("(%p)\n",This);
124
125 ref = InterlockedDecrement(&This->ref);
126
127 /* destroy the object if there are no more references to it */
128 if (ref == 0)
129 {
130 if (This->pMarshal) IUnknown_Release(This->pMarshal);
131 HeapFree(GetProcessHeap(),0,This);
132 }
133
134 return ref;
135 }
136
137 /******************************************************************************
138 * AntiMoniker_GetClassID
139 ******************************************************************************/
140 static HRESULT WINAPI
141 AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
142 {
143 TRACE("(%p,%p)\n",iface,pClassID);
144
145 if (pClassID==NULL)
146 return E_POINTER;
147
148 *pClassID = CLSID_AntiMoniker;
149
150 return S_OK;
151 }
152
153 /******************************************************************************
154 * AntiMoniker_IsDirty
155 ******************************************************************************/
156 static HRESULT WINAPI
157 AntiMonikerImpl_IsDirty(IMoniker* iface)
158 {
159 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
160 method in the OLE-provided moniker interfaces always return S_FALSE because
161 their internal state never changes. */
162
163 TRACE("(%p)\n",iface);
164
165 return S_FALSE;
166 }
167
168 /******************************************************************************
169 * AntiMoniker_Load
170 ******************************************************************************/
171 static HRESULT WINAPI
172 AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm)
173 {
174 DWORD constant=1,dwbuffer;
175 HRESULT res;
176
177 /* data read by this function is only a DWORD constant (must be 1) ! */
178 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),NULL);
179
180 if (SUCCEEDED(res)&& dwbuffer!=constant)
181 return E_FAIL;
182
183 return res;
184 }
185
186 /******************************************************************************
187 * AntiMoniker_Save
188 ******************************************************************************/
189 static HRESULT WINAPI
190 AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
191 {
192 static const DWORD constant = 1;
193 /* data written by this function is only a DWORD constant set to 1 ! */
194 return IStream_Write(pStm,&constant,sizeof(constant),NULL);
195 }
196
197 /******************************************************************************
198 * AntiMoniker_GetSizeMax
199 *
200 * PARAMS
201 * pcbSize [out] Pointer to size of stream needed to save object
202 ******************************************************************************/
203 static HRESULT WINAPI
204 AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
205 {
206 TRACE("(%p,%p)\n",iface,pcbSize);
207
208 if (!pcbSize)
209 return E_POINTER;
210
211 /* for more details see AntiMonikerImpl_Save comments */
212
213 /*
214 * Normally the sizemax must be sizeof DWORD, but
215 * I tested this function it usually return 16 bytes
216 * more than the number of bytes used by AntiMoniker::Save function
217 */
218 pcbSize->u.LowPart = sizeof(DWORD)+16;
219
220 pcbSize->u.HighPart=0;
221
222 return S_OK;
223 }
224
225 /******************************************************************************
226 * AntiMoniker_BindToObject
227 ******************************************************************************/
228 static HRESULT WINAPI
229 AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
230 REFIID riid, VOID** ppvResult)
231 {
232 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
233 return E_NOTIMPL;
234 }
235
236 /******************************************************************************
237 * AntiMoniker_BindToStorage
238 ******************************************************************************/
239 static HRESULT WINAPI
240 AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
241 REFIID riid, VOID** ppvResult)
242 {
243 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
244 return E_NOTIMPL;
245 }
246
247 /******************************************************************************
248 * AntiMoniker_Reduce
249 ******************************************************************************/
250 static HRESULT WINAPI
251 AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
252 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
253 {
254 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
255
256 if (ppmkReduced==NULL)
257 return E_POINTER;
258
259 AntiMonikerImpl_AddRef(iface);
260
261 *ppmkReduced=iface;
262
263 return MK_S_REDUCED_TO_SELF;
264 }
265 /******************************************************************************
266 * AntiMoniker_ComposeWith
267 ******************************************************************************/
268 static HRESULT WINAPI
269 AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
270 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
271 {
272
273 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
274
275 if ((ppmkComposite==NULL)||(pmkRight==NULL))
276 return E_POINTER;
277
278 *ppmkComposite=0;
279
280 if (fOnlyIfNotGeneric)
281 return MK_E_NEEDGENERIC;
282 else
283 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
284 }
285
286 /******************************************************************************
287 * AntiMoniker_Enum
288 ******************************************************************************/
289 static HRESULT WINAPI
290 AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
291 {
292 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
293
294 if (ppenumMoniker == NULL)
295 return E_POINTER;
296
297 *ppenumMoniker = NULL;
298
299 return S_OK;
300 }
301
302 /******************************************************************************
303 * AntiMoniker_IsEqual
304 ******************************************************************************/
305 static HRESULT WINAPI
306 AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
307 {
308 DWORD mkSys;
309
310 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
311
312 if (pmkOtherMoniker==NULL)
313 return S_FALSE;
314
315 IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
316
317 if (mkSys==MKSYS_ANTIMONIKER)
318 return S_OK;
319 else
320 return S_FALSE;
321 }
322
323 /******************************************************************************
324 * AntiMoniker_Hash
325 ******************************************************************************/
326 static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
327 {
328 if (pdwHash==NULL)
329 return E_POINTER;
330
331 *pdwHash = 0x80000001;
332
333 return S_OK;
334 }
335
336 /******************************************************************************
337 * AntiMoniker_IsRunning
338 ******************************************************************************/
339 static HRESULT WINAPI
340 AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
341 IMoniker* pmkNewlyRunning)
342 {
343 IRunningObjectTable* rot;
344 HRESULT res;
345
346 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
347
348 if (pbc==NULL)
349 return E_INVALIDARG;
350
351 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
352
353 if (FAILED(res))
354 return res;
355
356 res = IRunningObjectTable_IsRunning(rot,iface);
357
358 IRunningObjectTable_Release(rot);
359
360 return res;
361 }
362
363 /******************************************************************************
364 * AntiMoniker_GetTimeOfLastChange
365 ******************************************************************************/
366 static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
367 IBindCtx* pbc,
368 IMoniker* pmkToLeft,
369 FILETIME* pAntiTime)
370 {
371 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
372 return E_NOTIMPL;
373 }
374
375 /******************************************************************************
376 * AntiMoniker_Inverse
377 ******************************************************************************/
378 static HRESULT WINAPI
379 AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
380 {
381 TRACE("(%p,%p)\n",iface,ppmk);
382
383 if (ppmk==NULL)
384 return E_POINTER;
385
386 *ppmk=0;
387
388 return MK_E_NOINVERSE;
389 }
390
391 /******************************************************************************
392 * AntiMoniker_CommonPrefixWith
393 ******************************************************************************/
394 static HRESULT WINAPI
395 AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
396 {
397 DWORD mkSys;
398
399 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
400
401 if(mkSys==MKSYS_ANTIMONIKER){
402
403 IMoniker_AddRef(iface);
404
405 *ppmkPrefix=iface;
406
407 IMoniker_AddRef(iface);
408
409 return MK_S_US;
410 }
411 else
412 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
413 }
414
415 /******************************************************************************
416 * AntiMoniker_RelativePathTo
417 ******************************************************************************/
418 static HRESULT WINAPI
419 AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
420 {
421 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
422
423 if (ppmkRelPath==NULL)
424 return E_POINTER;
425
426 IMoniker_AddRef(pmOther);
427
428 *ppmkRelPath=pmOther;
429
430 return MK_S_HIM;
431 }
432
433 /******************************************************************************
434 * AntiMoniker_GetDisplayName
435 ******************************************************************************/
436 static HRESULT WINAPI
437 AntiMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
438 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
439 {
440 static const WCHAR back[]={'\\','.','.',0};
441
442 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
443
444 if (ppszDisplayName==NULL)
445 return E_POINTER;
446
447 if (pmkToLeft!=NULL){
448 FIXME("() pmkToLeft!=NULL not implemented\n");
449 return E_NOTIMPL;
450 }
451
452 *ppszDisplayName=CoTaskMemAlloc(sizeof(back));
453
454 if (*ppszDisplayName==NULL)
455 return E_OUTOFMEMORY;
456
457 lstrcpyW(*ppszDisplayName,back);
458
459 return S_OK;
460 }
461
462 /******************************************************************************
463 * AntiMoniker_ParseDisplayName
464 ******************************************************************************/
465 static HRESULT WINAPI
466 AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
467 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
468 ULONG* pchEaten, IMoniker** ppmkOut)
469 {
470 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
471 return E_NOTIMPL;
472 }
473
474 /******************************************************************************
475 * AntiMoniker_IsSystemMoniker
476 ******************************************************************************/
477 static HRESULT WINAPI
478 AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
479 {
480 TRACE("(%p,%p)\n",iface,pwdMksys);
481
482 if (!pwdMksys)
483 return E_POINTER;
484
485 (*pwdMksys)=MKSYS_ANTIMONIKER;
486
487 return S_OK;
488 }
489
490 /*******************************************************************************
491 * AntiMonikerIROTData_QueryInterface
492 *******************************************************************************/
493 static HRESULT WINAPI
494 AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
495 {
496 AntiMonikerImpl *This = impl_from_IROTData(iface);
497
498 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
499
500 return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
501 }
502
503 /***********************************************************************
504 * AntiMonikerIROTData_AddRef
505 */
506 static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
507 {
508 AntiMonikerImpl *This = impl_from_IROTData(iface);
509
510 TRACE("(%p)\n",iface);
511
512 return AntiMonikerImpl_AddRef(&This->IMoniker_iface);
513 }
514
515 /***********************************************************************
516 * AntiMonikerIROTData_Release
517 */
518 static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
519 {
520 AntiMonikerImpl *This = impl_from_IROTData(iface);
521
522 TRACE("(%p)\n",iface);
523
524 return AntiMonikerImpl_Release(&This->IMoniker_iface);
525 }
526
527 /******************************************************************************
528 * AntiMonikerIROTData_GetComparisonData
529 ******************************************************************************/
530 static HRESULT WINAPI
531 AntiMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,
532 ULONG cbMax, ULONG* pcbData)
533 {
534 DWORD constant = 1;
535
536 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
537
538 *pcbData = sizeof(CLSID) + sizeof(DWORD);
539 if (cbMax < *pcbData)
540 return E_OUTOFMEMORY;
541
542 memcpy(pbData, &CLSID_AntiMoniker, sizeof(CLSID));
543 memcpy(pbData+sizeof(CLSID), &constant, sizeof(DWORD));
544
545 return S_OK;
546 }
547
548 /********************************************************************************/
549 /* Virtual function table for the AntiMonikerImpl class which include IPersist,*/
550 /* IPersistStream and IMoniker functions. */
551 static const IMonikerVtbl VT_AntiMonikerImpl =
552 {
553 AntiMonikerImpl_QueryInterface,
554 AntiMonikerImpl_AddRef,
555 AntiMonikerImpl_Release,
556 AntiMonikerImpl_GetClassID,
557 AntiMonikerImpl_IsDirty,
558 AntiMonikerImpl_Load,
559 AntiMonikerImpl_Save,
560 AntiMonikerImpl_GetSizeMax,
561 AntiMonikerImpl_BindToObject,
562 AntiMonikerImpl_BindToStorage,
563 AntiMonikerImpl_Reduce,
564 AntiMonikerImpl_ComposeWith,
565 AntiMonikerImpl_Enum,
566 AntiMonikerImpl_IsEqual,
567 AntiMonikerImpl_Hash,
568 AntiMonikerImpl_IsRunning,
569 AntiMonikerImpl_GetTimeOfLastChange,
570 AntiMonikerImpl_Inverse,
571 AntiMonikerImpl_CommonPrefixWith,
572 AntiMonikerImpl_RelativePathTo,
573 AntiMonikerImpl_GetDisplayName,
574 AntiMonikerImpl_ParseDisplayName,
575 AntiMonikerImpl_IsSystemMoniker
576 };
577
578 /********************************************************************************/
579 /* Virtual function table for the IROTData class. */
580 static const IROTDataVtbl VT_ROTDataImpl =
581 {
582 AntiMonikerROTDataImpl_QueryInterface,
583 AntiMonikerROTDataImpl_AddRef,
584 AntiMonikerROTDataImpl_Release,
585 AntiMonikerROTDataImpl_GetComparisonData
586 };
587
588 /******************************************************************************
589 * AntiMoniker_Construct (local function)
590 *******************************************************************************/
591 static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This)
592 {
593
594 TRACE("(%p)\n",This);
595
596 /* Initialize the virtual function table. */
597 This->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl;
598 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
599 This->ref = 0;
600 This->pMarshal = NULL;
601
602 return S_OK;
603 }
604
605 /******************************************************************************
606 * CreateAntiMoniker [OLE32.@]
607 ******************************************************************************/
608 HRESULT WINAPI CreateAntiMoniker(IMoniker **ppmk)
609 {
610 AntiMonikerImpl* newAntiMoniker;
611 HRESULT hr;
612
613 TRACE("(%p)\n",ppmk);
614
615 newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl));
616
617 if (newAntiMoniker == 0)
618 return STG_E_INSUFFICIENTMEMORY;
619
620 hr = AntiMonikerImpl_Construct(newAntiMoniker);
621 if (FAILED(hr))
622 {
623 HeapFree(GetProcessHeap(),0,newAntiMoniker);
624 return hr;
625 }
626
627 return AntiMonikerImpl_QueryInterface(&newAntiMoniker->IMoniker_iface, &IID_IMoniker,
628 (void**)ppmk);
629 }
630
631 HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
632 IUnknown *pUnk, REFIID riid, void **ppv)
633 {
634 IMoniker *pMoniker;
635 HRESULT hr;
636
637 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
638
639 *ppv = NULL;
640
641 if (pUnk)
642 return CLASS_E_NOAGGREGATION;
643
644 hr = CreateAntiMoniker(&pMoniker);
645 if (FAILED(hr))
646 return hr;
647
648 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
649
650 if (FAILED(hr))
651 IMoniker_Release(pMoniker);
652
653 return hr;
654 }