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

Last change on this file since 7926 was 7926, checked in by sandervl, 24 years ago

Wine 20020215 resync

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