Added mappings for a few messages.
[wine] / dlls / oleaut32 / typelib.c
1 /*
2  *      TYPELIB
3  *
4  *      Copyright 1997  Marcus Meissner
5  *                    1999  Rein Klazes
6  *                    2000  Francois Jacques
7  * --------------------------------------------------------------------------------------
8  * Known problems (2000, Francois Jacques)
9  *
10  * - Tested using OLEVIEW (Platform SDK tool) only.
11  *   
12  * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are 
13  *   creating by doing a straight copy of the dispinterface instance and just changing 
14  *   its typekind. Pointed structures aren't copied - only the address of the pointers.
15  *   So when you release the dispinterface, you delete the vtable-interface structures
16  *   as well... fortunately, clean up of structures is not implemented.
17  * 
18  * - locale stuff is partially implemented but hasn't been tested.
19  *
20  * - imported typelib should be stored together in a linked list instead of having
21  *   independant TLBImpLib structures in each ITypeInfo. This way, imported libraries
22  *   are just imported once (major optimization)
23  *
24  * - typelib file is still read it's in entirety, but it is released now.
25  * - some garbage is read from function names on some very rare occasion
26  *
27  * --------------------------------------------------------------------------------------
28  *  Known problems left from previous implementation (1999, Rein Klazes) :
29  *
30  * -. Only one format of typelibs is supported
31  * -. Data structures are straightforward, but slow for look-ups.
32  * -. (related) nothing is hashed
33  * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
34  *      of them I don't know yet how to implement them.
35  * -. Most error return values are just guessed not checked with windows
36  *      behaviour.
37  * -. didn't bother with a c++ interface
38  * -. lousy fatal error handling
39  * -. some methods just return pointers to internal data structures, this is
40  *      partly laziness, partly I want to check how windows does it.
41  * 
42  */
43
44 #include "config.h"
45
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include <ctype.h>
50
51 #include "winerror.h"
52 #include "winnls.h"         /* for PRIMARYLANGID */
53 #include "winreg.h"         /* for HKEY_LOCAL_MACHINE */
54
55 #include "wine/obj_base.h"
56 #include "heap.h"
57 #include "ole2disp.h"
58 #include "typelib.h"
59
60 #include "debugtools.h"
61
62 DEFAULT_DEBUG_CHANNEL(ole);
63 DECLARE_DEBUG_CHANNEL(typelib);
64
65 /****************************************************************************
66  *              QueryPathOfRegTypeLib   [TYPELIB.14]
67  *
68  * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
69  * RETURNS
70  *      path of typelib
71  */
72 HRESULT WINAPI
73 QueryPathOfRegTypeLib16(        
74         REFGUID guid,   /* [in] referenced guid */
75         WORD wMaj,      /* [in] major version */
76         WORD wMin,      /* [in] minor version */
77         LCID lcid,      /* [in] locale id */
78         LPBSTR16 path   /* [out] path of typelib */
79 ) {
80         char    xguid[80];
81         char    typelibkey[100],pathname[260];
82         DWORD   plen;
83
84         TRACE("\n");
85
86         if (HIWORD(guid)) {
87             sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
88                      guid->Data1, guid->Data2, guid->Data3,
89                      guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
90                      guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
91                      wMaj,wMin,lcid);
92         } else {
93                 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
94                 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
95                 return E_FAIL;
96         }
97         plen = sizeof(pathname);
98         if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
99                 /* try again without lang specific id */
100                 if (SUBLANGID(lcid))
101                         return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
102                 FIXME("key %s not found\n",typelibkey);
103                 return E_FAIL;
104         }
105         *path = SysAllocString16(pathname);
106         return S_OK;
107 }
108  
109 /****************************************************************************
110  *              QueryPathOfRegTypeLib   [OLEAUT32.164]
111  * RETURNS
112  *      path of typelib
113  */
114 HRESULT WINAPI
115 QueryPathOfRegTypeLib(  
116         REFGUID guid,   /* [in] referenced guid */
117         WORD wMaj,      /* [in] major version */
118         WORD wMin,      /* [in] minor version */
119         LCID lcid,      /* [in] locale id */
120         LPBSTR path )   /* [out] path of typelib */
121 {
122     /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
123        string termination character on output strings */
124
125     HRESULT hr        = E_FAIL;
126
127     DWORD   dwPathLen = _MAX_PATH;
128     LCID    myLCID    = lcid;
129
130     char    szXGUID[80];
131     char    szTypeLibKey[100];
132     char    szPath[dwPathLen];
133
134     if ( !HIWORD(guid) )
135     {
136         sprintf(szXGUID,
137             "<guid 0x%08lx>",
138             (DWORD) guid);
139
140         FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
141         return E_FAIL;
142     }
143
144     while (hr != S_OK)
145     {
146         sprintf(szTypeLibKey,
147             "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
148             guid->Data1,    guid->Data2,    guid->Data3,
149             guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 
150             guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
151             wMaj,
152             wMin,
153             myLCID);
154
155         if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
156         {
157             if (!lcid)
158                 break;
159             else if (myLCID == lcid)
160             {
161                 /* try with sub-langid */
162                 myLCID = SUBLANGID(lcid);
163             }
164             else if ((myLCID == SUBLANGID(lcid)) && myLCID)
165             {
166                 /* try with system langid */
167                 myLCID = 0;
168             }
169             else
170             {
171                 break;
172             }
173         }
174         else
175         {
176             DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
177             BSTR bstrPath = SysAllocStringLen(NULL,len);
178
179             MultiByteToWideChar(CP_ACP,
180                                 MB_PRECOMPOSED,
181                                 szPath,
182                                 dwPathLen,
183                                 bstrPath,
184                                 len);
185            *path = bstrPath;
186            hr = S_OK;
187         }
188     }
189         
190     if (hr != S_OK)
191                 TRACE_(typelib)("%s not found\n", szTypeLibKey);
192         
193     return hr;
194 }
195
196 /******************************************************************************
197  * CreateTypeLib [OLEAUT32.160]  creates a typelib
198  *
199  * RETURNS
200  *    Success: S_OK
201  *    Failure: Status
202  */
203 HRESULT WINAPI CreateTypeLib(
204         SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
205 ) {
206     FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
207     return E_FAIL;
208 }
209 /******************************************************************************
210  * LoadTypeLib [TYPELIB.3]  Loads and registers a type library
211  * NOTES
212  *    Docs: OLECHAR FAR* szFile
213  *    Docs: iTypeLib FAR* FAR* pptLib
214  *
215  * RETURNS
216  *    Success: S_OK
217  *    Failure: Status
218  */
219 HRESULT WINAPI LoadTypeLib16(
220     LPOLESTR szFile, /* [in] Name of file to load from */
221     ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
222 {
223     FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
224
225     if (pptLib!=0)
226       *pptLib=0;
227
228     return E_FAIL;
229 }
230
231 /******************************************************************************
232  *              LoadTypeLib     [OLEAUT32.161]
233  * Loads and registers a type library
234  * NOTES
235  *    Docs: OLECHAR FAR* szFile
236  *    Docs: iTypeLib FAR* FAR* pptLib
237  *
238  * RETURNS
239  *    Success: S_OK
240  *    Failure: Status
241  */
242 int TLB_ReadTypeLib(PCHAR file, ITypeLib2 **ppTypelib);
243
244 HRESULT WINAPI LoadTypeLib(
245     const OLECHAR *szFile,/* [in] Name of file to load from */
246     ITypeLib * *pptLib)   /* [out] Pointer to pointer to loaded type library */
247 {
248     TRACE("\n");
249     return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
250 }
251
252 /******************************************************************************
253  *              LoadTypeLibEx   [OLEAUT32.183]
254  * Loads and optionally registers a type library
255  *
256  * RETURNS
257  *    Success: S_OK
258  *    Failure: Status
259  */
260 HRESULT WINAPI LoadTypeLibEx(
261     LPCOLESTR szFile,  /* [in] Name of file to load from */
262     REGKIND  regkind,  /* [in] Specify kind of registration */
263     ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
264 {
265     LPSTR p;
266     HRESULT res;
267     TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
268     
269     p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
270     
271     res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib);
272
273     if (SUCCEEDED(res))
274         switch(regkind)
275         {
276             case REGKIND_DEFAULT:
277                 /* FIXME: is this correct? */
278                 if (!p || !p[0] || (p[0] != '\\' && p[0] != '/' && p[1] != ':'))
279                     break;
280                 /* else fall-through */
281             case REGKIND_REGISTER:
282                 /* FIXME: Help path? */
283                 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
284                 {
285                     IUnknown_Release(*pptLib);
286                     *pptLib = 0;
287                 }
288                 break;
289             case REGKIND_NONE:
290                 break;
291         }
292
293     HeapFree(GetProcessHeap(),0,p);
294     TRACE(" returns %08lx\n",res);
295     return res;
296 }
297
298 /******************************************************************************
299  *              LoadRegTypeLib  [OLEAUT32.162]
300  */
301 HRESULT WINAPI LoadRegTypeLib(  
302         REFGUID rguid,          /* [in] referenced guid */
303         WORD wVerMajor,         /* [in] major version */
304         WORD wVerMinor,         /* [in] minor version */
305         LCID lcid,              /* [in] locale id */
306         ITypeLib **ppTLib)      /* [out] path of typelib */
307 {
308     BSTR bstr=NULL;
309     HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
310
311     if(SUCCEEDED(res))
312     {
313         res= LoadTypeLib(bstr, ppTLib);
314         SysFreeString(bstr);
315     }
316
317     TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
318
319     return res;
320 }       
321
322
323 /******************************************************************************
324  *              RegisterTypeLib [OLEAUT32.163]
325  * Adds information about a type library to the System Registry           
326  * NOTES
327  *    Docs: ITypeLib FAR * ptlib
328  *    Docs: OLECHAR FAR* szFullPath
329  *    Docs: OLECHAR FAR* szHelpDir
330  *
331  * RETURNS
332  *    Success: S_OK
333  *    Failure: Status
334  */
335 HRESULT WINAPI RegisterTypeLib(
336      ITypeLib * ptlib,     /* [in] Pointer to the library*/
337      OLECHAR * szFullPath, /* [in] full Path of the library*/
338      OLECHAR * szHelpDir)  /* [in] dir to the helpfile for the library,
339                                                          may be NULL*/
340 {
341     HRESULT res;
342     TLIBATTR *attr;
343     OLECHAR guid[80];
344     LPSTR guidA;
345     CHAR keyName[120];
346     HKEY key, subKey;
347
348     if (ptlib == NULL || szFullPath == NULL)
349         return E_INVALIDARG;
350
351     if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
352         return E_FAIL;
353
354     StringFromGUID2(&attr->guid, guid, 80);
355     guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
356     snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
357         guidA, attr->wMajorVerNum, attr->wMinorVerNum);
358     HeapFree(GetProcessHeap(), 0, guidA);
359
360     res = S_OK;
361     if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
362         KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
363     {
364         LPOLESTR doc;
365
366         if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
367         {
368             if (RegSetValueExW(key, NULL, 0, REG_SZ,
369                 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
370                 res = E_FAIL;
371
372             SysFreeString(doc);
373         }
374         else
375             res = E_FAIL;
376
377         /* FIXME: This *seems* to be 0 always, not sure though */
378         if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
379             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
380         {
381             if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
382                 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
383                 res = E_FAIL;
384
385             RegCloseKey(subKey);
386         }
387         else
388             res = E_FAIL;
389
390         if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
391             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
392         {
393             CHAR buf[20];
394             /* FIXME: is %u correct? */
395             snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
396             if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
397                 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
398                 res = E_FAIL;
399         }
400         RegCloseKey(key);
401     }
402     else
403         res = E_FAIL;
404
405     ITypeLib_ReleaseTLibAttr(ptlib, attr);
406     return res;
407 }
408
409
410 /******************************************************************************
411  *      UnRegisterTypeLib       [OLEAUT32.186]
412  * Removes information about a type library from the System Registry           
413  * NOTES
414  *
415  * RETURNS
416  *    Success: S_OK
417  *    Failure: Status
418  */
419 HRESULT WINAPI UnRegisterTypeLib(
420     REFGUID libid,      /* [in] Guid of the library */
421         WORD wVerMajor, /* [in] major version */
422         WORD wVerMinor, /* [in] minor version */
423         LCID lcid,      /* [in] locale id */
424         SYSKIND syskind)
425 {   
426     TRACE("(IID: %s): stub\n",debugstr_guid(libid));
427     return S_OK;        /* FIXME: pretend everything is OK */
428 }
429
430 /****************************************************************************
431  *      OaBuildVersion                          (TYPELIB.15)
432  *
433  * known TYPELIB.DLL versions:
434  *
435  * OLE 2.01 no OaBuildVersion() avail   1993    --      ---
436  * OLE 2.02                             1993-94 02     3002
437  * OLE 2.03                                     23      730
438  * OLE 2.03                                     03     3025
439  * OLE 2.03 W98 SE orig. file !!        1993-95 10     3024
440  * OLE 2.1   NT                         1993-95 ??      ???
441  * OLE 2.3.1 W95                                23      700
442  * OLE2 4.0  NT4SP6                     1993-98 40     4277
443  */
444 DWORD WINAPI OaBuildVersion16(void)
445 {
446     /* FIXME: I'd like to return the highest currently known version value
447      * in case the user didn't force a --winver, but I don't know how
448      * to retrieve the "versionForced" info from misc/version.c :(
449      * (this would be useful in other places, too) */
450     FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
451     switch(GetVersion() & 0x8000ffff)  /* mask off build number */
452     {
453     case 0x80000a03:  /* WIN31 */
454                 return MAKELONG(3027, 3); /* WfW 3.11 */
455     case 0x80000004:  /* WIN95 */
456                 return MAKELONG(700, 23); /* Win95A */
457     case 0x80000a04:  /* WIN98 */
458                 return MAKELONG(3024, 10); /* W98 SE */
459     case 0x00000004:  /* NT4 */
460                 return MAKELONG(4277, 40); /* NT4 SP6 */
461     default:
462         FIXME("Version value not known yet. Please investigate it!\n");
463                 return 0;
464     }
465 }
466
467 /* for better debugging info leave the static out for the time being */
468 #define static
469
470 /*======================= ITypeLib implementation =======================*/
471
472 typedef struct tagTLBCustData 
473 {
474     GUID guid;
475     VARIANT data;
476     struct tagTLBCustData* next;
477 } TLBCustData;
478
479 /* data structure for import typelibs */
480 typedef struct tagTLBImpLib
481 {
482     int offset;                 /* offset in the file */
483     GUID guid;                  /* libid */
484     BSTR name;                  /* name; */
485
486         LCID lcid;                                      /* lcid of imported typelib */
487
488         WORD wVersionMajor;         /* major version number */
489     WORD wVersionMinor;         /* minor version number */
490
491     struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib */
492     struct tagTLBImpLib * next;
493 } TLBImpLib;
494
495 /* internal ITypeLib data */
496 typedef struct tagITypeLibImpl
497 {
498     ICOM_VFIELD(ITypeLib2);
499     UINT ref;
500     TLIBATTR LibAttr;            /* guid,lcid,syskind,version,flags */
501     
502     /* strings can be stored in tlb as multibyte strings BUT they are *always*
503          * exported to the application as a UNICODE string.
504          */
505         BSTR Name;
506     BSTR DocString;
507     BSTR HelpFile;
508     BSTR HelpStringDll;
509     unsigned long  dwHelpContext;
510     int TypeInfoCount;          /* nr of typeinfo's in librarry */
511     struct tagITypeInfoImpl *pTypeInfo;   /* linked list of type info data */
512     int ctCustData;             /* number of items in cust data list */
513     TLBCustData * pCustData;    /* linked list to cust data; */
514     TLBImpLib   * pImpLibs;     /* linked list to all imported typelibs */
515     TYPEDESC * pTypeDesc;       /* array of TypeDescriptions found in the libary */
516 } ITypeLibImpl;
517
518 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
519
520 /* ITypeLib methods */
521 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength);
522
523 /*======================= ITypeInfo implementation =======================*/
524
525 /* data for refernced types in a coclass, or an inherited interface */
526 typedef struct tagTLBRefType
527 {
528     GUID guid;              /* guid of the referenced type */
529                             /* (important if its a imported type) */
530     HREFTYPE reference;
531     int flags;
532     int ctCustData;
533     TLBCustData * pCustData;/* linked list to custom data; */
534     TLBImpLib *pImpTLInfo;
535     struct tagTLBRefType * next;
536 } TLBRefType;
537
538 /* internal Parameter data */
539 typedef struct tagTLBParDesc
540 {
541     BSTR Name;
542     int ctCustData;
543     TLBCustData * pCustData;        /* linked list to cust data; */
544         TLBRefType * pRefType;                  /* linked list to referenced types */
545 } TLBParDesc;
546
547 /* internal Function data */
548 typedef struct tagTLBFuncDesc
549 {
550     FUNCDESC funcdesc;      /* lots of info on the function and its attributes. */
551     BSTR Name;             /* the name of this function */
552     TLBParDesc *pParamDesc; /* array with name and custom data */
553     int helpcontext;
554     int HelpStringContext;
555     BSTR HelpString;
556     BSTR Entry;            /* if its Hiword==0, it numeric; -1 is not present*/
557     int ctCustData;
558     TLBCustData * pCustData;        /* linked list to cust data; */
559     struct tagTLBFuncDesc * next; 
560 } TLBFuncDesc;
561
562 /* internal Variable data */
563 typedef struct tagTLBVarDesc
564 {
565     VARDESC vardesc;        /* lots of info on the variable and its attributes. */
566     BSTR Name;             /* the name of this variable */
567     int HelpContext;
568     int HelpStringContext;  /* fixme: where? */
569     BSTR HelpString;
570     int ctCustData;
571     TLBCustData * pCustData;/* linked list to cust data; */
572     struct tagTLBVarDesc * next; 
573 } TLBVarDesc;
574
575 /* internal TypeInfo data */
576 typedef struct tagITypeInfoImpl
577 {
578     ICOM_VFIELD(ITypeInfo2);
579     UINT ref;
580     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
581     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
582     int index;                  /* index in this typelib; */
583     /* type libs seem to store the doc strings in ascii 
584      * so why should we do it in unicode?
585      */
586     BSTR Name;
587     BSTR DocString;
588     unsigned long  dwHelpContext;
589     unsigned long  dwHelpStringContext;
590
591     /* functions  */
592     TLBFuncDesc * funclist;     /* linked list with function descriptions */
593
594     /* variables  */
595     TLBVarDesc * varlist;       /* linked list with variable descriptions */
596
597     /* Implemented Interfaces  */
598     TLBRefType * impltypelist;      
599     int ctCustData;
600     TLBCustData * pCustData;        /* linked list to cust data; */
601     struct tagITypeInfoImpl * next;
602 } ITypeInfoImpl;
603
604 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
605
606 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
607
608 typedef struct tagTLBContext
609 {
610         unsigned int oStart;  /* start of TLB in file */
611         unsigned int pos;     /* current pos */
612         unsigned int length;  /* total length */
613         void *mapping;        /* memory mapping */
614         TLBSegDir * pTblDir;
615         ITypeLibImpl* pLibInfo;
616 } TLBContext;
617
618
619 static void TLB_DoRefType(TLBContext *pcx, int offset, TLBRefType ** pprtd);
620
621 /*
622  debug
623 */
624 static void dump_VarType(VARTYPE vt,char *szVarType) {
625     /* FIXME : we could have better trace here, depending on the VARTYPE
626      * of the variant
627      */
628     switch(vt) {
629     case VT_UI1: sprintf(szVarType, "VT_UI"); break;
630     case VT_I2: sprintf(szVarType, "VT_I2"); break;
631     case VT_I4: sprintf(szVarType, "VT_I4"); break;
632     case VT_R4: sprintf(szVarType, "VT_R4"); break;
633     case VT_R8: sprintf(szVarType, "VT_R8"); break;
634     case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
635     case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
636     case VT_CY: sprintf(szVarType, "VT_CY"); break;
637     case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
638     case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
639     case VT_BYREF: case VT_UNKNOWN: sprintf(szVarType, "VT_BYREF"); break;
640     case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
641     case VT_ARRAY: sprintf(szVarType, "VT_ARRAY"); break;
642     case VT_I1: sprintf(szVarType, "VT_I2"); break;
643     case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
644     case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
645     case VT_INT: sprintf(szVarType, "VT_INT"); break;
646     case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
647     default: sprintf(szVarType, "unknown");break;
648     }
649 }
650 static void dump_ELEMDESC(ELEMDESC *edesc) {
651   char buf[200];
652   dump_VarType(edesc->tdesc.vt,buf);
653   MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
654   MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
655   MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
656 }
657 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
658   int i;
659   MESSAGE("memid is %d\n",(int)funcdesc->memid);
660   for (i=0;i<funcdesc->cParams;i++)
661       MESSAGE("Param %d:\n",i);dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
662   MESSAGE("\tfunckind: %d (",funcdesc->funckind);
663   switch (funcdesc->funckind) {
664   case FUNC_VIRTUAL: MESSAGE("virtual");break;
665   case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
666   case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
667   case FUNC_STATIC: MESSAGE("static");break;
668   case FUNC_DISPATCH: MESSAGE("dispatch");break;
669   default: MESSAGE("unknown");break;
670   }
671   MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
672   switch (funcdesc->invkind) {
673   case INVOKE_FUNC: MESSAGE("func");break;
674   case INVOKE_PROPERTYGET: MESSAGE("property get");break;
675   case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
676   case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
677   }
678   MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
679   switch (funcdesc->callconv) {
680   case CC_CDECL: MESSAGE("cdecl");break;
681   case CC_PASCAL: MESSAGE("pascal");break;
682   case CC_STDCALL: MESSAGE("stdcall");break;
683   case CC_SYSCALL: MESSAGE("syscall");break;
684   default:break;
685   }
686   MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
687   MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
688   MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
689 }
690 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
691 {
692   int i;
693   if (!TRACE_ON(typelib))
694       return;
695   MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
696   for (i=0;i<pfd->funcdesc.cParams;i++)
697       MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
698
699
700   dump_FUNCDESC(&(pfd->funcdesc));
701
702   MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
703   MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
704 }
705 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
706 {
707         while (pfd)
708         {
709           dump_TLBFuncDescOne(pfd);
710           pfd = pfd->next;
711         };
712 }
713 static void dump_TLBVarDesc(TLBVarDesc * pvd)
714 {
715         while (pvd)
716         {
717           TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
718           pvd = pvd->next;
719         };
720 }
721 static void dump_TLBRefType(TLBRefType * prt)
722 {
723         while (prt)
724         {
725           TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
726           TRACE_(typelib)("  href:0x%08lx\n", prt->reference);
727           prt = prt->next;
728         };
729 }
730
731 static void dump_Variant(VARIANT * pvar)
732 {
733     char szVarType[15];
734     
735     TRACE("(%p)\n", pvar);
736  
737     if (!pvar)  return;
738  
739     ZeroMemory(szVarType, sizeof(szVarType));
740                
741     /* FIXME : we could have better trace here, depending on the VARTYPE
742      * of the variant
743      */
744     dump_VarType(V_VT(pvar),szVarType);
745
746     TRACE("VARTYPE: %s\n", szVarType);
747     
748     switch (V_VT(pvar))
749     {
750         case VT_R4:
751             TRACE("%3.3e\n", V_UNION(pvar, fltVal));
752             break;
753             
754         case VT_R8:
755             TRACE("%3.3e\n", V_UNION(pvar, dblVal));
756             break;
757             
758         default:
759             TRACE("%ld\n", V_UNION(pvar, lVal));
760             break;
761     }       
762
763     if (pvar->vt & VT_BYREF)
764       return dump_Variant(pvar->u.pvarVal);
765 }
766
767 static void dump_DispParms(DISPPARAMS * pdp)
768 {
769     int index = 0;
770     
771     TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
772
773     while (index < pdp->cArgs)
774     {
775         dump_Variant( &pdp->rgvarg[index] );
776         ++index;
777     }
778 }
779
780 static char * typekind_desc[] =
781 {
782         "TKIND_ENUM",
783         "TKIND_RECORD",
784         "TKIND_MODULE",
785         "TKIND_INTERFACE",
786         "TKIND_DISPATCH",
787         "TKIND_COCLASS",
788         "TKIND_ALIAS",
789         "TKIND_UNION",
790         "TKIND_MAX"
791 };
792
793 static void dump_TypeInfo(ITypeInfoImpl * pty)
794 {
795     TRACE("%p ref=%u\n", pty, pty->ref);
796     TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
797     TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
798     TRACE("fct:%u var:%u impl:%u\n",
799       pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
800     TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
801     TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
802     dump_TLBFuncDesc(pty->funclist);
803     dump_TLBVarDesc(pty->varlist);
804     dump_TLBRefType(pty->impltypelist);
805 }
806
807 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
808 {
809     /* VT_LPWSTR is largest type that */
810     /* may appear in type description*/
811     {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
812     {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
813     {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
814     {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
815     {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
816     {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
817     {{0},30},{{0},31}
818 };
819
820 static void TLB_abort()
821 {
822     DebugBreak();
823 }
824 static void * TLB_Alloc(unsigned size)
825 {
826     void * ret;
827     if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
828         /* FIXME */
829         ERR("cannot allocate memory\n");
830     }
831     return ret;
832 }
833
834 static void TLB_Free(void * ptr)
835 {
836     HeapFree(GetProcessHeap(), 0, ptr);
837 }
838 /* read function */
839 DWORD TLB_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
840 {
841     TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
842        pcx->pos, count, pcx->oStart, pcx->length, where);
843
844     if (where != DO_NOT_SEEK)
845     {
846         where += pcx->oStart;
847         if (where > pcx->length)
848         {
849             /* FIXME */
850             ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
851             TLB_abort();
852         }
853         pcx->pos = where;
854     }
855     if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
856     memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
857     pcx->pos += count;
858     return count;
859 }
860
861 static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
862 {
863     TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
864
865     if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
866         memset(pGuid,0, sizeof(GUID));
867         return;
868     }
869     TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
870 }
871
872 BSTR TLB_ReadName( TLBContext *pcx, int offset)
873 {
874     char * name;
875     TLBNameIntro niName;
876     int lengthInChars;
877     WCHAR* pwstring = NULL;
878     BSTR bstrName = NULL;
879
880     TLB_Read(&niName, sizeof(niName), pcx,
881                                 pcx->pTblDir->pNametab.offset+offset);
882     niName.namelen &= 0xFF; /* FIXME: correct ? */
883     name=TLB_Alloc((niName.namelen & 0xff) +1);
884     TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
885     name[niName.namelen & 0xff]='\0';
886
887     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
888                                         name, -1, NULL, 0);
889
890     /* no invalid characters in string */
891     if (lengthInChars)
892     {
893         pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
894
895         /* don't check for invalid character since this has been done previously */
896         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
897
898         bstrName = SysAllocStringLen(pwstring, lengthInChars);
899         lengthInChars = SysStringLen(bstrName);
900         HeapFree(GetProcessHeap(), 0, pwstring);
901     }
902
903     TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
904     return bstrName;
905 }
906
907 BSTR TLB_ReadString( TLBContext *pcx, int offset)
908 {
909     char * string;
910     INT16 length;
911     int lengthInChars;
912     BSTR bstr = NULL;
913
914     if(offset<0) return NULL;
915     TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
916     if(length <= 0) return 0;
917     string=TLB_Alloc(length +1);
918     TLB_Read(string, length, pcx, DO_NOT_SEEK);
919     string[length]='\0';
920
921     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
922                                         string, -1, NULL, 0);
923
924     /* no invalid characters in string */
925     if (lengthInChars)
926     {
927         WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
928
929         /* don't check for invalid character since this has been done previously */
930         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
931
932         bstr = SysAllocStringLen(pwstring, lengthInChars);
933         lengthInChars = SysStringLen(bstr);
934         HeapFree(GetProcessHeap(), 0, pwstring);
935     }
936
937     TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
938     return bstr;
939 }
940 /*
941  * read a value and fill a VARIANT structure 
942  */
943 static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
944 {
945     int size;
946
947     TRACE_(typelib)("\n");
948
949     if(offset <0) { /* data is packed in here */
950         pVar->vt = (offset & 0x7c000000 )>> 26;
951         V_UNION(pVar, iVal) = offset & 0xffff;
952         return;
953     }
954     TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx, 
955         pcx->pTblDir->pCustData.offset + offset );
956     TRACE_(typelib)("Vartype = %x\n", pVar->vt);
957     switch(pVar->vt){
958         case VT_EMPTY:  /* FIXME: is this right? */
959         case VT_NULL:   /* FIXME: is this right? */
960         case VT_I2  :   /* this should not happen */
961         case VT_I4  :
962         case VT_R4  :
963         case VT_ERROR   : 
964         case VT_BOOL    : 
965         case VT_I1  : 
966         case VT_UI1 : 
967         case VT_UI2 : 
968         case VT_UI4 : 
969         case VT_INT : 
970         case VT_UINT    : 
971         case VT_VOID    : /* FIXME: is this right? */
972         case VT_HRESULT : 
973             size=4; break;
974         case VT_R8  :
975         case VT_CY  :
976         case VT_DATE    : 
977         case VT_I8  : 
978         case VT_UI8 : 
979         case VT_DECIMAL :  /* FIXME: is this right? */
980         case VT_FILETIME :
981             size=8;break;
982             /* pointer types with known behaviour */
983         case VT_BSTR    :{
984             char * ptr;
985             TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
986             if(size <= 0) {
987                 FIXME("BSTR length = %d?\n", size);
988             } else {
989                 ptr=TLB_Alloc(size);/* allocate temp buffer */
990                 TLB_Read(ptr, size, pcx, DO_NOT_SEEK); /* read string (ANSI) */
991                 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
992                 /* FIXME: do we need a AtoW conversion here? */
993                 V_UNION(pVar, bstrVal[size])=L'\0';
994                 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
995                 TLB_Free(ptr);
996             }
997         }
998         size=-4; break;
999     /* FIXME: this will not work AT ALL when the variant contains a pointer */
1000         case VT_DISPATCH :
1001         case VT_VARIANT : 
1002         case VT_UNKNOWN : 
1003         case VT_PTR : 
1004         case VT_SAFEARRAY :
1005         case VT_CARRAY  : 
1006         case VT_USERDEFINED : 
1007         case VT_LPSTR   : 
1008         case VT_LPWSTR  : 
1009         case VT_BLOB    : 
1010         case VT_STREAM  : 
1011         case VT_STORAGE : 
1012         case VT_STREAMED_OBJECT : 
1013         case VT_STORED_OBJECT   : 
1014         case VT_BLOB_OBJECT : 
1015         case VT_CF  : 
1016         case VT_CLSID   : 
1017         default: 
1018             size=0; 
1019             FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1020                 pVar->vt);
1021     }
1022
1023     if(size>0) /* (big|small) endian correct? */
1024         TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1025     return;
1026 }
1027 /*
1028  * create a linked list with custom data
1029  */
1030 static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1031 {
1032     TLBCDGuid entry;
1033     TLBCustData* pNew;
1034     int count=0;
1035
1036     TRACE_(typelib)("\n");
1037
1038     while(offset >=0){
1039         count++;
1040         pNew=TLB_Alloc(sizeof(TLBCustData));
1041         TLB_Read(&entry, sizeof(entry), pcx, 
1042             pcx->pTblDir->pCDGuids.offset+offset);
1043         TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1044         TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1045         /* add new custom data at head of the list */
1046         pNew->next=*ppCustData;
1047         *ppCustData=pNew;
1048         offset = entry.next;
1049     }
1050     return count;
1051 }
1052
1053 static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
1054 {
1055     if(type <0)
1056         pTd->vt=type & VT_TYPEMASK;
1057     else
1058         *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1059
1060     TRACE_(typelib)("vt type = %X\n", pTd->vt);
1061 }
1062
1063 static void 
1064 TLB_DoFuncs(TLBContext*     pcx, 
1065             int             cFuncs, 
1066             int             cVars,
1067             int             offset, 
1068             TLBFuncDesc**   pptfd)
1069 {
1070     /* 
1071      * member information is stored in a data structure at offset
1072      * indicated by the memoffset field of the typeinfo structure
1073      * There are several distinctive parts.
1074      * the first part starts with a field that holds the total length 
1075      * of this (first) part excluding this field. Then follow the records,
1076      * for each member there is one record.
1077      *
1078      * First entry is always the length of the record (excluding this
1079      * length word). 
1080      * Rest of the record depends on the type of the member. If there is 
1081      * a field indicating the member type (function variable intereface etc)
1082      * I have not found it yet. At this time we depend on the information
1083      * in the type info and the usual order how things are stored.
1084      *
1085      * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1086      * for each member;
1087      * 
1088      * Third is a equal sized array with file offsets to the name entry 
1089      * of each member.
1090      * 
1091      * Forth and last (?) part is an array with offsets to the records in the
1092      * first part of this file segment.
1093      */
1094
1095     int infolen, nameoffset, reclength, nrattributes, i;
1096     int recoffset = offset + sizeof(INT);
1097
1098     char recbuf[512];
1099     TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
1100
1101     TRACE_(typelib)("\n");
1102
1103     TLB_Read(&infolen, sizeof(INT), pcx, offset);
1104
1105     for ( i = 0; i < cFuncs ; i++ )
1106     {
1107         *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1108
1109         /* name, eventually add to a hash table */
1110         TLB_Read(&nameoffset, 
1111                  sizeof(INT), 
1112                  pcx, 
1113                  offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1114
1115         (*pptfd)->Name = TLB_ReadName(pcx, nameoffset);
1116
1117         /* read the function information record */
1118         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1119         
1120         reclength &= 0x1ff;
1121
1122         TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
1123
1124         /* do the attributes */
1125         nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1126                        / sizeof(int);
1127
1128         if ( nrattributes > 0 )
1129         {
1130             (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1131             
1132             if ( nrattributes > 1 )
1133             {
1134                 (*pptfd)->HelpString = TLB_ReadString(pcx,
1135                                                       pFuncRec->OptAttr[1]) ;
1136
1137                 if ( nrattributes > 2 )
1138                 {
1139                     if ( pFuncRec->FKCCIC & 0x2000 )
1140                     {
1141                        (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1142                     }
1143                     else
1144                     {
1145                         (*pptfd)->Entry = TLB_ReadString(pcx,
1146                                                          pFuncRec->OptAttr[2]);
1147                     }
1148                     if( nrattributes > 5 )
1149                     {
1150                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1151
1152                         if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1153                         {
1154                             TLB_CustData(pcx, 
1155                                          pFuncRec->OptAttr[6],
1156                                          &(*pptfd)->pCustData);
1157                         }
1158                     }
1159                 }
1160             }
1161         }
1162
1163         /* fill the FuncDesc Structure */
1164         TLB_Read( & (*pptfd)->funcdesc.memid, 
1165                   sizeof(INT), pcx, 
1166                   offset + infolen + ( i + 1) * sizeof(INT));
1167
1168         (*pptfd)->funcdesc.funckind   =  (pFuncRec->FKCCIC)      & 0x7;
1169         (*pptfd)->funcdesc.invkind    =  (pFuncRec->FKCCIC) >> 3 & 0xF;
1170         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
1171         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
1172         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
1173         (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
1174         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
1175
1176         TLB_GetTdesc(pcx, 
1177                      pFuncRec->DataType,   
1178                      &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1179
1180         /* do the parameters/arguments */
1181         if(pFuncRec->nrargs)
1182         {
1183             int j = 0;
1184             TLBParameterInfo paraminfo;
1185
1186             (*pptfd)->funcdesc.lprgelemdescParam = 
1187                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1188
1189             (*pptfd)->pParamDesc = 
1190                 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1191
1192             TLB_Read(&paraminfo,
1193                      sizeof(paraminfo), 
1194                      pcx, 
1195                      recoffset + reclength -
1196                         pFuncRec->nrargs * sizeof(TLBParameterInfo));
1197
1198             for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1199             {
1200                 TYPEDESC* lpArgTypeDesc = 0;
1201
1202                 TLB_GetTdesc(pcx, 
1203                              paraminfo.DataType,   
1204                              &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
1205
1206                 V_UNION(& ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1207                         paramdesc.wParamFlags) = paraminfo.Flags;
1208
1209                 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1210
1211                 /* SEEK value = jump to offset, 
1212                  * from there jump to the end of record,
1213                  * go back by (j-1) arguments
1214                  */
1215                 TLB_Read( &paraminfo ,
1216                           sizeof(TLBParameterInfo), pcx,
1217                           recoffset + reclength - ((pFuncRec->nrargs - j - 1) 
1218                                                    * sizeof(TLBParameterInfo)));
1219                 lpArgTypeDesc = 
1220                     & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1221
1222                 while ( lpArgTypeDesc != NULL )
1223                 {
1224                     switch ( lpArgTypeDesc->vt )
1225                     {
1226                     case VT_PTR:
1227                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1228                         break;
1229
1230                     case VT_CARRAY:
1231                         lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1232                         break;
1233
1234                     case VT_USERDEFINED:
1235                         (*pptfd)->pParamDesc[j].pRefType = 
1236                         TLB_Alloc(sizeof(TLBRefType));
1237
1238                         TLB_DoRefType(pcx, 
1239                                       lpArgTypeDesc->u.hreftype, 
1240                                       & ( (*pptfd)->pParamDesc[j].pRefType ));
1241
1242                         lpArgTypeDesc = NULL;
1243                         break;
1244
1245                     default:
1246                         lpArgTypeDesc = NULL;
1247                     }
1248                 }
1249             }
1250
1251
1252             /* parameter is the return value! */
1253             if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1254             {
1255                 TYPEDESC* lpArgTypeDesc;
1256
1257                 (*pptfd)->funcdesc.elemdescFunc = 
1258                 (*pptfd)->funcdesc.lprgelemdescParam[j];
1259
1260                 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1261
1262                 while ( lpArgTypeDesc != NULL )
1263                 {
1264                     switch ( lpArgTypeDesc->vt )
1265                     {
1266                     case VT_PTR:
1267                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1268                         break;
1269                     case VT_CARRAY:
1270                         lpArgTypeDesc = 
1271                         & (lpArgTypeDesc->u.lpadesc->tdescElem);
1272
1273                         break;
1274
1275                     case VT_USERDEFINED:
1276                         (*pptfd)->pParamDesc[j].pRefType 
1277                         = TLB_Alloc(sizeof(TLBRefType));
1278
1279                         TLB_DoRefType(pcx, 
1280                                       lpArgTypeDesc->u.hreftype, 
1281                                       &((*pptfd)->pParamDesc[j].pRefType));
1282
1283                         lpArgTypeDesc = NULL;
1284                         break;
1285
1286                     default:
1287                         lpArgTypeDesc = NULL;
1288                     }
1289                 }
1290             }
1291
1292             /* second time around */
1293             for(j=0;j<pFuncRec->nrargs;j++)
1294             {
1295                 /* name */
1296                 (*pptfd)->pParamDesc[j].Name =
1297                     TLB_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1298
1299                 /* default value */
1300                 if ( (PARAMFLAG_FHASDEFAULT & 
1301                       V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
1302                               paramdesc.wParamFlags)) &&
1303                      ((pFuncRec->FKCCIC) & 0x1000) )
1304                 {
1305                     INT* pInt = (INT *)((char *)pFuncRec + 
1306                                    reclength - 
1307                                    (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1308
1309                     PARAMDESC* pParamDesc = &V_UNION( 
1310                                   & ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1311                                   paramdesc);
1312
1313                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1314                     pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1315                     
1316                     TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 
1317                         pInt[j], pcx);
1318                 }
1319                 /* custom info */
1320                 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1321                 {
1322                     TLB_CustData(pcx, 
1323                                  pFuncRec->OptAttr[7+j],
1324                                  &(*pptfd)->pParamDesc[j].pCustData);
1325                 }
1326            }
1327         }
1328         
1329         /* scode is not used: archaic win16 stuff FIXME: right? */
1330         (*pptfd)->funcdesc.cScodes   = 0 ;
1331         (*pptfd)->funcdesc.lprgscode = NULL ;
1332         
1333         pptfd      = & ((*pptfd)->next);
1334         recoffset += reclength;
1335     }
1336 }
1337 static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
1338                           int offset, TLBVarDesc ** pptvd)
1339 {
1340     int infolen, nameoffset, reclength;
1341     char recbuf[256];
1342     TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
1343     int i;
1344     int recoffset;
1345
1346     TRACE_(typelib)("\n");
1347
1348     TLB_Read(&infolen,sizeof(INT), pcx, offset);
1349     TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen + 
1350         ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1351     recoffset += offset+sizeof(INT);
1352     for(i=0;i<cVars;i++){
1353         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1354     /* name, eventually add to a hash table */
1355         TLB_Read(&nameoffset, sizeof(INT), pcx, 
1356             offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1357         (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
1358     /* read the variable information record */
1359         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1360         reclength &=0xff;
1361         TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
1362     /* Optional data */
1363         if(reclength >(6*sizeof(INT)) )
1364             (*pptvd)->HelpContext=pVarRec->HelpContext;
1365         if(reclength >(7*sizeof(INT)) )
1366             (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
1367         if(reclength >(8*sizeof(INT)) )
1368         if(reclength >(9*sizeof(INT)) )
1369             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1370     /* fill the VarDesc Structure */
1371         TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 
1372             offset + infolen + ( i + 1) * sizeof(INT));
1373         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1374         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1375         TLB_GetTdesc(pcx, pVarRec->DataType,    
1376             &(*pptvd)->vardesc.elemdescVar.tdesc) ;
1377 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1378         if(pVarRec->VarKind == VAR_CONST ){
1379             V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
1380             TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue), 
1381                 pVarRec->OffsValue, pcx);
1382         }else
1383             V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
1384         pptvd=&((*pptvd)->next);
1385         recoffset += reclength;
1386     }
1387 }
1388 /* fill in data for a hreftype (offset). When the refernced type is contained
1389  * in the typelib, its just an (file) offset in the type info base dir.
1390  * If comes from import, its an offset+1 in the ImpInfo table
1391  * */
1392 static void TLB_DoRefType(TLBContext *pcx, 
1393                           int offset, TLBRefType ** pprtd)
1394 {
1395     int j;
1396
1397     TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1398
1399     if(!HREFTYPE_INTHISFILE( offset)) {
1400         /* external typelib */
1401         TLBImpInfo impinfo;
1402         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1403
1404         TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1405
1406         TLB_Read(&impinfo, sizeof(impinfo), pcx, 
1407             pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1408         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
1409             if(pImpLib->offset==impinfo.oImpFile) break;
1410             pImpLib=pImpLib->next;
1411         }
1412         if(pImpLib){
1413             (*pprtd)->reference=offset;
1414             (*pprtd)->pImpTLInfo = pImpLib;
1415             TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
1416         }else{
1417             ERR("Cannot find a reference\n");
1418             (*pprtd)->reference=-1;
1419             (*pprtd)->pImpTLInfo=(void *)-1;
1420         }
1421     }else{
1422         /* in this typelib */
1423         (*pprtd)->reference=offset;
1424         (*pprtd)->pImpTLInfo=(void *)-2;
1425     }
1426 }
1427
1428 /* process Implemented Interfaces of a com class */
1429 static void TLB_DoImplTypes(TLBContext *pcx, int count,
1430                           int offset, TLBRefType ** pprtd)
1431 {
1432     int i;
1433     TLBRefRecord refrec;
1434
1435     TRACE_(typelib)("\n");
1436
1437     for(i=0;i<count;i++){
1438         if(offset<0) break; /* paranoia */
1439         *pprtd=TLB_Alloc(sizeof(TLBRefType));
1440         TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1441         TLB_DoRefType(pcx, refrec.reftype, pprtd);
1442         (*pprtd)->flags=refrec.flags;
1443         (*pprtd)->ctCustData=
1444             TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
1445         offset=refrec.onext;
1446         pprtd=&((*pprtd)->next);
1447     }
1448 }
1449 /*
1450  * process a typeinfo record
1451  */
1452 ITypeInfoImpl * TLB_DoTypeInfo(
1453     TLBContext *pcx,
1454     int count,
1455     ITypeLibImpl * pLibInfo)
1456 {
1457     TLBTypeInfoBase tiBase;
1458     ITypeInfoImpl *ptiRet;
1459
1460     TRACE_(typelib)("count=%u\n", count);
1461
1462     ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1463     TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
1464         pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1465 /* this is where we are coming from */
1466     ptiRet->pTypeLib = pLibInfo;
1467     ptiRet->index=count;
1468 /* fill in the typeattr fields */
1469     FIXME("Assign constructor/destructor memid\n");
1470
1471     TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1472     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
1473     ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1474     ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1475     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
1476     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1477     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1478     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1479     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1480     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1481     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1482     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1483     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1484     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1485     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1486     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1487         TLB_GetTdesc(pcx, tiBase.datatype1, 
1488             &ptiRet->TypeAttr.tdescAlias) ;
1489
1490 /*  FIXME: */
1491 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
1492
1493 /* name, eventually add to a hash table */
1494     ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
1495     TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1496     /* help info */
1497     ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
1498     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1499     ptiRet->dwHelpContext=tiBase.helpcontext;
1500 /* note: InfoType's Help file and HelpStringDll come from the containing
1501  * library. Further HelpString and Docstring appear to be the same thing :(
1502  */
1503     /* functions */
1504     if(ptiRet->TypeAttr.cFuncs >0 )
1505         TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1506         tiBase.memoffset, & ptiRet->funclist);
1507     /* variables */
1508     if(ptiRet->TypeAttr.cVars >0 )
1509         TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1510         tiBase.memoffset, & ptiRet->varlist);
1511     if(ptiRet->TypeAttr.cImplTypes >0 ){
1512         switch(ptiRet->TypeAttr.typekind)
1513         {
1514         case TKIND_COCLASS:
1515             TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes , 
1516                 tiBase.datatype1, & ptiRet->impltypelist);
1517             break;
1518         case TKIND_DISPATCH:
1519             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1520             
1521             if (tiBase.datatype1 != -1)
1522             {
1523               TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1524             }
1525             else
1526             {
1527               char* szStdOle     = "stdole2.tlb\0";
1528               int   nStdOleLen = strlen(szStdOle);
1529                             
1530               ptiRet->impltypelist->guid             = IID_IDispatch;
1531               ptiRet->impltypelist->reference        = -1;
1532               ptiRet->impltypelist->pImpTLInfo       = TLB_Alloc(sizeof(TLBImpLib));
1533               ptiRet->impltypelist->pImpTLInfo->guid = IID_StdOle;             
1534               ptiRet->impltypelist->pImpTLInfo->name = SysAllocStringLen(NULL, nStdOleLen  + 1);
1535               
1536               MultiByteToWideChar(CP_ACP,
1537                                   MB_PRECOMPOSED,
1538                                   szStdOle,
1539                                   -1,
1540                                   ptiRet->impltypelist->pImpTLInfo->name,
1541                                   SysStringLen(ptiRet->impltypelist->pImpTLInfo->name));
1542                                   
1543               ptiRet->impltypelist->pImpTLInfo->lcid          = 0;
1544               ptiRet->impltypelist->pImpTLInfo->wVersionMajor = 2;
1545               ptiRet->impltypelist->pImpTLInfo->wVersionMinor = 0;
1546             }
1547             break;
1548         default:
1549             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1550             TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1551             break;
1552         }
1553     }
1554     ptiRet->ctCustData=
1555         TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1556
1557     TRACE_(typelib)("%s guid: %s kind:%s\n",
1558        debugstr_w(ptiRet->Name),
1559        debugstr_guid(&ptiRet->TypeAttr.guid),
1560        typekind_desc[ptiRet->TypeAttr.typekind]);
1561
1562     return ptiRet;
1563 }
1564
1565 /****************************************************************************
1566  *      TLB_ReadTypeLib
1567  *
1568  * find the type of the typelib file and map the typelib resource into
1569  * the memory
1570  */
1571 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1572 int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib)
1573 {
1574     int ret = E_FAIL;
1575     DWORD dwSignature = 0;
1576     HFILE hFile;
1577     int nStrLen = strlen(pszFileName);
1578     int i;
1579
1580     PCHAR pszTypeLibIndex = NULL;
1581     PCHAR pszDllName      = NULL;
1582
1583     TRACE_(typelib)("%s\n", pszFileName);
1584
1585     *ppTypeLib = NULL;
1586
1587     /* is it a DLL? */
1588         for (i=0 ; i < nStrLen ; ++i)
1589         {
1590             pszFileName[i] = tolower(pszFileName[i]);
1591         }
1592     pszTypeLibIndex = strstr(pszFileName, ".dll");
1593
1594     /* find if there's a back-slash after .DLL (good sign of the presence of a typelib index) */
1595     if (pszTypeLibIndex)
1596     {
1597       pszTypeLibIndex = strstr(pszTypeLibIndex, "\\");
1598     }
1599
1600     /* is there any thing after trailing back-slash  ? */
1601     if (pszTypeLibIndex && pszTypeLibIndex < pszFileName + nStrLen)
1602     {
1603       /* yes -> it's a index! store DLL name, without the trailing back-slash */
1604       size_t nMemToAlloc = pszTypeLibIndex - pszFileName;
1605       
1606       pszDllName = HeapAlloc(GetProcessHeap(),
1607                           HEAP_ZERO_MEMORY, 
1608                           nMemToAlloc + 1);
1609                           
1610       strncpy(pszDllName, pszFileName, nMemToAlloc);
1611       
1612       /* move index string pointer pass the backslash */
1613       while (*pszTypeLibIndex == '\\')
1614         ++pszTypeLibIndex;
1615     }
1616     else
1617     {
1618       /* No index, reset variable to 1 */
1619       pszDllName = HeapAlloc(GetProcessHeap(),
1620                           HEAP_ZERO_MEMORY, 
1621                           nStrLen + 1);
1622                           
1623       strncpy(pszDllName, pszFileName, nStrLen);
1624       
1625       pszTypeLibIndex = "1\0";
1626     }
1627
1628     TRACE_(typelib)("File name without index %s\n", pszDllName);
1629     TRACE_(typelib)("Index of typelib %s\n",        pszTypeLibIndex);
1630
1631
1632     /* check the signature of the file */
1633     hFile = CreateFileA( pszDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1634     if (INVALID_HANDLE_VALUE != hFile)
1635     {
1636       HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1637       if (hMapping)
1638       {
1639         LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1640         if(pBase)
1641         {
1642           /* first try to load as *.tlb */
1643           dwSignature = *((DWORD*) pBase);
1644           if ( dwSignature == MSFT_SIGNATURE)
1645           {
1646                 /* retrieve file size */
1647                 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1648     
1649             *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1650             ITypeLib2_AddRef(*ppTypeLib);
1651           }
1652           UnmapViewOfFile(pBase);
1653         }
1654         CloseHandle(hMapping);
1655       }
1656       CloseHandle(hFile);
1657     }
1658
1659     if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1660     {
1661       /* find the typelibrary resource*/
1662       HINSTANCE hinstDLL = LoadLibraryExA(pszDllName, 0, DONT_RESOLVE_DLL_REFERENCES|
1663                                           LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1664       if (hinstDLL)
1665       {
1666         HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(atoi(pszTypeLibIndex)), "TYPELIB");
1667         if (hrsrc)
1668         {
1669           HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1670           if (hGlobal)
1671           {
1672             LPVOID pBase = LockResource(hGlobal);
1673             DWORD  dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1674             
1675             if (pBase)
1676             {
1677               /* try to load as incore resource */
1678               dwSignature = *((DWORD*) pBase);
1679               if ( dwSignature == MSFT_SIGNATURE)
1680               {
1681                   *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1682                   ITypeLib2_AddRef(*ppTypeLib);
1683               }
1684               else
1685               {
1686                   FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1687               }
1688             }
1689             FreeResource( hGlobal );
1690           }
1691         }
1692         FreeLibrary(hinstDLL);
1693       }
1694     }
1695
1696     HeapFree(GetProcessHeap(), 0, pszDllName);
1697
1698     if(*ppTypeLib)
1699       ret = S_OK;
1700     else
1701       ERR("Loading of typelib %s failed with error 0x%08lx\n", pszFileName, GetLastError());
1702
1703     return ret;
1704 }
1705
1706 /*================== ITypeLib(2) Methods ===================================*/
1707
1708 /****************************************************************************
1709  *      ITypeLib2_Constructor
1710  *
1711  * loading a typelib from a in-memory image
1712  */
1713 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength)
1714 {
1715     TLBContext cx;
1716     long lPSegDir;
1717     TLB2Header tlbHeader;
1718     TLBSegDir tlbSegDir;
1719     ITypeLibImpl * pTypeLibImpl;
1720
1721     TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1722
1723     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1724     if (!pTypeLibImpl) return NULL;
1725
1726     ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1727     pTypeLibImpl->ref = 1;
1728
1729     /* get pointer to beginning of typelib data */
1730     cx.pos = 0;
1731     cx.oStart=0;
1732     cx.mapping = pLib;
1733     cx.pLibInfo = pTypeLibImpl;
1734     cx.length = dwTLBLength;
1735     
1736     /* read header */
1737     TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1738     TRACE("header:\n");
1739     TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1740     if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1741         FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1742         return NULL;
1743     }
1744     /* there is a small number of information here until the next important
1745      * part:
1746      * the segment directory . Try to calculate the amount of data */
1747     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1748
1749     /* now read the segment directory */
1750     TRACE("read segment directory (at %ld)\n",lPSegDir);
1751     TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);  
1752     cx.pTblDir = &tlbSegDir;
1753
1754     /* just check two entries */
1755     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1756     {
1757         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1758         HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1759         return NULL;
1760     }
1761
1762     /* now fill our internal data */
1763     /* TLIBATTR fields */
1764     TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1765     pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1766     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1767     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1768     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1769     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1770
1771     /* name, eventually add to a hash table */
1772     pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset);
1773
1774     /* help info */
1775     pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring);
1776     pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile);
1777
1778     if( tlbHeader.varflags & HELPDLLFLAG)
1779     {
1780             int offset;
1781             TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1782             pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset);
1783     }
1784
1785     pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1786
1787     /* custom data */
1788     if(tlbHeader.CustomDataOffset >= 0)
1789     {
1790         pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1791     }
1792
1793     /* fill in typedescriptions */
1794     if(tlbSegDir.pTypdescTab.length > 0)
1795     {
1796         int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1797         INT16 td[4];
1798         pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1799         TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1800         for(i=0; i<cTD; )
1801         {
1802             /* FIXME: add several sanity checks here */
1803             pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
1804             if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
1805             {
1806                 /* FIXME: check safearray */
1807                 if(td[3] < 0)
1808                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & stndTypeDesc[td[2]];
1809                 else
1810                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & pTypeLibImpl->pTypeDesc[td[2]/8];
1811             }
1812             else if(td[0] == VT_CARRAY)
1813             {
1814                 /* array descr table here */
1815                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = (void *)((int) td[2]);  /* temp store offset in*/
1816             }                             
1817             else if(td[0] == VT_USERDEFINED)
1818             {
1819                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),hreftype) = MAKELONG(td[2],td[3]);
1820             }
1821             if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
1822         }
1823
1824         /* second time around to fill the array subscript info */
1825         for(i=0;i<cTD;i++)
1826         {
1827             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
1828             if(tlbSegDir.pArrayDescriptions.offset>0)
1829             {
1830                 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc));
1831                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
1832
1833                 if(td[1]<0)
1834                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem.vt = td[0] & VT_TYPEMASK;
1835                 else
1836                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem = stndTypeDesc[td[0]/8];
1837
1838                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->cDims = td[2];
1839
1840                 for(j = 0; j<td[2]; j++)
1841                 {
1842                     TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements, 
1843                         sizeof(INT), &cx, DO_NOT_SEEK);
1844                     TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].lLbound, 
1845                         sizeof(INT), &cx, DO_NOT_SEEK);
1846                 }
1847             }
1848             else
1849             {
1850                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = NULL;
1851                 ERR("didn't find array description data\n");
1852             }
1853         }
1854     }
1855
1856     /* imported type libs */
1857     if(tlbSegDir.pImpFiles.offset>0)
1858     {
1859         TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
1860         int oGuid, offset = tlbSegDir.pImpFiles.offset;
1861         UINT16 size;
1862
1863         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
1864         {
1865             *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
1866             (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
1867             TLB_Read(&oGuid, sizeof(INT), &cx, offset);
1868
1869                         TLB_Read(&(*ppImpLib)->lcid,          sizeof(LCID),   &cx, DO_NOT_SEEK);
1870             TLB_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD),   &cx, DO_NOT_SEEK);
1871             TLB_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD),   &cx, DO_NOT_SEEK);
1872             TLB_Read(& size,                      sizeof(UINT16), &cx, DO_NOT_SEEK);
1873
1874             size >>= 2;
1875             (*ppImpLib)->name = TLB_Alloc(size+1);
1876             TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
1877             TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
1878             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
1879
1880             ppImpLib = &(*ppImpLib)->next;
1881         }
1882     }
1883
1884     /* type info's */
1885     if(tlbHeader.nrtypeinfos >= 0 )
1886     {
1887         /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
1888         ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
1889         int i;
1890
1891         for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
1892         {
1893             *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl);
1894
1895             ITypeInfo_AddRef((ITypeInfo*) *ppTI);
1896             ppTI = &((*ppTI)->next);
1897             (pTypeLibImpl->TypeInfoCount)++;
1898         }
1899     }
1900
1901     TRACE("(%p)\n", pTypeLibImpl);
1902     return (ITypeLib2*) pTypeLibImpl;
1903 }
1904
1905 /* ITypeLib::QueryInterface
1906  */
1907 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
1908         ITypeLib2 * iface,
1909         REFIID riid,
1910         VOID **ppvObject)
1911 {
1912     ICOM_THIS( ITypeLibImpl, iface);
1913
1914     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1915
1916     *ppvObject=NULL;
1917     if(IsEqualIID(riid, &IID_IUnknown) || 
1918        IsEqualIID(riid,&IID_ITypeLib)||
1919        IsEqualIID(riid,&IID_ITypeLib2))
1920     {
1921         *ppvObject = This;
1922     }
1923
1924     if(*ppvObject)
1925     {
1926         ITypeLib2_AddRef(iface);
1927         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1928         return S_OK;
1929     }
1930     TRACE("-- Interface: E_NOINTERFACE\n");
1931     return E_NOINTERFACE;
1932 }
1933
1934 /* ITypeLib::AddRef
1935  */
1936 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
1937 {
1938     ICOM_THIS( ITypeLibImpl, iface);
1939
1940     TRACE("(%p)->ref is %u\n",This, This->ref);
1941
1942     return ++(This->ref);
1943 }
1944
1945 /* ITypeLib::Release
1946  */
1947 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
1948 {
1949     ICOM_THIS( ITypeLibImpl, iface);
1950
1951     --(This->ref);
1952     
1953     TRACE("(%p)->(%u)\n",This, This->ref);
1954
1955     if (!This->ref)
1956     {
1957       /* fixme destroy child objects */
1958
1959       TRACE(" destroying ITypeLib(%p)\n",This);
1960
1961       if (This->Name)
1962       {
1963           SysFreeString(This->Name);
1964           This->Name = NULL;
1965       }
1966
1967       if (This->DocString)
1968       {
1969           SysFreeString(This->DocString);
1970           This->DocString = NULL;
1971       }
1972
1973       if (This->HelpFile)
1974       {
1975           SysFreeString(This->HelpFile);
1976           This->HelpFile = NULL;
1977       }
1978
1979       if (This->HelpStringDll)
1980       {
1981           SysFreeString(This->HelpStringDll);
1982           This->HelpStringDll = NULL;
1983       }
1984     
1985       ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
1986       HeapFree(GetProcessHeap(),0,This);
1987       return 0;
1988     }
1989
1990     return This->ref;
1991 }
1992
1993 /* ITypeLib::GetTypeInfoCount
1994  * 
1995  * Returns the number of type descriptions in the type library
1996  */
1997 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
1998 {
1999     ICOM_THIS( ITypeLibImpl, iface);
2000     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
2001     return This->TypeInfoCount;
2002 }
2003
2004 /* ITypeLib::GetTypeInfo
2005  *
2006  * retrieves the specified type description in the library.
2007  */
2008 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
2009     ITypeLib2 *iface,
2010     UINT index, 
2011     ITypeInfo **ppTInfo)
2012 {
2013     int i;
2014     
2015     ICOM_THIS( ITypeLibImpl, iface);
2016     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
2017
2018     TRACE("(%p)->(index=%d) \n", This, index);
2019
2020     if (!ppTInfo) return E_INVALIDARG;
2021     
2022     /* search element n in list */
2023     for(i=0; i < index; i++)
2024     {
2025       pTypeInfo = pTypeInfo->next;
2026       if (!pTypeInfo)
2027       {
2028         TRACE("-- element not found\n");
2029         return TYPE_E_ELEMENTNOTFOUND;
2030       }
2031     }   
2032
2033     *ppTInfo = (ITypeInfo *) pTypeInfo;
2034     
2035     ITypeInfo_AddRef(*ppTInfo);
2036     TRACE("-- found (%p)\n",*ppTInfo);
2037     return S_OK;
2038 }
2039
2040
2041 /* ITypeLibs::GetTypeInfoType
2042  *
2043  * Retrieves the type of a type description.
2044  */
2045 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
2046     ITypeLib2 *iface,
2047     UINT index,
2048     TYPEKIND *pTKind)
2049 {
2050     ICOM_THIS( ITypeLibImpl, iface);
2051     int i;
2052     ITypeInfoImpl *pTInfo = This->pTypeInfo;
2053
2054     TRACE("(%p) index %d \n",This, index);
2055
2056     if(!pTKind) return E_INVALIDARG;
2057     
2058     /* search element n in list */
2059     for(i=0; i < index; i++)
2060     {
2061       if(!pTInfo)
2062       {
2063         TRACE("-- element not found\n");
2064         return TYPE_E_ELEMENTNOTFOUND;
2065       }
2066       pTInfo = pTInfo->next;
2067     }
2068
2069     *pTKind = pTInfo->TypeAttr.typekind;
2070     TRACE("-- found Type (%d)\n", *pTKind);
2071     return S_OK;
2072 }
2073
2074 /* ITypeLib::GetTypeInfoOfGuid
2075  *
2076  * Retrieves the type description that corresponds to the specified GUID.
2077  *
2078  */
2079 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
2080     ITypeLib2 *iface,
2081     REFGUID guid,
2082     ITypeInfo **ppTInfo)
2083 {
2084     ICOM_THIS( ITypeLibImpl, iface);
2085     ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
2086
2087     TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
2088
2089     if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
2090
2091     /* search linked list for guid */
2092     while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
2093     {
2094       pTypeInfo = pTypeInfo->next;
2095
2096       if (!pTypeInfo)
2097       {
2098         /* end of list reached */
2099         TRACE("-- element not found\n");
2100         return TYPE_E_ELEMENTNOTFOUND;
2101       }
2102     }
2103
2104     TRACE("-- found (%p, %s)\n", 
2105           pTypeInfo, 
2106           debugstr_w(pTypeInfo->Name));
2107
2108     *ppTInfo = (ITypeInfo*)pTypeInfo;
2109     ITypeInfo_AddRef(*ppTInfo);
2110     return S_OK;
2111 }
2112
2113 /* ITypeLib::GetLibAttr
2114  *
2115  * Retrieves the structure that contains the library's attributes.
2116  *
2117  */
2118 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
2119         ITypeLib2 *iface, 
2120         LPTLIBATTR *ppTLibAttr)
2121 {
2122     ICOM_THIS( ITypeLibImpl, iface);
2123     TRACE("(%p)\n",This);
2124     /* FIXME: must do a copy here */
2125     *ppTLibAttr=&This->LibAttr;
2126     return S_OK;
2127 }
2128
2129 /* ITypeLib::GetTypeComp
2130  *
2131  * Enables a client compiler to bind to a library's types, variables,
2132  * constants, and global functions.
2133  *
2134  */
2135 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
2136         ITypeLib2 *iface,
2137         ITypeComp **ppTComp)
2138 {
2139     ICOM_THIS( ITypeLibImpl, iface);
2140     FIXME("(%p): stub!\n",This);
2141     return E_NOTIMPL;
2142 }
2143
2144 /* ITypeLib::GetDocumentation
2145  *
2146  * Retrieves the library's documentation string, the complete Help file name
2147  * and path, and the context identifier for the library Help topic in the Help
2148  * file.
2149  *
2150  */
2151 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
2152     ITypeLib2 *iface,
2153     INT index,
2154     BSTR *pBstrName,
2155     BSTR *pBstrDocString,
2156     DWORD *pdwHelpContext, 
2157     BSTR *pBstrHelpFile)
2158 {
2159     ICOM_THIS( ITypeLibImpl, iface);
2160     
2161     HRESULT result = E_INVALIDARG;
2162     
2163     ITypeInfo *pTInfo;
2164
2165    
2166     TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
2167         This, index,
2168         pBstrName, pBstrDocString, 
2169         pdwHelpContext, pBstrHelpFile);
2170    
2171     if(index<0)
2172     { 
2173        /* documentation for the typelib */
2174        if(pBstrName && This->Name)
2175        {
2176            *pBstrName = SysAllocString(This->Name);
2177
2178            if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
2179        }
2180        if(pBstrDocString && This->DocString)
2181        {
2182            *pBstrDocString = SysAllocString(This->DocString);
2183
2184            if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
2185        }
2186     
2187        if(pdwHelpContext)
2188        {
2189             *pdwHelpContext = This->dwHelpContext;
2190        }
2191        if(pBstrHelpFile && This->HelpFile)
2192        {
2193             *pBstrHelpFile = SysAllocString(This->HelpFile);
2194
2195             if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
2196        }
2197
2198        result = S_OK;
2199     }
2200     else 
2201     {
2202         /* for a typeinfo */
2203         result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
2204
2205         if(SUCCEEDED(result))
2206         {
2207             result = ITypeInfo_GetDocumentation(pTInfo, 
2208                                           MEMBERID_NIL,  
2209                                           pBstrName,
2210                                           pBstrDocString, 
2211                                           pdwHelpContext, pBstrHelpFile);
2212             
2213             ITypeInfo_Release(pTInfo);
2214         }
2215     }
2216     return result;
2217 }
2218
2219 /* ITypeLib::IsName
2220  *
2221  * Indicates whether a passed-in string contains the name of a type or member
2222  * described in the library.
2223  *
2224  */
2225 static HRESULT WINAPI ITypeLib2_fnIsName(
2226         ITypeLib2 *iface,
2227         LPOLESTR szNameBuf,
2228         ULONG lHashVal,
2229         BOOL *pfName)
2230 {
2231     ICOM_THIS( ITypeLibImpl, iface);
2232     ITypeInfoImpl *pTInfo;
2233     TLBFuncDesc *pFInfo;
2234     TLBVarDesc *pVInfo;
2235     int i;
2236     UINT nNameBufLen = SysStringLen(szNameBuf);
2237
2238     TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
2239           pfName);
2240
2241     *pfName=TRUE;
2242     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
2243         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2244         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2245             if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2246             for(i=0;i<pFInfo->funcdesc.cParams;i++)
2247                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
2248                     goto ITypeLib2_fnIsName_exit;
2249         }
2250         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2251             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2252        
2253     }
2254     *pfName=FALSE;
2255
2256 ITypeLib2_fnIsName_exit:
2257     TRACE("(%p)slow! search for %s: %s found!\n", This,
2258           debugstr_w(szNameBuf), *pfName?"NOT":"");
2259     
2260     return S_OK;
2261 }
2262
2263 /* ITypeLib::FindName
2264  *
2265  * Finds occurrences of a type description in a type library. This may be used
2266  * to quickly verify that a name exists in a type library.
2267  *
2268  */
2269 static HRESULT WINAPI ITypeLib2_fnFindName(
2270         ITypeLib2 *iface,
2271         LPOLESTR szNameBuf,
2272         ULONG lHashVal,
2273         ITypeInfo **ppTInfo,
2274         MEMBERID *rgMemId,
2275         UINT16 *pcFound)
2276 {
2277     ICOM_THIS( ITypeLibImpl, iface);
2278     ITypeInfoImpl *pTInfo;
2279     TLBFuncDesc *pFInfo;
2280     TLBVarDesc *pVInfo;
2281     int i,j = 0;
2282    
2283     UINT nNameBufLen = SysStringLen(szNameBuf);
2284
2285     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
2286         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2287         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2288             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2289             for(i=0;i<pFInfo->funcdesc.cParams;i++)
2290                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
2291                     goto ITypeLib2_fnFindName_exit;
2292         }
2293         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2294             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2295         continue;
2296 ITypeLib2_fnFindName_exit:
2297         ITypeInfo_AddRef((ITypeInfo*)pTInfo);
2298         ppTInfo[j]=(LPTYPEINFO)pTInfo;
2299         j++;
2300     }
2301     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
2302           This, *pcFound, debugstr_w(szNameBuf), j);
2303
2304     *pcFound=j;
2305     
2306     return S_OK;
2307 }
2308
2309 /* ITypeLib::ReleaseTLibAttr
2310  *
2311  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
2312  *
2313  */
2314 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
2315         ITypeLib2 *iface,
2316         TLIBATTR *pTLibAttr)
2317 {
2318     ICOM_THIS( ITypeLibImpl, iface);
2319     TRACE("freeing (%p)\n",This);
2320     /* nothing to do */
2321 }
2322
2323 /* ITypeLib2::GetCustData
2324  *
2325  * gets the custom data
2326  */
2327 static HRESULT WINAPI ITypeLib2_fnGetCustData(
2328         ITypeLib2 * iface,
2329         REFGUID guid, 
2330         VARIANT *pVarVal)
2331 {
2332     ICOM_THIS( ITypeLibImpl, iface);
2333     TLBCustData *pCData;
2334
2335     for(pCData=This->pCustData; pCData; pCData = pCData->next)
2336     {
2337       if( IsEqualIID(guid, &pCData->guid)) break;
2338     }
2339     
2340     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2341
2342     if(pCData)
2343     {
2344         VariantInit( pVarVal);
2345         VariantCopy( pVarVal, &pCData->data);
2346         return S_OK;
2347     }
2348     return E_INVALIDARG;  /* FIXME: correct? */
2349 }
2350
2351 /* ITypeLib2::GetLibStatistics
2352  *
2353  * Returns statistics about a type library that are required for efficient
2354  * sizing of hash tables.
2355  *
2356  */
2357 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
2358         ITypeLib2 * iface, 
2359         ULONG *pcUniqueNames,
2360         ULONG *pcchUniqueNames)
2361 {
2362     ICOM_THIS( ITypeLibImpl, iface);
2363
2364     FIXME("(%p): stub!\n", This);
2365
2366     if(pcUniqueNames) *pcUniqueNames=1;
2367     if(pcchUniqueNames) *pcchUniqueNames=1;
2368     return S_OK;
2369 }
2370
2371 /* ITypeLib2::GetDocumentation2
2372  *
2373  * Retrieves the library's documentation string, the complete Help file name
2374  * and path, the localization context to use, and the context ID for the
2375  * library Help topic in the Help file.
2376  *
2377  */
2378 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
2379         ITypeLib2 * iface, 
2380         INT index,
2381         LCID lcid,
2382         BSTR *pbstrHelpString,
2383         DWORD *pdwHelpStringContext,
2384         BSTR *pbstrHelpStringDll)
2385 {
2386     ICOM_THIS( ITypeLibImpl, iface);
2387     HRESULT result;
2388     ITypeInfo *pTInfo;
2389
2390     FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
2391
2392     /* the help string should be obtained from the helpstringdll,
2393      * using the _DLLGetDocumentation function, based on the supplied
2394      * lcid. Nice to do sometime...
2395      */
2396     if(index<0)
2397     {
2398       /* documentation for the typelib */
2399       if(pbstrHelpString)
2400         *pbstrHelpString=SysAllocString(This->DocString);
2401       if(pdwHelpStringContext)
2402         *pdwHelpStringContext=This->dwHelpContext;
2403       if(pbstrHelpStringDll)
2404         *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
2405
2406       result = S_OK;
2407     }
2408     else
2409     {
2410       /* for a typeinfo */
2411       result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
2412       
2413       if(SUCCEEDED(result))
2414       { 
2415         ITypeInfo2 * pTInfo2;
2416         result = ITypeInfo_QueryInterface(pTInfo, 
2417                                           &IID_ITypeInfo2, 
2418                                           (LPVOID*) &pTInfo2);
2419
2420         if(SUCCEEDED(result))
2421         {
2422           result = ITypeInfo2_GetDocumentation2(pTInfo2, 
2423                                            MEMBERID_NIL, 
2424                                            lcid,
2425                                            pbstrHelpString, 
2426                                            pdwHelpStringContext, 
2427                                            pbstrHelpStringDll);
2428   
2429           ITypeInfo2_Release(pTInfo2);
2430         }
2431             
2432         ITypeInfo_Release(pTInfo);
2433       }
2434     }
2435     return result;
2436 }
2437
2438 /* ITypeLib2::GetAllCustData
2439  *
2440  * Gets all custom data items for the library. 
2441  *
2442  */
2443 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
2444         ITypeLib2 * iface,
2445         CUSTDATA *pCustData)
2446 {
2447     ICOM_THIS( ITypeLibImpl, iface);
2448     TLBCustData *pCData;
2449     int i;
2450     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
2451     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
2452     if(pCustData->prgCustData ){
2453         pCustData->cCustData=This->ctCustData;
2454         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
2455             pCustData->prgCustData[i].guid=pCData->guid;
2456             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
2457         }
2458     }else{
2459         ERR(" OUT OF MEMORY! \n");
2460         return E_OUTOFMEMORY;
2461     }
2462     return S_OK;
2463 }
2464
2465 static ICOM_VTABLE(ITypeLib2) tlbvt = {
2466     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2467     ITypeLib2_fnQueryInterface,
2468     ITypeLib2_fnAddRef,
2469     ITypeLib2_fnRelease,
2470     ITypeLib2_fnGetTypeInfoCount,
2471     ITypeLib2_fnGetTypeInfo,
2472     ITypeLib2_fnGetTypeInfoType,
2473     ITypeLib2_fnGetTypeInfoOfGuid,
2474     ITypeLib2_fnGetLibAttr,
2475     ITypeLib2_fnGetTypeComp,
2476     ITypeLib2_fnGetDocumentation,
2477     ITypeLib2_fnIsName,
2478     ITypeLib2_fnFindName,
2479     ITypeLib2_fnReleaseTLibAttr,
2480
2481     ITypeLib2_fnGetCustData,
2482     ITypeLib2_fnGetLibStatistics,
2483     ITypeLib2_fnGetDocumentation2,
2484     ITypeLib2_fnGetAllCustData
2485  };
2486
2487 /*================== ITypeInfo(2) Methods ===================================*/
2488 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
2489 {
2490     ITypeInfoImpl * pTypeInfoImpl;
2491
2492     pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
2493     if (pTypeInfoImpl)
2494     {
2495       ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
2496       pTypeInfoImpl->ref=1;
2497     }
2498     TRACE("(%p)\n", pTypeInfoImpl);
2499     return (ITypeInfo2*) pTypeInfoImpl;
2500 }
2501
2502 /* ITypeInfo::QueryInterface
2503  */
2504 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
2505         ITypeInfo2 *iface,
2506         REFIID riid,
2507         VOID **ppvObject)
2508 {
2509     ICOM_THIS( ITypeLibImpl, iface);
2510
2511     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2512
2513     *ppvObject=NULL;
2514     if(IsEqualIID(riid, &IID_IUnknown) || 
2515             IsEqualIID(riid,&IID_ITypeInfo)||
2516             IsEqualIID(riid,&IID_ITypeInfo2))
2517         *ppvObject = This;
2518
2519     if(*ppvObject){
2520         ITypeInfo_AddRef(iface);
2521         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2522         return S_OK;
2523     }
2524     TRACE("-- Interface: E_NOINTERFACE\n");
2525     return E_NOINTERFACE;
2526 }
2527
2528 /* ITypeInfo::AddRef
2529  */
2530 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
2531 {
2532     ICOM_THIS( ITypeInfoImpl, iface);
2533
2534     ++(This->ref);
2535
2536     TRACE("(%p)->ref is %u\n",This, This->ref);
2537     return This->ref;
2538 }
2539
2540 /* ITypeInfo::Release
2541  */
2542 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
2543 {
2544     ICOM_THIS( ITypeInfoImpl, iface);
2545
2546     --(This->ref);
2547     
2548     TRACE("(%p)->(%u)\n",This, This->ref);
2549
2550     if (!This->ref)
2551     {
2552       FIXME("destroy child objects\n");
2553
2554       TRACE("destroying ITypeInfo(%p)\n",This); 
2555       if (This->Name)
2556       {
2557           SysFreeString(This->Name);
2558           This->Name = 0;
2559       }
2560       
2561       if (This->DocString)
2562       {
2563           SysFreeString(This->DocString);
2564           This->DocString = 0;
2565       }
2566
2567       if (This->next)
2568       {
2569         ITypeInfo_Release((ITypeInfo*)This->next);
2570       }
2571
2572       HeapFree(GetProcessHeap(),0,This);
2573       return 0;
2574     }
2575     return This->ref;
2576 }
2577
2578 /* ITypeInfo::GetTypeAttr
2579  *
2580  * Retrieves a TYPEATTR structure that contains the attributes of the type
2581  * description.
2582  *
2583  */
2584 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
2585         LPTYPEATTR  *ppTypeAttr)
2586 {
2587     ICOM_THIS( ITypeInfoImpl, iface);
2588     TRACE("(%p)\n",This);
2589     /* FIXME: must do a copy here */
2590     *ppTypeAttr=&This->TypeAttr;
2591     return S_OK;
2592 }
2593
2594 /* ITypeInfo::GetTypeComp
2595  *
2596  * Retrieves the ITypeComp interface for the type description, which enables a
2597  * client compiler to bind to the type description's members.
2598  *
2599  */
2600 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
2601         ITypeComp  * *ppTComp)
2602 {
2603     ICOM_THIS( ITypeInfoImpl, iface);
2604     FIXME("(%p) stub!\n", This);
2605     return S_OK;
2606 }
2607
2608 /* ITypeInfo::GetFuncDesc
2609  *
2610  * Retrieves the FUNCDESC structure that contains information about a
2611  * specified function.
2612  *
2613  */
2614 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
2615         LPFUNCDESC  *ppFuncDesc)
2616 {
2617     ICOM_THIS( ITypeInfoImpl, iface);
2618     int i;
2619     TLBFuncDesc * pFDesc; 
2620     TRACE("(%p) index %d\n", This, index);
2621     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
2622         ;
2623     if(pFDesc){
2624         /* FIXME: must do a copy here */
2625         *ppFuncDesc=&pFDesc->funcdesc;
2626         return S_OK;
2627     }
2628     return E_INVALIDARG;
2629 }
2630
2631 /* ITypeInfo::GetVarDesc
2632  *
2633  * Retrieves a VARDESC structure that describes the specified variable. 
2634  *
2635  */
2636 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
2637         LPVARDESC  *ppVarDesc)
2638 {
2639     ICOM_THIS( ITypeInfoImpl, iface);
2640     int i;
2641     TLBVarDesc * pVDesc; 
2642     TRACE("(%p) index %d\n", This, index);
2643     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
2644         ;
2645     if(pVDesc){
2646         /* FIXME: must do a copy here */
2647         *ppVarDesc=&pVDesc->vardesc;
2648         return S_OK;
2649     }
2650     return E_INVALIDARG;
2651 }
2652
2653 /* ITypeInfo_GetNames
2654  *
2655  * Retrieves the variable with the specified member ID (or the name of the
2656  * property or method and its parameters) that correspond to the specified
2657  * function ID.
2658  */
2659 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
2660         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
2661 {
2662     ICOM_THIS( ITypeInfoImpl, iface);
2663     TLBFuncDesc * pFDesc; 
2664     TLBVarDesc * pVDesc; 
2665     int i;
2666     TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
2667     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
2668     if(pFDesc)
2669     {
2670       /* function found, now return function and parameter names */
2671       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
2672       {
2673         if(!i)
2674                   *rgBstrNames=SysAllocString(pFDesc->Name);
2675         else
2676           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
2677       }
2678       *pcNames=i;
2679     }
2680     else
2681     {
2682       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
2683       if(pVDesc)
2684       {
2685         *rgBstrNames=SysAllocString(pVDesc->Name);
2686         *pcNames=1;
2687       }
2688       else
2689       {
2690         if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
2691         {
2692           /* recursive search */
2693           ITypeInfo *pTInfo;
2694           HRESULT result;
2695           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo);
2696           if(SUCCEEDED(result))
2697           {
2698             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
2699             ITypeInfo_Release(pTInfo);
2700             return result;
2701           }
2702           WARN("Could not search inherited interface!\n");
2703         }
2704         else
2705         {
2706           WARN("no names found\n");
2707         }
2708         *pcNames=0;
2709         return TYPE_E_ELEMENTNOTFOUND;
2710       }
2711     }
2712     return S_OK;
2713 }
2714
2715
2716 /* ITypeInfo::GetRefTypeOfImplType
2717  *
2718  * If a type description describes a COM class, it retrieves the type
2719  * description of the implemented interface types. For an interface,
2720  * GetRefTypeOfImplType returns the type information for inherited interfaces,
2721  * if any exist.
2722  *
2723  */
2724 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
2725         ITypeInfo2 *iface,
2726         UINT index,
2727         HREFTYPE  *pRefType)
2728 {
2729     ICOM_THIS( ITypeInfoImpl, iface);
2730     int(i);
2731     TLBRefType *pIref = This->impltypelist;
2732
2733     TRACE("(%p) index %d\n", This, index);
2734     dump_TypeInfo(This);
2735
2736     if(index==(UINT)-1)
2737     {
2738       /* only valid on dual interfaces;
2739          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
2740       */
2741       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
2742       
2743       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
2744           This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
2745       {
2746         *pRefType = -1;
2747       }
2748       else
2749       {
2750         if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2751         *pRefType = pIref->reference;
2752       }
2753     }
2754     else
2755     {
2756       /* get element n from linked list */
2757       for(i=0; pIref && i<index; i++)
2758       {
2759         pIref = pIref->next;
2760       }
2761       
2762       if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2763       
2764       *pRefType = pIref->reference;
2765       
2766       TRACE("-- 0x%08lx %s\n",pIref->reference, debugstr_guid(&pIref->guid) );
2767     }
2768     
2769     return S_OK;
2770    
2771 }
2772
2773 /* ITypeInfo::GetImplTypeFlags
2774  * 
2775  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 
2776  * or base interface in a type description.
2777  */
2778 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
2779         UINT index, INT  *pImplTypeFlags)
2780 {
2781     ICOM_THIS( ITypeInfoImpl, iface);
2782     int(i);
2783     TLBRefType *pIref;
2784     TRACE("(%p) index %d\n", This, index);
2785     for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
2786         ;
2787     if(i==index && pIref){
2788         *pImplTypeFlags=pIref->flags;
2789         return S_OK;
2790     }
2791     *pImplTypeFlags=0;
2792     return TYPE_E_ELEMENTNOTFOUND;
2793 }
2794
2795 /* GetIDsOfNames
2796  * Maps between member names and member IDs, and parameter names and
2797  * parameter IDs.
2798  */
2799 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
2800         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
2801 {
2802     ICOM_THIS( ITypeInfoImpl, iface);
2803     TLBFuncDesc * pFDesc; 
2804     TLBVarDesc * pVDesc; 
2805     HRESULT ret=S_OK;
2806         UINT nNameLen = SysStringLen(*rgszNames);
2807         
2808     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
2809             cNames);
2810     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
2811         int i, j;
2812         if( !memcmp(*rgszNames, pFDesc->Name, nNameLen)) {
2813             if(cNames) *pMemId=pFDesc->funcdesc.memid;
2814             for(i=1; i < cNames; i++){
2815                                 UINT nParamLen = SysStringLen(rgszNames[i]);
2816                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
2817                     if(memcmp(rgszNames[i],pFDesc->pParamDesc[j].Name, nParamLen))
2818                             break;
2819                 if( j<pFDesc->funcdesc.cParams)
2820                     pMemId[i]=j;
2821                 else
2822                    ret=DISP_E_UNKNOWNNAME;
2823             };
2824             return ret;
2825         }
2826     }   
2827     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
2828         if( !memcmp(*rgszNames, pVDesc->Name, nNameLen)) {
2829             if(cNames) *pMemId=pVDesc->vardesc.memid;
2830             return ret;
2831         }
2832     }
2833     /* not found, see if this is and interface with an inheritance */       
2834     if(This->TypeAttr.typekind==TKIND_INTERFACE && 
2835             This->TypeAttr.cImplTypes ){
2836         /* recursive search */
2837         ITypeInfo *pTInfo;
2838         ret=ITypeInfo_GetRefTypeInfo(iface, 
2839                 This->impltypelist->reference, &pTInfo);
2840         if(SUCCEEDED(ret)){
2841             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
2842             ITypeInfo_Release(pTInfo);
2843             return ret;
2844         }
2845         WARN("Could not search inherited interface!\n");
2846     } else
2847         WARN("no names found\n");
2848     return DISP_E_UNKNOWNNAME;
2849 }
2850
2851 /* ITypeInfo::Invoke
2852  * 
2853  * Invokes a method, or accesses a property of an object, that implements the
2854  * interface described by the type description.
2855  */
2856 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
2857     DWORD res;
2858
2859     if (TRACE_ON(ole)) {
2860         int i;
2861         MESSAGE("Calling %p(",func);
2862         for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
2863         MESSAGE(")\n");
2864     }
2865
2866     switch (callconv) {
2867     case CC_STDCALL:
2868
2869         switch (nrargs) {
2870         case 0: {
2871                 DWORD (WINAPI *xfunc)() = func;
2872                 res = xfunc();
2873                 break;
2874         }
2875         case 1: {
2876                 DWORD (WINAPI *xfunc)(DWORD) = func;
2877                 res = xfunc(args[0]);
2878                 break;
2879         }
2880         case 2: {
2881                 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
2882                 res = xfunc(args[0],args[1]);
2883                 break;
2884         }
2885         case 3: {
2886                 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
2887                 res = xfunc(args[0],args[1],args[2]);
2888                 break;
2889         }
2890         default:
2891                 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
2892                 res = -1;
2893                 break;
2894         }
2895         break;
2896     default:
2897         FIXME("unsupported calling convention %d\n",callconv);
2898         res = -1;
2899         break;
2900     }
2901     TRACE("returns %08lx\n",res);
2902     return res;
2903 }
2904
2905 static HRESULT WINAPI ITypeInfo_fnInvoke(
2906     ITypeInfo2 *iface,
2907     VOID  *pIUnk,
2908     MEMBERID memid,
2909     UINT16 dwFlags,
2910     DISPPARAMS  *pDispParams,
2911     VARIANT  *pVarResult,
2912     EXCEPINFO  *pExcepInfo,
2913     UINT  *pArgErr)
2914 {
2915     ICOM_THIS( ITypeInfoImpl, iface);
2916     TLBFuncDesc * pFDesc; 
2917     TLBVarDesc * pVDesc; 
2918     int i;
2919
2920     TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
2921       This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
2922     );
2923     dump_DispParms(pDispParams);
2924
2925     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2926         if (pFDesc->funcdesc.memid == memid) {
2927             if (pFDesc->funcdesc.invkind & (dwFlags & ~DISPATCH_METHOD))
2928                 break;
2929         }
2930     if (pFDesc) {
2931         dump_TLBFuncDescOne(pFDesc);
2932         switch (pFDesc->funcdesc.funckind) {
2933         case FUNC_PUREVIRTUAL:
2934         case FUNC_VIRTUAL: {
2935             DWORD res;
2936             DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
2937             DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
2938             args[0] = (DWORD)pIUnk;
2939
2940             for (i=0;i<pFDesc->funcdesc.cParams;i++) {
2941                 if (i<pDispParams->cArgs) {
2942                     TRACE("set %d to disparg type %d vs %d\n",i,
2943                             pDispParams->rgvarg[i].vt,
2944                             pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
2945                     );
2946                     args[i+1] = pDispParams->rgvarg[i].u.lVal;
2947                 } else {
2948                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
2949                     TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
2950                     /*FIXME: give pointers for the rest, so propertyget works*/
2951                     args[i+1] = (DWORD)&args2[i];
2952
2953                     /* If pointer to variant, pass reference to variant
2954                      * in result variant array.
2955                      */
2956                     if ((tdesc->vt == VT_PTR) &&
2957                         (tdesc->u.lptdesc->vt == VT_VARIANT) &&
2958                         pVarResult
2959                     )
2960                         args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
2961                 }
2962             }
2963             if (pFDesc->funcdesc.cParamsOpt)
2964                 FIXME("Does not support optional parameters (%d)\n",
2965                         pFDesc->funcdesc.cParamsOpt
2966                 );
2967
2968             res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
2969                     pFDesc->funcdesc.callconv,
2970                     pFDesc->funcdesc.cParams+1,
2971                     args
2972             );
2973             if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
2974                 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
2975                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
2976                     /* If we are a pointer to a variant, we are done already */
2977                     if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
2978                         continue;
2979
2980                     VariantInit(&pVarResult[i]);
2981                     pVarResult[i].u.intVal = args2[i];
2982
2983                     if (tdesc->vt == VT_PTR)
2984                         tdesc = tdesc->u.lptdesc;
2985                     pVarResult[i].vt = tdesc->vt;
2986
2987                     /* HACK: VB5 likes this.
2988                      * I do not know why. There is 1 example in MSDN which uses
2989                      * this which appears broken (mixes int vals and
2990                      * IDispatch*.).
2991                      */
2992                     if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
2993                         pVarResult[i].vt = VT_DISPATCH;
2994                     TRACE("storing into variant: [%d] type %d, val %08x\n",
2995                             i,pVarResult[i].vt,pVarResult[i].u.intVal
2996                     );
2997                 }
2998             }
2999             HeapFree(GetProcessHeap(),0,args2);
3000             HeapFree(GetProcessHeap(),0,args);
3001             return S_OK;
3002         }
3003         case FUNC_DISPATCH:  {
3004            IDispatch *disp;
3005            HRESULT hr;
3006
3007            hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
3008            if (hr) {
3009                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
3010                return hr;
3011            }
3012            FIXME("Calling Invoke in IDispatch iface. untested!\n");
3013            hr = IDispatch_Invoke(
3014                disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
3015                pVarResult,pExcepInfo,pArgErr
3016            );
3017            if (hr)
3018                FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
3019            IDispatch_Release(disp);
3020            return hr;
3021         }
3022         default:
3023            FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
3024            return E_FAIL;
3025         }
3026     } else {
3027         FIXME("variable based invoking not supported yet.\n");
3028         for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3029             if (pVDesc->vardesc.memid == memid) {
3030                 FIXME("varseek: Found memid name %s\n",debugstr_w(((LPWSTR)pVDesc->Name)));
3031                 dump_TLBVarDesc(pVDesc);
3032                 break;
3033             }
3034         }
3035     }
3036     FIXME("Did not find member id %d!\n",(int)memid);
3037     return DISP_E_MEMBERNOTFOUND;
3038 }
3039
3040 /* ITypeInfo::GetDocumentation
3041  * 
3042  * Retrieves the documentation string, the complete Help file name and path,
3043  * and the context ID for the Help topic for a specified type description.
3044  */
3045 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
3046         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
3047         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
3048 {
3049     ICOM_THIS( ITypeInfoImpl, iface);
3050     TLBFuncDesc * pFDesc; 
3051     TLBVarDesc * pVDesc; 
3052     TRACE("(%p) memid %ld Name(%p) DocString(%p)"
3053           " HelpContext(%p) HelpFile(%p)\n",
3054         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
3055     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
3056         if(pBstrName)
3057             *pBstrName=SysAllocString(This->Name);
3058         if(pBstrDocString)
3059             *pBstrDocString=SysAllocString(This->DocString);
3060         if(pdwHelpContext)
3061             *pdwHelpContext=This->dwHelpContext;
3062         if(pBstrHelpFile)
3063             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
3064         return S_OK;
3065     }else {/* for a member */
3066     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3067         if(pFDesc->funcdesc.memid==memid){
3068             return S_OK;
3069         }
3070     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
3071         if(pVDesc->vardesc.memid==memid){
3072             return S_OK;
3073         }
3074     }
3075     return TYPE_E_ELEMENTNOTFOUND;
3076 }
3077
3078 /*  ITypeInfo::GetDllEntry
3079  * 
3080  * Retrieves a description or specification of an entry point for a function
3081  * in a DLL.
3082  */
3083 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
3084         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
3085         WORD  *pwOrdinal)
3086 {
3087     ICOM_THIS( ITypeInfoImpl, iface);
3088     FIXME("(%p) stub!\n", This);
3089     return E_FAIL;
3090 }
3091
3092 /* ITypeInfo::GetRefTypeInfo
3093  * 
3094  * If a type description references other type descriptions, it retrieves
3095  * the referenced type descriptions.
3096  */
3097 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
3098         ITypeInfo2 *iface,
3099         HREFTYPE hRefType,
3100         ITypeInfo  **ppTInfo)
3101 {
3102     ICOM_THIS( ITypeInfoImpl, iface);
3103     HRESULT result = E_FAIL;
3104
3105     if(HREFTYPE_INTHISFILE(hRefType))
3106     {
3107       ITypeLib *pTLib;
3108       int Index;
3109       result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
3110       if(SUCCEEDED( result ))
3111       {
3112         result=ITypeLib2_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo);
3113         ITypeLib2_Release(pTLib );
3114       }
3115     }
3116         else if (hRefType == -1 && 
3117              (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
3118              (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
3119     {
3120           /* when we meet a DUAL dispinterface, we must create the interface 
3121           * version of it.
3122           */
3123           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
3124
3125                 
3126           /* the interface version contains the same information as the dispinterface
3127            * copy the contents of the structs.
3128            */
3129           *pTypeInfoImpl = *This;
3130           pTypeInfoImpl->ref = 1;
3131                 
3132           /* change the type to interface */
3133           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
3134                 
3135       *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
3136
3137           ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
3138
3139       result = S_OK;
3140         }
3141     else
3142     {
3143       /* imported type lib */
3144       TLBRefType   *pRefType     = NULL;
3145       
3146       /* search in implemented types */
3147       for( pRefType = This->impltypelist; 
3148            pRefType && (pRefType->reference != hRefType);
3149            pRefType = pRefType->next);
3150       
3151       if(!pRefType)
3152       {                       
3153         TYPEATTR*       pMyTypeAttr  = &This->TypeAttr;
3154         unsigned short  cFuncs       = pMyTypeAttr->cFuncs;
3155         unsigned short  cVars        = pMyTypeAttr->cVars;
3156         
3157         /* search in arguments */      
3158         if (cFuncs > 0)
3159         {
3160           unsigned short  cFuncIndex   = 0;
3161   
3162           TLBFuncDesc*    pCurrFunc    = This->funclist;
3163           
3164           for (cFuncIndex = 0; !pRefType && cFuncIndex < cFuncs ; ++cFuncIndex)
3165           {
3166             FUNCDESC*  pCurrFuncDesc = &pCurrFunc->funcdesc;
3167             
3168             short      cParams       = pCurrFuncDesc->cParams;
3169             short      cParamIndex   = 0;
3170               
3171             for (cParamIndex = 0 ; 
3172                  !pRefType && cParamIndex < cParams ; 
3173                  ++cParamIndex)
3174             {
3175               TLBParDesc* pCurrParamDesc = &(pCurrFunc->pParamDesc[cParamIndex]);
3176              
3177               if ( pCurrParamDesc->pRefType && pCurrParamDesc->pRefType->reference == hRefType)
3178               {
3179                 pRefType = pCurrParamDesc->pRefType;
3180                 break; /* also break from outer loop since pRefType != 0 */
3181               }
3182             }
3183             
3184             pCurrFunc = pCurrFunc->next;
3185           }
3186         }
3187         /* search in variables */
3188         else if (cVars > 0)
3189         {
3190           FIXME("search hreftype in variables, if any\n");
3191           result = E_INVALIDARG; // FIXME : correct?
3192         }
3193       }
3194       
3195       /* href-referenced typeinfo found! */
3196       if (pRefType || hRefType == -1)
3197       {
3198         ITypeLibImpl *pTypeLib = pRefType->pImpTLInfo->pImpTypeLib;
3199         
3200         if(pTypeLib) 
3201         {
3202           TRACE("typeinfo in imported typelib that is already loaded\n");
3203                   
3204           result = ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, 
3205                                            &pRefType->guid, 
3206                                            ppTInfo);
3207         }
3208         else
3209         {
3210           result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
3211                       pRefType->pImpTLInfo->wVersionMajor,
3212                       pRefType->pImpTLInfo->wVersionMinor,
3213                       pRefType->pImpTLInfo->lcid,
3214                       (LPTYPELIB *)&pTypeLib);
3215           
3216           if(!SUCCEEDED(result))
3217                   {
3218             BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
3219             TRACE("typeinfo in imported typelib that isn't already loaded\n");
3220             result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
3221             SysFreeString(libnam);
3222           } 
3223           if(SUCCEEDED(result))
3224           {
3225             result=ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
3226             pRefType->pImpTLInfo->pImpTypeLib = pTypeLib;
3227                         ITypeLib2_AddRef((ITypeLib*) pTypeLib);
3228           }        
3229         }
3230       }
3231     }
3232
3233     TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
3234           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
3235     return result;
3236 }
3237
3238 /* ITypeInfo::AddressOfMember
3239  * 
3240  * Retrieves the addresses of static functions or variables, such as those
3241  * defined in a DLL.
3242  */
3243 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
3244         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
3245 {
3246     ICOM_THIS( ITypeInfoImpl, iface);
3247     FIXME("(%p) stub!\n", This);
3248     return S_OK;
3249 }
3250
3251 /* ITypeInfo::CreateInstance
3252  * 
3253  * Creates a new instance of a type that describes a component object class 
3254  * (coclass).
3255  */
3256 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface, 
3257         IUnknown *pUnk, REFIID riid, VOID  **ppvObj) 
3258 {
3259     ICOM_THIS( ITypeInfoImpl, iface);
3260     FIXME("(%p) stub!\n", This);
3261     return S_OK;
3262 }
3263
3264 /* ITypeInfo::GetMops
3265  *
3266  * Retrieves marshaling information.
3267  */
3268 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
3269                                 BSTR  *pBstrMops)
3270 {
3271     ICOM_THIS( ITypeInfoImpl, iface);
3272     FIXME("(%p) stub!\n", This);
3273     return S_OK;
3274 }
3275
3276 /* ITypeInfo::GetContainingTypeLib
3277  * 
3278  * Retrieves the containing type library and the index of the type description
3279  * within that type library.
3280  */
3281 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
3282         ITypeLib  * *ppTLib, UINT  *pIndex)
3283 {
3284     ICOM_THIS( ITypeInfoImpl, iface);
3285     if (!pIndex)
3286         return E_INVALIDARG;
3287     *ppTLib=(LPTYPELIB )(This->pTypeLib);
3288     *pIndex=This->index;
3289     ITypeLib2_AddRef(*ppTLib);
3290     TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
3291     return S_OK;
3292 }
3293
3294 /* ITypeInfo::ReleaseTypeAttr
3295  *
3296  * Releases a TYPEATTR previously returned by GetTypeAttr.
3297  *
3298  */
3299 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
3300         TYPEATTR* pTypeAttr)
3301 {
3302     ICOM_THIS( ITypeInfoImpl, iface);
3303     TRACE("(%p)->(%p)\n", This, pTypeAttr);
3304     return S_OK;
3305 }
3306
3307 /* ITypeInfo::ReleaseFuncDesc
3308  *
3309  * Releases a FUNCDESC previously returned by GetFuncDesc. *
3310  */
3311 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
3312         ITypeInfo2 *iface,
3313         FUNCDESC *pFuncDesc)
3314 {
3315     ICOM_THIS( ITypeInfoImpl, iface);
3316     TRACE("(%p)->(%p)\n", This, pFuncDesc);
3317     return S_OK;
3318 }
3319
3320 /* ITypeInfo::ReleaseVarDesc
3321  *
3322  * Releases a VARDESC previously returned by GetVarDesc.
3323  */
3324 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
3325         VARDESC *pVarDesc)
3326 {
3327     ICOM_THIS( ITypeInfoImpl, iface);
3328     TRACE("(%p)->(%p)\n", This, pVarDesc);
3329     return S_OK;
3330 }
3331
3332 /* ITypeInfo2::GetTypeKind
3333  *
3334  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
3335  *
3336  */
3337 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
3338     TYPEKIND *pTypeKind)
3339 {
3340     ICOM_THIS( ITypeInfoImpl, iface);
3341     *pTypeKind=This->TypeAttr.typekind;
3342     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
3343     return S_OK;
3344 }
3345
3346 /* ITypeInfo2::GetTypeFlags
3347  *
3348  * Returns the type flags without any allocations. This returns a DWORD type
3349  * flag, which expands the type flags without growing the TYPEATTR (type
3350  * attribute). 
3351  *
3352  */
3353 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
3354     UINT *pTypeFlags)
3355 {
3356     ICOM_THIS( ITypeInfoImpl, iface);
3357     *pTypeFlags=This->TypeAttr.wTypeFlags;
3358     TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
3359      return S_OK;
3360 }
3361
3362 /* ITypeInfo2::GetFuncIndexOfMemId
3363  * Binds to a specific member based on a known DISPID, where the member name
3364  * is not known (for example, when binding to a default member).
3365  *
3366  */
3367 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
3368     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
3369 {
3370     ICOM_THIS( ITypeInfoImpl, iface);
3371     TLBFuncDesc *pFuncInfo;
3372     int i;
3373     HRESULT result;
3374     /* FIXME: should check for invKind??? */
3375     for(i=0, pFuncInfo=This->funclist;pFuncInfo && 
3376             memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
3377     if(pFuncInfo){
3378         *pFuncIndex=i;
3379         result= S_OK;
3380     }else{
3381         *pFuncIndex=0;
3382         result=E_INVALIDARG;
3383     }
3384     TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
3385           memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
3386     return result;
3387 }
3388
3389 /* TypeInfo2::GetVarIndexOfMemId
3390  *
3391  * Binds to a specific member based on a known DISPID, where the member name
3392  * is not known (for example, when binding to a default member). 
3393  *
3394  */
3395 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
3396     MEMBERID memid, UINT *pVarIndex)
3397 {
3398     ICOM_THIS( ITypeInfoImpl, iface);
3399     TLBVarDesc *pVarInfo;
3400     int i;
3401     HRESULT result;
3402     for(i=0, pVarInfo=This->varlist; pVarInfo && 
3403             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
3404         ;
3405     if(pVarInfo){
3406         *pVarIndex=i;
3407         result= S_OK;
3408     }else{
3409         *pVarIndex=0;
3410         result=E_INVALIDARG;
3411     }
3412     TRACE("(%p) memid 0x%08lx -> %s\n", This,
3413           memid, SUCCEEDED(result)? "SUCCES":"FAILED");
3414     return result;
3415 }
3416
3417 /* ITypeInfo2::GetCustData
3418  *
3419  * Gets the custom data
3420  */
3421 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
3422         ITypeInfo2 * iface,
3423         REFGUID guid,
3424         VARIANT *pVarVal)
3425 {
3426     ICOM_THIS( ITypeInfoImpl, iface);
3427     TLBCustData *pCData;
3428
3429     for(pCData=This->pCustData; pCData; pCData = pCData->next)
3430         if( IsEqualIID(guid, &pCData->guid)) break;
3431
3432     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3433
3434     if(pCData)
3435     {
3436         VariantInit( pVarVal);
3437         VariantCopy( pVarVal, &pCData->data);
3438         return S_OK;
3439     }
3440     return E_INVALIDARG;  /* FIXME: correct? */
3441 }
3442
3443 /* ITypeInfo2::GetFuncCustData
3444  *
3445  * Gets the custom data
3446  */
3447 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
3448         ITypeInfo2 * iface,
3449         UINT index,
3450         REFGUID guid,
3451         VARIANT *pVarVal)
3452 {
3453     ICOM_THIS( ITypeInfoImpl, iface);
3454     TLBCustData *pCData=NULL;
3455     TLBFuncDesc * pFDesc; 
3456     int i;
3457     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3458             pFDesc=pFDesc->next);
3459
3460     if(pFDesc)
3461         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
3462             if( IsEqualIID(guid, &pCData->guid)) break;
3463
3464     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3465
3466     if(pCData){
3467         VariantInit( pVarVal);
3468         VariantCopy( pVarVal, &pCData->data);
3469         return S_OK;
3470     }
3471     return E_INVALIDARG;  /* FIXME: correct? */
3472 }
3473
3474 /* ITypeInfo2::GetParamCustData
3475  *
3476  * Gets the custom data
3477  */
3478 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
3479         ITypeInfo2 * iface,
3480         UINT indexFunc,
3481         UINT indexParam,
3482         REFGUID guid,
3483         VARIANT *pVarVal)
3484 {   
3485     ICOM_THIS( ITypeInfoImpl, iface);
3486     TLBCustData *pCData=NULL;
3487     TLBFuncDesc * pFDesc; 
3488     int i;
3489
3490     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
3491
3492     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
3493         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 
3494                 pCData = pCData->next)
3495             if( IsEqualIID(guid, &pCData->guid)) break;
3496
3497     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3498
3499     if(pCData)
3500     {
3501         VariantInit( pVarVal);
3502         VariantCopy( pVarVal, &pCData->data);
3503         return S_OK;
3504     }
3505     return E_INVALIDARG;  /* FIXME: correct? */
3506 }
3507
3508 /* ITypeInfo2::GetVarcCustData
3509  *
3510  * Gets the custom data
3511  */
3512 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
3513         ITypeInfo2 * iface,
3514         UINT index,
3515         REFGUID guid,
3516         VARIANT *pVarVal)
3517 {   
3518     ICOM_THIS( ITypeInfoImpl, iface);
3519     TLBCustData *pCData=NULL;
3520     TLBVarDesc * pVDesc; 
3521     int i;
3522
3523     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
3524
3525     if(pVDesc)
3526     {
3527       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
3528       {
3529         if( IsEqualIID(guid, &pCData->guid)) break;
3530       }
3531     }
3532
3533     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3534
3535     if(pCData)
3536     {
3537         VariantInit( pVarVal);
3538         VariantCopy( pVarVal, &pCData->data);
3539         return S_OK;
3540     }
3541     return E_INVALIDARG;  /* FIXME: correct? */
3542 }
3543
3544 /* ITypeInfo2::GetImplcCustData
3545  *
3546  * Gets the custom data
3547  */
3548 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
3549         ITypeInfo2 * iface,
3550         UINT index,
3551         REFGUID guid,
3552         VARIANT *pVarVal)
3553 {   
3554     ICOM_THIS( ITypeInfoImpl, iface);
3555     TLBCustData *pCData=NULL;
3556     TLBRefType * pRDesc; 
3557     int i;
3558
3559     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
3560
3561     if(pRDesc)
3562     {
3563       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
3564       {
3565         if( IsEqualIID(guid, &pCData->guid)) break;
3566       }
3567     }
3568     
3569     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3570
3571     if(pCData)
3572     {
3573         VariantInit( pVarVal);
3574         VariantCopy( pVarVal, &pCData->data);
3575         return S_OK;
3576     }
3577     return E_INVALIDARG;  /* FIXME: correct? */
3578 }
3579
3580 /* ITypeInfo2::GetDocumentation2
3581  * 
3582  * Retrieves the documentation string, the complete Help file name and path,
3583  * the localization context to use, and the context ID for the library Help
3584  * topic in the Help file.
3585  *
3586  */
3587 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
3588         ITypeInfo2 * iface,
3589         MEMBERID memid,
3590         LCID lcid,
3591         BSTR *pbstrHelpString,
3592         DWORD *pdwHelpStringContext,
3593         BSTR *pbstrHelpStringDll)
3594 {
3595     ICOM_THIS( ITypeInfoImpl, iface);
3596     TLBFuncDesc * pFDesc; 
3597     TLBVarDesc * pVDesc; 
3598     TRACE("(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
3599           "HelpStringContext(%p) HelpStringDll(%p)\n",
3600           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
3601           pbstrHelpStringDll );
3602     /* the help string should be obtained from the helpstringdll,
3603      * using the _DLLGetDocumentation function, based on the supplied
3604      * lcid. Nice to do sometime...
3605      */
3606     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
3607         if(pbstrHelpString)
3608             *pbstrHelpString=SysAllocString(This->Name);
3609         if(pdwHelpStringContext)
3610             *pdwHelpStringContext=This->dwHelpStringContext;
3611         if(pbstrHelpStringDll)
3612             *pbstrHelpStringDll=
3613                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3614         return S_OK;
3615     }else {/* for a member */
3616     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3617         if(pFDesc->funcdesc.memid==memid){
3618              if(pbstrHelpString)
3619                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
3620             if(pdwHelpStringContext)
3621                 *pdwHelpStringContext=pFDesc->HelpStringContext;
3622             if(pbstrHelpStringDll)
3623                 *pbstrHelpStringDll=
3624                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3625         return S_OK;
3626     }
3627     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
3628         if(pVDesc->vardesc.memid==memid){
3629              if(pbstrHelpString)
3630                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
3631             if(pdwHelpStringContext)
3632                 *pdwHelpStringContext=pVDesc->HelpStringContext;
3633             if(pbstrHelpStringDll)
3634                 *pbstrHelpStringDll=
3635                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3636             return S_OK;
3637         }
3638     }
3639     return TYPE_E_ELEMENTNOTFOUND;
3640 }
3641
3642 /* ITypeInfo2::GetAllCustData
3643  *
3644  * Gets all custom data items for the Type info. 
3645  *
3646  */
3647 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
3648         ITypeInfo2 * iface,
3649         CUSTDATA *pCustData)
3650 {
3651     ICOM_THIS( ITypeInfoImpl, iface);
3652     TLBCustData *pCData;
3653     int i;
3654
3655     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
3656
3657     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3658     if(pCustData->prgCustData ){
3659         pCustData->cCustData=This->ctCustData;
3660         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3661             pCustData->prgCustData[i].guid=pCData->guid;
3662             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3663         }
3664     }else{
3665         ERR(" OUT OF MEMORY! \n");
3666         return E_OUTOFMEMORY;
3667     }
3668     return S_OK;
3669 }
3670
3671 /* ITypeInfo2::GetAllFuncCustData
3672  *
3673  * Gets all custom data items for the specified Function
3674  *
3675  */
3676 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
3677         ITypeInfo2 * iface,
3678         UINT index,
3679         CUSTDATA *pCustData)
3680 {
3681     ICOM_THIS( ITypeInfoImpl, iface);
3682     TLBCustData *pCData;
3683     TLBFuncDesc * pFDesc; 
3684     int i;
3685     TRACE("(%p) index %d\n", This, index); 
3686     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3687             pFDesc=pFDesc->next)
3688         ;
3689     if(pFDesc){
3690         pCustData->prgCustData =
3691             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
3692         if(pCustData->prgCustData ){
3693             pCustData->cCustData=pFDesc->ctCustData;
3694             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
3695                     pCData = pCData->next){
3696                 pCustData->prgCustData[i].guid=pCData->guid;
3697                 VariantCopy(& pCustData->prgCustData[i].varValue,
3698                         & pCData->data);
3699             }
3700         }else{
3701             ERR(" OUT OF MEMORY! \n");
3702             return E_OUTOFMEMORY;
3703         }
3704         return S_OK;
3705     }
3706     return TYPE_E_ELEMENTNOTFOUND;
3707 }
3708
3709 /* ITypeInfo2::GetAllParamCustData
3710  *
3711  * Gets all custom data items for the Functions
3712  *
3713  */
3714 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
3715     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
3716 {
3717     ICOM_THIS( ITypeInfoImpl, iface);
3718     TLBCustData *pCData=NULL;
3719     TLBFuncDesc * pFDesc; 
3720     int i;
3721     TRACE("(%p) index %d\n", This, indexFunc); 
3722     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
3723             pFDesc=pFDesc->next)
3724         ;
3725     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
3726         pCustData->prgCustData = 
3727             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
3728                     sizeof(CUSTDATAITEM));
3729         if(pCustData->prgCustData ){
3730             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
3731             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
3732                     pCData; i++, pCData = pCData->next){
3733                 pCustData->prgCustData[i].guid=pCData->guid;
3734                 VariantCopy(& pCustData->prgCustData[i].varValue,
3735                         & pCData->data);
3736             }
3737         }else{
3738             ERR(" OUT OF MEMORY! \n");
3739             return E_OUTOFMEMORY;
3740         }
3741         return S_OK;
3742     }
3743     return TYPE_E_ELEMENTNOTFOUND;
3744 }
3745
3746 /* ITypeInfo2::GetAllVarCustData
3747  *
3748  * Gets all custom data items for the specified Variable
3749  *
3750  */
3751 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
3752     UINT index, CUSTDATA *pCustData)
3753 {
3754     ICOM_THIS( ITypeInfoImpl, iface);
3755     TLBCustData *pCData;
3756     TLBVarDesc * pVDesc; 
3757     int i;
3758     TRACE("(%p) index %d\n", This, index); 
3759     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
3760             pVDesc=pVDesc->next)
3761         ;
3762     if(pVDesc){
3763         pCustData->prgCustData =
3764             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
3765         if(pCustData->prgCustData ){
3766             pCustData->cCustData=pVDesc->ctCustData;
3767             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
3768                     pCData = pCData->next){
3769                 pCustData->prgCustData[i].guid=pCData->guid;
3770                 VariantCopy(& pCustData->prgCustData[i].varValue,
3771                         & pCData->data);
3772             }
3773         }else{
3774             ERR(" OUT OF MEMORY! \n");
3775             return E_OUTOFMEMORY;
3776         }
3777         return S_OK;
3778     }
3779     return TYPE_E_ELEMENTNOTFOUND;
3780 }
3781
3782 /* ITypeInfo2::GetAllImplCustData
3783  *
3784  * Gets all custom data items for the specified implementation type
3785  *
3786  */
3787 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
3788         ITypeInfo2 * iface,
3789         UINT index,
3790         CUSTDATA *pCustData)
3791 {
3792     ICOM_THIS( ITypeInfoImpl, iface);
3793     TLBCustData *pCData;
3794     TLBRefType * pRDesc; 
3795     int i;
3796     TRACE("(%p) index %d\n", This, index); 
3797     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
3798             pRDesc=pRDesc->next)
3799         ;
3800     if(pRDesc){
3801         pCustData->prgCustData =
3802             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
3803         if(pCustData->prgCustData ){
3804             pCustData->cCustData=pRDesc->ctCustData;
3805             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
3806                     pCData = pCData->next){
3807                 pCustData->prgCustData[i].guid=pCData->guid;
3808                 VariantCopy(& pCustData->prgCustData[i].varValue,
3809                         & pCData->data);
3810             }
3811         }else{
3812             ERR(" OUT OF MEMORY! \n");
3813             return E_OUTOFMEMORY;
3814         }
3815         return S_OK;
3816     }
3817     return TYPE_E_ELEMENTNOTFOUND;
3818 }
3819
3820 static ICOM_VTABLE(ITypeInfo2) tinfvt = 
3821 {
3822     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3823
3824     ITypeInfo_fnQueryInterface,
3825     ITypeInfo_fnAddRef,
3826     ITypeInfo_fnRelease,
3827
3828     ITypeInfo_fnGetTypeAttr,
3829     ITypeInfo_fnGetTypeComp,
3830     ITypeInfo_fnGetFuncDesc,
3831     ITypeInfo_fnGetVarDesc,
3832     ITypeInfo_fnGetNames,
3833     ITypeInfo_fnGetRefTypeOfImplType,
3834     ITypeInfo_fnGetImplTypeFlags,
3835     ITypeInfo_fnGetIDsOfNames,
3836     ITypeInfo_fnInvoke,
3837     ITypeInfo_fnGetDocumentation,
3838     ITypeInfo_fnGetDllEntry,
3839     ITypeInfo_fnGetRefTypeInfo,
3840     ITypeInfo_fnAddressOfMember,
3841     ITypeInfo_fnCreateInstance,
3842     ITypeInfo_fnGetMops,
3843     ITypeInfo_fnGetContainingTypeLib,
3844     ITypeInfo_fnReleaseTypeAttr,
3845     ITypeInfo_fnReleaseFuncDesc,
3846     ITypeInfo_fnReleaseVarDesc,
3847
3848     ITypeInfo2_fnGetTypeKind,
3849     ITypeInfo2_fnGetTypeFlags,
3850     ITypeInfo2_fnGetFuncIndexOfMemId,
3851     ITypeInfo2_fnGetVarIndexOfMemId,
3852     ITypeInfo2_fnGetCustData,
3853     ITypeInfo2_fnGetFuncCustData,
3854     ITypeInfo2_fnGetParamCustData,
3855     ITypeInfo2_fnGetVarCustData,
3856     ITypeInfo2_fnGetImplTypeCustData,
3857     ITypeInfo2_fnGetDocumentation2,
3858     ITypeInfo2_fnGetAllCustData,
3859     ITypeInfo2_fnGetAllFuncCustData,
3860     ITypeInfo2_fnGetAllParamCustData,
3861     ITypeInfo2_fnGetAllVarCustData,
3862     ITypeInfo2_fnGetAllImplTypeCustData,
3863 };