source: trunk/src/ole32/compobj.c@ 7335

Last change on this file since 7335 was 7335, checked in by phaller, 24 years ago

replaced heap alloc by stack alloc

File size: 55.0 KB
Line 
1/*
2 * COMPOBJ library
3 *
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 Justin Bradford
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Sylvain St-Germain
8 */
9
10#include "config.h"
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <assert.h>
16#include "windef.h"
17#include "wtypes.h"
18#include "wingdi.h"
19#include "wine/winbase16.h"
20#include "winerror.h"
21#include "wownt32.h"
22#include "ole2ver.h"
23#include "debugtools.h"
24#include "heap.h"
25#include "winreg.h"
26#include "rpc.h"
27
28#include "wine/obj_base.h"
29#include "wine/obj_misc.h"
30#include "wine/obj_storage.h"
31#include "wine/obj_clientserver.h"
32
33#include "ole.h"
34#include "ifs.h"
35#include "compobj_private.h"
36
37#ifdef __WIN32OS2__
38#include <heapstring.h>
39
40#undef FIXME
41#undef TRACE
42#ifdef DEBUG
43#define TRACE WriteLog("OLE32: %s", __FUNCTION__); WriteLog
44#define FIXME WriteLog("FIXME OLE32: %s", __FUNCTION__); WriteLog
45#else
46#define TRACE 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
47#define FIXME 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
48#endif
49#endif
50
51DEFAULT_DEBUG_CHANNEL(ole);
52
53/****************************************************************************
54 * COM External Lock structures and methods declaration
55 *
56 * This api provides a linked list to managed external references to
57 * COM objects.
58 *
59 * The public interface consists of three calls:
60 * COM_ExternalLockAddRef
61 * COM_ExternalLockRelease
62 * COM_ExternalLockFreeList
63 */
64
65#define EL_END_OF_LIST 0
66#define EL_NOT_FOUND 0
67
68/*
69 * Declaration of the static structure that manage the
70 * external lock to COM objects.
71 */
72typedef struct COM_ExternalLock COM_ExternalLock;
73typedef struct COM_ExternalLockList COM_ExternalLockList;
74
75struct COM_ExternalLock
76{
77 IUnknown *pUnk; /* IUnknown referenced */
78 ULONG uRefCount; /* external lock counter to IUnknown object*/
79 COM_ExternalLock *next; /* Pointer to next element in list */
80};
81
82struct COM_ExternalLockList
83{
84 COM_ExternalLock *head; /* head of list */
85};
86
87/*
88 * Declaration and initialization of the static structure that manages
89 * the external lock to COM objects.
90 */
91static COM_ExternalLockList elList = { EL_END_OF_LIST };
92
93/*
94 * Public Interface to the external lock list
95 */
96static void COM_ExternalLockFreeList();
97static void COM_ExternalLockAddRef(IUnknown *pUnk);
98static void COM_ExternalLockRelease(IUnknown *pUnk, BOOL bRelAll);
99void COM_ExternalLockDump(); /* testing purposes, not static to avoid warning */
100
101/*
102 * Private methods used to managed the linked list
103 */
104static BOOL COM_ExternalLockInsert(
105 IUnknown *pUnk);
106
107static void COM_ExternalLockDelete(
108 COM_ExternalLock *element);
109
110static COM_ExternalLock* COM_ExternalLockFind(
111 IUnknown *pUnk);
112
113static COM_ExternalLock* COM_ExternalLockLocate(
114 COM_ExternalLock *element,
115 IUnknown *pUnk);
116
117/****************************************************************************
118 * This section defines variables internal to the COM module.
119 *
120 * TODO: Most of these things will have to be made thread-safe.
121 */
122HINSTANCE16 COMPOBJ_hInstance = 0;
123HINSTANCE COMPOBJ_hInstance32 = 0;
124static int COMPOBJ_Attach = 0;
125
126LPMALLOC16 currentMalloc16=NULL;
127LPMALLOC currentMalloc32=NULL;
128
129HTASK16 hETask = 0;
130WORD Table_ETask[62];
131
132/*
133 * This lock count counts the number of times CoInitialize is called. It is
134 * decreased every time CoUninitialize is called. When it hits 0, the COM
135 * libraries are freed
136 */
137static ULONG s_COMLockCount = 0;
138
139/*
140 * This linked list contains the list of registered class objects. These
141 * are mostly used to register the factories for out-of-proc servers of OLE
142 * objects.
143 *
144 * TODO: Make this data structure aware of inter-process communication. This
145 * means that parts of this will be exported to the Wine Server.
146 */
147typedef struct tagRegisteredClass
148{
149 CLSID classIdentifier;
150 LPUNKNOWN classObject;
151 DWORD runContext;
152 DWORD connectFlags;
153 DWORD dwCookie;
154 struct tagRegisteredClass* nextClass;
155} RegisteredClass;
156
157static RegisteredClass* firstRegisteredClass = NULL;
158
159/* this open DLL table belongs in a per process table, but my guess is that
160 * it shouldn't live in the kernel, so I'll put them out here in DLL
161 * space assuming that there is one OLE32 per process.
162 */
163typedef struct tagOpenDll {
164 HINSTANCE hLibrary;
165 struct tagOpenDll *next;
166} OpenDll;
167
168static OpenDll *openDllList = NULL; /* linked list of open dlls */
169
170/*****************************************************************************
171 * This section contains prototypes to internal methods for this
172 * module
173 */
174static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid,
175 DWORD dwClsContext,
176 LPUNKNOWN* ppUnk);
177
178static void COM_RevokeAllClasses();
179
180
181/******************************************************************************
182 * CoBuildVersion [COMPOBJ.1]
183 *
184 * RETURNS
185 * Current build version, hiword is majornumber, loword is minornumber
186 */
187DWORD WINAPI CoBuildVersion(void)
188{
189 TRACE("Returning version %d, build %d.\n", rmm, rup);
190 return (rmm<<16)+rup;
191}
192
193#ifndef __WIN32OS2__
194/******************************************************************************
195 * CoInitialize16 [COMPOBJ.2]
196 * Set the win16 IMalloc used for memory management
197 */
198HRESULT WINAPI CoInitialize16(
199 LPVOID lpReserved /* [in] pointer to win16 malloc interface */
200) {
201 currentMalloc16 = (LPMALLOC16)lpReserved;
202 return S_OK;
203}
204#endif
205
206/******************************************************************************
207 * CoInitialize [OLE32.26]
208 *
209 * Initializes the COM libraries.
210 *
211 * See CoInitializeEx
212 */
213HRESULT WINAPI CoInitialize(
214 LPVOID lpReserved /* [in] pointer to win32 malloc interface
215 (obsolete, should be NULL) */
216)
217{
218 /*
219 * Just delegate to the newer method.
220 */
221 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
222}
223
224/******************************************************************************
225 * CoInitializeEx [OLE32.163]
226 *
227 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
228 * used for memory management is obsolete.
229 *
230 * RETURNS
231 * S_OK if successful,
232 * S_FALSE if this function was called already.
233 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
234 * threading model.
235 *
236 * BUGS
237 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
238 * is never returned.
239 *
240 * See the windows documentation for more details.
241 */
242HRESULT WINAPI CoInitializeEx(
243 LPVOID lpReserved, /* [in] pointer to win32 malloc interface
244 (obsolete, should be NULL) */
245 DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */
246)
247{
248 HRESULT hr;
249
250 TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
251
252 if (lpReserved!=NULL)
253 {
254 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
255 }
256
257 /*
258 * Check for unsupported features.
259 */
260 if (dwCoInit!=COINIT_APARTMENTTHREADED)
261 {
262 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved, (int)dwCoInit, (int)dwCoInit);
263 /* Hope for the best and continue anyway */
264 }
265
266 /*
267 * Check the lock count. If this is the first time going through the initialize
268 * process, we have to initialize the libraries.
269 */
270 if (s_COMLockCount==0)
271 {
272 /*
273 * Initialize the various COM libraries and data structures.
274 */
275 TRACE("() - Initializing the COM libraries\n");
276
277 RunningObjectTableImpl_Initialize();
278
279 hr = S_OK;
280 }
281 else
282 hr = S_FALSE;
283
284 /*
285 * Crank-up that lock count.
286 */
287 s_COMLockCount++;
288
289 return hr;
290}
291
292#ifndef __WIN32OS2__
293/***********************************************************************
294 * CoUninitialize16 [COMPOBJ.3]
295 * Don't know what it does.
296 * 3-Nov-98 -- this was originally misspelled, I changed it to what I
297 * believe is the correct spelling
298 */
299void WINAPI CoUninitialize16(void)
300{
301 TRACE("()\n");
302 CoFreeAllLibraries();
303}
304#endif
305
306/***********************************************************************
307 * CoUninitialize [OLE32.47]
308 *
309 * This method will release the COM libraries.
310 *
311 * See the windows documentation for more details.
312 */
313void WINAPI CoUninitialize(void)
314{
315 TRACE("()\n");
316
317 /*
318 * Decrease the reference count.
319 */
320 s_COMLockCount--;
321
322 /*
323 * If we are back to 0 locks on the COM library, make sure we free
324 * all the associated data structures.
325 */
326 if (s_COMLockCount==0)
327 {
328 /*
329 * Release the various COM libraries and data structures.
330 */
331 TRACE("() - Releasing the COM libraries\n");
332
333 RunningObjectTableImpl_UnInitialize();
334 /*
335 * Release the references to the registered class objects.
336 */
337 COM_RevokeAllClasses();
338
339 /*
340 * This will free the loaded COM Dlls.
341 */
342 CoFreeAllLibraries();
343
344 /*
345 * This will free list of external references to COM objects.
346 */
347 COM_ExternalLockFreeList();
348}
349}
350
351#ifndef __WIN32OS2__
352/***********************************************************************
353 * CoGetMalloc16 [COMPOBJ.4]
354 * RETURNS
355 * The current win16 IMalloc
356 */
357HRESULT WINAPI CoGetMalloc16(
358 DWORD dwMemContext, /* [in] unknown */
359 LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */
360) {
361 if(!currentMalloc16)
362 currentMalloc16 = IMalloc16_Constructor();
363 *lpMalloc = currentMalloc16;
364 return S_OK;
365}
366#endif
367
368/******************************************************************************
369 * CoGetMalloc [OLE32.20]
370 *
371 * RETURNS
372 * The current win32 IMalloc
373 */
374HRESULT WINAPI CoGetMalloc(
375 DWORD dwMemContext, /* [in] unknown */
376 LPMALLOC *lpMalloc /* [out] current win32 malloc interface */
377) {
378 if(!currentMalloc32)
379 currentMalloc32 = IMalloc_Constructor();
380 *lpMalloc = currentMalloc32;
381 return S_OK;
382}
383
384#ifndef __WIN32OS2__
385/***********************************************************************
386 * CoCreateStandardMalloc16 [COMPOBJ.71]
387 */
388HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
389 LPMALLOC16 *lpMalloc)
390{
391 /* FIXME: docu says we shouldn't return the same allocator as in
392 * CoGetMalloc16 */
393 *lpMalloc = IMalloc16_Constructor();
394 return S_OK;
395}
396
397/******************************************************************************
398 * CoDisconnectObject [COMPOBJ.15]
399 */
400HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
401{
402 TRACE("(%p, %lx)\n",lpUnk,reserved);
403 return S_OK;
404}
405
406/***********************************************************************
407 * IsEqualGUID16 [COMPOBJ.18]
408 *
409 * Compares two Unique Identifiers.
410 *
411 * RETURNS
412 * TRUE if equal
413 */
414BOOL16 WINAPI IsEqualGUID16(
415 GUID* g1, /* [in] unique id 1 */
416 GUID* g2 /* [in] unique id 2 */
417) {
418 return !memcmp( g1, g2, sizeof(GUID) );
419}
420#endif
421
422/******************************************************************************
423 * CLSIDFromString16 [COMPOBJ.20]
424 * Converts a unique identifier from its string representation into
425 * the GUID struct.
426 *
427 * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6]
428 *
429 * RETURNS
430 * the converted GUID
431 */
432HRESULT WINAPI CLSIDFromString16(
433 LPCOLESTR16 idstr, /* [in] string representation of guid */
434 CLSID *id /* [out] GUID converted from string */
435) {
436 BYTE *s = (BYTE *) idstr;
437 BYTE *p;
438 int i;
439 BYTE table[256];
440
441 if (!s)
442 s = "{00000000-0000-0000-0000-000000000000}";
443 else { /* validate the CLSID string */
444
445 if (strlen(s) != 38)
446 return CO_E_CLASSSTRING;
447
448 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
449 return CO_E_CLASSSTRING;
450
451 for (i=1; i<37; i++)
452 {
453 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
454 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
455 ((s[i] >= 'a') && (s[i] <= 'f')) ||
456 ((s[i] >= 'A') && (s[i] <= 'F')))
457 )
458 return CO_E_CLASSSTRING;
459 }
460 }
461
462 TRACE("%s -> %p\n", s, id);
463
464 /* quick lookup table */
465 memset(table, 0, 256);
466
467 for (i = 0; i < 10; i++) {
468 table['0' + i] = i;
469 }
470 for (i = 0; i < 6; i++) {
471 table['A' + i] = i+10;
472 table['a' + i] = i+10;
473 }
474
475 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
476
477 p = (BYTE *) id;
478
479 s++; /* skip leading brace */
480 for (i = 0; i < 4; i++) {
481 p[3 - i] = table[*s]<<4 | table[*(s+1)];
482 s += 2;
483 }
484 p += 4;
485 s++; /* skip - */
486
487 for (i = 0; i < 2; i++) {
488 p[1-i] = table[*s]<<4 | table[*(s+1)];
489 s += 2;
490 }
491 p += 2;
492 s++; /* skip - */
493
494 for (i = 0; i < 2; i++) {
495 p[1-i] = table[*s]<<4 | table[*(s+1)];
496 s += 2;
497 }
498 p += 2;
499 s++; /* skip - */
500
501 /* these are just sequential bytes */
502 for (i = 0; i < 2; i++) {
503 *p++ = table[*s]<<4 | table[*(s+1)];
504 s += 2;
505 }
506 s++; /* skip - */
507
508 for (i = 0; i < 6; i++) {
509 *p++ = table[*s]<<4 | table[*(s+1)];
510 s += 2;
511 }
512
513 return S_OK;
514}
515
516/******************************************************************************
517 * CoCreateGuid[OLE32.6]
518 *
519 */
520HRESULT WINAPI CoCreateGuid(
521 GUID *pguid /* [out] points to the GUID to initialize */
522) {
523 return UuidCreate(pguid);
524}
525
526/******************************************************************************
527 * CLSIDFromString [OLE32.3]
528 * Converts a unique identifier from its string representation into
529 * the GUID struct.
530 *
531 * UNDOCUMENTED
532 * If idstr is not a valid CLSID string then it gets treated as a ProgID
533 *
534 * RETURNS
535 * the converted GUID
536 */
537HRESULT WINAPI CLSIDFromString(
538 LPCOLESTR idstr, /* [in] string representation of GUID */
539 CLSID *id /* [out] GUID represented by above string */
540) {
541#ifdef __WIN32OS2__
542 HRESULT ret;
543 LPOLESTR16 xid;
544 STACK_strdupWtoA(idstr, xid)
545 ret = CLSIDFromString16( (LPOLESTR16)xid,id);
546 if(ret != S_OK) { /* It appears a ProgID is also valid */
547 ret = CLSIDFromProgID(idstr, id);
548 }
549 return ret;
550#else
551 LPOLESTR16 xid = HEAP_strdupWtoA(GetProcessHeap(),0,idstr);
552 HRESULT ret = CLSIDFromString16(xid,id);
553 HeapFree(GetProcessHeap(),0,xid);
554 if(ret != S_OK) { /* It appears a ProgID is also valid */
555 ret = CLSIDFromProgID(idstr, id);
556 }
557 return ret;
558#endif
559}
560
561/******************************************************************************
562 * WINE_StringFromCLSID [Internal]
563 * Converts a GUID into the respective string representation.
564 *
565 * NOTES
566 *
567 * RETURNS
568 * the string representation and HRESULT
569 */
570#ifdef __WIN32OS2__
571HRESULT WINAPI WINE_StringFromCLSID(
572 const CLSID *id, /* [in] GUID to be converted */
573 LPSTR idstr /* [out] pointer to buffer to contain converted guid */
574#else
575static HRESULT WINE_StringFromCLSID(
576 const CLSID *id, /* [in] GUID to be converted */
577 LPSTR idstr /* [out] pointer to buffer to contain converted guid */
578#endif
579) {
580 static const char *hex = "0123456789ABCDEF";
581 char *s;
582 int i;
583
584 if (!id)
585 { ERR("called with id=Null\n");
586 *idstr = 0x00;
587 return E_FAIL;
588 }
589
590 sprintf(idstr, "{%08lX-%04X-%04X-%02X%02X-",
591 id->Data1, id->Data2, id->Data3,
592 id->Data4[0], id->Data4[1]);
593 s = &idstr[25];
594
595 /* 6 hex bytes */
596 for (i = 2; i < 8; i++) {
597 *s++ = hex[id->Data4[i]>>4];
598 *s++ = hex[id->Data4[i] & 0xf];
599 }
600
601 *s++ = '}';
602 *s++ = '\0';
603
604 TRACE("%p->%s\n", id, idstr);
605
606 return S_OK;
607}
608#ifndef __WIN32OS2__
609/******************************************************************************
610 * StringFromCLSID16 [COMPOBJ.19]
611 * Converts a GUID into the respective string representation.
612 * The target string is allocated using the OLE IMalloc.
613 * RETURNS
614 * the string representation and HRESULT
615 */
616HRESULT WINAPI StringFromCLSID16(
617 REFCLSID id, /* [in] the GUID to be converted */
618 LPOLESTR16 *idstr /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */
619
620) {
621 extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
622 DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode );
623 LPMALLOC16 mllc;
624 HRESULT ret;
625 DWORD args[2];
626
627 ret = CoGetMalloc16(0,&mllc);
628 if (ret) return ret;
629
630 args[0] = (DWORD)mllc;
631 args[1] = 40;
632
633 /* No need for a Callback entry, we have WOWCallback16Ex which does
634 * everything we need.
635 */
636 if (!K32WOWCallback16Ex(
637 (DWORD)((ICOM_VTABLE(IMalloc16)*)MapSL(
638 (SEGPTR)ICOM_VTBL(((LPMALLOC16)MapSL((SEGPTR)mllc))))
639 )->Alloc,
640 WCB16_CDECL,
641 2*sizeof(DWORD),
642 (LPVOID)args,
643 (LPDWORD)idstr
644 )) {
645 WARN("CallTo16 IMalloc16 failed\n");
646 return E_FAIL;
647 }
648 return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr));
649}
650#endif
651/******************************************************************************
652 * StringFromCLSID [OLE32.151]
653 * Converts a GUID into the respective string representation.
654 * The target string is allocated using the OLE IMalloc.
655 * RETURNS
656 * the string representation and HRESULT
657 */
658HRESULT WINAPI StringFromCLSID(
659 REFCLSID id, /* [in] the GUID to be converted */
660 LPOLESTR *idstr /* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
661) {
662 char buf[80];
663 HRESULT ret;
664 LPMALLOC mllc;
665
666 if ((ret=CoGetMalloc(0,&mllc)))
667 return ret;
668
669 ret=WINE_StringFromCLSID(id,buf);
670 if (!ret) {
671 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
672 *idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) );
673 MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len );
674 }
675 return ret;
676}
677
678/******************************************************************************
679 * StringFromGUID2 [COMPOBJ.76] [OLE32.152]
680 *
681 * Converts a global unique identifier into a string of an API-
682 * specified fixed format. (The usual {.....} stuff.)
683 *
684 * RETURNS
685 * The (UNICODE) string representation of the GUID in 'str'
686 * The length of the resulting string, 0 if there was any problem.
687 */
688INT WINAPI
689StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
690{
691 char xguid[80];
692
693 if (WINE_StringFromCLSID(id,xguid))
694 return 0;
695 return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
696}
697
698/******************************************************************************
699 * ProgIDFromCLSID [OLE32.133]
700 * Converts a class id into the respective Program ID. (By using a registry lookup)
701 * RETURNS S_OK on success
702 * riid associated with the progid
703 */
704
705HRESULT WINAPI ProgIDFromCLSID(
706 REFCLSID clsid, /* [in] class id as found in registry */
707 LPOLESTR *lplpszProgID/* [out] associated Prog ID */
708)
709{
710 char strCLSID[50], *buf, *buf2;
711 DWORD buf2len;
712 HKEY xhkey;
713 LPMALLOC mllc;
714 HRESULT ret = S_OK;
715
716 WINE_StringFromCLSID(clsid, strCLSID);
717
718 buf = HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID)+14);
719 sprintf(buf,"CLSID\\%s\\ProgID", strCLSID);
720 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
721 ret = REGDB_E_CLASSNOTREG;
722
723 HeapFree(GetProcessHeap(), 0, buf);
724
725 if (ret == S_OK)
726 {
727 buf2 = HeapAlloc(GetProcessHeap(), 0, 255);
728 buf2len = 255;
729 if (RegQueryValueA(xhkey, NULL, buf2, &buf2len))
730 ret = REGDB_E_CLASSNOTREG;
731
732 if (ret == S_OK)
733 {
734 if (CoGetMalloc(0,&mllc))
735 ret = E_OUTOFMEMORY;
736 else
737 {
738 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf2, -1, NULL, 0 );
739 *lplpszProgID = IMalloc_Alloc(mllc, len * sizeof(WCHAR) );
740 MultiByteToWideChar( CP_ACP, 0, buf2, -1, *lplpszProgID, len );
741 }
742 }
743 HeapFree(GetProcessHeap(), 0, buf2);
744 }
745
746 RegCloseKey(xhkey);
747 return ret;
748}
749
750/******************************************************************************
751 * CLSIDFromProgID16 [COMPOBJ.61]
752 * Converts a program id into the respective GUID. (By using a registry lookup)
753 * RETURNS
754 * riid associated with the progid
755 */
756HRESULT WINAPI CLSIDFromProgID16(
757 LPCOLESTR16 progid, /* [in] program id as found in registry */
758 LPCLSID riid /* [out] associated CLSID */
759) {
760 char *buf,buf2[80];
761 DWORD buf2len;
762 HRESULT err;
763 HKEY xhkey;
764
765 buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
766 sprintf(buf,"%s\\CLSID",progid);
767 if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) {
768 HeapFree(GetProcessHeap(),0,buf);
769 return CO_E_CLASSSTRING;
770 }
771 HeapFree(GetProcessHeap(),0,buf);
772 buf2len = sizeof(buf2);
773 if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) {
774 RegCloseKey(xhkey);
775 return CO_E_CLASSSTRING;
776 }
777 RegCloseKey(xhkey);
778 return CLSIDFromString16(buf2,riid);
779}
780
781/******************************************************************************
782 * CLSIDFromProgID [OLE32.2]
783 * Converts a program id into the respective GUID. (By using a registry lookup)
784 * RETURNS
785 * riid associated with the progid
786 */
787HRESULT WINAPI CLSIDFromProgID(
788 LPCOLESTR progid, /* [in] program id as found in registry */
789 LPCLSID riid /* [out] associated CLSID */
790) {
791#ifdef __WIN32OS2__
792 LPOLESTR16 pid;
793 STACK_strdupWtoA(progid, pid)
794 return CLSIDFromProgID16((LPOLESTR16)pid,riid);
795#else
796 LPOLESTR16 pid = HEAP_strdupWtoA(GetProcessHeap(),0,progid);
797 HRESULT ret = CLSIDFromProgID16(pid,riid);
798
799 HeapFree(GetProcessHeap(),0,pid);
800 return ret;
801#endif
802}
803
804
805
806/*****************************************************************************
807 * CoGetPSClsid [OLE32.22]
808 *
809 * This function returns the CLSID of the DLL that implements the proxy and stub
810 * for the specified interface.
811 *
812 * It determines this by searching the
813 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
814 * and any interface id registered by CoRegisterPSClsid within the current process.
815 *
816 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
817 */
818HRESULT WINAPI CoGetPSClsid(
819 REFIID riid, /* [in] Interface whose proxy/stub CLSID is to be returned */
820 CLSID *pclsid ) /* [out] Where to store returned proxy/stub CLSID */
821{
822 char *buf, buf2[40];
823 DWORD buf2len;
824 HKEY xhkey;
825
826 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
827
828 /* Get the input iid as a string */
829 WINE_StringFromCLSID(riid, buf2);
830 /* Allocate memory for the registry key we will construct.
831 (length of iid string plus constant length of static text */
832 buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27);
833 if (buf == NULL)
834 {
835 return (E_OUTOFMEMORY);
836 }
837
838 /* Construct the registry key we want */
839 sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2);
840
841 /* Open the key.. */
842 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
843 {
844 HeapFree(GetProcessHeap(),0,buf);
845 return (E_INVALIDARG);
846 }
847 HeapFree(GetProcessHeap(),0,buf);
848
849 /* ... Once we have the key, query the registry to get the
850 value of CLSID as a string, and convert it into a
851 proper CLSID structure to be passed back to the app */
852 buf2len = sizeof(buf2);
853 if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) )
854 {
855 RegCloseKey(xhkey);
856 return E_INVALIDARG;
857 }
858 RegCloseKey(xhkey);
859
860 /* We have the CLSid we want back from the registry as a string, so
861 lets convert it into a CLSID structure */
862 if ( (CLSIDFromString16(buf2,pclsid)) != NOERROR)
863 {
864 return E_INVALIDARG;
865 }
866
867 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
868 return (S_OK);
869}
870
871
872
873/***********************************************************************
874 * WriteClassStm
875 *
876 * This function write a CLSID on stream
877 */
878HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
879{
880 TRACE("(%p,%p)\n",pStm,rclsid);
881
882 if (rclsid==NULL)
883 return E_INVALIDARG;
884
885 return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL);
886}
887
888/***********************************************************************
889 * ReadClassStm
890 *
891 * This function read a CLSID from a stream
892 */
893HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID rclsid)
894{
895 ULONG nbByte;
896 HRESULT res;
897
898 TRACE("(%p,%p)\n",pStm,rclsid);
899
900 if (rclsid==NULL)
901 return E_INVALIDARG;
902
903 res = IStream_Read(pStm,(void*)rclsid,sizeof(CLSID),&nbByte);
904
905 if (FAILED(res))
906 return res;
907
908 if (nbByte != sizeof(CLSID))
909 return S_FALSE;
910 else
911 return S_OK;
912}
913
914#ifndef __WIN32OS2__
915/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
916/***********************************************************************
917 * LookupETask (COMPOBJ.94)
918 */
919HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) {
920 FIXME("(%p,%p),stub!\n",hTask,p);
921 if ((*hTask = GetCurrentTask()) == hETask) {
922 memcpy(p, Table_ETask, sizeof(Table_ETask));
923 }
924 return 0;
925}
926
927/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
928/***********************************************************************
929 * SetETask (COMPOBJ.95)
930 */
931HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) {
932 FIXME("(%04x,%p),stub!\n",hTask,p);
933 hETask = hTask;
934 return 0;
935}
936
937/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
938/***********************************************************************
939 * CallObjectInWOW (COMPOBJ.201)
940 */
941HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
942 FIXME("(%p,%p),stub!\n",p1,p2);
943 return 0;
944}
945
946/******************************************************************************
947 * CoRegisterClassObject16 [COMPOBJ.5]
948 *
949 * Don't know where it registers it ...
950 */
951HRESULT WINAPI CoRegisterClassObject16(
952 REFCLSID rclsid,
953 LPUNKNOWN pUnk,
954 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
955 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
956 LPDWORD lpdwRegister
957) {
958 char buf[80];
959
960 WINE_StringFromCLSID(rclsid,buf);
961
962 FIXME("(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
963 buf,pUnk,dwClsContext,flags,lpdwRegister
964 );
965 return 0;
966}
967
968
969/******************************************************************************
970 * CoRevokeClassObject16 [COMPOBJ.6]
971 *
972 */
973HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */
974{
975 FIXME("(0x%08lx),stub!\n", dwRegister);
976 return 0;
977}
978#endif
979
980
981/***
982 * COM_GetRegisteredClassObject
983 *
984 * This internal method is used to scan the registered class list to
985 * find a class object.
986 *
987 * Params:
988 * rclsid Class ID of the class to find.
989 * dwClsContext Class context to match.
990 * ppv [out] returns a pointer to the class object. Complying
991 * to normal COM usage, this method will increase the
992 * reference count on this object.
993 */
994static HRESULT COM_GetRegisteredClassObject(
995 REFCLSID rclsid,
996 DWORD dwClsContext,
997 LPUNKNOWN* ppUnk)
998{
999 RegisteredClass* curClass;
1000
1001 /*
1002 * Sanity check
1003 */
1004 assert(ppUnk!=0);
1005
1006 /*
1007 * Iterate through the whole list and try to match the class ID.
1008 */
1009 curClass = firstRegisteredClass;
1010
1011 while (curClass != 0)
1012 {
1013 /*
1014 * Check if we have a match on the class ID.
1015 */
1016 if (IsEqualGUID(&(curClass->classIdentifier), rclsid))
1017 {
1018 /*
1019 * Since we don't do out-of process or DCOM just right away, let's ignore the
1020 * class context.
1021 */
1022
1023 /*
1024 * We have a match, return the pointer to the class object.
1025 */
1026 *ppUnk = curClass->classObject;
1027
1028 IUnknown_AddRef(curClass->classObject);
1029
1030 return S_OK;
1031 }
1032
1033 /*
1034 * Step to the next class in the list.
1035 */
1036 curClass = curClass->nextClass;
1037 }
1038
1039 /*
1040 * If we get to here, we haven't found our class.
1041 */
1042 return S_FALSE;
1043}
1044
1045/******************************************************************************
1046 * CoRegisterClassObject [OLE32.36]
1047 *
1048 * This method will register the class object for a given class ID.
1049 *
1050 * See the Windows documentation for more details.
1051 */
1052HRESULT WINAPI CoRegisterClassObject(
1053 REFCLSID rclsid,
1054 LPUNKNOWN pUnk,
1055 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
1056 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
1057 LPDWORD lpdwRegister
1058)
1059{
1060 RegisteredClass* newClass;
1061 LPUNKNOWN foundObject;
1062 HRESULT hr;
1063 char buf[80];
1064
1065 WINE_StringFromCLSID(rclsid,buf);
1066
1067 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
1068 buf,pUnk,dwClsContext,flags,lpdwRegister);
1069
1070 /*
1071 * Perform a sanity check on the parameters
1072 */
1073 if ( (lpdwRegister==0) || (pUnk==0) )
1074 {
1075 return E_INVALIDARG;
1076}
1077
1078 /*
1079 * Initialize the cookie (out parameter)
1080 */
1081 *lpdwRegister = 0;
1082
1083 /*
1084 * First, check if the class is already registered.
1085 * If it is, this should cause an error.
1086 */
1087 hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
1088
1089 if (hr == S_OK)
1090 {
1091 /*
1092 * The COM_GetRegisteredClassObject increased the reference count on the
1093 * object so it has to be released.
1094 */
1095 IUnknown_Release(foundObject);
1096
1097 return CO_E_OBJISREG;
1098 }
1099
1100 /*
1101 * If it is not registered, we must create a new entry for this class and
1102 * append it to the registered class list.
1103 * We use the address of the chain node as the cookie since we are sure it's
1104 * unique.
1105 */
1106 newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
1107
1108 /*
1109 * Initialize the node.
1110 */
1111 newClass->classIdentifier = *rclsid;
1112 newClass->runContext = dwClsContext;
1113 newClass->connectFlags = flags;
1114 newClass->dwCookie = (DWORD)newClass;
1115 newClass->nextClass = firstRegisteredClass;
1116
1117 /*
1118 * Since we're making a copy of the object pointer, we have to increase its
1119 * reference count.
1120 */
1121 newClass->classObject = pUnk;
1122 IUnknown_AddRef(newClass->classObject);
1123
1124 firstRegisteredClass = newClass;
1125
1126 /*
1127 * Assign the out parameter (cookie)
1128 */
1129 *lpdwRegister = newClass->dwCookie;
1130
1131 /*
1132 * We're successful Yippee!
1133 */
1134 return S_OK;
1135}
1136
1137/***********************************************************************
1138 * CoRevokeClassObject [OLE32.40]
1139 *
1140 * This method will remove a class object from the class registry
1141 *
1142 * See the Windows documentation for more details.
1143 */
1144HRESULT WINAPI CoRevokeClassObject(
1145 DWORD dwRegister)
1146{
1147 RegisteredClass** prevClassLink;
1148 RegisteredClass* curClass;
1149
1150 TRACE("(%08lx)\n",dwRegister);
1151
1152 /*
1153 * Iterate through the whole list and try to match the cookie.
1154 */
1155 curClass = firstRegisteredClass;
1156 prevClassLink = &firstRegisteredClass;
1157
1158 while (curClass != 0)
1159 {
1160 /*
1161 * Check if we have a match on the cookie.
1162 */
1163 if (curClass->dwCookie == dwRegister)
1164 {
1165 /*
1166 * Remove the class from the chain.
1167 */
1168 *prevClassLink = curClass->nextClass;
1169
1170 /*
1171 * Release the reference to the class object.
1172 */
1173 IUnknown_Release(curClass->classObject);
1174
1175 /*
1176 * Free the memory used by the chain node.
1177 */
1178 HeapFree(GetProcessHeap(), 0, curClass);
1179
1180 return S_OK;
1181}
1182
1183 /*
1184 * Step to the next class in the list.
1185 */
1186 prevClassLink = &(curClass->nextClass);
1187 curClass = curClass->nextClass;
1188 }
1189
1190 /*
1191 * If we get to here, we haven't found our class.
1192 */
1193 return E_INVALIDARG;
1194}
1195
1196/***********************************************************************
1197 * CoGetClassObject [COMPOBJ.7]
1198 */
1199HRESULT WINAPI CoGetClassObject(
1200 REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
1201 REFIID iid, LPVOID *ppv
1202) {
1203 LPUNKNOWN regClassObject;
1204 HRESULT hres = E_UNEXPECTED;
1205 char xclsid[80];
1206 WCHAR dllName[MAX_PATH+1];
1207 DWORD dllNameLen = sizeof(dllName);
1208 HINSTANCE hLibrary;
1209#ifdef __WIN32OS2__
1210 typedef HRESULT (* CALLBACK DllGetClassObjectFunc)(REFCLSID clsid,
1211 REFIID iid, LPVOID *ppv);
1212#else
1213 typedef HRESULT CALLBACK (*DllGetClassObjectFunc)(REFCLSID clsid,
1214 REFIID iid, LPVOID *ppv);
1215#endif
1216 DllGetClassObjectFunc DllGetClassObject;
1217
1218 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1219
1220 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",
1221 debugstr_guid(rclsid),
1222 debugstr_guid(iid)
1223 );
1224
1225 if (pServerInfo) {
1226 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
1227 FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo);
1228 }
1229
1230 /*
1231 * First, try and see if we can't match the class ID with one of the
1232 * registered classes.
1233 */
1234 if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, &regClassObject))
1235 {
1236 /*
1237 * Get the required interface from the retrieved pointer.
1238 */
1239 hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
1240
1241 /*
1242 * Since QI got another reference on the pointer, we want to release the
1243 * one we already have. If QI was unsuccessful, this will release the object. This
1244 * is good since we are not returning it in the "out" parameter.
1245 */
1246 IUnknown_Release(regClassObject);
1247
1248 return hres;
1249 }
1250
1251 /* out of process and remote servers not supported yet */
1252 if ( ((CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER) & dwClsContext)
1253 && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
1254 ){
1255 FIXME("%s %s not supported!\n",
1256 (dwClsContext&CLSCTX_LOCAL_SERVER)?"CLSCTX_LOCAL_SERVER":"",
1257 (dwClsContext&CLSCTX_REMOTE_SERVER)?"CLSCTX_REMOTE_SERVER":""
1258 );
1259 return E_ACCESSDENIED;
1260 }
1261
1262 if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) {
1263 HKEY key;
1264 char buf[200];
1265
1266 sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
1267 hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
1268
1269 if (hres != ERROR_SUCCESS) {
1270 return REGDB_E_CLASSNOTREG;
1271 }
1272
1273 memset(dllName,0,sizeof(dllName));
1274 hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
1275 if (hres)
1276 return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
1277 RegCloseKey(key);
1278 TRACE("found InprocServer32 dll %s\n", debugstr_w(dllName));
1279
1280 /* open dll, call DllGetClassObject */
1281 hLibrary = CoLoadLibrary(dllName, TRUE);
1282 if (hLibrary == 0) {
1283 FIXME("couldn't load InprocServer32 dll %s\n", debugstr_w(dllName));
1284 return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
1285 }
1286 DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject");
1287 if (!DllGetClassObject) {
1288 /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
1289 FIXME("couldn't find function DllGetClassObject in %s\n", debugstr_w(dllName));
1290 return E_ACCESSDENIED;
1291 }
1292
1293 /*
1294 * Ask the DLL for its class object. (there was a note here about class
1295 * factories but this is good.
1296 */
1297 return DllGetClassObject(rclsid, iid, ppv);
1298 }
1299 return hres;
1300}
1301
1302/***********************************************************************
1303 * CoResumeClassObjects
1304 *
1305 * Resumes classobjects registered with REGCLS suspended
1306 */
1307HRESULT WINAPI CoResumeClassObjects(void)
1308{
1309 FIXME("\n");
1310 return S_OK;
1311}
1312
1313/***********************************************************************
1314 * GetClassFile
1315 *
1316 * This function supplies the CLSID associated with the given filename.
1317 */
1318HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid)
1319{
1320 IStorage *pstg=0;
1321 HRESULT res;
1322 int nbElm=0,length=0,i=0;
1323 LONG sizeProgId=20;
1324 LPOLESTR *pathDec=0,absFile=0,progId=0;
1325 WCHAR extention[100]={0};
1326
1327 TRACE("()\n");
1328
1329 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1330 if((StgIsStorageFile(filePathName))==S_OK){
1331
1332 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
1333
1334 if (SUCCEEDED(res))
1335 res=ReadClassStg(pstg,pclsid);
1336
1337 IStorage_Release(pstg);
1338
1339 return res;
1340 }
1341 /* if the file is not a storage object then attemps to match various bits in the file against a
1342 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1343 this case
1344
1345 for(i=0;i<nFileTypes;i++)
1346
1347 for(i=0;j<nPatternsForType;j++){
1348
1349 PATTERN pat;
1350 HANDLE hFile;
1351
1352 pat=ReadPatternFromRegistry(i,j);
1353 hFile=CreateFileW(filePathName,,,,,,hFile);
1354 SetFilePosition(hFile,pat.offset);
1355 ReadFile(hFile,buf,pat.size,NULL,NULL);
1356 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1357
1358 *pclsid=ReadCLSIDFromRegistry(i);
1359 return S_OK;
1360 }
1361 }
1362 */
1363
1364 /* if the obove strategies fail then search for the extension key in the registry */
1365
1366 /* get the last element (absolute file) in the path name */
1367 nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
1368 absFile=pathDec[nbElm-1];
1369
1370 /* failed if the path represente a directory and not an absolute file name*/
1371 if (lstrcmpW(absFile,(LPOLESTR)"\\"))
1372 return MK_E_INVALIDEXTENSION;
1373
1374 /* get the extension of the file */
1375 length=lstrlenW(absFile);
1376 for(i=length-1; ( (i>=0) && (extention[i]=absFile[i]) );i--);
1377
1378 /* get the progId associated to the extension */
1379 progId=CoTaskMemAlloc(sizeProgId);
1380
1381 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1382
1383 if (res==ERROR_MORE_DATA){
1384
1385 progId = CoTaskMemRealloc(progId,sizeProgId);
1386 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1387 }
1388 if (res==ERROR_SUCCESS)
1389 /* return the clsid associated to the progId */
1390 res= CLSIDFromProgID(progId,pclsid);
1391
1392 for(i=0; pathDec[i]!=NULL;i++)
1393 CoTaskMemFree(pathDec[i]);
1394 CoTaskMemFree(pathDec);
1395
1396 CoTaskMemFree(progId);
1397
1398 if (res==ERROR_SUCCESS)
1399 return res;
1400
1401 return MK_E_INVALIDEXTENSION;
1402}
1403#ifndef __WIN32OS2__
1404/******************************************************************************
1405 * CoRegisterMessageFilter16 [COMPOBJ.27]
1406 */
1407HRESULT WINAPI CoRegisterMessageFilter16(
1408 LPMESSAGEFILTER lpMessageFilter,
1409 LPMESSAGEFILTER *lplpMessageFilter
1410) {
1411 FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
1412 return 0;
1413}
1414#endif
1415
1416/***********************************************************************
1417 * CoCreateInstance [COMPOBJ.13, OLE32.7]
1418 */
1419HRESULT WINAPI CoCreateInstance(
1420 REFCLSID rclsid,
1421 LPUNKNOWN pUnkOuter,
1422 DWORD dwClsContext,
1423 REFIID iid,
1424 LPVOID *ppv)
1425{
1426 HRESULT hres;
1427 LPCLASSFACTORY lpclf = 0;
1428
1429 /*
1430 * Sanity check
1431 */
1432 if (ppv==0)
1433 return E_POINTER;
1434
1435 /*
1436 * Initialize the "out" parameter
1437 */
1438 *ppv = 0;
1439
1440 /*
1441 * Get a class factory to construct the object we want.
1442 */
1443 hres = CoGetClassObject(rclsid,
1444 dwClsContext,
1445 NULL,
1446 &IID_IClassFactory,
1447 (LPVOID)&lpclf);
1448
1449 if (FAILED(hres)) {
1450 FIXME("no instance created for %s, hres is 0x%08lx\n",debugstr_guid(iid),hres);
1451 return hres;
1452 }
1453
1454 /*
1455 * Create the object and don't forget to release the factory
1456 */
1457 hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv);
1458 IClassFactory_Release(lpclf);
1459
1460 return hres;
1461}
1462
1463/***********************************************************************
1464 * CoCreateInstanceEx [OLE32.165]
1465 */
1466HRESULT WINAPI CoCreateInstanceEx(
1467 REFCLSID rclsid,
1468 LPUNKNOWN pUnkOuter,
1469 DWORD dwClsContext,
1470 COSERVERINFO* pServerInfo,
1471 ULONG cmq,
1472 MULTI_QI* pResults)
1473{
1474 IUnknown* pUnk = NULL;
1475 HRESULT hr;
1476 ULONG index;
1477 int successCount = 0;
1478
1479 /*
1480 * Sanity check
1481 */
1482 if ( (cmq==0) || (pResults==NULL))
1483 return E_INVALIDARG;
1484
1485 if (pServerInfo!=NULL)
1486 FIXME("() non-NULL pServerInfo not supported!\n");
1487
1488 /*
1489 * Initialize all the "out" parameters.
1490 */
1491 for (index = 0; index < cmq; index++)
1492 {
1493 pResults[index].pItf = NULL;
1494 pResults[index].hr = E_NOINTERFACE;
1495 }
1496
1497 /*
1498 * Get the object and get its IUnknown pointer.
1499 */
1500 hr = CoCreateInstance(rclsid,
1501 pUnkOuter,
1502 dwClsContext,
1503 &IID_IUnknown,
1504 (VOID**)&pUnk);
1505
1506 if (hr)
1507 return hr;
1508
1509 /*
1510 * Then, query for all the interfaces requested.
1511 */
1512 for (index = 0; index < cmq; index++)
1513 {
1514 pResults[index].hr = IUnknown_QueryInterface(pUnk,
1515 pResults[index].pIID,
1516 (VOID**)&(pResults[index].pItf));
1517
1518 if (pResults[index].hr == S_OK)
1519 successCount++;
1520 }
1521
1522 /*
1523 * Release our temporary unknown pointer.
1524 */
1525 IUnknown_Release(pUnk);
1526
1527 if (successCount == 0)
1528 return E_NOINTERFACE;
1529
1530 if (successCount!=cmq)
1531 return CO_S_NOTALLINTERFACES;
1532
1533 return S_OK;
1534}
1535
1536/***********************************************************************
1537 * CoFreeLibrary [COMPOBJ.13]
1538 */
1539void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
1540{
1541 OpenDll *ptr, *prev;
1542 OpenDll *tmp;
1543
1544 /* lookup library in linked list */
1545 prev = NULL;
1546 for (ptr = openDllList; ptr != NULL; ptr=ptr->next) {
1547 if (ptr->hLibrary == hLibrary) {
1548 break;
1549 }
1550 prev = ptr;
1551 }
1552
1553 if (ptr == NULL) {
1554 /* shouldn't happen if user passed in a valid hLibrary */
1555 return;
1556 }
1557 /* assert: ptr points to the library entry to free */
1558
1559 /* free library and remove node from list */
1560 FreeLibrary(hLibrary);
1561 if (ptr == openDllList) {
1562 tmp = openDllList->next;
1563 HeapFree(GetProcessHeap(), 0, openDllList);
1564 openDllList = tmp;
1565 } else {
1566 tmp = ptr->next;
1567 HeapFree(GetProcessHeap(), 0, ptr);
1568 prev->next = tmp;
1569 }
1570
1571}
1572
1573
1574/***********************************************************************
1575 * CoFreeAllLibraries [COMPOBJ.12]
1576 */
1577void WINAPI CoFreeAllLibraries(void)
1578{
1579 OpenDll *ptr, *tmp;
1580
1581 for (ptr = openDllList; ptr != NULL; ) {
1582 tmp=ptr->next;
1583 CoFreeLibrary(ptr->hLibrary);
1584 ptr = tmp;
1585 }
1586}
1587
1588
1589
1590/***********************************************************************
1591 * CoFreeUnusedLibraries [COMPOBJ.17]
1592 */
1593void WINAPI CoFreeUnusedLibraries(void)
1594{
1595 OpenDll *ptr, *tmp;
1596 typedef HRESULT(*DllCanUnloadNowFunc)(void);
1597 DllCanUnloadNowFunc DllCanUnloadNow;
1598
1599 for (ptr = openDllList; ptr != NULL; ) {
1600 DllCanUnloadNow = (DllCanUnloadNowFunc)
1601 GetProcAddress(ptr->hLibrary, "DllCanUnloadNow");
1602
1603 if ( (DllCanUnloadNow != NULL) &&
1604 (DllCanUnloadNow() == S_OK) ) {
1605 tmp=ptr->next;
1606 CoFreeLibrary(ptr->hLibrary);
1607 ptr = tmp;
1608 } else {
1609 ptr=ptr->next;
1610 }
1611 }
1612}
1613
1614/***********************************************************************
1615 * CoFileTimeNow [COMPOBJ.82, OLE32.10]
1616 * RETURNS
1617 * the current system time in lpFileTime
1618 */
1619HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time */
1620{
1621 GetSystemTimeAsFileTime( lpFileTime );
1622 return S_OK;
1623}
1624
1625/***********************************************************************
1626 * CoTaskMemAlloc (OLE32.43)
1627 * RETURNS
1628 * pointer to newly allocated block
1629 */
1630LPVOID WINAPI CoTaskMemAlloc(
1631 ULONG size /* [in] size of memoryblock to be allocated */
1632) {
1633 LPMALLOC lpmalloc;
1634 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1635
1636 if (FAILED(ret))
1637 return NULL;
1638
1639 return IMalloc_Alloc(lpmalloc,size);
1640}
1641/***********************************************************************
1642 * CoTaskMemFree (OLE32.44)
1643 */
1644VOID WINAPI CoTaskMemFree(
1645 LPVOID ptr /* [in] pointer to be freed */
1646) {
1647 LPMALLOC lpmalloc;
1648 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1649
1650 if (FAILED(ret))
1651 return;
1652
1653 IMalloc_Free(lpmalloc, ptr);
1654}
1655
1656/***********************************************************************
1657 * CoTaskMemRealloc (OLE32.45)
1658 * RETURNS
1659 * pointer to newly allocated block
1660 */
1661LPVOID WINAPI CoTaskMemRealloc(
1662 LPVOID pvOld,
1663 ULONG size) /* [in] size of memoryblock to be allocated */
1664{
1665 LPMALLOC lpmalloc;
1666 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1667
1668 if (FAILED(ret))
1669 return NULL;
1670
1671 return IMalloc_Realloc(lpmalloc, pvOld, size);
1672}
1673
1674/***********************************************************************
1675 * CoLoadLibrary (OLE32.30)
1676 */
1677HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
1678{
1679 HINSTANCE hLibrary;
1680 OpenDll *ptr;
1681 OpenDll *tmp;
1682
1683 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
1684
1685 hLibrary = LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
1686
1687 if (!bAutoFree)
1688 return hLibrary;
1689
1690 if (openDllList == NULL) {
1691 /* empty list -- add first node */
1692 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1693 openDllList->hLibrary=hLibrary;
1694 openDllList->next = NULL;
1695 } else {
1696 /* search for this dll */
1697 int found = FALSE;
1698 for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
1699 if (ptr->hLibrary == hLibrary) {
1700 found = TRUE;
1701 break;
1702 }
1703 }
1704 if (!found) {
1705 /* dll not found, add it */
1706 tmp = openDllList;
1707 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1708 openDllList->hLibrary = hLibrary;
1709 openDllList->next = tmp;
1710 }
1711 }
1712
1713 return hLibrary;
1714}
1715
1716/***********************************************************************
1717 * CoInitializeWOW (OLE32.27)
1718 */
1719HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
1720 FIXME("(0x%08lx,0x%08lx),stub!\n",x,y);
1721 return 0;
1722}
1723
1724#ifndef __WIN32OS2__
1725/******************************************************************************
1726 * CoLockObjectExternal16 [COMPOBJ.63]
1727 */
1728HRESULT WINAPI CoLockObjectExternal16(
1729 LPUNKNOWN pUnk, /* [in] object to be locked */
1730 BOOL16 fLock, /* [in] do lock */
1731 BOOL16 fLastUnlockReleases /* [in] ? */
1732) {
1733 FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
1734 return S_OK;
1735}
1736#endif
1737
1738/******************************************************************************
1739 * CoLockObjectExternal [OLE32.31]
1740 */
1741HRESULT WINAPI CoLockObjectExternal(
1742 LPUNKNOWN pUnk, /* [in] object to be locked */
1743 BOOL fLock, /* [in] do lock */
1744 BOOL fLastUnlockReleases) /* [in] unlock all */
1745{
1746
1747 if (fLock)
1748 {
1749 /*
1750 * Increment the external lock coutner, COM_ExternalLockAddRef also
1751 * increment the object's internal lock counter.
1752 */
1753 COM_ExternalLockAddRef( pUnk);
1754 }
1755 else
1756 {
1757 /*
1758 * Decrement the external lock coutner, COM_ExternalLockRelease also
1759 * decrement the object's internal lock counter.
1760 */
1761 COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
1762 }
1763
1764 return S_OK;
1765}
1766
1767#ifndef __WIN32OS2__
1768/***********************************************************************
1769 * CoGetState16 [COMPOBJ.115]
1770 */
1771HRESULT WINAPI CoGetState16(LPDWORD state)
1772{
1773 FIXME("(%p),stub!\n", state);
1774 *state = 0;
1775 return S_OK;
1776}
1777/***********************************************************************
1778 * CoSetState [COM32.42]
1779 */
1780HRESULT WINAPI CoSetState(LPDWORD state)
1781{
1782 FIXME("(%p),stub!\n", state);
1783 if (state) *state = 0;
1784 return S_OK;
1785}
1786#endif
1787/***********************************************************************
1788 * CoCreateFreeThreadedMarshaler [OLE32.5]
1789 */
1790HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal)
1791{
1792 FIXME ("(%p %p): stub\n", punkOuter, ppunkMarshal);
1793
1794 return S_OK;
1795}
1796
1797
1798/***********************************************************************
1799 * DllGetClassObject [OLE32.63]
1800 */
1801HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1802{
1803 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
1804 *ppv = NULL;
1805 return CLASS_E_CLASSNOTAVAILABLE;
1806}
1807
1808
1809/***
1810 * COM_RevokeAllClasses
1811 *
1812 * This method is called when the COM libraries are uninitialized to
1813 * release all the references to the class objects registered with
1814 * the library
1815 */
1816static void COM_RevokeAllClasses()
1817{
1818 while (firstRegisteredClass!=0)
1819 {
1820 CoRevokeClassObject(firstRegisteredClass->dwCookie);
1821 }
1822}
1823
1824/****************************************************************************
1825 * COM External Lock methods implementation
1826 */
1827
1828/****************************************************************************
1829 * Public - Method that increments the count for a IUnknown* in the linked
1830 * list. The item is inserted if not already in the list.
1831 */
1832static void COM_ExternalLockAddRef(
1833 IUnknown *pUnk)
1834{
1835 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1836
1837 /*
1838 * Add an external lock to the object. If it was already externally
1839 * locked, just increase the reference count. If it was not.
1840 * add the item to the list.
1841 */
1842 if ( externalLock == EL_NOT_FOUND )
1843 COM_ExternalLockInsert(pUnk);
1844 else
1845 externalLock->uRefCount++;
1846
1847 /*
1848 * Add an internal lock to the object
1849 */
1850 IUnknown_AddRef(pUnk);
1851}
1852
1853/****************************************************************************
1854 * Public - Method that decrements the count for a IUnknown* in the linked
1855 * list. The item is removed from the list if its count end up at zero or if
1856 * bRelAll is TRUE.
1857 */
1858static void COM_ExternalLockRelease(
1859 IUnknown *pUnk,
1860 BOOL bRelAll)
1861{
1862 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1863
1864 if ( externalLock != EL_NOT_FOUND )
1865 {
1866 do
1867 {
1868 externalLock->uRefCount--; /* release external locks */
1869 IUnknown_Release(pUnk); /* release local locks as well */
1870
1871 if ( bRelAll == FALSE )
1872 break; /* perform single release */
1873
1874 } while ( externalLock->uRefCount > 0 );
1875
1876 if ( externalLock->uRefCount == 0 ) /* get rid of the list entry */
1877 COM_ExternalLockDelete(externalLock);
1878 }
1879}
1880/****************************************************************************
1881 * Public - Method that frees the content of the list.
1882 */
1883static void COM_ExternalLockFreeList()
1884{
1885 COM_ExternalLock *head;
1886
1887 head = elList.head; /* grab it by the head */
1888 while ( head != EL_END_OF_LIST )
1889 {
1890 COM_ExternalLockDelete(head); /* get rid of the head stuff */
1891
1892 head = elList.head; /* get the new head... */
1893 }
1894}
1895
1896/****************************************************************************
1897 * Public - Method that dump the content of the list.
1898 */
1899void COM_ExternalLockDump()
1900{
1901 COM_ExternalLock *current = elList.head;
1902
1903 DPRINTF("\nExternal lock list contains:\n");
1904
1905 while ( current != EL_END_OF_LIST )
1906 {
1907 DPRINTF( "\t%p with %lu references count.\n", current->pUnk, current->uRefCount);
1908
1909 /* Skip to the next item */
1910 current = current->next;
1911 }
1912
1913}
1914
1915/****************************************************************************
1916 * Internal - Find a IUnknown* in the linked list
1917 */
1918static COM_ExternalLock* COM_ExternalLockFind(
1919 IUnknown *pUnk)
1920{
1921 return COM_ExternalLockLocate(elList.head, pUnk);
1922}
1923
1924/****************************************************************************
1925 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1926 */
1927static COM_ExternalLock* COM_ExternalLockLocate(
1928 COM_ExternalLock *element,
1929 IUnknown *pUnk)
1930{
1931 if ( element == EL_END_OF_LIST )
1932 return EL_NOT_FOUND;
1933
1934 else if ( element->pUnk == pUnk ) /* We found it */
1935 return element;
1936
1937 else /* Not the right guy, keep on looking */
1938 return COM_ExternalLockLocate( element->next, pUnk);
1939}
1940
1941/****************************************************************************
1942 * Internal - Insert a new IUnknown* to the linked list
1943 */
1944static BOOL COM_ExternalLockInsert(
1945 IUnknown *pUnk)
1946{
1947 COM_ExternalLock *newLock = NULL;
1948 COM_ExternalLock *previousHead = NULL;
1949
1950 /*
1951 * Allocate space for the new storage object
1952 */
1953 newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
1954
1955 if (newLock!=NULL)
1956 {
1957 if ( elList.head == EL_END_OF_LIST )
1958 {
1959 elList.head = newLock; /* The list is empty */
1960 }
1961 else
1962 {
1963 /*
1964 * insert does it at the head
1965 */
1966 previousHead = elList.head;
1967 elList.head = newLock;
1968 }
1969
1970 /*
1971 * Set new list item data member
1972 */
1973 newLock->pUnk = pUnk;
1974 newLock->uRefCount = 1;
1975 newLock->next = previousHead;
1976
1977 return TRUE;
1978 }
1979 else
1980 return FALSE;
1981}
1982
1983/****************************************************************************
1984 * Internal - Method that removes an item from the linked list.
1985 */
1986static void COM_ExternalLockDelete(
1987 COM_ExternalLock *itemList)
1988{
1989 COM_ExternalLock *current = elList.head;
1990
1991 if ( current == itemList )
1992 {
1993 /*
1994 * this section handles the deletion of the first node
1995 */
1996 elList.head = itemList->next;
1997 HeapFree( GetProcessHeap(), 0, itemList);
1998 }
1999 else
2000 {
2001 do
2002 {
2003 if ( current->next == itemList ) /* We found the item to free */
2004 {
2005 current->next = itemList->next; /* readjust the list pointers */
2006
2007 HeapFree( GetProcessHeap(), 0, itemList);
2008 break;
2009 }
2010
2011 /* Skip to the next item */
2012 current = current->next;
2013
2014 } while ( current != EL_END_OF_LIST );
2015 }
2016}
2017
2018#ifndef __WIN32OS2__
2019/***********************************************************************
2020 * COMPOBJ_DllEntryPoint [COMPOBJ.entry]
2021 *
2022 * Initialization code for the COMPOBJ DLL
2023 *
2024 * RETURNS:
2025 */
2026BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)
2027{
2028 TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize,
2029 res1, res2);
2030 switch(Reason)
2031 {
2032 case DLL_PROCESS_ATTACH:
2033 if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst;
2034 break;
2035
2036 case DLL_PROCESS_DETACH:
2037 if(!--COMPOBJ_Attach)
2038 COMPOBJ_hInstance = 0;
2039 break;
2040 }
2041 return TRUE;
2042}
2043#endif
2044/******************************************************************************
2045 * OleGetAutoConvert [OLE32.104]
2046 */
2047HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
2048{
2049 HKEY hkey = 0;
2050 char buf[200];
2051 WCHAR wbuf[200];
2052 DWORD len;
2053 HRESULT res = S_OK;
2054
2055 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2056 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2057 {
2058 res = REGDB_E_CLASSNOTREG;
2059 goto done;
2060 }
2061 len = 200;
2062 /* we can just query for the default value of AutoConvertTo key like that,
2063 without opening the AutoConvertTo key and querying for NULL (default) */
2064 if (RegQueryValueA(hkey,"AutoConvertTo",buf,&len))
2065 {
2066 res = REGDB_E_KEYMISSING;
2067 goto done;
2068 }
2069 MultiByteToWideChar( CP_ACP, 0, buf, -1, wbuf, sizeof(wbuf)/sizeof(WCHAR) );
2070 CLSIDFromString(wbuf,pClsidNew);
2071done:
2072 if (hkey) RegCloseKey(hkey);
2073
2074 return res;
2075}
2076
2077/******************************************************************************
2078 * OleSetAutoConvert [OLE32.126]
2079 */
2080HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
2081{
2082 HKEY hkey = 0, hkeyConvert = 0;
2083 char buf[200], szClsidNew[200];
2084 HRESULT res = S_OK;
2085
2086 TRACE("(%p,%p);\n", clsidOld, clsidNew);
2087 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2088 WINE_StringFromCLSID(clsidNew, szClsidNew);
2089 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2090 {
2091 res = REGDB_E_CLASSNOTREG;
2092 goto done;
2093 }
2094 if (RegCreateKeyA(hkey, "AutoConvertTo", &hkeyConvert))
2095 {
2096 res = REGDB_E_WRITEREGDB;
2097 goto done;
2098 }
2099 if (RegSetValueExA(hkeyConvert, NULL, 0,
2100 REG_SZ, (LPBYTE)szClsidNew, strlen(szClsidNew)+1))
2101 {
2102 res = REGDB_E_WRITEREGDB;
2103 goto done;
2104 }
2105
2106done:
2107 if (hkeyConvert) RegCloseKey(hkeyConvert);
2108 if (hkey) RegCloseKey(hkey);
2109
2110 return res;
2111}
2112
2113/***********************************************************************
2114 * IsEqualGUID [OLE32.76]
2115 *
2116 * Compares two Unique Identifiers.
2117 *
2118 * RETURNS
2119 * TRUE if equal
2120 */
2121#undef IsEqualGUID
2122BOOL WINAPI IsEqualGUID(
2123 REFGUID rguid1, /* [in] unique id 1 */
2124 REFGUID rguid2 /* [in] unique id 2 */
2125 )
2126{
2127 return !memcmp(rguid1,rguid2,sizeof(GUID));
2128}
2129
2130#ifdef __WIN32OS2__
2131// ----------------------------------------------------------------------
2132// CLSIDFromStringA()
2133// @@@PH: this is not a WINE API, but a replacement for CLSIDFromString16
2134// which used to accept ASCII strings instead of OLE strings
2135// ----------------------------------------------------------------------
2136
2137HRESULT WIN32API CLSIDFromStringA(
2138 LPCSTR lpsz, // [in] - ASCII string CLSID
2139 LPCLSID pclsid) // [out] - Binary CLSID
2140{
2141 return CLSIDFromString16(lpsz, pclsid);
2142}
2143#endif
Note: See TracBrowser for help on using the repository browser.