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

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

Fixed out-of-scope FIXME,TRACE,WARN macros

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