Sync with trunk revision 63128.
[reactos.git] / dll / win32 / oleaut32 / oleaut.c
1 /*
2 * OLEAUT32
3 *
4 * Copyright 1999, 2000 Marcus Meissner
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 "precomp.h"
22
23 #include <initguid.h>
24 #include <oleaut32_oaidl.h>
25
26 #include "typelib.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(ole);
29 WINE_DECLARE_DEBUG_CHANNEL(heap);
30
31 /******************************************************************************
32 * BSTR {OLEAUT32}
33 *
34 * NOTES
35 * BSTR is a simple typedef for a wide-character string used as the principle
36 * string type in ole automation. When encapsulated in a Variant type they are
37 * automatically copied and destroyed as the variant is processed.
38 *
39 * The low level BSTR API allows manipulation of these strings and is used by
40 * higher level API calls to manage the strings transparently to the caller.
41 *
42 * Internally the BSTR type is allocated with space for a DWORD byte count before
43 * the string data begins. This is undocumented and non-system code should not
44 * access the count directly. Use SysStringLen() or SysStringByteLen()
45 * instead. Note that the byte count does not include the terminating NUL.
46 *
47 * To create a new BSTR, use SysAllocString(), SysAllocStringLen() or
48 * SysAllocStringByteLen(). To change the size of an existing BSTR, use SysReAllocString()
49 * or SysReAllocStringLen(). Finally to destroy a string use SysFreeString().
50 *
51 * BSTR's are cached by Ole Automation by default. To override this behaviour
52 * either set the environment variable 'OANOCACHE', or call SetOaNoCache().
53 *
54 * SEE ALSO
55 * 'Inside OLE, second edition' by Kraig Brockshmidt.
56 */
57
58 static BOOL bstr_cache_enabled;
59
60 static CRITICAL_SECTION cs_bstr_cache;
61 static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg =
62 {
63 0, 0, &cs_bstr_cache,
64 { &cs_bstr_cache_dbg.ProcessLocksList, &cs_bstr_cache_dbg.ProcessLocksList },
65 0, 0, { (DWORD_PTR)(__FILE__ ": bstr_cache") }
66 };
67 static CRITICAL_SECTION cs_bstr_cache = { &cs_bstr_cache_dbg, -1, 0, 0, 0, 0 };
68
69 typedef struct {
70 DWORD size;
71 union {
72 char ptr[1];
73 WCHAR str[1];
74 DWORD dwptr[1];
75 } u;
76 } bstr_t;
77
78 #define BUCKET_SIZE 16
79 #define BUCKET_BUFFER_SIZE 6
80
81 typedef struct {
82 unsigned short head;
83 unsigned short cnt;
84 bstr_t *buf[BUCKET_BUFFER_SIZE];
85 } bstr_cache_entry_t;
86
87 #define ARENA_INUSE_FILLER 0x55
88 #define ARENA_TAIL_FILLER 0xab
89 #define ARENA_FREE_FILLER 0xfeeefeee
90
91 static bstr_cache_entry_t bstr_cache[0x10000/BUCKET_SIZE];
92
93 static inline size_t bstr_alloc_size(size_t size)
94 {
95 return (FIELD_OFFSET(bstr_t, u.ptr[size]) + sizeof(WCHAR) + BUCKET_SIZE-1) & ~(BUCKET_SIZE-1);
96 }
97
98 static inline bstr_t *bstr_from_str(BSTR str)
99 {
100 return CONTAINING_RECORD(str, bstr_t, u.str);
101 }
102
103 static inline bstr_cache_entry_t *get_cache_entry(size_t size)
104 {
105 unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size-1])/BUCKET_SIZE;
106 return bstr_cache_enabled && cache_idx < sizeof(bstr_cache)/sizeof(*bstr_cache)
107 ? bstr_cache + cache_idx
108 : NULL;
109 }
110
111 static bstr_t *alloc_bstr(size_t size)
112 {
113 bstr_cache_entry_t *cache_entry = get_cache_entry(size+sizeof(WCHAR));
114 bstr_t *ret;
115
116 if(cache_entry) {
117 EnterCriticalSection(&cs_bstr_cache);
118
119 if(!cache_entry->cnt) {
120 cache_entry = get_cache_entry(size+sizeof(WCHAR)+BUCKET_SIZE);
121 if(cache_entry && !cache_entry->cnt)
122 cache_entry = NULL;
123 }
124
125 if(cache_entry) {
126 ret = cache_entry->buf[cache_entry->head++];
127 cache_entry->head %= BUCKET_BUFFER_SIZE;
128 cache_entry->cnt--;
129 }
130
131 LeaveCriticalSection(&cs_bstr_cache);
132
133 if(cache_entry) {
134 if(WARN_ON(heap)) {
135 size_t tail;
136
137 memset(ret, ARENA_INUSE_FILLER, FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)]));
138 tail = bstr_alloc_size(size) - FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)]);
139 if(tail)
140 memset(ret->u.ptr+size+sizeof(WCHAR), ARENA_TAIL_FILLER, tail);
141 }
142 ret->size = size;
143 return ret;
144 }
145 }
146
147 ret = HeapAlloc(GetProcessHeap(), 0, bstr_alloc_size(size));
148 if(ret)
149 ret->size = size;
150 return ret;
151 }
152
153 /******************************************************************************
154 * SysStringLen [OLEAUT32.7]
155 *
156 * Get the allocated length of a BSTR in wide characters.
157 *
158 * PARAMS
159 * str [I] BSTR to find the length of
160 *
161 * RETURNS
162 * The allocated length of str, or 0 if str is NULL.
163 *
164 * NOTES
165 * See BSTR.
166 * The returned length may be different from the length of the string as
167 * calculated by lstrlenW(), since it returns the length that was used to
168 * allocate the string by SysAllocStringLen().
169 */
170 UINT WINAPI SysStringLen(BSTR str)
171 {
172 return str ? bstr_from_str(str)->size/sizeof(WCHAR) : 0;
173 }
174
175 /******************************************************************************
176 * SysStringByteLen [OLEAUT32.149]
177 *
178 * Get the allocated length of a BSTR in bytes.
179 *
180 * PARAMS
181 * str [I] BSTR to find the length of
182 *
183 * RETURNS
184 * The allocated length of str, or 0 if str is NULL.
185 *
186 * NOTES
187 * See SysStringLen(), BSTR().
188 */
189 UINT WINAPI SysStringByteLen(BSTR str)
190 {
191 return str ? bstr_from_str(str)->size : 0;
192 }
193
194 /******************************************************************************
195 * SysAllocString [OLEAUT32.2]
196 *
197 * Create a BSTR from an OLESTR.
198 *
199 * PARAMS
200 * str [I] Source to create BSTR from
201 *
202 * RETURNS
203 * Success: A BSTR allocated with SysAllocStringLen().
204 * Failure: NULL, if oleStr is NULL.
205 *
206 * NOTES
207 * See BSTR.
208 * MSDN (October 2001) incorrectly states that NULL is returned if oleStr has
209 * a length of 0. Native Win32 and this implementation both return a valid
210 * empty BSTR in this case.
211 */
212 BSTR WINAPI SysAllocString(LPCOLESTR str)
213 {
214 if (!str) return 0;
215
216 /* Delegate this to the SysAllocStringLen32 method. */
217 return SysAllocStringLen(str, lstrlenW(str));
218 }
219
220 /******************************************************************************
221 * SysFreeString [OLEAUT32.6]
222 *
223 * Free a BSTR.
224 *
225 * PARAMS
226 * str [I] BSTR to free.
227 *
228 * RETURNS
229 * Nothing.
230 *
231 * NOTES
232 * See BSTR.
233 * str may be NULL, in which case this function does nothing.
234 */
235 void WINAPI SysFreeString(BSTR str)
236 {
237 bstr_cache_entry_t *cache_entry;
238 bstr_t *bstr;
239
240 if(!str)
241 return;
242
243 bstr = bstr_from_str(str);
244 cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR));
245 if(cache_entry) {
246 unsigned i;
247
248 EnterCriticalSection(&cs_bstr_cache);
249
250 /* According to tests, freeing a string that's already in cache doesn't corrupt anything.
251 * For that to work we need to search the cache. */
252 for(i=0; i < cache_entry->cnt; i++) {
253 if(cache_entry->buf[(cache_entry->head+i) % BUCKET_BUFFER_SIZE] == bstr) {
254 WARN_(heap)("String already is in cache!\n");
255 LeaveCriticalSection(&cs_bstr_cache);
256 return;
257 }
258 }
259
260 if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
261 cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr;
262 cache_entry->cnt++;
263
264 if(WARN_ON(heap)) {
265 unsigned n = bstr_alloc_size(bstr->size) / sizeof(DWORD) - 1;
266 bstr->size = ARENA_FREE_FILLER;
267 for(i=0; i<n; i++)
268 bstr->u.dwptr[i] = ARENA_FREE_FILLER;
269 }
270
271 LeaveCriticalSection(&cs_bstr_cache);
272 return;
273 }
274
275 LeaveCriticalSection(&cs_bstr_cache);
276 }
277
278 HeapFree(GetProcessHeap(), 0, bstr);
279 }
280
281 /******************************************************************************
282 * SysAllocStringLen [OLEAUT32.4]
283 *
284 * Create a BSTR from an OLESTR of a given wide character length.
285 *
286 * PARAMS
287 * str [I] Source to create BSTR from
288 * len [I] Length of oleStr in wide characters
289 *
290 * RETURNS
291 * Success: A newly allocated BSTR from SysAllocStringByteLen()
292 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
293 *
294 * NOTES
295 * See BSTR(), SysAllocStringByteLen().
296 */
297 BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
298 {
299 bstr_t *bstr;
300 DWORD size;
301
302 /* Detect integer overflow. */
303 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
304 return NULL;
305
306 TRACE("%s\n", debugstr_wn(str, len));
307
308 size = len*sizeof(WCHAR);
309 bstr = alloc_bstr(size);
310 if(!bstr)
311 return NULL;
312
313 if(str) {
314 memcpy(bstr->u.str, str, size);
315 bstr->u.str[len] = 0;
316 }else {
317 memset(bstr->u.str, 0, size+sizeof(WCHAR));
318 }
319
320 return bstr->u.str;
321 }
322
323 /******************************************************************************
324 * SysReAllocStringLen [OLEAUT32.5]
325 *
326 * Change the length of a previously created BSTR.
327 *
328 * PARAMS
329 * old [O] BSTR to change the length of
330 * str [I] New source for pbstr
331 * len [I] Length of oleStr in wide characters
332 *
333 * RETURNS
334 * Success: 1. The size of pbstr is updated.
335 * Failure: 0, if len >= 0x80000000 or memory allocation fails.
336 *
337 * NOTES
338 * See BSTR(), SysAllocStringByteLen().
339 * *old may be changed by this function.
340 */
341 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
342 {
343 /* Detect integer overflow. */
344 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
345 return 0;
346
347 if (*old!=NULL) {
348 BSTR old_copy = *old;
349 DWORD newbytelen = len*sizeof(WCHAR);
350 bstr_t *bstr = HeapReAlloc(GetProcessHeap(),0,((DWORD*)*old)-1,bstr_alloc_size(newbytelen));
351 *old = bstr->u.str;
352 bstr->size = newbytelen;
353 /* Subtle hidden feature: The old string data is still there
354 * when 'in' is NULL!
355 * Some Microsoft program needs it.
356 * FIXME: Is it a sideeffect of BSTR caching?
357 */
358 if (str && old_copy!=str) memmove(*old, str, newbytelen);
359 (*old)[len] = 0;
360 } else {
361 /*
362 * Allocate the new string
363 */
364 *old = SysAllocStringLen(str, len);
365 }
366
367 return 1;
368 }
369
370 /******************************************************************************
371 * SysAllocStringByteLen [OLEAUT32.150]
372 *
373 * Create a BSTR from an OLESTR of a given byte length.
374 *
375 * PARAMS
376 * str [I] Source to create BSTR from
377 * len [I] Length of oleStr in bytes
378 *
379 * RETURNS
380 * Success: A newly allocated BSTR
381 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
382 *
383 * NOTES
384 * -If len is 0 or oleStr is NULL the resulting string is empty ("").
385 * -This function always NUL terminates the resulting BSTR.
386 * -oleStr may be either an LPCSTR or LPCOLESTR, since it is copied
387 * without checking for a terminating NUL.
388 * See BSTR.
389 */
390 BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len)
391 {
392 bstr_t *bstr;
393
394 /* Detect integer overflow. */
395 if (len >= (UINT_MAX-sizeof(WCHAR)-sizeof(DWORD)))
396 return NULL;
397
398 bstr = alloc_bstr(len);
399 if(!bstr)
400 return NULL;
401
402 if(str) {
403 memcpy(bstr->u.ptr, str, len);
404 bstr->u.ptr[len] = bstr->u.ptr[len+1] = 0;
405 }else {
406 memset(bstr->u.ptr, 0, len+sizeof(WCHAR));
407 }
408
409 return bstr->u.str;
410 }
411
412 /******************************************************************************
413 * SysReAllocString [OLEAUT32.3]
414 *
415 * Change the length of a previously created BSTR.
416 *
417 * PARAMS
418 * old [I/O] BSTR to change the length of
419 * str [I] New source for pbstr
420 *
421 * RETURNS
422 * Success: 1
423 * Failure: 0.
424 *
425 * NOTES
426 * See BSTR(), SysAllocStringStringLen().
427 */
428 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR str)
429 {
430 /*
431 * Sanity check
432 */
433 if (old==NULL)
434 return 0;
435
436 /*
437 * Make sure we free the old string.
438 */
439 SysFreeString(*old);
440
441 /*
442 * Allocate the new string
443 */
444 *old = SysAllocString(str);
445
446 return 1;
447 }
448
449 /******************************************************************************
450 * SetOaNoCache (OLEAUT32.327)
451 *
452 * Instruct Ole Automation not to cache BSTR allocations.
453 *
454 * PARAMS
455 * None.
456 *
457 * RETURNS
458 * Nothing.
459 *
460 * NOTES
461 * SetOaNoCache does not release cached strings, so it leaks by design.
462 */
463 void WINAPI SetOaNoCache(void)
464 {
465 TRACE("\n");
466 bstr_cache_enabled = FALSE;
467 }
468
469 static const WCHAR _delimiter[] = {'!',0}; /* default delimiter apparently */
470 static const WCHAR *pdelimiter = &_delimiter[0];
471
472 /***********************************************************************
473 * RegisterActiveObject (OLEAUT32.33)
474 *
475 * Registers an object in the global item table.
476 *
477 * PARAMS
478 * punk [I] Object to register.
479 * rcid [I] CLSID of the object.
480 * dwFlags [I] Flags.
481 * pdwRegister [O] Address to store cookie of object registration in.
482 *
483 * RETURNS
484 * Success: S_OK.
485 * Failure: HRESULT code.
486 */
487 HRESULT WINAPI RegisterActiveObject(
488 LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
489 ) {
490 WCHAR guidbuf[80];
491 HRESULT ret;
492 LPRUNNINGOBJECTTABLE runobtable;
493 LPMONIKER moniker;
494 DWORD rot_flags = ROTFLAGS_REGISTRATIONKEEPSALIVE; /* default registration is strong */
495
496 StringFromGUID2(rcid,guidbuf,39);
497 ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
498 if (FAILED(ret))
499 return ret;
500 ret = GetRunningObjectTable(0,&runobtable);
501 if (FAILED(ret)) {
502 IMoniker_Release(moniker);
503 return ret;
504 }
505 if(dwFlags == ACTIVEOBJECT_WEAK)
506 rot_flags = 0;
507 ret = IRunningObjectTable_Register(runobtable,rot_flags,punk,moniker,pdwRegister);
508 IRunningObjectTable_Release(runobtable);
509 IMoniker_Release(moniker);
510 return ret;
511 }
512
513 /***********************************************************************
514 * RevokeActiveObject (OLEAUT32.34)
515 *
516 * Revokes an object from the global item table.
517 *
518 * PARAMS
519 * xregister [I] Registration cookie.
520 * reserved [I] Reserved. Set to NULL.
521 *
522 * RETURNS
523 * Success: S_OK.
524 * Failure: HRESULT code.
525 */
526 HRESULT WINAPI RevokeActiveObject(DWORD xregister,LPVOID reserved)
527 {
528 LPRUNNINGOBJECTTABLE runobtable;
529 HRESULT ret;
530
531 ret = GetRunningObjectTable(0,&runobtable);
532 if (FAILED(ret)) return ret;
533 ret = IRunningObjectTable_Revoke(runobtable,xregister);
534 if (SUCCEEDED(ret)) ret = S_OK;
535 IRunningObjectTable_Release(runobtable);
536 return ret;
537 }
538
539 /***********************************************************************
540 * GetActiveObject (OLEAUT32.35)
541 *
542 * Gets an object from the global item table.
543 *
544 * PARAMS
545 * rcid [I] CLSID of the object.
546 * preserved [I] Reserved. Set to NULL.
547 * ppunk [O] Address to store object into.
548 *
549 * RETURNS
550 * Success: S_OK.
551 * Failure: HRESULT code.
552 */
553 HRESULT WINAPI GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
554 {
555 WCHAR guidbuf[80];
556 HRESULT ret;
557 LPRUNNINGOBJECTTABLE runobtable;
558 LPMONIKER moniker;
559
560 StringFromGUID2(rcid,guidbuf,39);
561 ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
562 if (FAILED(ret))
563 return ret;
564 ret = GetRunningObjectTable(0,&runobtable);
565 if (FAILED(ret)) {
566 IMoniker_Release(moniker);
567 return ret;
568 }
569 ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk);
570 IRunningObjectTable_Release(runobtable);
571 IMoniker_Release(moniker);
572 return ret;
573 }
574
575
576 /***********************************************************************
577 * OaBuildVersion [OLEAUT32.170]
578 *
579 * Get the Ole Automation build version.
580 *
581 * PARAMS
582 * None
583 *
584 * RETURNS
585 * The build version.
586 *
587 * NOTES
588 * Known oleaut32.dll versions:
589 *| OLE Ver. Comments Date Build Ver.
590 *| -------- ------------------------- ---- ---------
591 *| OLE 2.1 NT 1993-95 10 3023
592 *| OLE 2.1 10 3027
593 *| Win32s Ver 1.1e 20 4049
594 *| OLE 2.20 W95/NT 1993-96 20 4112
595 *| OLE 2.20 W95/NT 1993-96 20 4118
596 *| OLE 2.20 W95/NT 1993-96 20 4122
597 *| OLE 2.30 W95/NT 1993-98 30 4265
598 *| OLE 2.40 NT?? 1993-98 40 4267
599 *| OLE 2.40 W98 SE orig. file 1993-98 40 4275
600 *| OLE 2.40 W2K orig. file 1993-XX 40 4514
601 *
602 * Currently the versions returned are 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
603 * and 2.40 for all later versions. The build number is maximum, i.e. 0xffff.
604 */
605 ULONG WINAPI OaBuildVersion(void)
606 {
607 switch(GetVersion() & 0x8000ffff) /* mask off build number */
608 {
609 case 0x80000a03: /* WIN31 */
610 return MAKELONG(0xffff, 20);
611 case 0x00003303: /* NT351 */
612 return MAKELONG(0xffff, 30);
613 case 0x80000004: /* WIN95; I'd like to use the "standard" w95 minor
614 version here (30), but as we still use w95
615 as default winver (which is good IMHO), I better
616 play safe and use the latest value for w95 for now.
617 Change this as soon as default winver gets changed
618 to something more recent */
619 case 0x80000a04: /* WIN98 */
620 case 0x00000004: /* NT40 */
621 case 0x00000005: /* W2K */
622 return MAKELONG(0xffff, 40);
623 case 0x00000105: /* WinXP */
624 case 0x00000006: /* Vista */
625 case 0x00000106: /* Win7 */
626 return MAKELONG(0xffff, 50);
627 default:
628 FIXME("Version value not known yet. Please investigate it !\n");
629 return MAKELONG(0xffff, 40); /* for now return the same value as for w2k */
630 }
631 }
632
633 /******************************************************************************
634 * OleTranslateColor [OLEAUT32.421]
635 *
636 * Convert an OLE_COLOR to a COLORREF.
637 *
638 * PARAMS
639 * clr [I] Color to convert
640 * hpal [I] Handle to a palette for the conversion
641 * pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok
642 *
643 * RETURNS
644 * Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL.
645 * Failure: E_INVALIDARG, if any argument is invalid.
646 *
647 * FIXME
648 * Document the conversion rules.
649 */
650 HRESULT WINAPI OleTranslateColor(
651 OLE_COLOR clr,
652 HPALETTE hpal,
653 COLORREF* pColorRef)
654 {
655 COLORREF colorref;
656 BYTE b = HIBYTE(HIWORD(clr));
657
658 TRACE("(%08x, %p, %p)\n", clr, hpal, pColorRef);
659
660 /*
661 * In case pColorRef is NULL, provide our own to simplify the code.
662 */
663 if (pColorRef == NULL)
664 pColorRef = &colorref;
665
666 switch (b)
667 {
668 case 0x00:
669 {
670 if (hpal != 0)
671 *pColorRef = PALETTERGB(GetRValue(clr),
672 GetGValue(clr),
673 GetBValue(clr));
674 else
675 *pColorRef = clr;
676
677 break;
678 }
679
680 case 0x01:
681 {
682 if (hpal != 0)
683 {
684 PALETTEENTRY pe;
685 /*
686 * Validate the palette index.
687 */
688 if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
689 return E_INVALIDARG;
690 }
691
692 *pColorRef = clr;
693
694 break;
695 }
696
697 case 0x02:
698 *pColorRef = clr;
699 break;
700
701 case 0x80:
702 {
703 int index = LOBYTE(LOWORD(clr));
704
705 /*
706 * Validate GetSysColor index.
707 */
708 if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR))
709 return E_INVALIDARG;
710
711 *pColorRef = GetSysColor(index);
712
713 break;
714 }
715
716 default:
717 return E_INVALIDARG;
718 }
719
720 return S_OK;
721 }
722
723 extern HRESULT WINAPI OLEAUTPS_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN;
724 extern BOOL WINAPI OLEAUTPS_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
725 extern HRESULT WINAPI OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN;
726 extern HRESULT WINAPI OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN;
727
728 extern void _get_STDFONT_CF(LPVOID *);
729 extern void _get_STDPIC_CF(LPVOID *);
730
731 static HRESULT WINAPI PSDispatchFacBuf_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv)
732 {
733 if (IsEqualIID(riid, &IID_IUnknown) ||
734 IsEqualIID(riid, &IID_IPSFactoryBuffer))
735 {
736 IPSFactoryBuffer_AddRef(iface);
737 *ppv = iface;
738 return S_OK;
739 }
740 return E_NOINTERFACE;
741 }
742
743 static ULONG WINAPI PSDispatchFacBuf_AddRef(IPSFactoryBuffer *iface)
744 {
745 return 2;
746 }
747
748 static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface)
749 {
750 return 1;
751 }
752
753 static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface, IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv)
754 {
755 IPSFactoryBuffer *pPSFB;
756 HRESULT hr;
757
758 if (IsEqualIID(riid, &IID_IDispatch))
759 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB);
760 else
761 hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB);
762
763 if (FAILED(hr)) return hr;
764
765 hr = IPSFactoryBuffer_CreateProxy(pPSFB, pUnkOuter, riid, ppProxy, ppv);
766
767 IPSFactoryBuffer_Release(pPSFB);
768 return hr;
769 }
770
771 static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface, REFIID riid, IUnknown *pUnkOuter, IRpcStubBuffer **ppStub)
772 {
773 IPSFactoryBuffer *pPSFB;
774 HRESULT hr;
775
776 if (IsEqualIID(riid, &IID_IDispatch))
777 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB);
778 else
779 hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB);
780
781 if (FAILED(hr)) return hr;
782
783 hr = IPSFactoryBuffer_CreateStub(pPSFB, riid, pUnkOuter, ppStub);
784
785 IPSFactoryBuffer_Release(pPSFB);
786 return hr;
787 }
788
789 static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl =
790 {
791 PSDispatchFacBuf_QueryInterface,
792 PSDispatchFacBuf_AddRef,
793 PSDispatchFacBuf_Release,
794 PSDispatchFacBuf_CreateProxy,
795 PSDispatchFacBuf_CreateStub
796 };
797
798 /* This is the whole PSFactoryBuffer object, just the vtableptr */
799 static const IPSFactoryBufferVtbl *pPSDispatchFacBuf = &PSDispatchFacBuf_Vtbl;
800
801 /***********************************************************************
802 * DllGetClassObject (OLEAUT32.@)
803 */
804 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
805 {
806 *ppv = NULL;
807 if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
808 if (IsEqualGUID(iid,&IID_IClassFactory)) {
809 _get_STDFONT_CF(ppv);
810 IClassFactory_AddRef((IClassFactory*)*ppv);
811 return S_OK;
812 }
813 }
814 if (IsEqualGUID(rclsid,&CLSID_StdPicture)) {
815 if (IsEqualGUID(iid,&IID_IClassFactory)) {
816 _get_STDPIC_CF(ppv);
817 IClassFactory_AddRef((IClassFactory*)*ppv);
818 return S_OK;
819 }
820 }
821 if (IsEqualCLSID(rclsid, &CLSID_PSDispatch) && IsEqualIID(iid, &IID_IPSFactoryBuffer)) {
822 *ppv = &pPSDispatchFacBuf;
823 IPSFactoryBuffer_AddRef((IPSFactoryBuffer *)*ppv);
824 return S_OK;
825 }
826 if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
827 if (S_OK==TMARSHAL_DllGetClassObject(rclsid,iid,ppv))
828 return S_OK;
829 /*FALLTHROUGH*/
830 }
831 if (IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) ||
832 IsEqualCLSID(rclsid, &CLSID_PSTypeLib) ||
833 IsEqualCLSID(rclsid, &CLSID_PSDispatch) ||
834 IsEqualCLSID(rclsid, &CLSID_PSEnumVariant))
835 return OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, iid, ppv);
836
837 return OLEAUTPS_DllGetClassObject(rclsid, iid, ppv);
838 }
839
840 /***********************************************************************
841 * DllCanUnloadNow (OLEAUT32.@)
842 *
843 * Determine if this dll can be unloaded from the callers address space.
844 *
845 * PARAMS
846 * None.
847 *
848 * RETURNS
849 * Always returns S_FALSE. This dll cannot be unloaded.
850 */
851 HRESULT WINAPI DllCanUnloadNow(void)
852 {
853 return S_FALSE;
854 }
855
856 /*****************************************************************************
857 * DllMain [OLEAUT32.@]
858 */
859 BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
860 {
861 static const WCHAR oanocacheW[] = {'o','a','n','o','c','a','c','h','e',0};
862
863 if(fdwReason == DLL_PROCESS_ATTACH)
864 bstr_cache_enabled = !GetEnvironmentVariableW(oanocacheW, NULL, 0);
865
866 return OLEAUTPS_DllMain( hInstDll, fdwReason, lpvReserved );
867 }
868
869 /***********************************************************************
870 * DllRegisterServer (OLEAUT32.@)
871 */
872 HRESULT WINAPI DllRegisterServer(void)
873 {
874 return OLEAUTPS_DllRegisterServer();
875 }
876
877 /***********************************************************************
878 * DllUnregisterServer (OLEAUT32.@)
879 */
880 HRESULT WINAPI DllUnregisterServer(void)
881 {
882 return OLEAUTPS_DllUnregisterServer();
883 }
884
885 /***********************************************************************
886 * OleIconToCursor (OLEAUT32.415)
887 */
888 HCURSOR WINAPI OleIconToCursor( HINSTANCE hinstExe, HICON hIcon)
889 {
890 FIXME("(%p,%p), partially implemented.\n",hinstExe,hIcon);
891 /* FIXME: make an extended conversation from HICON to HCURSOR */
892 return CopyCursor(hIcon);
893 }