Documentation updates.
[wine] / ole / compobj.c
1 /*
2  *      COMPOBJ library
3  *
4  *      Copyright 1995  Martin von Loewis
5  */
6
7 #define INITGUID
8
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include "ole.h"
14 #include "ole2.h"
15 #include "winerror.h"
16 #include "debug.h"
17 #include "file.h"
18 #include "compobj.h"
19 #include "heap.h"
20 #include "ldt.h"
21 #include "interfaces.h"
22 #include "shlobj.h"
23 #include "ddraw.h"
24 #include "dsound.h"
25 #include "dinput.h"
26 #include "d3d.h"
27 #include "dplay.h"
28
29
30 LPMALLOC16 currentMalloc16=NULL;
31 LPMALLOC32 currentMalloc32=NULL;
32
33 HTASK16 hETask = 0;
34 WORD Table_ETask[62];
35
36 /******************************************************************************
37  *           CoBuildVersion [COMPOBJ.1]
38  *
39  * RETURNS
40  *      Current built version, hiword is majornumber, loword is minornumber
41  */
42 DWORD WINAPI CoBuildVersion()
43 {
44     TRACE(ole,"(void)\n");
45     return (rmm<<16)+rup;
46 }
47
48 /******************************************************************************
49  *              CoInitialize16  [COMPOBJ.2]
50  * Set the win16 IMalloc used for memory management
51  */
52 HRESULT WINAPI CoInitialize16(
53         LPMALLOC16 lpReserved   /* [in] pointer to win16 malloc interface */
54 ) {
55     currentMalloc16 = lpReserved;
56     return S_OK;
57 }
58
59 /******************************************************************************
60  *              CoInitialize32  [OLE32.26]
61  * Set the win32 IMalloc used for memorymanagement
62  */
63 HRESULT WINAPI CoInitialize32(
64         LPMALLOC32 lpReserved   /* [in] pointer to win32 malloc interface */
65 ) {
66     currentMalloc32 = lpReserved;
67     return S_OK;
68 }
69
70 /***********************************************************************
71  *           CoUnitialize   [COMPOBJ.3]
72  * Don't know what it does.
73  */
74 void WINAPI CoUnitialize()
75 {
76     TRACE(ole,"(void)\n");
77 }
78
79 /***********************************************************************
80  *           CoGetMalloc16    [COMPOBJ.4]
81  * RETURNS
82  *      The current win16 IMalloc
83  */
84 HRESULT WINAPI CoGetMalloc16(
85         DWORD dwMemContext,     /* [in] unknown */
86         LPMALLOC16 * lpMalloc   /* [out] current win16 malloc interface */
87 ) {
88     if(!currentMalloc16)
89         currentMalloc16 = IMalloc16_Constructor();
90     *lpMalloc = currentMalloc16;
91     return S_OK;
92 }
93
94 /******************************************************************************
95  *              CoGetMalloc32   [OLE32.20]
96  *
97  * RETURNS
98  *      The current win32 IMalloc
99  */
100 HRESULT WINAPI CoGetMalloc32(
101         DWORD dwMemContext,     /* [in] unknown */
102         LPMALLOC32 *lpMalloc    /* [out] current win32 malloc interface */
103 ) {
104     if(!currentMalloc32)
105         currentMalloc32 = IMalloc32_Constructor();
106     *lpMalloc = currentMalloc32;
107     return S_OK;
108 }
109
110 /***********************************************************************
111  *           CoCreateStandardMalloc16 [COMPOBJ.71]
112  */
113 OLESTATUS WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
114                                           LPMALLOC16 *lpMalloc)
115 {
116     /* FIXME: docu says we shouldn't return the same allocator as in
117      * CoGetMalloc16 */
118     *lpMalloc = IMalloc16_Constructor();
119     return S_OK;
120 }
121
122 /******************************************************************************
123  *              CoDisconnectObject      [COMPOBJ.15]
124  */
125 OLESTATUS WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
126 {
127     TRACE(ole,"%p %lx\n",lpUnk,reserved);
128     return S_OK;
129 }
130
131 /***********************************************************************
132  *           IsEqualGUID [COMPOBJ.18]
133  * Compares two Unique Identifiers
134  * RETURNS
135  *      TRUE if equal
136  */
137 BOOL16 WINAPI IsEqualGUID(
138         GUID* g1,       /* [in] unique id 1 */
139         GUID* g2        /* [in] unique id 2 */
140 ) {
141     return !memcmp( g1, g2, sizeof(GUID) );
142 }
143
144 /******************************************************************************
145  *              CLSIDFromString16       [COMPOBJ.20]
146  * Converts a unique identifier from it's string representation into 
147  * the GUID struct.
148  *
149  * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6] 
150  *
151  * RETURNS
152  *      the converted GUID
153  */
154 OLESTATUS WINAPI CLSIDFromString16(
155         LPCOLESTR16 idstr,      /* [in] string representation of guid */
156         CLSID *id               /* [out] GUID converted from string */
157 ) {
158   BYTE *s = (BYTE *) idstr;
159   BYTE *p;
160   int   i;
161   BYTE table[256];
162
163   TRACE(ole,"%s -> %p\n", idstr, id);
164
165   /* quick lookup table */
166   memset(table, 0, 256);
167
168   for (i = 0; i < 10; i++) {
169     table['0' + i] = i;
170   }
171   for (i = 0; i < 6; i++) {
172     table['A' + i] = i+10;
173     table['a' + i] = i+10;
174   }
175
176   /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
177
178   if (strlen(idstr) != 38)
179     return OLE_ERROR_OBJECT;
180
181   p = (BYTE *) id;
182
183   s++;  /* skip leading brace  */
184   for (i = 0; i < 4; i++) {
185     p[3 - i] = table[*s]<<4 | table[*(s+1)];
186     s += 2;
187   }
188   p += 4;
189   s++;  /* skip - */
190
191   for (i = 0; i < 2; i++) {
192     p[1-i] = table[*s]<<4 | table[*(s+1)];
193     s += 2;
194   }
195   p += 2;
196   s++;  /* skip - */
197
198   for (i = 0; i < 2; i++) {
199     p[1-i] = table[*s]<<4 | table[*(s+1)];
200     s += 2;
201   }
202   p += 2;
203   s++;  /* skip - */
204
205   /* these are just sequential bytes */
206   for (i = 0; i < 2; i++) {
207     *p++ = table[*s]<<4 | table[*(s+1)];
208     s += 2;
209   }
210   s++;  /* skip - */
211
212   for (i = 0; i < 6; i++) {
213     *p++ = table[*s]<<4 | table[*(s+1)];
214     s += 2;
215   }
216
217   return S_OK;
218 }
219
220 /******************************************************************************
221  *              CLSIDFromString32       [OLE32.3]
222  * Converts a unique identifier from it's string representation into 
223  * the GUID struct.
224  * RETURNS
225  *      the converted GUID
226  */
227 OLESTATUS WINAPI CLSIDFromString32(
228         LPCOLESTR32 idstr,      /* [in] string representation of GUID */
229         CLSID *id               /* [out] GUID represented by above string */
230 ) {
231     LPOLESTR16      xid = HEAP_strdupWtoA(GetProcessHeap(),0,idstr);
232     OLESTATUS       ret = CLSIDFromString16(xid,id);
233
234     HeapFree(GetProcessHeap(),0,xid);
235     return ret;
236 }
237
238 /******************************************************************************
239  *              WINE_StringFromCLSID    [???]
240  * Converts a GUID into the respective string representation.
241  *
242  * NOTES
243  *    Why is this WINAPI?
244  *
245  * RETURNS
246  *      the string representation and OLESTATUS
247  */
248 OLESTATUS WINAPI WINE_StringFromCLSID(
249         const CLSID *id,        /* [in] GUID to be converted */
250         LPSTR idstr             /* [out] pointer to buffer to contain converted guid */
251 ) {
252   static const char *hex = "0123456789ABCDEF";
253   char *s;
254   int   i;
255
256   if (!id)
257         { ERR(ole,"called with id=Null\n");
258           *idstr = 0x00;
259           return E_FAIL;
260         }
261         
262   sprintf(idstr, "{%08lx-%04x-%04x-%02x%02x-",
263           id->Data1, id->Data2, id->Data3,
264           id->Data4[0], id->Data4[1]);
265   s = &idstr[25];
266
267   /* 6 hex bytes */
268   for (i = 2; i < 8; i++) {
269     *s++ = hex[id->Data4[i]>>4];
270     *s++ = hex[id->Data4[i] & 0xf];
271   }
272
273   *s++ = '}';
274   *s++ = '\0';
275
276   for (i = strlen(idstr)-1; i >= 0; i--) {
277     idstr[i] = toupper(idstr[i]);
278   }
279
280   TRACE(ole,"%p->%s\n", id, idstr);
281
282   return OLE_OK;
283 }
284
285 /******************************************************************************
286  *              StringFromCLSID16       [COMPOBJ.19]
287  * Converts a GUID into the respective string representation.
288  * The target string is allocated using the OLE IMalloc.
289  * RETURNS
290  *      the string representation and OLESTATUS
291  */
292 OLESTATUS WINAPI StringFromCLSID16(
293         const CLSID *id,        /* [in] the GUID to be converted */
294         LPOLESTR16 *idstr       /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */
295
296 ) {
297     LPMALLOC16  mllc;
298     OLESTATUS   ret;
299     DWORD       args[2];
300
301     ret = CoGetMalloc16(0,&mllc);
302     if (ret) return ret;
303
304     args[0] = (DWORD)mllc;
305     args[1] = 40;
306
307     /* No need for a Callback entry, we have WOWCallback16Ex which does
308      * everything we need.
309      */
310     if (!WOWCallback16Ex(
311         (FARPROC16)((LPMALLOC16_VTABLE)PTR_SEG_TO_LIN(
312                 ((LPMALLOC16)PTR_SEG_TO_LIN(mllc))->lpvtbl)
313         )->fnAlloc,
314         WCB16_CDECL,
315         2,
316         (LPVOID)args,
317         (LPDWORD)idstr
318     )) {
319         WARN(ole,"CallTo16 IMalloc16 failed\n");
320         return E_FAIL;
321     }
322     return WINE_StringFromCLSID(id,PTR_SEG_TO_LIN(*idstr));
323 }
324
325 /******************************************************************************
326  *              StringFromCLSID32       [OLE32.151]
327  * Converts a GUID into the respective string representation.
328  * The target string is allocated using the OLE IMalloc.
329  * RETURNS
330  *      the string representation and OLESTATUS
331  */
332 OLESTATUS WINAPI StringFromCLSID32(
333         const CLSID *id,        /* [in] the GUID to be converted */
334         LPOLESTR32 *idstr       /* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
335 ) {
336         char            buf[80];
337         OLESTATUS       ret;
338         LPMALLOC32      mllc;
339
340         if ((ret=CoGetMalloc32(0,&mllc)))
341                 return ret;
342
343         ret=WINE_StringFromCLSID(id,buf);
344         if (!ret) {
345                 *idstr = mllc->lpvtbl->fnAlloc(mllc,strlen(buf)*2+2);
346                 lstrcpyAtoW(*idstr,buf);
347         }
348         return ret;
349 }
350
351 /******************************************************************************
352  *              StringFromGUID2 [COMPOBJ.76] [OLE32.152]
353  *
354  * Converts a global unique identifier into a string of an API-
355  * specified fixed format. (The usual {.....} stuff.)
356  *
357  * RETURNS
358  *      The (UNICODE) string representation of the GUID in 'str'
359  *      The length of the resulting string, 0 if there was any problem.
360  */
361 INT32 WINAPI
362 StringFromGUID2(REFGUID id, LPOLESTR32 str, INT32 cmax)
363 {
364   char          xguid[80];
365
366   if (WINE_StringFromCLSID(id,xguid))
367         return 0;
368   if (strlen(xguid)>=cmax)
369         return 0;
370   lstrcpyAtoW(str,xguid);
371   return strlen(xguid);
372 }
373
374 /******************************************************************************
375  *              CLSIDFromProgID16       [COMPOBJ.61]
376  * Converts a program id into the respective GUID. (By using a registry lookup)
377  * RETURNS
378  *      riid associated with the progid
379  */
380 OLESTATUS WINAPI CLSIDFromProgID16(
381         LPCOLESTR16 progid,     /* [in] program id as found in registry */
382         LPCLSID riid            /* [out] associated CLSID */
383 ) {
384         char    *buf,buf2[80];
385         DWORD   buf2len;
386         HRESULT err;
387         HKEY    xhkey;
388
389         buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
390         sprintf(buf,"%s\\CLSID",progid);
391         if ((err=RegOpenKey32A(HKEY_CLASSES_ROOT,buf,&xhkey))) {
392                 HeapFree(GetProcessHeap(),0,buf);
393                 return OLE_ERROR_GENERIC;
394         }
395         HeapFree(GetProcessHeap(),0,buf);
396         buf2len = sizeof(buf2);
397         if ((err=RegQueryValue32A(xhkey,NULL,buf2,&buf2len))) {
398                 RegCloseKey(xhkey);
399                 return OLE_ERROR_GENERIC;
400         }
401         RegCloseKey(xhkey);
402         return CLSIDFromString16(buf2,riid);
403 }
404
405 /******************************************************************************
406  *              CLSIDFromProgID32       [OLE32.2]
407  * Converts a program id into the respective GUID. (By using a registry lookup)
408  * RETURNS
409  *      riid associated with the progid
410  */
411 OLESTATUS WINAPI CLSIDFromProgID32(
412         LPCOLESTR32 progid,     /* [in] program id as found in registry */
413         LPCLSID riid            /* [out] associated CLSID */
414 ) {
415         LPOLESTR16 pid = HEAP_strdupWtoA(GetProcessHeap(),0,progid);
416         OLESTATUS       ret = CLSIDFromProgID16(pid,riid);
417
418         HeapFree(GetProcessHeap(),0,pid);
419         return ret;
420 }
421
422 /***********************************************************************
423  *           LookupETask (COMPOBJ.94)
424  */
425 OLESTATUS WINAPI LookupETask(HTASK16 *hTask,LPVOID p) {
426         FIXME(ole,"(%p,%p),stub!\n",hTask,p);
427         if ((*hTask = GetCurrentTask()) == hETask) {
428                 memcpy(p, Table_ETask, sizeof(Table_ETask));
429         }
430         return 0;
431 }
432
433 /***********************************************************************
434  *           SetETask (COMPOBJ.95)
435  */
436 OLESTATUS WINAPI SetETask(HTASK16 hTask, LPVOID p) {
437         FIXME(ole,"(%04x,%p),stub!\n",hTask,p);
438         hETask = hTask;
439         return 0;
440 }
441
442 /***********************************************************************
443  *           CallObjectInWOW (COMPOBJ.201)
444  */
445 OLESTATUS WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
446         FIXME(ole,"(%p,%p),stub!\n",p1,p2);
447         return 0;
448 }
449
450 /******************************************************************************
451  *              CoRegisterClassObject16 [COMPOBJ.5]
452  *
453  * Don't know where it registers it ...
454  */
455 OLESTATUS WINAPI CoRegisterClassObject16(
456         REFCLSID rclsid,
457         LPUNKNOWN pUnk,
458         DWORD dwClsContext,
459         DWORD flags,
460         LPDWORD lpdwRegister
461 ) {
462         char    buf[80];
463
464         WINE_StringFromCLSID(rclsid,buf);
465
466         FIXME(ole,"(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
467                 buf,pUnk,dwClsContext,flags,lpdwRegister
468         );
469         return 0;
470 }
471
472 /******************************************************************************
473  *              CoRegisterClassObject32 [OLE32.36]
474  *
475  * Don't know where it registers it ...
476  */
477 OLESTATUS WINAPI CoRegisterClassObject32(
478         REFCLSID rclsid,
479         LPUNKNOWN pUnk,
480         DWORD dwClsContext,
481         DWORD flags,
482         LPDWORD lpdwRegister
483 ) {
484     char buf[80];
485
486     WINE_StringFromCLSID(rclsid,buf);
487
488     FIXME(ole,"(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
489             buf,pUnk,dwClsContext,flags,lpdwRegister
490     );
491     return 0;
492 }
493
494 /***********************************************************************
495  *           CoGetClassObject [COMPOBJ.7]
496  */
497 HRESULT WINAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext,
498                         LPVOID pvReserved, REFIID iid, LPVOID *ppv)
499 {
500     char xclsid[50],xiid[50];
501     LPCLASSFACTORY lpclf;
502     HRESULT hres = E_UNEXPECTED;
503
504     WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
505     WINE_StringFromCLSID((LPCLSID)iid,xiid);
506     TRACE(ole,"\n\tCLSID:\t%s,\n\tIID:\t%s\n",xclsid,xiid);
507
508     *ppv = NULL;
509     lpclf = IClassFactory_Constructor();
510     if (lpclf)
511     {
512         hres = lpclf->lpvtbl->fnQueryInterface(lpclf,iid, ppv);
513         lpclf->lpvtbl->fnRelease(lpclf);
514     }
515     return hres;
516 }
517
518 /******************************************************************************
519  *              CoRegisterMessageFilter16       [COMPOBJ.27]
520  */
521 OLESTATUS WINAPI CoRegisterMessageFilter16(
522         LPMESSAGEFILTER lpMessageFilter,
523         LPMESSAGEFILTER *lplpMessageFilter
524 ) {
525         FIXME(ole,"(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
526         return 0;
527 }
528
529 /***********************************************************************
530  *           CoCreateInstance [COMPOBJ.13, OLE32.7]
531  */
532 HRESULT WINAPI CoCreateInstance(
533         REFCLSID rclsid,
534         LPUNKNOWN pUnkOuter,
535         DWORD dwClsContext,
536         REFIID iid,
537         LPVOID *ppv
538 ) {
539 #if 0
540         char buf[80],xbuf[80];
541
542         if (rclsid)
543                 WINE_StringFromCLSID(rclsid,buf);
544         else
545                 sprintf(buf,"<rclsid-0x%08lx>",(DWORD)rclsid);
546         if (iid)
547                 WINE_StringFromCLSID(iid,xbuf);
548         else
549                 sprintf(xbuf,"<iid-0x%08lx>",(DWORD)iid);
550
551         FIXME(ole,"(%s,%p,0x%08lx,%s,%p): stub !\n",buf,pUnkOuter,dwClsContext,xbuf,ppv);
552         *ppv = NULL;
553 #else   
554         HRESULT hres;
555         LPCLASSFACTORY lpclf = 0;
556
557         CoGetClassObject(rclsid, dwClsContext, NULL, &IID_IClassFactory, (LPVOID)&lpclf);
558         hres = lpclf->lpvtbl->fnCreateInstance(lpclf, pUnkOuter, iid, ppv);
559         lpclf->lpvtbl->fnRelease(lpclf);
560         return hres;
561 #endif
562 }
563
564 /***********************************************************************
565  *           CoFreeUnusedLibraries [COMPOBJ.17]
566  */
567 void WINAPI CoFreeUnusedLibraries()
568 {
569         FIXME(ole,"(), stub !\n");
570 }
571
572 /***********************************************************************
573  *           CoFileTimeNow [COMPOBJ.82, OLE32.10]
574  * RETURNS
575  *      the current system time in lpFileTime
576  */
577 HRESULT WINAPI CoFileTimeNow(
578         FILETIME *lpFileTime    /* [out] the current time */
579 ) {
580         DOSFS_UnixTimeToFileTime(time(NULL), lpFileTime, 0);
581         return S_OK;
582 }
583
584 /***********************************************************************
585  *           CoTaskMemAlloc (OLE32.43)
586  * RETURNS
587  *      pointer to newly allocated block
588  */
589 LPVOID WINAPI CoTaskMemAlloc(
590         ULONG size      /* [in] size of memoryblock to be allocated */
591 ) {
592     LPMALLOC32  lpmalloc;
593     HRESULT     ret = CoGetMalloc32(0,&lpmalloc);
594
595     if (ret) 
596         return NULL;
597     return lpmalloc->lpvtbl->fnAlloc(lpmalloc,size);
598 }
599
600 /***********************************************************************
601  *           CoTaskMemFree (OLE32.44)
602  */
603 VOID WINAPI CoTaskMemFree(
604         LPVOID ptr      /* [in] pointer to be freed */
605 ) {
606     LPMALLOC32  lpmalloc;
607     HRESULT     ret = CoGetMalloc32(0,&lpmalloc);
608
609     if (ret) return;
610     return lpmalloc->lpvtbl->fnFree(lpmalloc,ptr);
611 }
612
613 /***********************************************************************
614  *           CoInitializeWOW (OLE32.27)
615  */
616 HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
617     FIXME(ole,"(0x%08lx,0x%08lx),stub!\n",x,y);
618     return 0;
619 }
620
621 /******************************************************************************
622  *              CoLockObjectExternal16  [COMPOBJ.63]
623  */
624 HRESULT WINAPI CoLockObjectExternal16(
625     LPUNKNOWN pUnk,             /* [in] object to be locked */
626     BOOL16 fLock,               /* [in] do lock */
627     BOOL16 fLastUnlockReleases  /* [in] ? */
628 ) {
629     FIXME(ole,"(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
630     return S_OK;
631 }
632
633 /******************************************************************************
634  *              CoLockObjectExternal32  [OLE32.31]
635  */
636 HRESULT WINAPI CoLockObjectExternal32(
637     LPUNKNOWN pUnk,             /* [in] object to be locked */
638     BOOL32 fLock,               /* [in] do lock */
639     BOOL32 fLastUnlockReleases  /* [in] ? */
640 ) {
641     FIXME(ole,"(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
642     return S_OK;
643 }
644
645 /***********************************************************************
646  *           CoGetState16 [COMPOBJ.115]
647  */
648 HRESULT WINAPI CoGetState16(LPDWORD state)
649 {
650     FIXME(ole, "(%p),stub!\n", state);
651     *state = 0;
652     return S_OK;
653 }
654 /***********************************************************************
655  *           CoSetState32 [COM32.42]
656  */
657 HRESULT WINAPI CoSetState32(LPDWORD state)
658 {
659     FIXME(ole, "(%p),stub!\n", state);
660     *state = 0;
661     return S_OK;
662 }