mfplat/sample: Optimize copying to 2d buffer.
[wine.git] / dlls / compobj.dll16 / compobj.c
blob12a41775333057d49d8ac9439c69c1ed516c3cb7
1 /*
2 * 16 bit ole functions
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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "objbase.h"
36 #include "ole2.h"
37 #include "rpc.h"
38 #include "winerror.h"
39 #include "winreg.h"
40 #include "wownt32.h"
41 #include "wtypes.h"
42 #include "wine/winbase16.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48 typedef LPCSTR LPCOLESTR16;
50 #define CHARS_IN_GUID 39
52 typedef struct
54 SEGPTR QueryInterface;
55 SEGPTR AddRef;
56 SEGPTR Release;
57 SEGPTR Alloc;
58 SEGPTR Realloc;
59 SEGPTR Free;
60 SEGPTR GetSize;
61 SEGPTR DidAlloc;
62 SEGPTR HeapMinimize;
63 } IMalloc16Vtbl;
65 typedef struct
67 SEGPTR lpVtbl;
68 } IMalloc16;
70 static ULONG call_IMalloc_AddRef(SEGPTR iface)
72 IMalloc16 *malloc = MapSL(iface);
73 IMalloc16Vtbl *vtbl = MapSL(malloc->lpVtbl);
74 DWORD args[1], ret;
76 args[0] = iface;
77 WOWCallback16Ex(vtbl->AddRef, WCB16_CDECL, sizeof(args), args, &ret);
78 return ret;
81 static ULONG call_IMalloc_Release(SEGPTR iface)
83 IMalloc16 *malloc = MapSL(iface);
84 IMalloc16Vtbl *vtbl = MapSL(malloc->lpVtbl);
85 DWORD args[1], ret;
87 args[0] = iface;
88 WOWCallback16Ex(vtbl->Release, WCB16_CDECL, sizeof(args), args, &ret);
89 return ret;
92 static SEGPTR call_IMalloc_Alloc(SEGPTR iface, DWORD size)
94 IMalloc16 *malloc = MapSL(iface);
95 IMalloc16Vtbl *vtbl = MapSL(malloc->lpVtbl);
96 DWORD args[2], ret;
98 args[0] = iface;
99 args[1] = size;
100 WOWCallback16Ex(vtbl->Alloc, WCB16_CDECL, sizeof(args), args, &ret);
101 return ret;
104 static HTASK16 hETask = 0;
105 static WORD Table_ETask[62];
107 static SEGPTR compobj_malloc;
109 /* --- IMalloc16 implementation */
112 typedef struct
114 IMalloc16 IMalloc16_iface;
115 LONG refcount;
116 } IMalloc16Impl;
118 static inline IMalloc16Impl *impl_from_IMalloc16(IMalloc16 *iface)
120 return CONTAINING_RECORD(iface, IMalloc16Impl, IMalloc16_iface);
123 /******************************************************************************
124 * IMalloc16_QueryInterface [COMPOBJ.500]
126 HRESULT CDECL IMalloc16_fnQueryInterface(IMalloc16* iface,REFIID refiid,LPVOID *obj) {
127 IMalloc16Impl *This = impl_from_IMalloc16(iface);
129 TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
130 if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
131 !memcmp(&IID_IMalloc,refiid,sizeof(IID_IMalloc))
133 *obj = This;
134 return 0;
136 return OLE_E_ENUM_NOMORE;
139 /******************************************************************************
140 * IMalloc16_AddRef [COMPOBJ.501]
142 ULONG CDECL IMalloc16_fnAddRef(IMalloc16 *iface)
144 IMalloc16Impl *malloc = impl_from_IMalloc16(iface);
145 ULONG refcount = InterlockedIncrement(&malloc->refcount);
146 TRACE("%p increasing refcount to %lu.\n", malloc, refcount);
147 return refcount;
150 /******************************************************************************
151 * IMalloc16_Release [COMPOBJ.502]
153 ULONG CDECL IMalloc16_fnRelease(SEGPTR iface)
155 IMalloc16Impl *malloc = impl_from_IMalloc16(MapSL(iface));
156 ULONG refcount = InterlockedDecrement(&malloc->refcount);
157 TRACE("%p decreasing refcount to %lu.\n", malloc, refcount);
158 if (!refcount)
160 UnMapLS(iface);
161 HeapFree(GetProcessHeap(), 0, malloc);
163 return refcount;
166 /******************************************************************************
167 * IMalloc16_Alloc [COMPOBJ.503]
169 SEGPTR CDECL IMalloc16_fnAlloc(IMalloc16* iface,DWORD cb) {
170 IMalloc16Impl *This = impl_from_IMalloc16(iface);
172 TRACE("(%p)->Alloc(%ld)\n",This,cb);
173 return MapLS( HeapAlloc( GetProcessHeap(), 0, cb ) );
176 /******************************************************************************
177 * IMalloc16_Free [COMPOBJ.505]
179 VOID CDECL IMalloc16_fnFree(IMalloc16* iface,SEGPTR pv)
181 void *ptr = MapSL(pv);
182 IMalloc16Impl *This = impl_from_IMalloc16(iface);
183 TRACE("(%p)->Free(%08lx)\n",This,pv);
184 UnMapLS(pv);
185 HeapFree( GetProcessHeap(), 0, ptr );
188 /******************************************************************************
189 * IMalloc16_Realloc [COMPOBJ.504]
191 SEGPTR CDECL IMalloc16_fnRealloc(IMalloc16* iface,SEGPTR pv,DWORD cb)
193 SEGPTR ret;
194 IMalloc16Impl *This = impl_from_IMalloc16(iface);
196 TRACE("(%p)->Realloc(%08lx,%ld)\n",This,pv,cb);
197 if (!pv)
198 ret = IMalloc16_fnAlloc(iface, cb);
199 else if (cb) {
200 ret = MapLS( HeapReAlloc( GetProcessHeap(), 0, MapSL(pv), cb ) );
201 UnMapLS(pv);
202 } else {
203 IMalloc16_fnFree(iface, pv);
204 ret = 0;
206 return ret;
209 /******************************************************************************
210 * IMalloc16_GetSize [COMPOBJ.506]
212 DWORD CDECL IMalloc16_fnGetSize(IMalloc16* iface,SEGPTR pv)
214 IMalloc16Impl *This = impl_from_IMalloc16(iface);
216 TRACE("(%p)->GetSize(%08lx)\n",This,pv);
217 return HeapSize( GetProcessHeap(), 0, MapSL(pv) );
220 /******************************************************************************
221 * IMalloc16_DidAlloc [COMPOBJ.507]
223 INT16 CDECL IMalloc16_fnDidAlloc(IMalloc16* iface,LPVOID pv) {
224 IMalloc16Impl *This = impl_from_IMalloc16(iface);
226 TRACE("(%p)->DidAlloc(%p)\n",This,pv);
227 return (INT16)-1;
230 /******************************************************************************
231 * IMalloc16_HeapMinimize [COMPOBJ.508]
233 LPVOID CDECL IMalloc16_fnHeapMinimize(IMalloc16* iface) {
234 IMalloc16Impl *This = impl_from_IMalloc16(iface);
236 TRACE("(%p)->HeapMinimize()\n",This);
237 return NULL;
240 /******************************************************************************
241 * IMalloc16_Constructor [VTABLE]
243 static SEGPTR IMalloc16_Constructor(void)
245 static IMalloc16Vtbl vt16;
246 static SEGPTR msegvt16;
247 IMalloc16Impl* This;
248 HMODULE16 hcomp = GetModuleHandle16("COMPOBJ");
250 This = HeapAlloc( GetProcessHeap(), 0, sizeof(IMalloc16Impl) );
251 if (!msegvt16)
253 #define VTENT(x) vt16.x = (SEGPTR)GetProcAddress16(hcomp,"IMalloc16_"#x);assert(vt16.x)
254 VTENT(QueryInterface);
255 VTENT(AddRef);
256 VTENT(Release);
257 VTENT(Alloc);
258 VTENT(Realloc);
259 VTENT(Free);
260 VTENT(GetSize);
261 VTENT(DidAlloc);
262 VTENT(HeapMinimize);
263 #undef VTENT
264 msegvt16 = MapLS( &vt16 );
266 This->IMalloc16_iface.lpVtbl = msegvt16;
267 This->refcount = 1;
268 return MapLS(This);
271 /******************************************************************************
272 * CoBuildVersion [COMPOBJ.1]
274 DWORD WINAPI CoBuildVersion16(void)
276 return CoBuildVersion();
279 /***********************************************************************
280 * CoGetMalloc [COMPOBJ.4]
282 HRESULT WINAPI CoGetMalloc16(MEMCTX context, SEGPTR *malloc)
284 call_IMalloc_AddRef(*malloc = compobj_malloc);
285 return S_OK;
288 /***********************************************************************
289 * CoCreateStandardMalloc [COMPOBJ.71]
291 HRESULT WINAPI CoCreateStandardMalloc16(MEMCTX context, SEGPTR *malloc)
293 /* FIXME: docu says we shouldn't return the same allocator as in
294 * CoGetMalloc16 */
295 *malloc = IMalloc16_Constructor();
296 return S_OK;
299 /***********************************************************************
300 * CoMemAlloc [COMPOBJ.151]
302 SEGPTR WINAPI CoMemAlloc(DWORD size, MEMCTX context, DWORD unknown)
304 TRACE("size %lu, context %d, unknown %#lx.\n", size, context, unknown);
305 if (context != MEMCTX_TASK)
306 FIXME("Ignoring context %d.\n", context);
307 if (unknown)
308 FIXME("Ignoring unknown parameter %#lx.\n", unknown);
310 return call_IMalloc_Alloc(compobj_malloc, size);
313 /***********************************************************************
314 * CoInitialize [COMPOBJ.2]
316 HRESULT WINAPI CoInitialize16(SEGPTR malloc)
318 if (!malloc)
319 CoCreateStandardMalloc16(MEMCTX_TASK, &compobj_malloc);
320 else
321 call_IMalloc_AddRef(compobj_malloc = malloc);
322 return S_OK;
325 /***********************************************************************
326 * CoUninitialize [COMPOBJ.3]
327 * Don't know what it does.
328 * 3-Nov-98 -- this was originally misspelled, I changed it to what I
329 * believe is the correct spelling
331 void WINAPI CoUninitialize16(void)
333 TRACE("\n");
335 CoFreeAllLibraries();
336 call_IMalloc_Release(compobj_malloc);
337 compobj_malloc = 0;
340 /***********************************************************************
341 * CoFreeUnusedLibraries [COMPOBJ.17]
343 void WINAPI CoFreeUnusedLibraries16(void)
345 CoFreeUnusedLibraries();
348 /***********************************************************************
349 * IsEqualGUID [COMPOBJ.18]
351 * Compares two Unique Identifiers.
353 * RETURNS
354 * TRUE if equal
356 BOOL16 WINAPI IsEqualGUID16(
357 GUID* g1, /* [in] unique id 1 */
358 GUID* g2) /* [in] unique id 2 */
360 return !memcmp( g1, g2, sizeof(GUID) );
363 /******************************************************************************
364 * CLSIDFromString [COMPOBJ.20]
365 * Converts a unique identifier from its string representation into
366 * the GUID struct.
368 * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6]
370 * RETURNS
371 * the converted GUID
373 HRESULT WINAPI CLSIDFromString16(
374 LPCOLESTR16 idstr, /* [in] string representation of guid */
375 CLSID *id) /* [out] GUID converted from string */
377 const BYTE *s;
378 int i;
379 BYTE table[256];
381 if (!idstr) {
382 memset( id, 0, sizeof (CLSID) );
383 return S_OK;
386 /* validate the CLSID string */
387 if (strlen(idstr) != 38)
388 return CO_E_CLASSSTRING;
390 s = (const BYTE *) idstr;
391 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
392 return CO_E_CLASSSTRING;
394 for (i=1; i<37; i++) {
395 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
396 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
397 ((s[i] >= 'a') && (s[i] <= 'f')) ||
398 ((s[i] >= 'A') && (s[i] <= 'F'))))
399 return CO_E_CLASSSTRING;
402 TRACE("%s -> %p\n", s, id);
404 /* quick lookup table */
405 memset(table, 0, 256);
407 for (i = 0; i < 10; i++) {
408 table['0' + i] = i;
410 for (i = 0; i < 6; i++) {
411 table['A' + i] = i+10;
412 table['a' + i] = i+10;
415 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
417 id->Data1 = (table[s[1]] << 28 | table[s[2]] << 24 | table[s[3]] << 20 | table[s[4]] << 16 |
418 table[s[5]] << 12 | table[s[6]] << 8 | table[s[7]] << 4 | table[s[8]]);
419 id->Data2 = table[s[10]] << 12 | table[s[11]] << 8 | table[s[12]] << 4 | table[s[13]];
420 id->Data3 = table[s[15]] << 12 | table[s[16]] << 8 | table[s[17]] << 4 | table[s[18]];
422 /* these are just sequential bytes */
423 id->Data4[0] = table[s[20]] << 4 | table[s[21]];
424 id->Data4[1] = table[s[22]] << 4 | table[s[23]];
425 id->Data4[2] = table[s[25]] << 4 | table[s[26]];
426 id->Data4[3] = table[s[27]] << 4 | table[s[28]];
427 id->Data4[4] = table[s[29]] << 4 | table[s[30]];
428 id->Data4[5] = table[s[31]] << 4 | table[s[32]];
429 id->Data4[6] = table[s[33]] << 4 | table[s[34]];
430 id->Data4[7] = table[s[35]] << 4 | table[s[36]];
432 return S_OK;
435 /***********************************************************************
436 * StringFromCLSID [COMPOBJ.151]
438 HRESULT WINAPI StringFromCLSID16(REFCLSID id, SEGPTR *str)
440 WCHAR buffer[40];
441 if (!(*str = CoMemAlloc(40, MEMCTX_TASK, 0)))
442 return E_OUTOFMEMORY;
443 StringFromGUID2( id, buffer, 40 );
444 WideCharToMultiByte( CP_ACP, 0, buffer, -1, MapSL(*str), 40, NULL, NULL );
445 return S_OK;
448 /***********************************************************************
449 * ProgIDFromCLSID [COMPOBJ.151]
451 HRESULT WINAPI ProgIDFromCLSID16(REFCLSID clsid, SEGPTR *str)
453 LPOLESTR progid;
454 HRESULT ret;
456 ret = ProgIDFromCLSID( clsid, &progid );
457 if (ret == S_OK)
459 INT len = WideCharToMultiByte( CP_ACP, 0, progid, -1, NULL, 0, NULL, NULL );
460 if ((*str = CoMemAlloc(len, MEMCTX_TASK, 0)))
461 WideCharToMultiByte( CP_ACP, 0, progid, -1, MapSL(*str), len, NULL, NULL );
462 CoTaskMemFree( progid );
464 return ret;
467 /***********************************************************************
468 * LookupETask (COMPOBJ.94)
470 HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) {
471 FIXME("(%p,%p),stub!\n",hTask,p);
472 if ((*hTask = GetCurrentTask()) == hETask) {
473 memcpy(p, Table_ETask, sizeof(Table_ETask));
475 return 0;
478 /***********************************************************************
479 * SetETask (COMPOBJ.95)
481 HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) {
482 FIXME("(%04x,%p),stub!\n",hTask,p);
483 hETask = hTask;
484 return 0;
487 /***********************************************************************
488 * CALLOBJECTINWOW (COMPOBJ.201)
490 HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
491 FIXME("(%p,%p),stub!\n",p1,p2);
492 return 0;
495 /******************************************************************************
496 * CoRegisterClassObject [COMPOBJ.5]
498 * Don't know where it registers it ...
500 HRESULT WINAPI CoRegisterClassObject16(
501 REFCLSID rclsid,
502 LPUNKNOWN pUnk,
503 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
504 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
505 LPDWORD lpdwRegister
507 FIXME("(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
508 debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister
510 return 0;
513 /******************************************************************************
514 * CoRevokeClassObject [COMPOBJ.6]
517 HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */
519 FIXME("(0x%08lx),stub!\n", dwRegister);
520 return 0;
523 /******************************************************************************
524 * IsValidInterface [COMPOBJ.23]
526 * Determines whether a pointer is a valid interface.
528 * PARAMS
529 * punk [I] Interface to be tested.
531 * RETURNS
532 * TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
534 BOOL WINAPI IsValidInterface16(SEGPTR punk)
536 DWORD **ptr;
538 if (IsBadReadPtr16(punk,4))
539 return FALSE;
540 ptr = MapSL(punk);
541 if (IsBadReadPtr16((SEGPTR)ptr[0],4)) /* check vtable ptr */
542 return FALSE;
543 ptr = MapSL((SEGPTR)ptr[0]); /* ptr to first method */
544 if (IsBadReadPtr16((SEGPTR)ptr[0],2))
545 return FALSE;
546 return TRUE;
549 /******************************************************************************
550 * CoFileTimeToDosDateTime [COMPOBJ.30]
552 BOOL16 WINAPI CoFileTimeToDosDateTime16(const FILETIME *ft, LPWORD lpDosDate, LPWORD lpDosTime)
554 return FileTimeToDosDateTime(ft, lpDosDate, lpDosTime);
557 /******************************************************************************
558 * CoDosDateTimeToFileTime [COMPOBJ.31]
560 BOOL16 WINAPI CoDosDateTimeToFileTime16(WORD wDosDate, WORD wDosTime, FILETIME *ft)
562 return DosDateTimeToFileTime(wDosDate, wDosTime, ft);
565 /******************************************************************************
566 * CoGetCurrentProcess [COMPOBJ.34]
568 DWORD WINAPI CoGetCurrentProcess16(void)
570 return CoGetCurrentProcess();
573 /******************************************************************************
574 * CoRegisterMessageFilter [COMPOBJ.27]
576 HRESULT WINAPI CoRegisterMessageFilter16(
577 LPMESSAGEFILTER lpMessageFilter,
578 LPMESSAGEFILTER *lplpMessageFilter
580 FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
581 return 0;
584 /******************************************************************************
585 * CoLockObjectExternal [COMPOBJ.63]
587 HRESULT WINAPI CoLockObjectExternal16(
588 LPUNKNOWN pUnk, /* [in] object to be locked */
589 BOOL16 fLock, /* [in] do lock */
590 BOOL16 fLastUnlockReleases /* [in] ? */
592 FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
593 return S_OK;
596 /***********************************************************************
597 * CoGetState [COMPOBJ.115]
599 HRESULT WINAPI CoGetState16(LPDWORD state)
601 FIXME("(%p),stub!\n", state);
603 *state = 0;
604 return S_OK;
607 /***********************************************************************
608 * DllEntryPoint [COMPOBJ.116]
610 * Initialization code for the COMPOBJ DLL
612 * RETURNS:
614 BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)
616 TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize, res1, res2);
617 return TRUE;
620 /******************************************************************************
621 * CLSIDFromProgID [COMPOBJ.61]
623 * Converts a program ID into the respective GUID.
625 * PARAMS
626 * progid [I] program id as found in registry
627 * riid [O] associated CLSID
629 * RETURNS
630 * Success: S_OK
631 * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.
633 HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid)
635 char *buf,buf2[80];
636 LONG buf2len;
637 HKEY xhkey;
639 buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
640 sprintf(buf,"%s\\CLSID",progid);
641 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey)) {
642 HeapFree(GetProcessHeap(),0,buf);
643 return CO_E_CLASSSTRING;
645 HeapFree(GetProcessHeap(),0,buf);
646 buf2len = sizeof(buf2);
647 if (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) {
648 RegCloseKey(xhkey);
649 return CO_E_CLASSSTRING;
651 RegCloseKey(xhkey);
652 return CLSIDFromString16(buf2,riid);
655 /******************************************************************************
656 * StringFromGUID2 [COMPOBJ.76]
658 INT16 WINAPI StringFromGUID216(REFGUID id, char *str, INT16 cmax)
660 static const char format[] = "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}";
661 if (!id || cmax < CHARS_IN_GUID) return 0;
662 sprintf( str, format, id->Data1, id->Data2, id->Data3,
663 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
664 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
665 return CHARS_IN_GUID;
669 /***********************************************************************
670 * CoFileTimeNow [COMPOBJ.82]
672 HRESULT WINAPI CoFileTimeNow16( FILETIME *lpFileTime )
674 return CoFileTimeNow( lpFileTime );
677 /***********************************************************************
678 * CoGetClassObject [COMPOBJ.7]
681 HRESULT WINAPI CoGetClassObject16(
682 SEGPTR rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
683 SEGPTR riid, SEGPTR ppv)
685 LPVOID *ppvl = MapSL(ppv);
687 TRACE("CLSID: %s, IID: %s\n", debugstr_guid(MapSL(rclsid)), debugstr_guid(MapSL(riid)));
689 *ppvl = NULL;
691 if (pServerInfo) {
692 FIXME("pServerInfo->name=%s pAuthInfo=%p\n",
693 debugstr_w(pServerInfo->pwszName), pServerInfo->pAuthInfo);
696 if (CLSCTX_INPROC_SERVER & dwClsContext)
698 char idstr[CHARS_IN_GUID];
699 char buf_key[CHARS_IN_GUID+19], dllpath[MAX_PATH+1];
700 LONG dllpath_len = sizeof(dllpath);
702 HMODULE16 dll;
703 FARPROC16 DllGetClassObject;
705 WORD args[6];
706 DWORD dwRet;
708 StringFromGUID216(MapSL(rclsid), idstr, CHARS_IN_GUID);
709 sprintf(buf_key, "CLSID\\%s\\InprocServer", idstr);
710 if (RegQueryValueA(HKEY_CLASSES_ROOT, buf_key, dllpath, &dllpath_len))
712 ERR("class %s not registered\n", debugstr_guid(MapSL(rclsid)));
713 return REGDB_E_CLASSNOTREG;
716 dll = LoadLibrary16(dllpath);
717 if (!dll)
719 ERR("couldn't load in-process dll %s\n", debugstr_a(dllpath));
720 return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
723 DllGetClassObject = GetProcAddress16(dll, "DllGetClassObject");
724 if (!DllGetClassObject)
726 ERR("couldn't find function DllGetClassObject in %s\n", debugstr_a(dllpath));
727 FreeLibrary16(dll);
728 return CO_E_DLLNOTFOUND;
731 TRACE("calling DllGetClassObject %p\n", DllGetClassObject);
732 args[5] = SELECTOROF(rclsid);
733 args[4] = OFFSETOF(rclsid);
734 args[3] = SELECTOROF(riid);
735 args[2] = OFFSETOF(riid);
736 args[1] = SELECTOROF(ppv);
737 args[0] = OFFSETOF(ppv);
738 WOWCallback16Ex((DWORD) DllGetClassObject, WCB16_PASCAL, sizeof(args), args, &dwRet);
739 if (dwRet != S_OK)
741 ERR("DllGetClassObject returned error 0x%08lx\n", dwRet);
742 FreeLibrary16(dll);
743 return dwRet;
746 return S_OK;
749 FIXME("semi-stub\n");
750 return E_NOTIMPL;
753 /******************************************************************************
754 * CoCreateGuid [COMPOBJ.73]
756 HRESULT WINAPI CoCreateGuid16(GUID *pguid)
758 return CoCreateGuid( pguid );
761 /***********************************************************************
762 * CoCreateInstance [COMPOBJ.13]
764 HRESULT WINAPI CoCreateInstance16(
765 REFCLSID rclsid,
766 LPUNKNOWN pUnkOuter,
767 DWORD dwClsContext,
768 REFIID iid,
769 LPVOID *ppv)
771 FIXME("(%s, %p, %lx, %s, %p), stub!\n",
772 debugstr_guid(rclsid), pUnkOuter, dwClsContext, debugstr_guid(iid),
775 return E_NOTIMPL;
778 /***********************************************************************
779 * CoDisconnectObject [COMPOBJ.15]
781 HRESULT WINAPI CoDisconnectObject16( LPUNKNOWN lpUnk, DWORD reserved )
783 FIXME("(%p, 0x%08lx): stub!\n", lpUnk, reserved);
784 return E_NOTIMPL;