Get rid of the non-standard ICOM_THIS macro.
[wine] / dlls / oleaut32 / typelib.c
1 /*
2  *      TYPELIB
3  *
4  *      Copyright 1997  Marcus Meissner
5  *                    1999  Rein Klazes
6  *                    2000  Francois Jacques
7  *                    2001  Huw D M Davies for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * --------------------------------------------------------------------------------------
24  * Known problems (2000, Francois Jacques)
25  *
26  * - Tested using OLEVIEW (Platform SDK tool) only.
27  *
28  * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29  *   creating by doing a straight copy of the dispinterface instance and just changing
30  *   its typekind. Pointed structures aren't copied - only the address of the pointers.
31  *   So when you release the dispinterface, you delete the vtable-interface structures
32  *   as well... fortunately, clean up of structures is not implemented.
33  *
34  * - locale stuff is partially implemented but hasn't been tested.
35  *
36  * - typelib file is still read in its entirety, but it is released now.
37  * - some garbage is read from function names on some very rare occasions.
38  *
39  * --------------------------------------------------------------------------------------
40  *  Known problems left from previous implementation (1999, Rein Klazes) :
41  *
42  * -. Data structures are straightforward, but slow for look-ups.
43  * -. (related) nothing is hashed
44  * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45  *      of them I don't know yet how to implement them.
46  * -. Most error return values are just guessed not checked with windows
47  *      behaviour.
48  * -. didn't bother with a c++ interface
49  * -. lousy fatal error handling
50  * -. some methods just return pointers to internal data structures, this is
51  *      partly laziness, partly I want to check how windows does it.
52  *
53  */
54
55 #include "config.h"
56 #include "wine/port.h"
57
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <ctype.h>
63
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
66 #include "winerror.h"
67 #include "windef.h"
68 #include "winbase.h"
69 #include "winnls.h"
70 #include "winreg.h"
71 #include "winuser.h"
72
73 #include "wine/unicode.h"
74 #include "objbase.h"
75 #include "heap.h"
76 #include "ole2disp.h"
77 #include "typelib.h"
78 #include "wine/debug.h"
79 #include "variant.h"
80
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
83
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
86
87 /****************************************************************************
88  *              FromLExxx
89  *
90  * Takes p_iVal (which is in little endian) and returns it
91  *   in the host machine's byte order.
92  */
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
95 {
96   return (((p_iVal & 0x00FF) << 8) |
97           ((p_iVal & 0xFF00) >> 8));
98 }
99
100
101 static DWORD FromLEDWord(DWORD p_iVal)
102 {
103   return (((p_iVal & 0x000000FF) << 24) |
104           ((p_iVal & 0x0000FF00) <<  8) |
105           ((p_iVal & 0x00FF0000) >>  8) |
106           ((p_iVal & 0xFF000000) >> 24));
107 }
108 #else
109 #define FromLEWord(X)  (X)
110 #define FromLEDWord(X) (X)
111 #endif
112
113
114 /****************************************************************************
115  *              FromLExxx
116  *
117  * Fix byte order in any structure if necessary
118  */
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
121 {
122   WORD *Val = p_Val;
123
124   p_iSize /= sizeof(WORD);
125
126   while (p_iSize) {
127     *Val = FromLEWord(*Val);
128     Val++;
129     p_iSize--;
130   }
131 }
132
133
134 static void FromLEDWords(void *p_Val, int p_iSize)
135 {
136   DWORD *Val = p_Val;
137
138   p_iSize /= sizeof(DWORD);
139
140   while (p_iSize) {
141     *Val = FromLEDWord(*Val);
142     Val++;
143     p_iSize--;
144   }
145 }
146 #else
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
149 #endif
150
151
152 /****************************************************************************
153  *              QueryPathOfRegTypeLib   [OLEAUT32.164]
154  * RETURNS
155  *      path of typelib
156  */
157 HRESULT WINAPI
158 QueryPathOfRegTypeLib(
159         REFGUID guid,   /* [in] referenced guid */
160         WORD wMaj,      /* [in] major version */
161         WORD wMin,      /* [in] minor version */
162         LCID lcid,      /* [in] locale id */
163         LPBSTR path )   /* [out] path of typelib */
164 {
165     /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166        string termination character on output strings */
167
168     HRESULT hr        = E_FAIL;
169
170     LCID    myLCID    = lcid;
171
172     char    szXGUID[80];
173     char    szTypeLibKey[100];
174     char    szPath[MAX_PATH];
175     DWORD   dwPathLen = sizeof(szPath);
176
177     if ( !HIWORD(guid) )
178     {
179         sprintf(szXGUID,
180             "<guid 0x%08lx>",
181             (DWORD) guid);
182
183         FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
184         return E_FAIL;
185     }
186
187     while (hr != S_OK)
188     {
189         sprintf(szTypeLibKey,
190             "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191             guid->Data1,    guid->Data2,    guid->Data3,
192             guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
193             guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
194             wMaj,
195             wMin,
196             myLCID);
197
198         if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
199         {
200             if (!lcid)
201                 break;
202             else if (myLCID == lcid)
203             {
204                 /* try with sub-langid */
205                 myLCID = SUBLANGID(lcid);
206             }
207             else if ((myLCID == SUBLANGID(lcid)) && myLCID)
208             {
209                 /* try with system langid */
210                 myLCID = 0;
211             }
212             else
213             {
214                 break;
215             }
216         }
217         else
218         {
219             DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
220             BSTR bstrPath = SysAllocStringLen(NULL,len);
221
222             MultiByteToWideChar(CP_ACP,
223                                 MB_PRECOMPOSED,
224                                 szPath,
225                                 dwPathLen,
226                                 bstrPath,
227                                 len);
228            *path = bstrPath;
229            hr = S_OK;
230         }
231     }
232
233     if (hr != S_OK)
234                 TRACE_(typelib)("%s not found\n", szTypeLibKey);
235
236     return hr;
237 }
238
239 /******************************************************************************
240  * CreateTypeLib [OLEAUT32.160]  creates a typelib
241  *
242  * RETURNS
243  *    Success: S_OK
244  *    Failure: Status
245  */
246 HRESULT WINAPI CreateTypeLib(
247         SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
248 ) {
249     FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
250     return E_FAIL;
251 }
252 /******************************************************************************
253  *              LoadTypeLib     [OLEAUT32.161]
254  * Loads and registers a type library
255  * NOTES
256  *    Docs: OLECHAR FAR* szFile
257  *    Docs: iTypeLib FAR* FAR* pptLib
258  *
259  * RETURNS
260  *    Success: S_OK
261  *    Failure: Status
262  */
263 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
264
265 HRESULT WINAPI LoadTypeLib(
266     const OLECHAR *szFile,/* [in] Name of file to load from */
267     ITypeLib * *pptLib)   /* [out] Pointer to pointer to loaded type library */
268 {
269     TRACE("\n");
270     return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
271 }
272
273 /******************************************************************************
274  *              LoadTypeLibEx   [OLEAUT32.183]
275  * Loads and optionally registers a type library
276  *
277  * RETURNS
278  *    Success: S_OK
279  *    Failure: Status
280  */
281 HRESULT WINAPI LoadTypeLibEx(
282     LPCOLESTR szFile,  /* [in] Name of file to load from */
283     REGKIND  regkind,  /* [in] Specify kind of registration */
284     ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
285 {
286     WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
287     WCHAR *pIndexStr;
288     HRESULT res;
289     INT index = 1;
290
291     TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
292
293     *pptLib = NULL;
294     if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
295                     NULL)) {
296
297         /* Look for a trailing '\\' followed by an index */
298         pIndexStr = strrchrW(szFile, '\\');
299         if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
300             index = atoiW(pIndexStr);
301             memcpy(szFileCopy, szFile,
302                    (pIndexStr - szFile - 1) * sizeof(WCHAR));
303             szFileCopy[pIndexStr - szFile - 1] = '\0';
304             if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
305                             szPath,NULL))
306                 return TYPE_E_CANTLOADLIBRARY;
307             if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
308                 return TYPE_E_CANTLOADLIBRARY;
309         } else {
310             WCHAR tstpath[260];
311             static const WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
312             int i;
313
314             lstrcpyW(tstpath,szFile);
315             CharLowerW(tstpath);
316             for (i=0;i<strlenW(tstpath);i++) {
317                 if (tstpath[i] == 's') {
318                     if (!strcmpW(tstpath+i,stdole32tlb)) {
319                         MESSAGE("\n");
320                         MESSAGE("**************************************************************************\n");
321                         MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322                         MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323                         MESSAGE("on the Microsoft Download Pages.\n");
324                         MESSAGE("**************************************************************************\n");
325                         break;
326                     }
327                 }
328             }
329             FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
330             return TYPE_E_CANTLOADLIBRARY;
331         }
332     }
333
334     TRACE("File %s index %d\n", debugstr_w(szPath), index);
335
336     res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
337
338     if (SUCCEEDED(res))
339         switch(regkind)
340         {
341             case REGKIND_DEFAULT:
342                 /* don't register typelibs supplied with full path. Experimentation confirms the following */
343                 if ((!szFile) ||
344                     ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
345                     (szFile[0] && (szFile[1] == ':'))) break;
346                 /* else fall-through */
347
348             case REGKIND_REGISTER:
349                 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
350                 {
351                     IUnknown_Release(*pptLib);
352                     *pptLib = 0;
353                 }
354                 break;
355             case REGKIND_NONE:
356                 break;
357         }
358
359     TRACE(" returns %08lx\n",res);
360     return res;
361 }
362
363 /******************************************************************************
364  *              LoadRegTypeLib  [OLEAUT32.162]
365  */
366 HRESULT WINAPI LoadRegTypeLib(
367         REFGUID rguid,          /* [in] referenced guid */
368         WORD wVerMajor,         /* [in] major version */
369         WORD wVerMinor,         /* [in] minor version */
370         LCID lcid,              /* [in] locale id */
371         ITypeLib **ppTLib)      /* [out] path of typelib */
372 {
373     BSTR bstr=NULL;
374     HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
375
376     if(SUCCEEDED(res))
377     {
378         res= LoadTypeLib(bstr, ppTLib);
379         SysFreeString(bstr);
380     }
381
382     TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
383
384     return res;
385 }
386
387
388 /******************************************************************************
389  *              RegisterTypeLib [OLEAUT32.163]
390  * Adds information about a type library to the System Registry
391  * NOTES
392  *    Docs: ITypeLib FAR * ptlib
393  *    Docs: OLECHAR FAR* szFullPath
394  *    Docs: OLECHAR FAR* szHelpDir
395  *
396  * RETURNS
397  *    Success: S_OK
398  *    Failure: Status
399  */
400 HRESULT WINAPI RegisterTypeLib(
401      ITypeLib * ptlib,     /* [in] Pointer to the library*/
402      OLECHAR * szFullPath, /* [in] full Path of the library*/
403      OLECHAR * szHelpDir)  /* [in] dir to the helpfile for the library,
404                                                          may be NULL*/
405 {
406     HRESULT res;
407     TLIBATTR *attr;
408     OLECHAR guid[80];
409     LPSTR guidA;
410     CHAR keyName[120];
411     CHAR tmp[MAX_PATH];
412     HKEY key, subKey;
413     UINT types, tidx;
414     TYPEKIND kind;
415     DWORD disposition;
416     static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
417
418     if (ptlib == NULL || szFullPath == NULL)
419         return E_INVALIDARG;
420
421     if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
422         return E_FAIL;
423
424     StringFromGUID2(&attr->guid, guid, 80);
425     guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
426     snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
427         guidA, attr->wMajorVerNum, attr->wMinorVerNum);
428     HeapFree(GetProcessHeap(), 0, guidA);
429
430     res = S_OK;
431     if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
432         KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
433     {
434         LPOLESTR doc;
435
436         /* Set the human-readable name of the typelib */
437         if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
438         {
439             if (RegSetValueExW(key, NULL, 0, REG_SZ,
440                 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
441                 res = E_FAIL;
442
443             SysFreeString(doc);
444         }
445         else
446             res = E_FAIL;
447
448         /* Make up the name of the typelib path subkey */
449         sprintf(tmp, "%lu\\", attr->lcid);
450         switch(attr->syskind) {
451         case SYS_WIN16:
452             strcat(tmp, "win16");
453             break;
454
455         case SYS_WIN32:
456             strcat(tmp, "win32");
457             break;
458
459         default:
460             TRACE("Typelib is for unsupported syskind %i\n", attr->syskind);
461             res = E_FAIL;
462             break;
463         }
464
465         /* Create the typelib path subkey */
466         if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0,
467             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
468         {
469             if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
470                 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
471                 res = E_FAIL;
472
473             RegCloseKey(subKey);
474         }
475         else
476             res = E_FAIL;
477
478         /* Create the flags subkey */
479         if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
480             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
481         {
482             CHAR buf[20];
483             /* FIXME: is %u correct? */
484             snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
485             if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
486                 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
487                 res = E_FAIL;
488
489             RegCloseKey(subKey);
490         }
491         else
492             res = E_FAIL;
493
494         /* create the helpdir subkey */
495         if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0,
496             KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
497         {
498             BOOL freeHelpDir = FALSE;
499             OLECHAR* pIndexStr;
500
501             /* if we created a new key, and helpDir was null, set the helpdir
502                to the directory which contains the typelib. However,
503                if we just opened an existing key, we leave the helpdir alone */
504             if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
505                 szHelpDir = SysAllocString(szFullPath);
506                 pIndexStr = strrchrW(szHelpDir, '\\');
507                 if (pIndexStr) {
508                     *pIndexStr = 0;
509                 }
510                 freeHelpDir = TRUE;
511             }
512
513             /* if we have an szHelpDir, set it! */
514             if (szHelpDir != NULL) {
515                 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
516                     (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
517                     res = E_FAIL;
518                 }
519             }
520
521             /* tidy up */
522             if (freeHelpDir) SysFreeString(szHelpDir);
523             RegCloseKey(subKey);
524
525         } else {
526             res = E_FAIL;
527         }
528
529         RegCloseKey(key);
530     }
531     else
532         res = E_FAIL;
533
534     /* register OLE Automation-compatible interfaces for this typelib */
535     types = ITypeLib_GetTypeInfoCount(ptlib);
536     for (tidx=0; tidx<types; tidx++) {
537         if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
538             LPOLESTR name = NULL;
539             ITypeInfo *tinfo = NULL;
540
541             ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
542
543             switch (kind) {
544             case TKIND_INTERFACE:
545                 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
546                 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
547                 break;
548
549             case TKIND_DISPATCH:
550                 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
551                 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
552                 break;
553
554             default:
555                 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
556                 break;
557             }
558
559             if (tinfo) {
560                 TYPEATTR *tattr = NULL;
561                 ITypeInfo_GetTypeAttr(tinfo, &tattr);
562
563                 if (tattr) {
564                     TRACE_(typelib)("guid=%s, flags=%04x (",
565                                     debugstr_guid(&tattr->guid),
566                                     tattr->wTypeFlags);
567
568                     if (TRACE_ON(typelib)) {
569 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
570                         XX(FAPPOBJECT);
571                         XX(FCANCREATE);
572                         XX(FLICENSED);
573                         XX(FPREDECLID);
574                         XX(FHIDDEN);
575                         XX(FCONTROL);
576                         XX(FDUAL);
577                         XX(FNONEXTENSIBLE);
578                         XX(FOLEAUTOMATION);
579                         XX(FRESTRICTED);
580                         XX(FAGGREGATABLE);
581                         XX(FREPLACEABLE);
582                         XX(FDISPATCHABLE);
583                         XX(FREVERSEBIND);
584                         XX(FPROXY);
585 #undef XX
586                         MESSAGE("\n");
587                     }
588
589                     /*
590                      * FIXME: The 1 is just here until we implement rpcrt4
591                      *        stub/proxy handling. Until then it helps IShield
592                      *        v6 to work.
593                      */
594                     if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
595                     {
596                         if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
597                             FIXME("Registering non-oleautomation interface!\n");
598                         }
599
600                         /* register interface<->typelib coupling */
601                         StringFromGUID2(&tattr->guid, guid, 80);
602                         guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
603                         snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
604                         HeapFree(GetProcessHeap(), 0, guidA);
605
606                         if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
607                                             KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
608                             if (name)
609                                 RegSetValueExW(key, NULL, 0, REG_SZ,
610                                                (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
611
612                             if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
613                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
614                                 RegSetValueExA(subKey, NULL, 0, REG_SZ,
615                                                PSOA, strlen(PSOA));
616                                 RegCloseKey(subKey);
617                             }
618
619                             if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
620                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
621                                 RegSetValueExA(subKey, NULL, 0, REG_SZ,
622                                                PSOA, strlen(PSOA));
623                                 RegCloseKey(subKey);
624                             }
625
626                             if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
627                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
628                                 CHAR ver[32];
629                                 StringFromGUID2(&attr->guid, guid, 80);
630                                 snprintf(ver, sizeof(ver), "%x.%x",
631                                          attr->wMajorVerNum, attr->wMinorVerNum);
632                                 RegSetValueExW(subKey, NULL, 0, REG_SZ,
633                                                (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
634                                 RegSetValueExA(subKey, "Version", 0, REG_SZ,
635                                                ver, lstrlenA(ver));
636                                 RegCloseKey(subKey);
637                             }
638
639                             RegCloseKey(key);
640                         }
641                     }
642
643                     ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
644                 }
645
646                 ITypeInfo_Release(tinfo);
647             }
648
649             SysFreeString(name);
650         }
651     }
652
653     ITypeLib_ReleaseTLibAttr(ptlib, attr);
654
655     return res;
656 }
657
658
659 /******************************************************************************
660  *      UnRegisterTypeLib       [OLEAUT32.186]
661  * Removes information about a type library from the System Registry
662  * NOTES
663  *
664  * RETURNS
665  *    Success: S_OK
666  *    Failure: Status
667  */
668 HRESULT WINAPI UnRegisterTypeLib(
669     REFGUID libid,      /* [in] Guid of the library */
670         WORD wVerMajor, /* [in] major version */
671         WORD wVerMinor, /* [in] minor version */
672         LCID lcid,      /* [in] locale id */
673         SYSKIND syskind)
674 {
675     BSTR tlibPath = NULL;
676     DWORD tmpLength;
677     CHAR keyName[MAX_PATH];
678     CHAR* syskindName;
679     CHAR subKeyName[MAX_PATH];
680     LPSTR guidA;
681     int result = S_OK;
682     DWORD i = 0;
683     OLECHAR guid[80];
684     BOOL deleteOtherStuff;
685     HKEY key = NULL;
686     HKEY subKey = NULL;
687     TYPEATTR* typeAttr = NULL;
688     TYPEKIND kind;
689     ITypeInfo* typeInfo = NULL;
690     ITypeLib* typeLib = NULL;
691     int numTypes;
692
693     TRACE("(IID: %s): stub\n",debugstr_guid(libid));
694
695     /* Create the path to the key */
696     StringFromGUID2(libid, guid, 80);
697     guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
698     snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
699         guidA, wVerMajor, wVerMinor);
700     HeapFree(GetProcessHeap(), 0, guidA);
701
702     /* Work out the syskind name */
703     switch(syskind) {
704     case SYS_WIN16:
705         syskindName = "win16";
706         break;
707
708     case SYS_WIN32:
709         syskindName = "win32";
710         break;
711
712     default:
713         TRACE("Unsupported syskind %i\n", syskind);
714         result = E_INVALIDARG;
715         goto end;
716     }
717
718     /* get the path to the typelib on disk */
719     if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
720         result = E_INVALIDARG;
721         goto end;
722     }
723
724     /* Try and open the key to the type library. */
725     if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
726         result = E_INVALIDARG;
727         goto end;
728     }
729
730     /* Try and load the type library */
731     if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
732         result = TYPE_E_INVALIDSTATE;
733         goto end;
734     }
735
736     /* remove any types registered with this typelib */
737     numTypes = ITypeLib_GetTypeInfoCount(typeLib);
738     for (i=0; i<numTypes; i++) {
739         /* get the kind of type */
740         if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
741             goto enddeleteloop;
742         }
743
744         /* skip non-interfaces, and get type info for the type */
745         if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
746             goto enddeleteloop;
747         }
748         if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
749             goto enddeleteloop;
750         }
751         if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
752             goto enddeleteloop;
753         }
754
755         /* the path to the type */
756         StringFromGUID2(&typeAttr->guid, guid, 80);
757         guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
758         snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA);
759         HeapFree(GetProcessHeap(), 0, guidA);
760
761         /* Delete its bits */
762         if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
763             goto enddeleteloop;
764         }
765         RegDeleteKeyA(subKey, "ProxyStubClsid");
766         RegDeleteKeyA(subKey, "ProxyStubClsid32");
767         RegDeleteKeyA(subKey, "TypeLib");
768         RegCloseKey(subKey);
769         subKey = NULL;
770         RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName);
771
772 enddeleteloop:
773         if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
774         typeAttr = NULL;
775         if (typeInfo) ITypeInfo_Release(typeInfo);
776         typeInfo = NULL;
777     }
778
779     /* Now, delete the type library path subkey */
780     sprintf(subKeyName, "%lu\\%s", lcid, syskindName);
781     RegDeleteKeyA(key, subKeyName);
782     sprintf(subKeyName, "%lu", lcid);
783     RegDeleteKeyA(key, subKeyName);
784
785     /* check if there is anything besides the FLAGS/HELPDIR keys.
786        If there is, we don't delete them */
787     tmpLength = sizeof(subKeyName);
788     deleteOtherStuff = TRUE;
789     i = 0;
790     while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
791         tmpLength = sizeof(subKeyName);
792
793         /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
794         if (!strcmp(subKeyName, "FLAGS")) continue;
795         if (!strcmp(subKeyName, "HELPDIR")) continue;
796         deleteOtherStuff = FALSE;
797         break;
798     }
799
800     /* only delete the other parts of the key if we're absolutely sure */
801     if (deleteOtherStuff) {
802         RegDeleteKeyA(key, "FLAGS");
803         RegDeleteKeyA(key, "HELPDIR");
804         RegCloseKey(key);
805         key = NULL;
806
807         StringFromGUID2(libid, guid, 80);
808         guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
809         sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor);
810         RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
811         sprintf(keyName, "TypeLib\\%s", guidA);
812         RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
813         HeapFree(GetProcessHeap(), 0, guidA);
814     }
815
816 end:
817     if (tlibPath) SysFreeString(tlibPath);
818     if (typeLib) ITypeLib_Release(typeLib);
819     if (subKey) RegCloseKey(subKey);
820     if (key) RegCloseKey(key);
821     return result;
822 }
823
824 /*======================= ITypeLib implementation =======================*/
825
826 typedef struct tagTLBCustData
827 {
828     GUID guid;
829     VARIANT data;
830     struct tagTLBCustData* next;
831 } TLBCustData;
832
833 /* data structure for import typelibs */
834 typedef struct tagTLBImpLib
835 {
836     int offset;                 /* offset in the file (MSFT)
837                                    offset in nametable (SLTG)
838                                    just used to identify library while reading
839                                    data from file */
840     GUID guid;                  /* libid */
841     BSTR name;                  /* name */
842
843     LCID lcid;                  /* lcid of imported typelib */
844
845     WORD wVersionMajor;         /* major version number */
846     WORD wVersionMinor;         /* minor version number */
847
848     struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
849                                             NULL if not yet loaded */
850     struct tagTLBImpLib * next;
851 } TLBImpLib;
852
853 /* internal ITypeLib data */
854 typedef struct tagITypeLibImpl
855 {
856     ITypeLib2Vtbl *lpVtbl;
857     ITypeCompVtbl *lpVtblTypeComp;
858     UINT ref;
859     TLIBATTR LibAttr;            /* guid,lcid,syskind,version,flags */
860
861     /* strings can be stored in tlb as multibyte strings BUT they are *always*
862      * exported to the application as a UNICODE string.
863      */
864     BSTR Name;
865     BSTR DocString;
866     BSTR HelpFile;
867     BSTR HelpStringDll;
868     unsigned long  dwHelpContext;
869     int TypeInfoCount;          /* nr of typeinfo's in librarry */
870     struct tagITypeInfoImpl *pTypeInfo;   /* linked list of type info data */
871     int ctCustData;             /* number of items in cust data list */
872     TLBCustData * pCustData;    /* linked list to cust data */
873     TLBImpLib   * pImpLibs;     /* linked list to all imported typelibs */
874     TYPEDESC * pTypeDesc;       /* array of TypeDescriptions found in the
875                                    libary. Only used while read MSFT
876                                    typelibs */
877
878     /* typelibs are cached, keyed by path, so store the linked list info within them */
879     struct tagITypeLibImpl *next, *prev;
880     WCHAR *path;
881 } ITypeLibImpl;
882
883 static struct ITypeLib2Vtbl tlbvt;
884 static struct ITypeCompVtbl tlbtcvt;
885
886 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
887 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
888
889 /* ITypeLib methods */
890 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
891 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
892
893 /*======================= ITypeInfo implementation =======================*/
894
895 /* data for refernced types */
896 typedef struct tagTLBRefType
897 {
898     INT index;              /* Type index for internal ref or for external ref
899                                it the format is SLTG.  -2 indicates to
900                                use guid */
901
902     GUID guid;              /* guid of the referenced type */
903                             /* if index == TLB_REF_USE_GUID */
904
905     HREFTYPE reference;     /* The href of this ref */
906     TLBImpLib *pImpTLInfo;  /* If ref is external ptr to library data
907                                TLB_REF_INTERNAL for internal refs
908                                TLB_REF_NOT_FOUND for broken refs */
909
910     struct tagTLBRefType * next;
911 } TLBRefType;
912
913 #define TLB_REF_USE_GUID -2
914
915 #define TLB_REF_INTERNAL (void*)-2
916 #define TLB_REF_NOT_FOUND (void*)-1
917
918 /* internal Parameter data */
919 typedef struct tagTLBParDesc
920 {
921     BSTR Name;
922     int ctCustData;
923     TLBCustData * pCustData;        /* linked list to cust data */
924 } TLBParDesc;
925
926 /* internal Function data */
927 typedef struct tagTLBFuncDesc
928 {
929     FUNCDESC funcdesc;      /* lots of info on the function and its attributes. */
930     BSTR Name;             /* the name of this function */
931     TLBParDesc *pParamDesc; /* array with param names and custom data */
932     int helpcontext;
933     int HelpStringContext;
934     BSTR HelpString;
935     BSTR Entry;            /* if its Hiword==0, it numeric; -1 is not present*/
936     int ctCustData;
937     TLBCustData * pCustData;        /* linked list to cust data; */
938     struct tagTLBFuncDesc * next;
939 } TLBFuncDesc;
940
941 /* internal Variable data */
942 typedef struct tagTLBVarDesc
943 {
944     VARDESC vardesc;        /* lots of info on the variable and its attributes. */
945     BSTR Name;             /* the name of this variable */
946     int HelpContext;
947     int HelpStringContext;  /* FIXME: where? */
948     BSTR HelpString;
949     int ctCustData;
950     TLBCustData * pCustData;/* linked list to cust data; */
951     struct tagTLBVarDesc * next;
952 } TLBVarDesc;
953
954 /* internal implemented interface data */
955 typedef struct tagTLBImplType
956 {
957     HREFTYPE hRef;          /* hRef of interface */
958     int implflags;          /* IMPLFLAG_*s */
959     int ctCustData;
960     TLBCustData * pCustData;/* linked list to custom data; */
961     struct tagTLBImplType *next;
962 } TLBImplType;
963
964 /* internal TypeInfo data */
965 typedef struct tagITypeInfoImpl
966 {
967     ITypeInfo2Vtbl *lpVtbl;
968     ITypeCompVtbl  *lpVtblTypeComp;
969     UINT ref;
970     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
971     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
972     int index;                  /* index in this typelib; */
973     /* type libs seem to store the doc strings in ascii
974      * so why should we do it in unicode?
975      */
976     BSTR Name;
977     BSTR DocString;
978     unsigned long  dwHelpContext;
979     unsigned long  dwHelpStringContext;
980
981     /* functions  */
982     TLBFuncDesc * funclist;     /* linked list with function descriptions */
983
984     /* variables  */
985     TLBVarDesc * varlist;       /* linked list with variable descriptions */
986
987     /* Implemented Interfaces  */
988     TLBImplType * impltypelist;
989
990     TLBRefType * reflist;
991     int ctCustData;
992     TLBCustData * pCustData;        /* linked list to cust data; */
993     struct tagITypeInfoImpl * next;
994 } ITypeInfoImpl;
995
996 static struct ITypeInfo2Vtbl tinfvt;
997 static struct ITypeCompVtbl  tcompvt;
998
999 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
1000
1001 typedef struct tagTLBContext
1002 {
1003         unsigned int oStart;  /* start of TLB in file */
1004         unsigned int pos;     /* current pos */
1005         unsigned int length;  /* total length */
1006         void *mapping;        /* memory mapping */
1007         MSFT_SegDir * pTblDir;
1008         ITypeLibImpl* pLibInfo;
1009 } TLBContext;
1010
1011
1012 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1013
1014 /*
1015  debug
1016 */
1017 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1018     if (pTD->vt & VT_RESERVED)
1019         szVarType += strlen(strcpy(szVarType, "reserved | "));
1020     if (pTD->vt & VT_BYREF)
1021         szVarType += strlen(strcpy(szVarType, "ref to "));
1022     if (pTD->vt & VT_ARRAY)
1023         szVarType += strlen(strcpy(szVarType, "array of "));
1024     if (pTD->vt & VT_VECTOR)
1025         szVarType += strlen(strcpy(szVarType, "vector of "));
1026     switch(pTD->vt & VT_TYPEMASK) {
1027     case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1028     case VT_I2: sprintf(szVarType, "VT_I2"); break;
1029     case VT_I4: sprintf(szVarType, "VT_I4"); break;
1030     case VT_R4: sprintf(szVarType, "VT_R4"); break;
1031     case VT_R8: sprintf(szVarType, "VT_R8"); break;
1032     case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1033     case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1034     case VT_CY: sprintf(szVarType, "VT_CY"); break;
1035     case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1036     case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1037     case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1038     case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1039     case VT_I1: sprintf(szVarType, "VT_I1"); break;
1040     case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1041     case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1042     case VT_INT: sprintf(szVarType, "VT_INT"); break;
1043     case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1044     case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1045     case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1046     case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1047     case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1048                                  pTD->u.hreftype); break;
1049     case VT_PTR: sprintf(szVarType, "ptr to ");
1050       dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1051       break;
1052     case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1053       dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1054       break;
1055     case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1056                             pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1057       dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1058       break;
1059
1060     default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1061     }
1062 }
1063
1064 void dump_ELEMDESC(ELEMDESC *edesc) {
1065   char buf[200];
1066   dump_TypeDesc(&edesc->tdesc,buf);
1067   MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1068   MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1069   MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1070 }
1071 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1072   int i;
1073   MESSAGE("memid is %08lx\n",funcdesc->memid);
1074   for (i=0;i<funcdesc->cParams;i++) {
1075       MESSAGE("Param %d:\n",i);
1076       dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1077   }
1078   MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1079   switch (funcdesc->funckind) {
1080   case FUNC_VIRTUAL: MESSAGE("virtual");break;
1081   case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1082   case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1083   case FUNC_STATIC: MESSAGE("static");break;
1084   case FUNC_DISPATCH: MESSAGE("dispatch");break;
1085   default: MESSAGE("unknown");break;
1086   }
1087   MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1088   switch (funcdesc->invkind) {
1089   case INVOKE_FUNC: MESSAGE("func");break;
1090   case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1091   case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1092   case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1093   }
1094   MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1095   switch (funcdesc->callconv) {
1096   case CC_CDECL: MESSAGE("cdecl");break;
1097   case CC_PASCAL: MESSAGE("pascal");break;
1098   case CC_STDCALL: MESSAGE("stdcall");break;
1099   case CC_SYSCALL: MESSAGE("syscall");break;
1100   default:break;
1101   }
1102   MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1103   MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1104   MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1105
1106   MESSAGE("\telemdescFunc (return value type):\n");
1107   dump_ELEMDESC(&funcdesc->elemdescFunc);
1108 }
1109
1110 void dump_IDLDESC(IDLDESC *idl) {
1111   MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1112 }
1113
1114 static const char * typekind_desc[] =
1115 {
1116         "TKIND_ENUM",
1117         "TKIND_RECORD",
1118         "TKIND_MODULE",
1119         "TKIND_INTERFACE",
1120         "TKIND_DISPATCH",
1121         "TKIND_COCLASS",
1122         "TKIND_ALIAS",
1123         "TKIND_UNION",
1124         "TKIND_MAX"
1125 };
1126
1127 void dump_TYPEATTR(TYPEATTR *tattr) {
1128   char buf[200];
1129   MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1130   MESSAGE("\tlcid: %ld\n",tattr->lcid);
1131   MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1132   MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1133   MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1134   MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1135   MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1136   MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1137   MESSAGE("\tcVars: %d\n", tattr->cVars);
1138   MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1139   MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1140   MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1141   MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1142   MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1143   dump_TypeDesc(&tattr->tdescAlias,buf);
1144   MESSAGE("\ttypedesc: %s\n", buf);
1145   dump_IDLDESC(&tattr->idldescType);
1146 }
1147
1148 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1149 {
1150   int i;
1151   if (!TRACE_ON(typelib))
1152       return;
1153   MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1154   for (i=0;i<pfd->funcdesc.cParams;i++)
1155       MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1156
1157
1158   dump_FUNCDESC(&(pfd->funcdesc));
1159
1160   MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1161   MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1162 }
1163 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1164 {
1165         while (pfd)
1166         {
1167           dump_TLBFuncDescOne(pfd);
1168           pfd = pfd->next;
1169         };
1170 }
1171 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1172 {
1173         while (pvd)
1174         {
1175           TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1176           pvd = pvd->next;
1177         };
1178 }
1179
1180 static void dump_TLBImpLib(TLBImpLib *import)
1181 {
1182     TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1183                     debugstr_w(import->name));
1184     TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1185                     import->wVersionMinor, import->lcid, import->offset);
1186 }
1187
1188 static void dump_TLBRefType(TLBRefType * prt)
1189 {
1190         while (prt)
1191         {
1192           TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1193           if(prt->index == -1)
1194             TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1195           else
1196             TRACE_(typelib)("type no: %d\n", prt->index);
1197
1198           if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1199              prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1200               TRACE_(typelib)("in lib\n");
1201               dump_TLBImpLib(prt->pImpTLInfo);
1202           }
1203           prt = prt->next;
1204         };
1205 }
1206
1207 static void dump_TLBImplType(TLBImplType * impl)
1208 {
1209     while (impl) {
1210         TRACE_(typelib)(
1211                 "implementing/inheriting interface hRef = %lx implflags %x\n",
1212                 impl->hRef, impl->implflags);
1213         impl = impl->next;
1214     }
1215 }
1216
1217 void dump_Variant(VARIANT * pvar)
1218 {
1219     SYSTEMTIME st;
1220
1221     TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1222
1223     if (pvar)
1224     {
1225       if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1226           V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1227       {
1228         TRACE(",%p", V_BYREF(pvar));
1229       }
1230       else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1231       {
1232         TRACE(",FIXME");
1233       }
1234       else switch (V_TYPE(pvar))
1235       {
1236       case VT_I1:   TRACE(",%d", V_I1(pvar)); break;
1237       case VT_UI1:  TRACE(",%d", V_UI1(pvar)); break;
1238       case VT_I2:   TRACE(",%d", V_I2(pvar)); break;
1239       case VT_UI2:  TRACE(",%d", V_UI2(pvar)); break;
1240       case VT_INT:
1241       case VT_I4:   TRACE(",%ld", V_I4(pvar)); break;
1242       case VT_UINT:
1243       case VT_UI4:  TRACE(",%ld", V_UI4(pvar)); break;
1244       case VT_I8:   TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1245                           (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1246       case VT_UI8:  TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1247                           (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1248       case VT_R4:   TRACE(",%3.3e", V_R4(pvar)); break;
1249       case VT_R8:   TRACE(",%3.3e", V_R8(pvar)); break;
1250       case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1251       case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1252       case VT_CY:   TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1253                            V_CY(pvar).s.Lo); break;
1254       case VT_DATE:
1255         if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1256           TRACE(",<invalid>");
1257         else
1258           TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1259                 st.wHour, st.wMinute, st.wSecond);
1260         break;
1261       case VT_ERROR:
1262       case VT_VOID:
1263       case VT_USERDEFINED:
1264       case VT_EMPTY:
1265       case VT_NULL:  break;
1266       default:       TRACE(",?"); break;
1267       }
1268     }
1269     TRACE("}\n");
1270 }
1271
1272 static void dump_DispParms(DISPPARAMS * pdp)
1273 {
1274     int index = 0;
1275
1276     TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1277
1278     while (index < pdp->cArgs)
1279     {
1280         dump_Variant( &pdp->rgvarg[index] );
1281         ++index;
1282     }
1283 }
1284
1285 static void dump_TypeInfo(ITypeInfoImpl * pty)
1286 {
1287     TRACE("%p ref=%u\n", pty, pty->ref);
1288     TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1289     TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1290     TRACE("fct:%u var:%u impl:%u\n",
1291       pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1292     TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1293     TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1294     dump_TLBFuncDesc(pty->funclist);
1295     dump_TLBVarDesc(pty->varlist);
1296     dump_TLBImplType(pty->impltypelist);
1297 }
1298
1299 void dump_VARDESC(VARDESC *v)
1300 {
1301     MESSAGE("memid %ld\n",v->memid);
1302     MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1303     MESSAGE("oInst %ld\n",v->u.oInst);
1304     dump_ELEMDESC(&(v->elemdescVar));
1305     MESSAGE("wVarFlags %x\n",v->wVarFlags);
1306     MESSAGE("varkind %d\n",v->varkind);
1307 }
1308
1309 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1310 {
1311     /* VT_LPWSTR is largest type that */
1312     /* may appear in type description*/
1313     {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1314     {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1315     {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1316     {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1317     {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1318     {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1319     {{0},30},{{0},31}
1320 };
1321
1322 static void TLB_abort()
1323 {
1324     DebugBreak();
1325 }
1326 static void * TLB_Alloc(unsigned size)
1327 {
1328     void * ret;
1329     if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1330         /* FIXME */
1331         ERR("cannot allocate memory\n");
1332     }
1333     return ret;
1334 }
1335
1336 static void TLB_Free(void * ptr)
1337 {
1338     HeapFree(GetProcessHeap(), 0, ptr);
1339 }
1340
1341
1342 /**********************************************************************
1343  *
1344  *  Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1345  */
1346 /* read function */
1347 DWORD MSFT_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
1348 {
1349     TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1350        pcx->pos, count, pcx->oStart, pcx->length, where);
1351
1352     if (where != DO_NOT_SEEK)
1353     {
1354         where += pcx->oStart;
1355         if (where > pcx->length)
1356         {
1357             /* FIXME */
1358             ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1359             TLB_abort();
1360         }
1361         pcx->pos = where;
1362     }
1363     if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1364     memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1365     pcx->pos += count;
1366     return count;
1367 }
1368
1369 static DWORD MSFT_ReadLEDWords(void *buffer,  DWORD count, TLBContext *pcx,
1370                                long where )
1371 {
1372   DWORD ret;
1373
1374   ret = MSFT_Read(buffer, count, pcx, where);
1375   FromLEDWords(buffer, ret);
1376
1377   return ret;
1378 }
1379
1380 static DWORD MSFT_ReadLEWords(void *buffer,  DWORD count, TLBContext *pcx,
1381                               long where )
1382 {
1383   DWORD ret;
1384
1385   ret = MSFT_Read(buffer, count, pcx, where);
1386   FromLEWords(buffer, ret);
1387
1388   return ret;
1389 }
1390
1391 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1392 {
1393     if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1394         memset(pGuid,0, sizeof(GUID));
1395         return;
1396     }
1397     MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1398     pGuid->Data1 = FromLEDWord(pGuid->Data1);
1399     pGuid->Data2 = FromLEWord(pGuid->Data2);
1400     pGuid->Data3 = FromLEWord(pGuid->Data3);
1401     TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1402 }
1403
1404 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1405 {
1406     char * name;
1407     MSFT_NameIntro niName;
1408     int lengthInChars;
1409     WCHAR* pwstring = NULL;
1410     BSTR bstrName = NULL;
1411
1412     MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1413                       pcx->pTblDir->pNametab.offset+offset);
1414     niName.namelen &= 0xFF; /* FIXME: correct ? */
1415     name=TLB_Alloc((niName.namelen & 0xff) +1);
1416     MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1417     name[niName.namelen & 0xff]='\0';
1418
1419     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1420                                         name, -1, NULL, 0);
1421
1422     /* no invalid characters in string */
1423     if (lengthInChars)
1424     {
1425         pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1426
1427         /* don't check for invalid character since this has been done previously */
1428         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1429
1430         bstrName = SysAllocStringLen(pwstring, lengthInChars);
1431         lengthInChars = SysStringLen(bstrName);
1432         HeapFree(GetProcessHeap(), 0, pwstring);
1433     }
1434
1435     TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1436     return bstrName;
1437 }
1438
1439 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1440 {
1441     char * string;
1442     INT16 length;
1443     int lengthInChars;
1444     BSTR bstr = NULL;
1445
1446     if(offset<0) return NULL;
1447     MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1448     if(length <= 0) return 0;
1449     string=TLB_Alloc(length +1);
1450     MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1451     string[length]='\0';
1452
1453     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1454                                         string, -1, NULL, 0);
1455
1456     /* no invalid characters in string */
1457     if (lengthInChars)
1458     {
1459         WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1460
1461         /* don't check for invalid character since this has been done previously */
1462         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1463
1464         bstr = SysAllocStringLen(pwstring, lengthInChars);
1465         lengthInChars = SysStringLen(bstr);
1466         HeapFree(GetProcessHeap(), 0, pwstring);
1467     }
1468
1469     TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1470     return bstr;
1471 }
1472 /*
1473  * read a value and fill a VARIANT structure
1474  */
1475 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1476 {
1477     int size;
1478
1479     TRACE_(typelib)("\n");
1480
1481     if(offset <0) { /* data are packed in here */
1482         V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1483         V_UNION(pVar, iVal) = offset & 0xffff;
1484         return;
1485     }
1486     MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1487                      pcx->pTblDir->pCustData.offset + offset );
1488     TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1489     switch (V_VT(pVar)){
1490         case VT_EMPTY:  /* FIXME: is this right? */
1491         case VT_NULL:   /* FIXME: is this right? */
1492         case VT_I2  :   /* this should not happen */
1493         case VT_I4  :
1494         case VT_R4  :
1495         case VT_ERROR   :
1496         case VT_BOOL    :
1497         case VT_I1  :
1498         case VT_UI1 :
1499         case VT_UI2 :
1500         case VT_UI4 :
1501         case VT_INT :
1502         case VT_UINT    :
1503         case VT_VOID    : /* FIXME: is this right? */
1504         case VT_HRESULT :
1505             size=4; break;
1506         case VT_R8  :
1507         case VT_CY  :
1508         case VT_DATE    :
1509         case VT_I8  :
1510         case VT_UI8 :
1511         case VT_DECIMAL :  /* FIXME: is this right? */
1512         case VT_FILETIME :
1513             size=8;break;
1514             /* pointer types with known behaviour */
1515         case VT_BSTR    :{
1516             char * ptr;
1517             MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1518             if(size < 0) {
1519                 FIXME("BSTR length = %d?\n", size);
1520             } else {
1521                 ptr=TLB_Alloc(size);/* allocate temp buffer */
1522                 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1523                 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1524                 /* FIXME: do we need a AtoW conversion here? */
1525                 V_UNION(pVar, bstrVal[size])=L'\0';
1526                 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1527                 TLB_Free(ptr);
1528             }
1529         }
1530         size=-4; break;
1531     /* FIXME: this will not work AT ALL when the variant contains a pointer */
1532         case VT_DISPATCH :
1533         case VT_VARIANT :
1534         case VT_UNKNOWN :
1535         case VT_PTR :
1536         case VT_SAFEARRAY :
1537         case VT_CARRAY  :
1538         case VT_USERDEFINED :
1539         case VT_LPSTR   :
1540         case VT_LPWSTR  :
1541         case VT_BLOB    :
1542         case VT_STREAM  :
1543         case VT_STORAGE :
1544         case VT_STREAMED_OBJECT :
1545         case VT_STORED_OBJECT   :
1546         case VT_BLOB_OBJECT :
1547         case VT_CF  :
1548         case VT_CLSID   :
1549         default:
1550             size=0;
1551             FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1552                 V_VT(pVar));
1553     }
1554
1555     if(size>0) /* (big|small) endian correct? */
1556         MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1557     return;
1558 }
1559 /*
1560  * create a linked list with custom data
1561  */
1562 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1563 {
1564     MSFT_CDGuid entry;
1565     TLBCustData* pNew;
1566     int count=0;
1567
1568     TRACE_(typelib)("\n");
1569
1570     while(offset >=0){
1571         count++;
1572         pNew=TLB_Alloc(sizeof(TLBCustData));
1573         MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1574         MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1575         MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1576         /* add new custom data at head of the list */
1577         pNew->next=*ppCustData;
1578         *ppCustData=pNew;
1579         offset = entry.next;
1580     }
1581     return count;
1582 }
1583
1584 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1585                           ITypeInfoImpl *pTI)
1586 {
1587     if(type <0)
1588         pTd->vt=type & VT_TYPEMASK;
1589     else
1590         *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1591
1592     if(pTd->vt == VT_USERDEFINED)
1593       MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1594
1595     TRACE_(typelib)("vt type = %X\n", pTd->vt);
1596 }
1597
1598 static void
1599 MSFT_DoFuncs(TLBContext*     pcx,
1600             ITypeInfoImpl*  pTI,
1601             int             cFuncs,
1602             int             cVars,
1603             int             offset,
1604             TLBFuncDesc**   pptfd)
1605 {
1606     /*
1607      * member information is stored in a data structure at offset
1608      * indicated by the memoffset field of the typeinfo structure
1609      * There are several distinctive parts.
1610      * the first part starts with a field that holds the total length
1611      * of this (first) part excluding this field. Then follow the records,
1612      * for each member there is one record.
1613      *
1614      * First entry is always the length of the record (excluding this
1615      * length word).
1616      * Rest of the record depends on the type of the member. If there is
1617      * a field indicating the member type (function variable intereface etc)
1618      * I have not found it yet. At this time we depend on the information
1619      * in the type info and the usual order how things are stored.
1620      *
1621      * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1622      * for each member;
1623      *
1624      * Third is a equal sized array with file offsets to the name entry
1625      * of each member.
1626      *
1627      * Forth and last (?) part is an array with offsets to the records in the
1628      * first part of this file segment.
1629      */
1630
1631     int infolen, nameoffset, reclength, nrattributes, i;
1632     int recoffset = offset + sizeof(INT);
1633
1634     char recbuf[512];
1635     MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1636
1637     TRACE_(typelib)("\n");
1638
1639     MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1640
1641     for ( i = 0; i < cFuncs ; i++ )
1642     {
1643         *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1644
1645         /* name, eventually add to a hash table */
1646         MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1647                           offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1648
1649         (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1650
1651         /* read the function information record */
1652         MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1653
1654         reclength &= 0x1ff;
1655
1656         MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1657
1658         /* do the attributes */
1659         nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1660                        / sizeof(int);
1661
1662         if ( nrattributes > 0 )
1663         {
1664             (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1665
1666             if ( nrattributes > 1 )
1667             {
1668                 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1669                                                       pFuncRec->OptAttr[1]) ;
1670
1671                 if ( nrattributes > 2 )
1672                 {
1673                     if ( pFuncRec->FKCCIC & 0x2000 )
1674                     {
1675                        (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1676                     }
1677                     else
1678                     {
1679                         (*pptfd)->Entry = MSFT_ReadString(pcx,
1680                                                          pFuncRec->OptAttr[2]);
1681                     }
1682                     if( nrattributes > 5 )
1683                     {
1684                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1685
1686                         if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1687                         {
1688                             MSFT_CustData(pcx,
1689                                           pFuncRec->OptAttr[6],
1690                                           &(*pptfd)->pCustData);
1691                         }
1692                     }
1693                 }
1694             }
1695         }
1696
1697         /* fill the FuncDesc Structure */
1698         MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1699                            offset + infolen + ( i + 1) * sizeof(INT));
1700
1701         (*pptfd)->funcdesc.funckind   =  (pFuncRec->FKCCIC)      & 0x7;
1702         (*pptfd)->funcdesc.invkind    =  (pFuncRec->FKCCIC) >> 3 & 0xF;
1703         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
1704         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
1705         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
1706         (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
1707         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
1708
1709         MSFT_GetTdesc(pcx,
1710                       pFuncRec->DataType,
1711                       &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1712                       pTI);
1713
1714         /* do the parameters/arguments */
1715         if(pFuncRec->nrargs)
1716         {
1717             int j = 0;
1718             MSFT_ParameterInfo paraminfo;
1719
1720             (*pptfd)->funcdesc.lprgelemdescParam =
1721                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1722
1723             (*pptfd)->pParamDesc =
1724                 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1725
1726             MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1727                               recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1728
1729             for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1730             {
1731                 TYPEDESC* lpArgTypeDesc = 0;
1732
1733                 MSFT_GetTdesc(pcx,
1734                               paraminfo.DataType,
1735                               &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1736                               pTI);
1737
1738                 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1739
1740                 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1741
1742                 /* SEEK value = jump to offset,
1743                  * from there jump to the end of record,
1744                  * go back by (j-1) arguments
1745                  */
1746                 MSFT_ReadLEDWords( &paraminfo ,
1747                            sizeof(MSFT_ParameterInfo), pcx,
1748                            recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1749                                                * sizeof(MSFT_ParameterInfo)));
1750                 lpArgTypeDesc =
1751                     & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1752
1753                 while ( lpArgTypeDesc != NULL )
1754                 {
1755                     switch ( lpArgTypeDesc->vt )
1756                     {
1757                     case VT_PTR:
1758                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1759                         break;
1760
1761                     case VT_CARRAY:
1762                         lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1763                         break;
1764
1765                     case VT_USERDEFINED:
1766                         MSFT_DoRefType(pcx, pTI,
1767                                        lpArgTypeDesc->u.hreftype);
1768
1769                         lpArgTypeDesc = NULL;
1770                         break;
1771
1772                     default:
1773                         lpArgTypeDesc = NULL;
1774                     }
1775                 }
1776             }
1777
1778
1779             /* parameter is the return value! */
1780             if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1781             {
1782                 TYPEDESC* lpArgTypeDesc;
1783
1784                 (*pptfd)->funcdesc.elemdescFunc =
1785                 (*pptfd)->funcdesc.lprgelemdescParam[j];
1786
1787                 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1788
1789                 while ( lpArgTypeDesc != NULL )
1790                 {
1791                     switch ( lpArgTypeDesc->vt )
1792                     {
1793                     case VT_PTR:
1794                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1795                         break;
1796                     case VT_CARRAY:
1797                         lpArgTypeDesc =
1798                         & (lpArgTypeDesc->u.lpadesc->tdescElem);
1799
1800                         break;
1801
1802                     case VT_USERDEFINED:
1803                         MSFT_DoRefType(pcx,
1804                                        pTI,
1805                                        lpArgTypeDesc->u.hreftype);
1806
1807                         lpArgTypeDesc = NULL;
1808                         break;
1809
1810                     default:
1811                         lpArgTypeDesc = NULL;
1812                     }
1813                 }
1814             }
1815
1816             /* second time around */
1817             for(j=0;j<pFuncRec->nrargs;j++)
1818             {
1819                 /* name */
1820                 (*pptfd)->pParamDesc[j].Name =
1821                     MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1822
1823                 /* default value */
1824                 if ( (PARAMFLAG_FHASDEFAULT &
1825                       (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1826                      ((pFuncRec->FKCCIC) & 0x1000) )
1827                 {
1828                     INT* pInt = (INT *)((char *)pFuncRec +
1829                                    reclength -
1830                                    (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1831
1832                     PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1833
1834                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1835                     pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1836
1837                     MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1838                         pInt[j], pcx);
1839                 }
1840                 /* custom info */
1841                 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1842                 {
1843                     MSFT_CustData(pcx,
1844                                   pFuncRec->OptAttr[7+j],
1845                                   &(*pptfd)->pParamDesc[j].pCustData);
1846                 }
1847            }
1848         }
1849
1850         /* scode is not used: archaic win16 stuff FIXME: right? */
1851         (*pptfd)->funcdesc.cScodes   = 0 ;
1852         (*pptfd)->funcdesc.lprgscode = NULL ;
1853
1854         pptfd      = & ((*pptfd)->next);
1855         recoffset += reclength;
1856     }
1857 }
1858
1859 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1860                        int cVars, int offset, TLBVarDesc ** pptvd)
1861 {
1862     int infolen, nameoffset, reclength;
1863     char recbuf[256];
1864     MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1865     int i;
1866     int recoffset;
1867
1868     TRACE_(typelib)("\n");
1869
1870     MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1871     MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1872                       ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1873     recoffset += offset+sizeof(INT);
1874     for(i=0;i<cVars;i++){
1875         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1876     /* name, eventually add to a hash table */
1877         MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1878                           offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1879         (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1880     /* read the variable information record */
1881         MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1882         reclength &=0xff;
1883         MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1884     /* Optional data */
1885         if(reclength >(6*sizeof(INT)) )
1886             (*pptvd)->HelpContext=pVarRec->HelpContext;
1887         if(reclength >(7*sizeof(INT)) )
1888             (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1889         if(reclength >(8*sizeof(INT)) )
1890         if(reclength >(9*sizeof(INT)) )
1891             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1892     /* fill the VarDesc Structure */
1893         MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1894                           offset + infolen + ( i + 1) * sizeof(INT));
1895         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1896         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1897         MSFT_GetTdesc(pcx, pVarRec->DataType,
1898             &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1899 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1900         if(pVarRec->VarKind == VAR_CONST ){
1901             (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1902             MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1903                 pVarRec->OffsValue, pcx);
1904         } else
1905             (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1906         pptvd=&((*pptvd)->next);
1907         recoffset += reclength;
1908     }
1909 }
1910 /* fill in data for a hreftype (offset). When the refernced type is contained
1911  * in the typelib, it's just an (file) offset in the type info base dir.
1912  * If comes from import, it's an offset+1 in the ImpInfo table
1913  * */
1914 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1915                           int offset)
1916 {
1917     int j;
1918     TLBRefType **ppRefType = &pTI->reflist;
1919
1920     TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1921
1922     while(*ppRefType) {
1923         if((*ppRefType)->reference == offset)
1924             return;
1925         ppRefType = &(*ppRefType)->next;
1926     }
1927
1928     *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1929                            sizeof(**ppRefType));
1930
1931     if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1932         /* external typelib */
1933         MSFT_ImpInfo impinfo;
1934         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1935
1936         TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1937
1938         MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1939                           pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1940         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
1941             if(pImpLib->offset==impinfo.oImpFile) break;
1942             pImpLib=pImpLib->next;
1943         }
1944         if(pImpLib){
1945             (*ppRefType)->reference=offset;
1946             (*ppRefType)->pImpTLInfo = pImpLib;
1947             MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1948             (*ppRefType)->index = TLB_REF_USE_GUID;
1949         }else{
1950             ERR("Cannot find a reference\n");
1951             (*ppRefType)->reference=-1;
1952             (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1953         }
1954     }else{
1955         /* in this typelib */
1956         (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1957         (*ppRefType)->reference=offset;
1958         (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1959     }
1960 }
1961
1962 /* process Implemented Interfaces of a com class */
1963 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1964                             int offset)
1965 {
1966     int i;
1967     MSFT_RefRecord refrec;
1968     TLBImplType **ppImpl = &pTI->impltypelist;
1969
1970     TRACE_(typelib)("\n");
1971
1972     for(i=0;i<count;i++){
1973         if(offset<0) break; /* paranoia */
1974         *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1975         MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1976         MSFT_DoRefType(pcx, pTI, refrec.reftype);
1977         (*ppImpl)->hRef = refrec.reftype;
1978         (*ppImpl)->implflags=refrec.flags;
1979         (*ppImpl)->ctCustData=
1980             MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1981         offset=refrec.onext;
1982         ppImpl=&((*ppImpl)->next);
1983     }
1984 }
1985 /*
1986  * process a typeinfo record
1987  */
1988 ITypeInfoImpl * MSFT_DoTypeInfo(
1989     TLBContext *pcx,
1990     int count,
1991     ITypeLibImpl * pLibInfo)
1992 {
1993     MSFT_TypeInfoBase tiBase;
1994     ITypeInfoImpl *ptiRet;
1995
1996     TRACE_(typelib)("count=%u\n", count);
1997
1998     ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1999     MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2000                       pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2001 /* this is where we are coming from */
2002     ptiRet->pTypeLib = pLibInfo;
2003     ptiRet->index=count;
2004 /* fill in the typeattr fields */
2005     WARN("Assign constructor/destructor memid\n");
2006
2007     MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2008     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
2009     ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2010     ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2011     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
2012     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2013     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2014     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2015     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2016     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2017     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2018     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2019     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2020     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2021     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2022     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2023         MSFT_GetTdesc(pcx, tiBase.datatype1,
2024             &ptiRet->TypeAttr.tdescAlias, ptiRet);
2025
2026 /*  FIXME: */
2027 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
2028
2029 /* name, eventually add to a hash table */
2030     ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2031     TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2032     /* help info */
2033     ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2034     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2035     ptiRet->dwHelpContext=tiBase.helpcontext;
2036 /* note: InfoType's Help file and HelpStringDll come from the containing
2037  * library. Further HelpString and Docstring appear to be the same thing :(
2038  */
2039     /* functions */
2040     if(ptiRet->TypeAttr.cFuncs >0 )
2041         MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2042                     ptiRet->TypeAttr.cVars,
2043                     tiBase.memoffset, & ptiRet->funclist);
2044     /* variables */
2045     if(ptiRet->TypeAttr.cVars >0 )
2046         MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2047                    ptiRet->TypeAttr.cVars,
2048                    tiBase.memoffset, & ptiRet->varlist);
2049     if(ptiRet->TypeAttr.cImplTypes >0 ) {
2050         switch(ptiRet->TypeAttr.typekind)
2051         {
2052         case TKIND_COCLASS:
2053             MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2054                 tiBase.datatype1);
2055             break;
2056         case TKIND_DISPATCH:
2057             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2058
2059             if (tiBase.datatype1 != -1)
2060             {
2061               MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2062               ptiRet->impltypelist->hRef = tiBase.datatype1;
2063             }
2064             else
2065             { /* FIXME: This is a really bad hack to add IDispatch */
2066               const char* szStdOle = "stdole2.tlb\0";
2067               int   nStdOleLen = strlen(szStdOle);
2068               TLBRefType **ppRef = &ptiRet->reflist;
2069
2070               while(*ppRef) {
2071                 if((*ppRef)->reference == -1)
2072                   break;
2073                 ppRef = &(*ppRef)->next;
2074               }
2075               if(!*ppRef) {
2076                 *ppRef = TLB_Alloc(sizeof(**ppRef));
2077                 (*ppRef)->guid             = IID_IDispatch;
2078                 (*ppRef)->reference        = -1;
2079                 (*ppRef)->index            = TLB_REF_USE_GUID;
2080                 (*ppRef)->pImpTLInfo       = TLB_Alloc(sizeof(TLBImpLib));
2081                 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2082                 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2083                                                               nStdOleLen  + 1);
2084
2085                 MultiByteToWideChar(CP_ACP,
2086                                     MB_PRECOMPOSED,
2087                                     szStdOle,
2088                                     -1,
2089                                     (*ppRef)->pImpTLInfo->name,
2090                                     SysStringLen((*ppRef)->pImpTLInfo->name));
2091
2092                 (*ppRef)->pImpTLInfo->lcid          = 0;
2093                 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2094                 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2095               }
2096             }
2097             break;
2098         default:
2099             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2100             MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2101             ptiRet->impltypelist->hRef = tiBase.datatype1;
2102             break;
2103        }
2104     }
2105     ptiRet->ctCustData=
2106         MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2107
2108     TRACE_(typelib)("%s guid: %s kind:%s\n",
2109        debugstr_w(ptiRet->Name),
2110        debugstr_guid(&ptiRet->TypeAttr.guid),
2111        typekind_desc[ptiRet->TypeAttr.typekind]);
2112
2113     return ptiRet;
2114 }
2115
2116 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2117  * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2118  * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2119  * tradeoff here.
2120  */
2121 static ITypeLibImpl *tlb_cache_first;
2122 static CRITICAL_SECTION cache_section;
2123 static CRITICAL_SECTION_DEBUG cache_section_debug =
2124 {
2125     0, 0, &cache_section,
2126     { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2127       0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2128 };
2129 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2130
2131
2132 /****************************************************************************
2133  *      TLB_ReadTypeLib
2134  *
2135  * find the type of the typelib file and map the typelib resource into
2136  * the memory
2137  */
2138 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2139 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2140 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2141 {
2142     ITypeLibImpl *entry;
2143     int ret = TYPE_E_CANTLOADLIBRARY;
2144     DWORD dwSignature = 0;
2145     HANDLE hFile;
2146
2147     TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2148
2149     *ppTypeLib = NULL;
2150
2151     /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2152     EnterCriticalSection(&cache_section);
2153     for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2154     {
2155         if (!strcmpiW(entry->path, pszFileName))
2156         {
2157             TRACE("cache hit\n");
2158             *ppTypeLib = (ITypeLib2*)entry;
2159             ITypeLib_AddRef(*ppTypeLib);
2160             LeaveCriticalSection(&cache_section);
2161             return S_OK;
2162         }
2163     }
2164     LeaveCriticalSection(&cache_section);
2165
2166     /* check the signature of the file */
2167     hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2168     if (INVALID_HANDLE_VALUE != hFile)
2169     {
2170       HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2171       if (hMapping)
2172       {
2173         LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2174         if(pBase)
2175         {
2176           /* retrieve file size */
2177           DWORD dwTLBLength = GetFileSize(hFile, NULL);
2178
2179           /* first try to load as *.tlb */
2180           dwSignature = FromLEDWord(*((DWORD*) pBase));
2181           if ( dwSignature == MSFT_SIGNATURE)
2182           {
2183             *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2184           }
2185           else if ( dwSignature == SLTG_SIGNATURE)
2186           {
2187             *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2188           }
2189           UnmapViewOfFile(pBase);
2190         }
2191         CloseHandle(hMapping);
2192       }
2193       CloseHandle(hFile);
2194     }
2195
2196     if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2197     {
2198       /* find the typelibrary resource*/
2199       HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2200                                           LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2201       if (hinstDLL)
2202       {
2203         HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2204           "TYPELIB");
2205         if (hrsrc)
2206         {
2207           HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2208           if (hGlobal)
2209           {
2210             LPVOID pBase = LockResource(hGlobal);
2211             DWORD  dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2212
2213             if (pBase)
2214             {
2215               /* try to load as incore resource */
2216               dwSignature = FromLEDWord(*((DWORD*) pBase));
2217               if ( dwSignature == MSFT_SIGNATURE)
2218               {
2219                   *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2220               }
2221               else if ( dwSignature == SLTG_SIGNATURE)
2222               {
2223                   *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2224               }
2225               else
2226               {
2227                   FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2228               }
2229             }
2230             FreeResource( hGlobal );
2231           }
2232         }
2233         FreeLibrary(hinstDLL);
2234       }
2235     }
2236
2237     if(*ppTypeLib) {
2238         ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2239
2240         TRACE("adding to cache\n");
2241         impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2242         lstrcpyW(impl->path, pszFileName);
2243         /* We should really canonicalise the path here. */
2244
2245         /* FIXME: check if it has added already in the meantime */
2246         EnterCriticalSection(&cache_section);
2247         if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2248         impl->prev = NULL;
2249         tlb_cache_first = impl;
2250         LeaveCriticalSection(&cache_section);
2251         ret = S_OK;
2252     } else
2253         ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2254
2255     return ret;
2256 }
2257
2258 /*================== ITypeLib(2) Methods ===================================*/
2259
2260 /****************************************************************************
2261  *      ITypeLib2_Constructor_MSFT
2262  *
2263  * loading an MSFT typelib from an in-memory image
2264  */
2265 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2266 {
2267     TLBContext cx;
2268     long lPSegDir;
2269     MSFT_Header tlbHeader;
2270     MSFT_SegDir tlbSegDir;
2271     ITypeLibImpl * pTypeLibImpl;
2272
2273     TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2274
2275     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2276     if (!pTypeLibImpl) return NULL;
2277
2278     pTypeLibImpl->lpVtbl = &tlbvt;
2279     pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2280     pTypeLibImpl->ref = 1;
2281
2282     /* get pointer to beginning of typelib data */
2283     cx.pos = 0;
2284     cx.oStart=0;
2285     cx.mapping = pLib;
2286     cx.pLibInfo = pTypeLibImpl;
2287     cx.length = dwTLBLength;
2288
2289     /* read header */
2290     MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2291     TRACE("header:\n");
2292     TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2293     if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2294         FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2295         return NULL;
2296     }
2297     /* there is a small amount of information here until the next important
2298      * part:
2299      * the segment directory . Try to calculate the amount of data */
2300     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2301
2302     /* now read the segment directory */
2303     TRACE("read segment directory (at %ld)\n",lPSegDir);
2304     MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2305     cx.pTblDir = &tlbSegDir;
2306
2307     /* just check two entries */
2308     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2309     {
2310         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2311         HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2312         return NULL;
2313     }
2314
2315     /* now fill our internal data */
2316     /* TLIBATTR fields */
2317     MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2318
2319     /*    pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2320     /* Windows seems to have zero here, is this correct? */
2321     if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2322       pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2323     else
2324       pTypeLibImpl->LibAttr.lcid = 0;
2325
2326     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2327     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2328     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2329     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2330
2331     /* name, eventually add to a hash table */
2332     pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2333
2334     /* help info */
2335     pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2336     pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2337
2338     if( tlbHeader.varflags & HELPDLLFLAG)
2339     {
2340             int offset;
2341             MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2342             pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2343     }
2344
2345     pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2346
2347     /* custom data */
2348     if(tlbHeader.CustomDataOffset >= 0)
2349     {
2350         pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2351     }
2352
2353     /* fill in typedescriptions */
2354     if(tlbSegDir.pTypdescTab.length > 0)
2355     {
2356         int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2357         INT16 td[4];
2358         pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2359         MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2360         for(i=0; i<cTD; )
2361         {
2362             /* FIXME: add several sanity checks here */
2363             pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2364             if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2365             {
2366                 /* FIXME: check safearray */
2367                 if(td[3] < 0)
2368                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2369                 else
2370                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2371             }
2372             else if(td[0] == VT_CARRAY)
2373             {
2374                 /* array descr table here */
2375                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]);  /* temp store offset in*/
2376             }
2377             else if(td[0] == VT_USERDEFINED)
2378             {
2379                 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2380             }
2381             if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2382         }
2383
2384         /* second time around to fill the array subscript info */
2385         for(i=0;i<cTD;i++)
2386         {
2387             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2388             if(tlbSegDir.pArrayDescriptions.offset>0)
2389             {
2390                 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2391                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2392
2393                 if(td[1]<0)
2394                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2395                 else
2396                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2397
2398                 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2399
2400                 for(j = 0; j<td[2]; j++)
2401                 {
2402                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2403                                       sizeof(INT), &cx, DO_NOT_SEEK);
2404                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2405                                       sizeof(INT), &cx, DO_NOT_SEEK);
2406                 }
2407             }
2408             else
2409             {
2410                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2411                 ERR("didn't find array description data\n");
2412             }
2413         }
2414     }
2415
2416     /* imported type libs */
2417     if(tlbSegDir.pImpFiles.offset>0)
2418     {
2419         TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2420         int oGuid, offset = tlbSegDir.pImpFiles.offset;
2421         UINT16 size;
2422
2423         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2424         {
2425             char *name;
2426             DWORD len;
2427
2428             *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2429             (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2430             MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2431
2432             MSFT_ReadLEDWords(&(*ppImpLib)->lcid,         sizeof(LCID),   &cx, DO_NOT_SEEK);
2433             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2434             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2435             MSFT_ReadLEWords(& size,                      sizeof(UINT16), &cx, DO_NOT_SEEK);
2436
2437             size >>= 2;
2438             name = TLB_Alloc(size+1);
2439             MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2440             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2441             (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2442             MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2443             TLB_Free(name);
2444
2445             MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2446             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2447
2448             ppImpLib = &(*ppImpLib)->next;
2449         }
2450     }
2451
2452     /* type info's */
2453     if(tlbHeader.nrtypeinfos >= 0 )
2454     {
2455         /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2456         ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2457         int i;
2458
2459         for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2460         {
2461             *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2462
2463             ppTI = &((*ppTI)->next);
2464             (pTypeLibImpl->TypeInfoCount)++;
2465         }
2466     }
2467
2468     TRACE("(%p)\n", pTypeLibImpl);
2469     return (ITypeLib2*) pTypeLibImpl;
2470 }
2471
2472
2473 static BSTR TLB_MultiByteToBSTR(char *ptr)
2474 {
2475     DWORD len;
2476     WCHAR *nameW;
2477     BSTR ret;
2478
2479     len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2480     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2481     MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2482     ret = SysAllocString(nameW);
2483     HeapFree(GetProcessHeap(), 0, nameW);
2484     return ret;
2485 }
2486
2487 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2488 {
2489   char b[3];
2490   int i;
2491   short s;
2492
2493   if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2494     FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2495     return FALSE;
2496   }
2497
2498   guid->Data4[0] = s >> 8;
2499   guid->Data4[1] = s & 0xff;
2500
2501   b[2] = '\0';
2502   for(i = 0; i < 6; i++) {
2503     memcpy(b, str + 24 + 2 * i, 2);
2504     guid->Data4[i + 2] = strtol(b, NULL, 16);
2505   }
2506   return TRUE;
2507 }
2508
2509 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2510 {
2511     WORD bytelen;
2512     DWORD len;
2513     WCHAR *nameW;
2514
2515     *pBstr = NULL;
2516     bytelen = *(WORD*)ptr;
2517     if(bytelen == 0xffff) return 2;
2518     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2519     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2520     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2521     *pBstr = SysAllocStringLen(nameW, len);
2522     HeapFree(GetProcessHeap(), 0, nameW);
2523     return bytelen + 2;
2524 }
2525
2526 static WORD SLTG_ReadStringA(char *ptr, char **str)
2527 {
2528     WORD bytelen;
2529
2530     *str = NULL;
2531     bytelen = *(WORD*)ptr;
2532     if(bytelen == 0xffff) return 2;
2533     *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2534     memcpy(*str, ptr + 2, bytelen);
2535     (*str)[bytelen] = '\0';
2536     return bytelen + 2;
2537 }
2538
2539 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2540 {
2541     char *ptr = pLibBlk;
2542     WORD w;
2543
2544     if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2545         FIXME("libblk magic = %04x\n", w);
2546         return 0;
2547     }
2548
2549     ptr += 6;
2550     if((w = *(WORD*)ptr) != 0xffff) {
2551         FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2552         ptr += w;
2553     }
2554     ptr += 2;
2555
2556     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2557
2558     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2559
2560     pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2561     ptr += 4;
2562
2563     pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2564     ptr += 2;
2565
2566     if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2567         pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2568     else
2569         pTypeLibImpl->LibAttr.lcid = 0;
2570     ptr += 2;
2571
2572     ptr += 4; /* skip res12 */
2573
2574     pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2575     ptr += 2;
2576
2577     pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2578     ptr += 2;
2579
2580     pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2581     ptr += 2;
2582
2583     memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2584     ptr += sizeof(GUID);
2585
2586     return ptr - (char*)pLibBlk;
2587 }
2588
2589 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2590 {
2591     BOOL done = FALSE;
2592     TYPEDESC *pTD = &pElem->tdesc;
2593
2594     /* Handle [in/out] first */
2595     if((*pType & 0xc000) == 0xc000)
2596         pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2597     else if(*pType & 0x8000)
2598         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2599     else if(*pType & 0x4000)
2600         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2601     else
2602         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2603
2604     if(*pType & 0x2000)
2605         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2606
2607     if(*pType & 0x80)
2608         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2609
2610     while(!done) {
2611         if((*pType & 0xe00) == 0xe00) {
2612             pTD->vt = VT_PTR;
2613             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2614                                        sizeof(TYPEDESC));
2615             pTD = pTD->u.lptdesc;
2616         }
2617         switch(*pType & 0x7f) {
2618         case VT_PTR:
2619             pTD->vt = VT_PTR;
2620             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2621                                        sizeof(TYPEDESC));
2622             pTD = pTD->u.lptdesc;
2623             break;
2624
2625         case VT_USERDEFINED:
2626             pTD->vt = VT_USERDEFINED;
2627             pTD->u.hreftype = *(++pType) / 4;
2628             done = TRUE;
2629             break;
2630
2631         case VT_CARRAY:
2632           {
2633             /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2634                array */
2635
2636             SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2637
2638             pTD->vt = VT_CARRAY;
2639             pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2640                                 sizeof(ARRAYDESC) +
2641                                 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2642             pTD->u.lpadesc->cDims = pSA->cDims;
2643             memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2644                    pSA->cDims * sizeof(SAFEARRAYBOUND));
2645
2646             pTD = &pTD->u.lpadesc->tdescElem;
2647             break;
2648           }
2649
2650         case VT_SAFEARRAY:
2651           {
2652             /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2653                useful? */
2654
2655             pType++;
2656             pTD->vt = VT_SAFEARRAY;
2657             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2658                                        sizeof(TYPEDESC));
2659             pTD = pTD->u.lptdesc;
2660             break;
2661           }
2662         default:
2663             pTD->vt = *pType & 0x7f;
2664             done = TRUE;
2665             break;
2666         }
2667         pType++;
2668     }
2669     return pType;
2670 }
2671
2672
2673 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2674                         char *pNameTable)
2675 {
2676     int ref;
2677     char *name;
2678     TLBRefType **ppRefType;
2679
2680     if(pRef->magic != SLTG_REF_MAGIC) {
2681         FIXME("Ref magic = %x\n", pRef->magic);
2682         return;
2683     }
2684     name = ( (char*)(&pRef->names) + pRef->number);
2685
2686     ppRefType = &pTI->reflist;
2687     for(ref = 0; ref < pRef->number >> 3; ref++) {
2688         char *refname;
2689         unsigned int lib_offs, type_num;
2690
2691         *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692                                sizeof(**ppRefType));
2693
2694         name += SLTG_ReadStringA(name, &refname);
2695         if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2696             FIXME("Can't sscanf ref\n");
2697         if(lib_offs != 0xffff) {
2698             TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2699
2700             while(*import) {
2701                 if((*import)->offset == lib_offs)
2702                     break;
2703                 import = &(*import)->next;
2704             }
2705             if(!*import) {
2706                 char fname[MAX_PATH+1];
2707                 int len;
2708
2709                 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2710                                     sizeof(**import));
2711                 (*import)->offset = lib_offs;
2712                 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2713                                     &(*import)->guid);
2714                 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2715                           &(*import)->wVersionMajor,
2716                           &(*import)->wVersionMinor,
2717                           &(*import)->lcid, fname) != 4) {
2718                   FIXME("can't sscanf ref %s\n",
2719                         pNameTable + lib_offs + 40);
2720                 }
2721                 len = strlen(fname);
2722                 if(fname[len-1] != '#')
2723                     FIXME("fname = %s\n", fname);
2724                 fname[len-1] = '\0';
2725                 (*import)->name = TLB_MultiByteToBSTR(fname);
2726             }
2727             (*ppRefType)->pImpTLInfo = *import;
2728         } else { /* internal ref */
2729           (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2730         }
2731         (*ppRefType)->reference = ref;
2732         (*ppRefType)->index = type_num;
2733
2734         HeapFree(GetProcessHeap(), 0, refname);
2735         ppRefType = &(*ppRefType)->next;
2736     }
2737     if((BYTE)*name != SLTG_REF_MAGIC)
2738       FIXME("End of ref block magic = %x\n", *name);
2739     dump_TLBRefType(pTI->reflist);
2740 }
2741
2742 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2743                           BOOL OneOnly)
2744 {
2745     SLTG_ImplInfo *info;
2746     TLBImplType **ppImplType = &pTI->impltypelist;
2747     /* I don't really get this structure, usually it's 0x16 bytes
2748        long, but iuser.tlb contains some that are 0x18 bytes long.
2749        That's ok because we can use the next ptr to jump to the next
2750        one. But how do we know the length of the last one?  The WORD
2751        at offs 0x8 might be the clue.  For now I'm just assuming that
2752        the last one is the regular 0x16 bytes. */
2753
2754     info = (SLTG_ImplInfo*)pBlk;
2755     while(1) {
2756         *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2757                                 sizeof(**ppImplType));
2758         (*ppImplType)->hRef = info->ref;
2759         (*ppImplType)->implflags = info->impltypeflags;
2760         pTI->TypeAttr.cImplTypes++;
2761         ppImplType = &(*ppImplType)->next;
2762
2763         if(info->next == 0xffff)
2764             break;
2765         if(OneOnly)
2766             FIXME("Interface inheriting more than one interface\n");
2767         info = (SLTG_ImplInfo*)(pBlk + info->next);
2768     }
2769     info++; /* see comment at top of function */
2770     return (char*)info;
2771 }
2772
2773 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2774                                               char *pNameTable)
2775 {
2776     SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2777     SLTG_MemberHeader *pMemHeader;
2778     char *pFirstItem, *pNextItem;
2779
2780     if(pTIHeader->href_table != 0xffffffff) {
2781         SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2782                     pNameTable);
2783     }
2784
2785
2786     pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2787
2788     pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2789
2790     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2791         pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2792     }
2793
2794     return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2795 }
2796
2797
2798 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2799                                                 char *pNameTable)
2800 {
2801     SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2802     SLTG_MemberHeader *pMemHeader;
2803     SLTG_Function *pFunc;
2804     char *pFirstItem, *pNextItem;
2805     TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2806     int num = 0;
2807
2808     if(pTIHeader->href_table != 0xffffffff) {
2809         SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2810                     pNameTable);
2811     }
2812
2813     pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2814
2815     pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2816
2817     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2818         pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2819     }
2820
2821     for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2822         pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2823
2824         int param;
2825         WORD *pType, *pArg;
2826
2827         if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2828            pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2829             FIXME("func magic = %02x\n", pFunc->magic);
2830             return NULL;
2831         }
2832         *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2833                                 sizeof(**ppFuncDesc));
2834         (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2835
2836         (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2837         (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2838         (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2839         (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2840         (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2841         (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2842
2843         if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2844             (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2845
2846         if(pFunc->retnextopt & 0x80)
2847             pType = &pFunc->rettype;
2848         else
2849             pType = (WORD*)(pFirstItem + pFunc->rettype);
2850
2851
2852         SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2853
2854         (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2855           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2856                     (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2857         (*ppFuncDesc)->pParamDesc =
2858           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2859                     (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2860
2861         pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2862
2863         for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2864             char *paramName = pNameTable + *pArg;
2865             BOOL HaveOffs;
2866             /* If arg type follows then paramName points to the 2nd
2867                letter of the name, else the next WORD is an offset to
2868                the arg type and paramName points to the first letter.
2869                So let's take one char off paramName and see if we're
2870                pointing at an alpha-numeric char.  However if *pArg is
2871                0xffff or 0xfffe then the param has no name, the former
2872                meaning that the next WORD is the type, the latter
2873                meaning the the next WORD is an offset to the type. */
2874
2875             HaveOffs = FALSE;
2876             if(*pArg == 0xffff)
2877                 paramName = NULL;
2878             else if(*pArg == 0xfffe) {
2879                 paramName = NULL;
2880                 HaveOffs = TRUE;
2881             }
2882             else if(!isalnum(*(paramName-1)))
2883                 HaveOffs = TRUE;
2884
2885             pArg++;
2886
2887             if(HaveOffs) { /* the next word is an offset to type */
2888                 pType = (WORD*)(pFirstItem + *pArg);
2889                 SLTG_DoType(pType, pFirstItem,
2890                             &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2891                 pArg++;
2892             } else {
2893                 if(paramName)
2894                   paramName--;
2895                 pArg = SLTG_DoType(pArg, pFirstItem,
2896                            &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2897             }
2898
2899             /* Are we an optional param ? */
2900             if((*ppFuncDesc)->funcdesc.cParams - param <=
2901                (*ppFuncDesc)->funcdesc.cParamsOpt)
2902               (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2903
2904             if(paramName) {
2905                 (*ppFuncDesc)->pParamDesc[param].Name =
2906                   TLB_MultiByteToBSTR(paramName);
2907             }
2908         }
2909
2910         ppFuncDesc = &((*ppFuncDesc)->next);
2911         if(pFunc->next == 0xffff) break;
2912     }
2913     pTI->TypeAttr.cFuncs = num;
2914     dump_TLBFuncDesc(pTI->funclist);
2915     return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2916 }
2917
2918 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2919                                              char *pNameTable)
2920 {
2921   SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2922   SLTG_MemberHeader *pMemHeader;
2923   SLTG_RecordItem *pItem;
2924   char *pFirstItem;
2925   TLBVarDesc **ppVarDesc = &pTI->varlist;
2926   int num = 0;
2927   WORD *pType;
2928   char buf[300];
2929
2930   pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2931
2932   pFirstItem = (char*)(pMemHeader + 1);
2933   for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2934       pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2935       if(pItem->magic != SLTG_RECORD_MAGIC) {
2936           FIXME("record magic = %02x\n", pItem->magic);
2937           return NULL;
2938       }
2939       *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2940                              sizeof(**ppVarDesc));
2941       (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2942       (*ppVarDesc)->vardesc.memid = pItem->memid;
2943       (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2944       (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2945
2946       if(pItem->typepos == 0x02)
2947           pType = &pItem->type;
2948       else if(pItem->typepos == 0x00)
2949           pType = (WORD*)(pFirstItem + pItem->type);
2950       else {
2951           FIXME("typepos = %02x\n", pItem->typepos);
2952           break;
2953       }
2954
2955       SLTG_DoType(pType, pFirstItem,
2956                   &(*ppVarDesc)->vardesc.elemdescVar);
2957
2958       /* FIXME("helpcontext, helpstring\n"); */
2959
2960       dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2961
2962       ppVarDesc = &((*ppVarDesc)->next);
2963       if(pItem->next == 0xffff) break;
2964   }
2965   pTI->TypeAttr.cVars = num;
2966   return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2967 }
2968
2969 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2970                                            char *pNameTable)
2971 {
2972   SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2973   SLTG_MemberHeader *pMemHeader;
2974   SLTG_AliasItem *pItem;
2975   int i, mustbelast;
2976
2977   pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2978   pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2979
2980   mustbelast = 0;
2981   /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2982   for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2983     if (pItem->vt == 0xffff) {
2984       if (i<(pMemHeader->cbExtra/4-1))
2985         FIXME("Endmarker too early in process alias data!\n");
2986       break;
2987     }
2988     if (mustbelast) {
2989       FIXME("Chain extends over last entry?\n");
2990       break;
2991     }
2992     if (pItem->vt == VT_USERDEFINED) {
2993       pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2994       /* guessing here ... */
2995       FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2996       pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2997       mustbelast = 1;
2998     } else {
2999       FIXME("alias %d: 0x%x\n",i,pItem->vt);
3000       FIXME("alias %d: 0x%x\n",i,pItem->res02);
3001     }
3002     pItem++;
3003   }
3004   return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3005 }
3006
3007 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3008                                            char *pNameTable)
3009 {
3010   SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3011   SLTG_MemberHeader *pMemHeader;
3012   SLTG_AliasItem *pItem;
3013
3014   pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3015   pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3016   FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3017   FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3018   return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3019 }
3020
3021 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3022                                            char *pNameTable)
3023 {
3024   SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3025   SLTG_MemberHeader *pMemHeader;
3026   SLTG_EnumItem *pItem;
3027   char *pFirstItem;
3028   TLBVarDesc **ppVarDesc = &pTI->varlist;
3029   int num = 0;
3030
3031   pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3032
3033   pFirstItem = (char*)(pMemHeader + 1);
3034   for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3035       pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3036       if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3037           FIXME("enumitem magic = %04x\n", pItem->magic);
3038           return NULL;
3039       }
3040       *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3041                              sizeof(**ppVarDesc));
3042       (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3043       (*ppVarDesc)->vardesc.memid = pItem->memid;
3044       (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3045                                                      sizeof(VARIANT));
3046       V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3047       V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3048         *(INT*)(pItem->value + pFirstItem);
3049       (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3050       (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3051       /* FIXME("helpcontext, helpstring\n"); */
3052
3053       ppVarDesc = &((*ppVarDesc)->next);
3054       if(pItem->next == 0xffff) break;
3055   }
3056   pTI->TypeAttr.cVars = num;
3057   return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3058 }
3059
3060 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3061    managable copy of it into this */
3062 typedef struct {
3063   WORD small_no;
3064   char *index_name;
3065   char *other_name;
3066   WORD res1a;
3067   WORD name_offs;
3068   WORD more_bytes;
3069   char *extra;
3070   WORD res20;
3071   DWORD helpcontext;
3072   WORD res26;
3073   GUID uuid;
3074 } SLTG_InternalOtherTypeInfo;
3075
3076 /****************************************************************************
3077  *      ITypeLib2_Constructor_SLTG
3078  *
3079  * loading a SLTG typelib from an in-memory image
3080  */
3081 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3082 {
3083     ITypeLibImpl *pTypeLibImpl;
3084     SLTG_Header *pHeader;
3085     SLTG_BlkEntry *pBlkEntry;
3086     SLTG_Magic *pMagic;
3087     SLTG_Index *pIndex;
3088     SLTG_Pad9 *pPad9;
3089     LPVOID pBlk, pFirstBlk;
3090     SLTG_LibBlk *pLibBlk;
3091     SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3092     char *pAfterOTIBlks = NULL;
3093     char *pNameTable, *ptr;
3094     int i;
3095     DWORD len, order;
3096     ITypeInfoImpl **ppTypeInfoImpl;
3097
3098     TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3099
3100     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3101     if (!pTypeLibImpl) return NULL;
3102
3103     pTypeLibImpl->lpVtbl = &tlbvt;
3104     pTypeLibImpl->ref = 1;
3105
3106     pHeader = pLib;
3107
3108     TRACE("header:\n");
3109     TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3110           pHeader->nrOfFileBlks );
3111     if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3112         FIXME("Header type magic 0x%08lx not supported.\n",
3113               pHeader->SLTG_magic);
3114         return NULL;
3115     }
3116
3117     /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3118     pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3119
3120     /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3121     pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3122
3123     /* Next we have a magic block */
3124     pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3125
3126     /* Let's see if we're still in sync */
3127     if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3128               sizeof(SLTG_COMPOBJ_MAGIC))) {
3129         FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3130         return NULL;
3131     }
3132     if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3133               sizeof(SLTG_DIR_MAGIC))) {
3134         FIXME("dir magic = %s\n", pMagic->dir_magic);
3135         return NULL;
3136     }
3137
3138     pIndex = (SLTG_Index*)(pMagic+1);
3139
3140     pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3141
3142     pFirstBlk = (LPVOID)(pPad9 + 1);
3143
3144     /* We'll set up a ptr to the main library block, which is the last one. */
3145
3146     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3147           pBlkEntry[order].next != 0;
3148           order = pBlkEntry[order].next - 1, i++) {
3149        pBlk = (char*)pBlk + pBlkEntry[order].len;
3150     }
3151     pLibBlk = pBlk;
3152
3153     len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3154
3155     /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3156        interspersed */
3157
3158     len += 0x40;
3159
3160     /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3161
3162     pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3163                                    sizeof(*pOtherTypeInfoBlks) *
3164                                    pTypeLibImpl->TypeInfoCount);
3165
3166
3167     ptr = (char*)pLibBlk + len;
3168
3169     for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3170         WORD w, extra;
3171         len = 0;
3172
3173         pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3174
3175         w = *(WORD*)(ptr + 2);
3176         if(w != 0xffff) {
3177             len += w;
3178             pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3179                                                          w+1);
3180             memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3181             pOtherTypeInfoBlks[i].index_name[w] = '\0';
3182         }
3183         w = *(WORD*)(ptr + 4 + len);
3184         if(w != 0xffff) {
3185             TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3186             len += w;
3187             pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3188                                                          w+1);
3189             memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3190             pOtherTypeInfoBlks[i].other_name[w] = '\0';
3191         }
3192         pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3193         pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3194         extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3195         if(extra) {
3196             pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3197                                                     extra);
3198             memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3199             len += extra;
3200         }
3201         pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3202         pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3203         pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3204         memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3205         len += sizeof(SLTG_OtherTypeInfo);
3206         ptr += len;
3207     }
3208
3209     pAfterOTIBlks = ptr;
3210
3211     /* Skip this WORD and get the next DWORD */
3212     len = *(DWORD*)(pAfterOTIBlks + 2);
3213
3214     /* Now add this to pLibBLk look at what we're pointing at and
3215        possibly add 0x20, then add 0x216, sprinkle a bit a magic
3216        dust and we should be pointing at the beginning of the name
3217        table */
3218
3219     pNameTable = (char*)pLibBlk + len;
3220
3221    switch(*(WORD*)pNameTable) {
3222    case 0xffff:
3223        break;
3224    case 0x0200:
3225        pNameTable += 0x20;
3226        break;
3227    default:
3228        FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3229        break;
3230    }
3231
3232     pNameTable += 0x216;
3233
3234     pNameTable += 2;
3235
3236     TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3237
3238     pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3239
3240
3241     /* Hopefully we now have enough ptrs set up to actually read in
3242        some TypeInfos.  It's not clear which order to do them in, so
3243        I'll just follow the links along the BlkEntry chain and read
3244        them in in the order in which they're in the file */
3245
3246     ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3247
3248     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3249         pBlkEntry[order].next != 0;
3250         order = pBlkEntry[order].next - 1, i++) {
3251
3252       SLTG_TypeInfoHeader *pTIHeader;
3253       SLTG_TypeInfoTail *pTITail;
3254
3255       if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3256                 pOtherTypeInfoBlks[i].index_name)) {
3257         FIXME("Index strings don't match\n");
3258         return NULL;
3259       }
3260
3261       pTIHeader = pBlk;
3262       if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3263         FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3264         return NULL;
3265       }
3266       *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3267       (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3268       (*ppTypeInfoImpl)->index = i;
3269       (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3270                                              pOtherTypeInfoBlks[i].name_offs +
3271                                              pNameTable);
3272       (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3273       memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3274              sizeof(GUID));
3275       (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3276       (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3277       (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3278       (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3279         (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3280
3281       if((pTIHeader->typeflags1 & 7) != 2)
3282         FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3283       if(pTIHeader->typeflags3 != 2)
3284         FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3285
3286       TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3287             debugstr_w((*ppTypeInfoImpl)->Name),
3288             typekind_desc[pTIHeader->typekind],
3289             debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3290             (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3291
3292       switch(pTIHeader->typekind) {
3293       case TKIND_ENUM:
3294         pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3295         break;
3296
3297       case TKIND_RECORD:
3298         pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3299         break;
3300
3301       case TKIND_INTERFACE:
3302         pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3303         break;
3304
3305       case TKIND_COCLASS:
3306         pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3307         break;
3308
3309       case TKIND_ALIAS:
3310         pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3311         if (pTITail->tdescalias_vt)
3312           (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3313         break;
3314
3315       case TKIND_DISPATCH:
3316         pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3317         break;
3318
3319       default:
3320         FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3321         pTITail = NULL;
3322         break;
3323
3324       }
3325
3326       if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3327                        but we've already set those */
3328           (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3329           (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3330           (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3331
3332 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3333           X(06);
3334           X(08);
3335           X(0a);
3336           X(0c);
3337           X(0e);
3338           X(10);
3339           X(12);
3340           X(16);
3341           X(18);
3342           X(1a);
3343           X(1c);
3344           X(1e);
3345           X(24);
3346           X(26);
3347           X(2a);
3348           X(2c);
3349           X(2e);
3350           X(30);
3351           X(32);
3352           X(34);
3353       }
3354       ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3355       pBlk = (char*)pBlk + pBlkEntry[order].len;
3356     }
3357
3358     if(i != pTypeLibImpl->TypeInfoCount) {
3359       FIXME("Somehow processed %d TypeInfos\n", i);
3360       return NULL;
3361     }
3362
3363     HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3364     return (ITypeLib2*)pTypeLibImpl;
3365 }
3366
3367 /* ITypeLib::QueryInterface
3368  */
3369 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3370         ITypeLib2 * iface,
3371         REFIID riid,
3372         VOID **ppvObject)
3373 {
3374     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3375
3376     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3377
3378     *ppvObject=NULL;
3379     if(IsEqualIID(riid, &IID_IUnknown) ||
3380        IsEqualIID(riid,&IID_ITypeLib)||
3381        IsEqualIID(riid,&IID_ITypeLib2))
3382     {
3383         *ppvObject = This;
3384     }
3385
3386     if(*ppvObject)
3387     {
3388         ITypeLib2_AddRef(iface);
3389         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3390         return S_OK;
3391     }
3392     TRACE("-- Interface: E_NOINTERFACE\n");
3393     return E_NOINTERFACE;
3394 }
3395
3396 /* ITypeLib::AddRef
3397  */
3398 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3399 {
3400     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3401
3402     TRACE("(%p)->ref was %u\n",This, This->ref);
3403
3404     return ++(This->ref);
3405 }
3406
3407 /* ITypeLib::Release
3408  */
3409 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3410 {
3411     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3412
3413     --(This->ref);
3414
3415     TRACE("(%p)->(%u)\n",This, This->ref);
3416
3417     if (!This->ref)
3418     {
3419       /* remove cache entry */
3420       TRACE("removing from cache list\n");
3421       EnterCriticalSection(&cache_section);
3422       if (This->next) This->next->prev = This->prev;
3423       if (This->prev) This->prev->next = This->next;
3424       else tlb_cache_first = This->next;
3425       LeaveCriticalSection(&cache_section);
3426
3427       /* FIXME destroy child objects */
3428       TRACE(" destroying ITypeLib(%p)\n",This);
3429
3430       if (This->Name)
3431       {
3432           SysFreeString(This->Name);
3433           This->Name = NULL;
3434       }
3435
3436       if (This->DocString)
3437       {
3438           SysFreeString(This->DocString);
3439           This->DocString = NULL;
3440       }
3441
3442       if (This->HelpFile)
3443       {
3444           SysFreeString(This->HelpFile);
3445           This->HelpFile = NULL;
3446       }
3447
3448       if (This->HelpStringDll)
3449       {
3450           SysFreeString(This->HelpStringDll);
3451           This->HelpStringDll = NULL;
3452       }
3453
3454       if (This->pTypeInfo) /* can be NULL */
3455           ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3456       HeapFree(GetProcessHeap(),0,This);
3457       return 0;
3458     }
3459
3460     return This->ref;
3461 }
3462
3463 /* ITypeLib::GetTypeInfoCount
3464  *
3465  * Returns the number of type descriptions in the type library
3466  */
3467 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3468 {
3469     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3470     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3471     return This->TypeInfoCount;
3472 }
3473
3474 /* ITypeLib::GetTypeInfo
3475  *
3476  * retrieves the specified type description in the library.
3477  */
3478 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3479     ITypeLib2 *iface,
3480     UINT index,
3481     ITypeInfo **ppTInfo)
3482 {
3483     int i;
3484
3485     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3486     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3487
3488     TRACE("(%p)->(index=%d) \n", This, index);
3489
3490     if (!ppTInfo) return E_INVALIDARG;
3491
3492     /* search element n in list */
3493     for(i=0; i < index; i++)
3494     {
3495       pTypeInfo = pTypeInfo->next;
3496       if (!pTypeInfo)
3497       {
3498         TRACE("-- element not found\n");
3499         return TYPE_E_ELEMENTNOTFOUND;
3500       }
3501     }
3502
3503     *ppTInfo = (ITypeInfo *) pTypeInfo;
3504
3505     ITypeInfo_AddRef(*ppTInfo);
3506     TRACE("-- found (%p)\n",*ppTInfo);
3507     return S_OK;
3508 }
3509
3510
3511 /* ITypeLibs::GetTypeInfoType
3512  *
3513  * Retrieves the type of a type description.
3514  */
3515 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3516     ITypeLib2 *iface,
3517     UINT index,
3518     TYPEKIND *pTKind)
3519 {
3520     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3521     int i;
3522     ITypeInfoImpl *pTInfo = This->pTypeInfo;
3523
3524     TRACE("(%p) index %d \n",This, index);
3525
3526     if(!pTKind) return E_INVALIDARG;
3527
3528     /* search element n in list */
3529     for(i=0; i < index; i++)
3530     {
3531       if(!pTInfo)
3532       {
3533         TRACE("-- element not found\n");
3534         return TYPE_E_ELEMENTNOTFOUND;
3535       }
3536       pTInfo = pTInfo->next;
3537     }
3538
3539     *pTKind = pTInfo->TypeAttr.typekind;
3540     TRACE("-- found Type (%d)\n", *pTKind);
3541     return S_OK;
3542 }
3543
3544 /* ITypeLib::GetTypeInfoOfGuid
3545  *
3546  * Retrieves the type description that corresponds to the specified GUID.
3547  *
3548  */
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3550     ITypeLib2 *iface,
3551     REFGUID guid,
3552     ITypeInfo **ppTInfo)
3553 {
3554     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3555     ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3556
3557     TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3558
3559     if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3560
3561     /* search linked list for guid */
3562     while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3563     {
3564       pTypeInfo = pTypeInfo->next;
3565
3566       if (!pTypeInfo)
3567       {
3568         /* end of list reached */
3569         TRACE("-- element not found\n");
3570         return TYPE_E_ELEMENTNOTFOUND;
3571       }
3572     }
3573
3574     TRACE("-- found (%p, %s)\n",
3575           pTypeInfo,
3576           debugstr_w(pTypeInfo->Name));
3577
3578     *ppTInfo = (ITypeInfo*)pTypeInfo;
3579     ITypeInfo_AddRef(*ppTInfo);
3580     return S_OK;
3581 }
3582
3583 /* ITypeLib::GetLibAttr
3584  *
3585  * Retrieves the structure that contains the library's attributes.
3586  *
3587  */
3588 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3589         ITypeLib2 *iface,
3590         LPTLIBATTR *ppTLibAttr)
3591 {
3592     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3593     TRACE("(%p)\n",This);
3594     *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3595     memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3596     return S_OK;
3597 }
3598
3599 /* ITypeLib::GetTypeComp
3600  *
3601  * Enables a client compiler to bind to a library's types, variables,
3602  * constants, and global functions.
3603  *
3604  */
3605 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3606         ITypeLib2 *iface,
3607         ITypeComp **ppTComp)
3608 {
3609     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3610
3611     TRACE("(%p)->(%p)\n",This,ppTComp);
3612     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3613     ITypeComp_AddRef(*ppTComp);
3614
3615     return S_OK;
3616 }
3617
3618 /* ITypeLib::GetDocumentation
3619  *
3620  * Retrieves the library's documentation string, the complete Help file name
3621  * and path, and the context identifier for the library Help topic in the Help
3622  * file.
3623  *
3624  * On a successful return all non-null BSTR pointers will have been set,
3625  * possibly to NULL.
3626  */
3627 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3628     ITypeLib2 *iface,
3629     INT index,
3630     BSTR *pBstrName,
3631     BSTR *pBstrDocString,
3632     DWORD *pdwHelpContext,
3633     BSTR *pBstrHelpFile)
3634 {
3635     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3636
3637     HRESULT result = E_INVALIDARG;
3638
3639     ITypeInfo *pTInfo;
3640
3641
3642     TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3643         This, index,
3644         pBstrName, pBstrDocString,
3645         pdwHelpContext, pBstrHelpFile);
3646
3647     if(index<0)
3648     {
3649         /* documentation for the typelib */
3650         if(pBstrName)
3651         {
3652             if (This->Name)
3653                 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3654             else
3655                 *pBstrName = NULL;
3656         }
3657         if(pBstrDocString)
3658         {
3659             if (This->DocString)
3660                 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3661             else if (This->Name)
3662                 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3663             else
3664                 *pBstrDocString = NULL;
3665         }
3666         if(pdwHelpContext)
3667         {
3668             *pdwHelpContext = This->dwHelpContext;
3669         }
3670         if(pBstrHelpFile)
3671         {
3672             if (This->HelpFile)
3673                 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3674             else
3675                 *pBstrHelpFile = NULL;
3676         }
3677
3678         result = S_OK;
3679     }
3680     else
3681     {
3682         /* for a typeinfo */
3683         result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3684
3685         if(SUCCEEDED(result))
3686         {
3687             result = ITypeInfo_GetDocumentation(pTInfo,
3688                                           MEMBERID_NIL,
3689                                           pBstrName,
3690                                           pBstrDocString,
3691                                           pdwHelpContext, pBstrHelpFile);
3692
3693             ITypeInfo_Release(pTInfo);
3694         }
3695     }
3696     return result;
3697 memerr3:
3698     if (pBstrDocString) SysFreeString (*pBstrDocString);
3699 memerr2:
3700     if (pBstrName) SysFreeString (*pBstrName);
3701 memerr1:
3702     return STG_E_INSUFFICIENTMEMORY;
3703 }
3704
3705 /* ITypeLib::IsName
3706  *
3707  * Indicates whether a passed-in string contains the name of a type or member
3708  * described in the library.
3709  *
3710  */
3711 static HRESULT WINAPI ITypeLib2_fnIsName(
3712         ITypeLib2 *iface,
3713         LPOLESTR szNameBuf,
3714         ULONG lHashVal,
3715         BOOL *pfName)
3716 {
3717     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3718     ITypeInfoImpl *pTInfo;
3719     TLBFuncDesc *pFInfo;
3720     TLBVarDesc *pVInfo;
3721     int i;
3722     UINT nNameBufLen = SysStringLen(szNameBuf);
3723
3724     TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3725           pfName);
3726
3727     *pfName=TRUE;
3728     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3729         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3730         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3731             if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3732             for(i=0;i<pFInfo->funcdesc.cParams;i++)
3733                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3734                     goto ITypeLib2_fnIsName_exit;
3735         }
3736         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3737             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3738
3739     }
3740     *pfName=FALSE;
3741
3742 ITypeLib2_fnIsName_exit:
3743     TRACE("(%p)slow! search for %s: %s found!\n", This,
3744           debugstr_w(szNameBuf), *pfName?"NOT":"");
3745
3746     return S_OK;
3747 }
3748
3749 /* ITypeLib::FindName
3750  *
3751  * Finds occurrences of a type description in a type library. This may be used
3752  * to quickly verify that a name exists in a type library.
3753  *
3754  */
3755 static HRESULT WINAPI ITypeLib2_fnFindName(
3756         ITypeLib2 *iface,
3757         LPOLESTR szNameBuf,
3758         ULONG lHashVal,
3759         ITypeInfo **ppTInfo,
3760         MEMBERID *rgMemId,
3761         UINT16 *pcFound)
3762 {
3763     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3764     ITypeInfoImpl *pTInfo;
3765     TLBFuncDesc *pFInfo;
3766     TLBVarDesc *pVInfo;
3767     int i,j = 0;
3768
3769     UINT nNameBufLen = SysStringLen(szNameBuf);
3770
3771     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3772         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3773         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3774             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3775             for(i=0;i<pFInfo->funcdesc.cParams;i++)
3776                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3777                     goto ITypeLib2_fnFindName_exit;
3778         }
3779         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3780             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3781         continue;
3782 ITypeLib2_fnFindName_exit:
3783         ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3784         ppTInfo[j]=(LPTYPEINFO)pTInfo;
3785         j++;
3786     }
3787     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3788           This, *pcFound, debugstr_w(szNameBuf), j);
3789
3790     *pcFound=j;
3791
3792     return S_OK;
3793 }
3794
3795 /* ITypeLib::ReleaseTLibAttr
3796  *
3797  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3798  *
3799  */
3800 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3801         ITypeLib2 *iface,
3802         TLIBATTR *pTLibAttr)
3803 {
3804     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3805     TRACE("freeing (%p)\n",This);
3806     HeapFree(GetProcessHeap(),0,pTLibAttr);
3807
3808 }
3809
3810 /* ITypeLib2::GetCustData
3811  *
3812  * gets the custom data
3813  */
3814 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3815         ITypeLib2 * iface,
3816         REFGUID guid,
3817         VARIANT *pVarVal)
3818 {
3819     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3820     TLBCustData *pCData;
3821
3822     for(pCData=This->pCustData; pCData; pCData = pCData->next)
3823     {
3824       if( IsEqualIID(guid, &pCData->guid)) break;
3825     }
3826
3827     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3828
3829     if(pCData)
3830     {
3831         VariantInit( pVarVal);
3832         VariantCopy( pVarVal, &pCData->data);
3833         return S_OK;
3834     }
3835     return E_INVALIDARG;  /* FIXME: correct? */
3836 }
3837
3838 /* ITypeLib2::GetLibStatistics
3839  *
3840  * Returns statistics about a type library that are required for efficient
3841  * sizing of hash tables.
3842  *
3843  */
3844 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3845         ITypeLib2 * iface,
3846         ULONG *pcUniqueNames,
3847         ULONG *pcchUniqueNames)
3848 {
3849     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3850
3851     FIXME("(%p): stub!\n", This);
3852
3853     if(pcUniqueNames) *pcUniqueNames=1;
3854     if(pcchUniqueNames) *pcchUniqueNames=1;
3855     return S_OK;
3856 }
3857
3858 /* ITypeLib2::GetDocumentation2
3859  *
3860  * Retrieves the library's documentation string, the complete Help file name
3861  * and path, the localization context to use, and the context ID for the
3862  * library Help topic in the Help file.
3863  *
3864  */
3865 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3866         ITypeLib2 * iface,
3867         INT index,
3868         LCID lcid,
3869         BSTR *pbstrHelpString,
3870         DWORD *pdwHelpStringContext,
3871         BSTR *pbstrHelpStringDll)
3872 {
3873     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3874     HRESULT result;
3875     ITypeInfo *pTInfo;
3876
3877     FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3878
3879     /* the help string should be obtained from the helpstringdll,
3880      * using the _DLLGetDocumentation function, based on the supplied
3881      * lcid. Nice to do sometime...
3882      */
3883     if(index<0)
3884     {
3885       /* documentation for the typelib */
3886       if(pbstrHelpString)
3887         *pbstrHelpString=SysAllocString(This->DocString);
3888       if(pdwHelpStringContext)
3889         *pdwHelpStringContext=This->dwHelpContext;
3890       if(pbstrHelpStringDll)
3891         *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3892
3893       result = S_OK;
3894     }
3895     else
3896     {
3897       /* for a typeinfo */
3898       result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3899
3900       if(SUCCEEDED(result))
3901       {
3902         ITypeInfo2 * pTInfo2;
3903         result = ITypeInfo_QueryInterface(pTInfo,
3904                                           &IID_ITypeInfo2,
3905                                           (LPVOID*) &pTInfo2);
3906
3907         if(SUCCEEDED(result))
3908         {
3909           result = ITypeInfo2_GetDocumentation2(pTInfo2,
3910                                            MEMBERID_NIL,
3911                                            lcid,
3912                                            pbstrHelpString,
3913                                            pdwHelpStringContext,
3914                                            pbstrHelpStringDll);
3915
3916           ITypeInfo2_Release(pTInfo2);
3917         }
3918
3919         ITypeInfo_Release(pTInfo);
3920       }
3921     }
3922     return result;
3923 }
3924
3925 /* ITypeLib2::GetAllCustData
3926  *
3927  * Gets all custom data items for the library.
3928  *
3929  */
3930 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3931         ITypeLib2 * iface,
3932         CUSTDATA *pCustData)
3933 {
3934     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3935     TLBCustData *pCData;
3936     int i;
3937     TRACE("(%p) returning %d items\n", This, This->ctCustData);
3938     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3939     if(pCustData->prgCustData ){
3940         pCustData->cCustData=This->ctCustData;
3941         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3942             pCustData->prgCustData[i].guid=pCData->guid;
3943             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3944         }
3945     }else{
3946         ERR(" OUT OF MEMORY! \n");
3947         return E_OUTOFMEMORY;
3948     }
3949     return S_OK;
3950 }
3951
3952 static ITypeLib2Vtbl tlbvt = {
3953     ITypeLib2_fnQueryInterface,
3954     ITypeLib2_fnAddRef,
3955     ITypeLib2_fnRelease,
3956     ITypeLib2_fnGetTypeInfoCount,
3957     ITypeLib2_fnGetTypeInfo,
3958     ITypeLib2_fnGetTypeInfoType,
3959     ITypeLib2_fnGetTypeInfoOfGuid,
3960     ITypeLib2_fnGetLibAttr,
3961     ITypeLib2_fnGetTypeComp,
3962     ITypeLib2_fnGetDocumentation,
3963     ITypeLib2_fnIsName,
3964     ITypeLib2_fnFindName,
3965     ITypeLib2_fnReleaseTLibAttr,
3966
3967     ITypeLib2_fnGetCustData,
3968     ITypeLib2_fnGetLibStatistics,
3969     ITypeLib2_fnGetDocumentation2,
3970     ITypeLib2_fnGetAllCustData
3971  };
3972
3973
3974 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3975 {
3976     ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3977
3978     return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3979 }
3980
3981 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3982 {
3983     ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3984
3985     return ITypeInfo_AddRef((ITypeInfo *)This);
3986 }
3987
3988 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3989 {
3990     ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3991
3992     return ITypeInfo_Release((ITypeInfo *)This);
3993 }
3994
3995 static HRESULT WINAPI ITypeLibComp_fnBind(
3996     ITypeComp * iface,
3997     OLECHAR * szName,
3998     unsigned long lHash,
3999     unsigned short wFlags,
4000     ITypeInfo ** ppTInfo,
4001     DESCKIND * pDescKind,
4002     BINDPTR * pBindPtr)
4003 {
4004     FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4005     return E_NOTIMPL;
4006 }
4007
4008 static HRESULT WINAPI ITypeLibComp_fnBindType(
4009     ITypeComp * iface,
4010     OLECHAR * szName,
4011     unsigned long lHash,
4012     ITypeInfo ** ppTInfo,
4013     ITypeComp ** ppTComp)
4014 {
4015     FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4016     return E_NOTIMPL;
4017 }
4018
4019 static ITypeCompVtbl tlbtcvt =
4020 {
4021
4022     ITypeLibComp_fnQueryInterface,
4023     ITypeLibComp_fnAddRef,
4024     ITypeLibComp_fnRelease,
4025
4026     ITypeLibComp_fnBind,
4027     ITypeLibComp_fnBindType
4028 };
4029
4030 /*================== ITypeInfo(2) Methods ===================================*/
4031 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4032 {
4033     ITypeInfoImpl * pTypeInfoImpl;
4034
4035     pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4036     if (pTypeInfoImpl)
4037     {
4038       pTypeInfoImpl->lpVtbl = &tinfvt;
4039       pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4040       pTypeInfoImpl->ref=1;
4041     }
4042     TRACE("(%p)\n", pTypeInfoImpl);
4043     return (ITypeInfo2*) pTypeInfoImpl;
4044 }
4045
4046 /* ITypeInfo::QueryInterface
4047  */
4048 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4049         ITypeInfo2 *iface,
4050         REFIID riid,
4051         VOID **ppvObject)
4052 {
4053     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4054
4055     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4056
4057     *ppvObject=NULL;
4058     if(IsEqualIID(riid, &IID_IUnknown) ||
4059             IsEqualIID(riid,&IID_ITypeInfo)||
4060             IsEqualIID(riid,&IID_ITypeInfo2))
4061         *ppvObject = This;
4062
4063     if(*ppvObject){
4064         ITypeInfo_AddRef(iface);
4065         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4066         return S_OK;
4067     }
4068     TRACE("-- Interface: E_NOINTERFACE\n");
4069     return E_NOINTERFACE;
4070 }
4071
4072 /* ITypeInfo::AddRef
4073  */
4074 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4075 {
4076     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4077
4078     ++(This->ref);
4079     ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4080
4081     TRACE("(%p)->ref is %u\n",This, This->ref);
4082     return This->ref;
4083 }
4084
4085 /* ITypeInfo::Release
4086  */
4087 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4088 {
4089     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4090
4091     --(This->ref);
4092
4093     TRACE("(%p)->(%u)\n",This, This->ref);
4094
4095     if (This->ref)   {
4096       /* We don't release ITypeLib when ref=0 becouse
4097          it means that funtion is called by ITypeLi2_Release */
4098       ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4099     } else   {
4100       FIXME("destroy child objects\n");
4101
4102       TRACE("destroying ITypeInfo(%p)\n",This);
4103       if (This->Name)
4104       {
4105           SysFreeString(This->Name);
4106           This->Name = 0;
4107       }
4108
4109       if (This->DocString)
4110       {
4111           SysFreeString(This->DocString);
4112           This->DocString = 0;
4113       }
4114
4115       if (This->next)
4116       {
4117         ITypeInfo_Release((ITypeInfo*)This->next);
4118       }
4119
4120       HeapFree(GetProcessHeap(),0,This);
4121       return 0;
4122     }
4123     return This->ref;
4124 }
4125
4126 /* ITypeInfo::GetTypeAttr
4127  *
4128  * Retrieves a TYPEATTR structure that contains the attributes of the type
4129  * description.
4130  *
4131  */
4132 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4133         LPTYPEATTR  *ppTypeAttr)
4134 {
4135     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4136     TRACE("(%p)\n",This);
4137     /* FIXME: must do a copy here */
4138     *ppTypeAttr=&This->TypeAttr;
4139     return S_OK;
4140 }
4141
4142 /* ITypeInfo::GetTypeComp
4143  *
4144  * Retrieves the ITypeComp interface for the type description, which enables a
4145  * client compiler to bind to the type description's members.
4146  *
4147  */
4148 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4149         ITypeComp  * *ppTComp)
4150 {
4151     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4152
4153     TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4154
4155     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4156     ITypeComp_AddRef(*ppTComp);
4157     return S_OK;
4158 }
4159
4160 /* ITypeInfo::GetFuncDesc
4161  *
4162  * Retrieves the FUNCDESC structure that contains information about a
4163  * specified function.
4164  *
4165  */
4166 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4167         LPFUNCDESC  *ppFuncDesc)
4168 {
4169     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4170     int i;
4171     TLBFuncDesc * pFDesc;
4172     TRACE("(%p) index %d\n", This, index);
4173     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4174         ;
4175     if(pFDesc){
4176         /* FIXME: must do a copy here */
4177         *ppFuncDesc=&pFDesc->funcdesc;
4178         return S_OK;
4179     }
4180     return E_INVALIDARG;
4181 }
4182
4183 /* ITypeInfo::GetVarDesc
4184  *
4185  * Retrieves a VARDESC structure that describes the specified variable.
4186  *
4187  */
4188 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4189         LPVARDESC  *ppVarDesc)
4190 {
4191     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4192     int i;
4193     TLBVarDesc * pVDesc;
4194     TRACE("(%p) index %d\n", This, index);
4195     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4196         ;
4197     if(pVDesc){
4198         /* FIXME: must do a copy here */
4199         *ppVarDesc=&pVDesc->vardesc;
4200         return S_OK;
4201     }
4202     return E_INVALIDARG;
4203 }
4204
4205 /* ITypeInfo_GetNames
4206  *
4207  * Retrieves the variable with the specified member ID (or the name of the
4208  * property or method and its parameters) that correspond to the specified
4209  * function ID.
4210  */
4211 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4212         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
4213 {
4214     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4215     TLBFuncDesc * pFDesc;
4216     TLBVarDesc * pVDesc;
4217     int i;
4218     TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4219     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4220     if(pFDesc)
4221     {
4222       /* function found, now return function and parameter names */
4223       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4224       {
4225         if(!i)
4226           *rgBstrNames=SysAllocString(pFDesc->Name);
4227         else
4228           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4229       }
4230       *pcNames=i;
4231     }
4232     else
4233     {
4234       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4235       if(pVDesc)
4236       {
4237         *rgBstrNames=SysAllocString(pVDesc->Name);
4238         *pcNames=1;
4239       }
4240       else
4241       {
4242         if(This->TypeAttr.cImplTypes &&
4243            (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4244           /* recursive search */
4245           ITypeInfo *pTInfo;
4246           HRESULT result;
4247           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4248                                           &pTInfo);
4249           if(SUCCEEDED(result))
4250           {
4251             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4252             ITypeInfo_Release(pTInfo);
4253             return result;
4254           }
4255           WARN("Could not search inherited interface!\n");
4256         }
4257         else
4258         {
4259           WARN("no names found\n");
4260         }
4261         *pcNames=0;
4262         return TYPE_E_ELEMENTNOTFOUND;
4263       }
4264     }
4265     return S_OK;
4266 }
4267
4268
4269 /* ITypeInfo::GetRefTypeOfImplType
4270  *
4271  * If a type description describes a COM class, it retrieves the type
4272  * description of the implemented interface types. For an interface,
4273  * GetRefTypeOfImplType returns the type information for inherited interfaces,
4274  * if any exist.
4275  *
4276  */
4277 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4278         ITypeInfo2 *iface,
4279         UINT index,
4280         HREFTYPE  *pRefType)
4281 {
4282     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4283     int(i);
4284     TLBImplType *pImpl = This->impltypelist;
4285
4286     TRACE("(%p) index %d\n", This, index);
4287     if (TRACE_ON(ole)) dump_TypeInfo(This);
4288
4289     if(index==(UINT)-1)
4290     {
4291       /* only valid on dual interfaces;
4292          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4293       */
4294       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4295
4296       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4297           This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4298       {
4299         *pRefType = -1;
4300       }
4301       else
4302       {
4303         if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4304         *pRefType = pImpl->hRef;
4305       }
4306     }
4307     else
4308     {
4309       /* get element n from linked list */
4310       for(i=0; pImpl && i<index; i++)
4311       {
4312         pImpl = pImpl->next;
4313       }
4314
4315       if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4316
4317       *pRefType = pImpl->hRef;
4318
4319       TRACE("-- 0x%08lx\n", pImpl->hRef );
4320     }
4321
4322     return S_OK;
4323
4324 }
4325
4326 /* ITypeInfo::GetImplTypeFlags
4327  *
4328  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4329  * or base interface in a type description.
4330  */
4331 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4332         UINT index, INT  *pImplTypeFlags)
4333 {
4334     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4335     int i;
4336     TLBImplType *pImpl;
4337
4338     TRACE("(%p) index %d\n", This, index);
4339     for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4340         i++, pImpl=pImpl->next)
4341         ;
4342     if(i==index && pImpl){
4343         *pImplTypeFlags=pImpl->implflags;
4344         return S_OK;
4345     }
4346     *pImplTypeFlags=0;
4347     return TYPE_E_ELEMENTNOTFOUND;
4348 }
4349
4350 /* GetIDsOfNames
4351  * Maps between member names and member IDs, and parameter names and
4352  * parameter IDs.
4353  */
4354 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4355         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
4356 {
4357     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4358     TLBFuncDesc * pFDesc;
4359     TLBVarDesc * pVDesc;
4360     HRESULT ret=S_OK;
4361
4362     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4363             cNames);
4364     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4365         int i, j;
4366         if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4367             if(cNames) *pMemId=pFDesc->funcdesc.memid;
4368             for(i=1; i < cNames; i++){
4369                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4370                     if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4371                             break;
4372                 if( j<pFDesc->funcdesc.cParams)
4373                     pMemId[i]=j;
4374                 else
4375                    ret=DISP_E_UNKNOWNNAME;
4376             };
4377             return ret;
4378         }
4379     }
4380     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4381         if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4382             if(cNames) *pMemId=pVDesc->vardesc.memid;
4383             return ret;
4384         }
4385     }
4386     /* not found, see if this is and interface with an inheritance */
4387     if(This->TypeAttr.cImplTypes &&
4388        (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4389         /* recursive search */
4390         ITypeInfo *pTInfo;
4391         ret=ITypeInfo_GetRefTypeInfo(iface,
4392                 This->impltypelist->hRef, &pTInfo);
4393         if(SUCCEEDED(ret)){
4394             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4395             ITypeInfo_Release(pTInfo);
4396             return ret;
4397         }
4398         WARN("Could not search inherited interface!\n");
4399     } else
4400         WARN("no names found\n");
4401     return DISP_E_UNKNOWNNAME;
4402 }
4403
4404 /* ITypeInfo::Invoke
4405  *
4406  * Invokes a method, or accesses a property of an object, that implements the
4407  * interface described by the type description.
4408  */
4409 DWORD
4410 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4411     DWORD res;
4412
4413     if (TRACE_ON(ole)) {
4414         int i;
4415         TRACE("Calling %p(",func);
4416         for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4417         TRACE(")\n");
4418     }
4419
4420     switch (callconv) {
4421     case CC_STDCALL:
4422
4423         switch (nrargs) {
4424         case 0:
4425                 res = func();
4426                 break;
4427         case 1:
4428                 res = func(args[0]);
4429                 break;
4430         case 2:
4431                 res = func(args[0],args[1]);
4432                 break;
4433         case 3:
4434                 res = func(args[0],args[1],args[2]);
4435                 break;
4436         case 4:
4437                 res = func(args[0],args[1],args[2],args[3]);
4438                 break;
4439         case 5:
4440                 res = func(args[0],args[1],args[2],args[3],args[4]);
4441                 break;
4442         case 6:
4443                 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4444                 break;
4445         case 7:
4446                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4447                 break;
4448         case 8:
4449                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4450                 break;
4451         case 9:
4452                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4453                 break;
4454         case 10:
4455                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4456                 break;
4457         case 11:
4458                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4459                 break;
4460         default:
4461                 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4462                 res = -1;
4463                 break;
4464         }
4465         break;
4466     default:
4467         FIXME("unsupported calling convention %d\n",callconv);
4468         res = -1;
4469         break;
4470     }
4471     TRACE("returns %08lx\n",res);
4472     return res;
4473 }
4474
4475 extern int const _argsize(DWORD vt);
4476
4477 /****************************************************************************
4478  * Helper functions for Dispcall / Invoke, which copies one variant
4479  * with target type onto the argument stack.
4480  */
4481 static HRESULT
4482 _copy_arg(      ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4483                 DWORD *argpos, VARIANT *arg, VARTYPE vt
4484 ) {
4485     UINT arglen = _argsize(vt)*sizeof(DWORD);
4486     VARTYPE     oldvt;
4487     VARIANT     va;
4488
4489     if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4490         memcpy(argpos,&arg,sizeof(void*));
4491         return S_OK;
4492     }
4493
4494     if (V_VT(arg) == vt) {
4495         memcpy(argpos, &V_UNION(arg,lVal), arglen);
4496         return S_OK;
4497     }
4498
4499     if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4500         memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4501         return S_OK;
4502     }
4503
4504     if (vt == VT_VARIANT) {
4505         memcpy(argpos, arg, arglen);
4506         return S_OK;
4507     }
4508     /* Deref BYREF vars if there is need */
4509     if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4510         memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4511         return S_OK;
4512     }
4513     if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4514         /* in this context, if the type lib specifies IUnknown*, giving an
4515            IDispatch* is correct; so, don't invoke VariantChangeType */
4516         memcpy(argpos,&V_UNION(arg,lVal), arglen);
4517         return S_OK;
4518     }
4519     if ((vt == VT_PTR) && tdesc)
4520         return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4521
4522     if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4523         ITypeInfo       *tinfo2 = NULL;
4524         TYPEATTR        *tattr = NULL;
4525         HRESULT         hres;
4526
4527         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4528         if (hres) {
4529             FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4530                   "while coercing from vt 0x%x. Copying 4 byte.\n",
4531                   tdesc->u.hreftype,V_VT(arg));
4532             memcpy(argpos, &V_UNION(arg,lVal), 4);
4533             return S_OK;
4534         }
4535         hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4536         if( hres )
4537         {
4538             ERR("GetTypeAttr failed\n");
4539             ITypeInfo_Release(tinfo2);
4540             return hres;
4541         }
4542         switch (tattr->typekind) {
4543         case TKIND_ENUM:
4544           switch ( V_VT( arg ) ) {
4545           case VT_I2:
4546              *argpos = V_UNION(arg,iVal);
4547              hres = S_OK;
4548              break;
4549           case VT_I4:
4550              memcpy(argpos, &V_UNION(arg,lVal), 4);
4551              hres = S_OK;
4552              break;
4553           default:
4554              FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4555              hres = E_FAIL;
4556              break;
4557           }
4558           break;
4559
4560         case TKIND_ALIAS:
4561             tdesc = &(tattr->tdescAlias);
4562             hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4563             break;
4564
4565         case TKIND_INTERFACE:
4566             if (V_VT(arg) == VT_DISPATCH) {
4567                 IDispatch *disp;
4568                 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4569                     memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4570                     hres = S_OK;
4571                     break;
4572                 }
4573                 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4574                                              &IID_IDispatch,(LPVOID*)&disp);
4575                 if (SUCCEEDED(hres)) {
4576                     memcpy(argpos,&disp,4);
4577                     IUnknown_Release(V_UNION(arg,pdispVal));
4578                     hres = S_OK;
4579                     break;
4580                 }
4581                 FIXME("Failed to query IDispatch interface from %s while "
4582                      "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4583                 hres = E_FAIL;
4584                 break;
4585             }
4586             if (V_VT(arg) == VT_UNKNOWN) {
4587                 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4588                 hres = S_OK;
4589                 break;
4590             }
4591             FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4592                   V_VT(arg),debugstr_guid(&(tattr->guid)));
4593             hres = E_FAIL;
4594             break;
4595
4596         case TKIND_DISPATCH:
4597             if (V_VT(arg) == VT_DISPATCH) {
4598                 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4599                 hres = S_OK;
4600             }
4601             else {
4602                 hres = E_FAIL;
4603                 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4604             }
4605             break;
4606         case TKIND_RECORD:
4607             FIXME("TKIND_RECORD unhandled.\n");
4608             hres = E_FAIL;
4609             break;
4610         default:
4611             FIXME("TKIND %d unhandled.\n",tattr->typekind);
4612             hres = E_FAIL;
4613             break;
4614         }
4615         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4616         ITypeInfo_Release(tinfo2);
4617         return hres;
4618     }
4619
4620     oldvt = V_VT(arg);
4621     VariantInit(&va);
4622     if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4623         memcpy(argpos,&V_UNION(&va,lVal), arglen);
4624         FIXME("Should not use VariantChangeType here."
4625               " (conversion from 0x%x -> 0x%x) %08lx\n",
4626                 V_VT(arg), vt, *argpos
4627         );
4628         return S_OK;
4629     }
4630     ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4631     return E_FAIL;
4632 }
4633
4634 /***********************************************************************
4635  *              DispCallFunc (OLEAUT32.@)
4636  */
4637 HRESULT WINAPI
4638 DispCallFunc(
4639     void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4640     VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4641 ) {
4642     int i, argsize, argspos;
4643     DWORD *args;
4644     HRESULT hres;
4645
4646     TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4647         pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4648     );
4649     /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4650     So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4651     argsize = 1;
4652     for (i=0;i<cActuals;i++) {
4653         TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4654         dump_Variant(prgpvarg[i]);
4655         argsize += _argsize(prgvt[i]);
4656     }
4657     args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4658     args[0] = (DWORD)pvInstance;      /* this is the fake IDispatch interface pointer */
4659     argspos = 1;
4660     for (i=0;i<cActuals;i++) {
4661         VARIANT *arg = prgpvarg[i];
4662         TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4663         _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4664         argspos += _argsize(prgvt[i]);
4665     }
4666
4667     if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4668     {
4669         _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4670         hres=S_OK;
4671     }
4672     else
4673     {
4674         FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4675         hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4676         FIXME("Method returned %lx\n",hres);
4677     }
4678     HeapFree(GetProcessHeap(),0,args);
4679     return hres;
4680 }
4681
4682 static HRESULT WINAPI ITypeInfo_fnInvoke(
4683     ITypeInfo2 *iface,
4684     VOID  *pIUnk,
4685     MEMBERID memid,
4686     UINT16 dwFlags,
4687     DISPPARAMS  *pDispParams,
4688     VARIANT  *pVarResult,
4689     EXCEPINFO  *pExcepInfo,
4690     UINT  *pArgErr)
4691 {
4692     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4693     TLBFuncDesc * pFDesc;
4694     TLBVarDesc * pVDesc;
4695     int i;
4696     HRESULT hres;
4697
4698     TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4699       This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4700     );
4701     dump_DispParms(pDispParams);
4702
4703     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4704         if (pFDesc->funcdesc.memid == memid) {
4705             if (pFDesc->funcdesc.invkind & dwFlags)
4706                 break;
4707         }
4708     
4709     if (pFDesc) {
4710         if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4711         /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4712         switch (pFDesc->funcdesc.funckind) {
4713         case FUNC_PUREVIRTUAL:
4714         case FUNC_VIRTUAL: {
4715             DWORD res;
4716             int   numargs, numargs2, argspos, args2pos;
4717             DWORD *args , *args2;
4718             VARIANT *rgvarg = HeapAlloc(GetProcessHeap(),0,sizeof(VARIANT)*pFDesc->funcdesc.cParams);
4719             memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4720
4721             numargs = 1; numargs2 = 0;
4722             for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4723                 if (i<pDispParams->cArgs)
4724                     numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4725                 else {
4726                     numargs     += 1; /* sizeof(lpvoid) */
4727                     numargs2    += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4728                 }
4729             }
4730
4731             args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4732             args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4733
4734             args[0] = (DWORD)pIUnk;
4735             argspos = 1; args2pos = 0;
4736             for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4737                 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4738                 if (i<pDispParams->cArgs) {
4739                     VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4740                     TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4741                     USHORT paramFlags = pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags;
4742                     if (paramFlags & PARAMFLAG_FOPT) {
4743                         if(i < pFDesc->funcdesc.cParams-pFDesc->funcdesc.cParamsOpt)
4744                             ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4745                         if(V_VT(arg) == VT_EMPTY
4746                           || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) {
4747                                /* FIXME: Documentation says that we do this when parameter is left unspecified.
4748                                          How to determine it? */
4749
4750                             if(paramFlags & PARAMFLAG_FHASDEFAULT)
4751                                 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4752                             V_VT(arg) = VT_ERROR;
4753                             V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4754                             arglen = _argsize(VT_ERROR);
4755                         }
4756                     }
4757                     hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4758                     if (FAILED(hres)) return hres;
4759                     argspos += arglen;
4760                 } else if(pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4761                     VARIANT *arg = &rgvarg[i];
4762                     TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4763                     if(i < pFDesc->funcdesc.cParams-pFDesc->funcdesc.cParamsOpt)
4764                         ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4765                     if(pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4766                         FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4767                     V_VT(arg) = VT_ERROR;
4768                     V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4769                     arglen = _argsize(VT_ERROR);
4770                     hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4771                     if (FAILED(hres)) return hres;
4772                     argspos += arglen;
4773                 } else {
4774                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4775                     if (tdesc->vt != VT_PTR)
4776                         FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4777                     /*FIXME: give pointers for the rest, so propertyget works*/
4778                     args[argspos] = (DWORD)&args2[args2pos];
4779
4780                     /* If pointer to variant, pass reference it. */
4781                     if ((tdesc->vt == VT_PTR) &&
4782                         (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4783                         pVarResult
4784                     )
4785                         args[argspos]= (DWORD)pVarResult;
4786                     argspos     += 1;
4787                     args2pos    += arglen;
4788                 }
4789             }
4790             if (pFDesc->funcdesc.cParamsOpt < 0)
4791                 FIXME("Does not support optional parameters (%d)\n",
4792                         pFDesc->funcdesc.cParamsOpt
4793                 );
4794
4795             res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4796                     pFDesc->funcdesc.callconv,
4797                     numargs,
4798                     args
4799             );
4800
4801             HeapFree(GetProcessHeap(), 0, rgvarg);
4802
4803             if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4804                 args2pos = 0;
4805                 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4806                     int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4807                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4808                    TYPEDESC i4_tdesc;
4809                    i4_tdesc.vt = VT_I4;
4810
4811                     /* If we are a pointer to a variant, we are done already */
4812                     if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4813                         continue;
4814
4815                     VariantInit(pVarResult);
4816                     memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4817
4818                     if (tdesc->vt == VT_PTR)
4819                         tdesc = tdesc->u.lptdesc;
4820                     if (tdesc->vt == VT_USERDEFINED) {
4821                         ITypeInfo       *tinfo2;
4822                         TYPEATTR        *tattr;
4823
4824                         hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4825                         if (hres) {
4826                             FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4827                             return E_FAIL;
4828                         }
4829                         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4830                         switch (tattr->typekind) {
4831                         case TKIND_ENUM:
4832                            /* force the return type to be VT_I4 */
4833                            tdesc = &i4_tdesc;
4834                             break;
4835                         case TKIND_ALIAS:
4836                             TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4837                             tdesc = &(tattr->tdescAlias);
4838                             break;
4839
4840                         case TKIND_INTERFACE:
4841                             FIXME("TKIND_INTERFACE unhandled.\n");
4842                             break;
4843                         case TKIND_DISPATCH:
4844                             FIXME("TKIND_DISPATCH unhandled.\n");
4845                             break;
4846                         case TKIND_RECORD:
4847                             FIXME("TKIND_RECORD unhandled.\n");
4848                             break;
4849                         default:
4850                             FIXME("TKIND %d unhandled.\n",tattr->typekind);
4851                             break;
4852                         }
4853                         ITypeInfo_Release(tinfo2);
4854                     }
4855                     V_VT(pVarResult) = tdesc->vt;
4856
4857                     /* HACK: VB5 likes this.
4858                      * I do not know why. There is 1 example in MSDN which uses
4859                      * this which appears broken (mixes int vals and
4860                      * IDispatch*.).
4861                      */
4862                     if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4863                         V_VT(pVarResult) = VT_DISPATCH;
4864                     TRACE("storing into variant:\n");
4865                     dump_Variant(pVarResult);
4866                     args2pos += arglen;
4867                 }
4868             }
4869             HeapFree(GetProcessHeap(),0,args2);
4870             HeapFree(GetProcessHeap(),0,args);
4871             return S_OK;
4872         }
4873         case FUNC_DISPATCH:  {
4874            IDispatch *disp;
4875            HRESULT hr;
4876
4877            hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4878            if (hr) {
4879                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4880                return hr;
4881            }
4882            FIXME("Calling Invoke in IDispatch iface. untested!\n");
4883            hr = IDispatch_Invoke(
4884                disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4885                pVarResult,pExcepInfo,pArgErr
4886            );
4887            if (hr)
4888                FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4889            IDispatch_Release(disp);
4890            return hr;
4891         }
4892         default:
4893            FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4894            return E_FAIL;
4895         }
4896     } else {
4897         for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4898             if (pVDesc->vardesc.memid == memid) {
4899                 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4900                 dump_TLBVarDesc(pVDesc);
4901                 break;
4902             }
4903         }
4904     }
4905     /* not found, look for it in inherited interfaces */
4906     if (This->TypeAttr.cImplTypes &&
4907         (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4908         /* recursive search */
4909         ITypeInfo *pTInfo;
4910         HRESULT hr;
4911         hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4912         if(SUCCEEDED(hr)){
4913             hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4914             ITypeInfo_Release(pTInfo);
4915             return hr;
4916         }
4917         WARN("Could not search inherited interface!\n");
4918     }
4919     ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4920     return DISP_E_MEMBERNOTFOUND;
4921 }
4922
4923 /* ITypeInfo::GetDocumentation
4924  *
4925  * Retrieves the documentation string, the complete Help file name and path,
4926  * and the context ID for the Help topic for a specified type description.
4927  *
4928  * (Can be tested by the Visual Basic Editor in Word for instance.)
4929  */
4930 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4931         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
4932         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
4933 {
4934     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4935     TLBFuncDesc * pFDesc;
4936     TLBVarDesc * pVDesc;
4937     TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4938           " HelpContext(%p) HelpFile(%p)\n",
4939         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4940     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4941         if(pBstrName)
4942             *pBstrName=SysAllocString(This->Name);
4943         if(pBstrDocString)
4944             *pBstrDocString=SysAllocString(This->DocString);
4945         if(pdwHelpContext)
4946             *pdwHelpContext=This->dwHelpContext;
4947         if(pBstrHelpFile)
4948             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4949         return S_OK;
4950     }else {/* for a member */
4951     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4952         if(pFDesc->funcdesc.memid==memid){
4953           if(pBstrName)
4954             *pBstrName = SysAllocString(pFDesc->Name);
4955           if(pBstrDocString)
4956             *pBstrDocString=SysAllocString(pFDesc->HelpString);
4957           if(pdwHelpContext)
4958             *pdwHelpContext=pFDesc->helpcontext;
4959           return S_OK;
4960         }
4961     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4962         if(pVDesc->vardesc.memid==memid){
4963             if(pBstrName)
4964               *pBstrName = SysAllocString(pVDesc->Name);
4965             if(pBstrDocString)
4966               *pBstrDocString=SysAllocString(pVDesc->HelpString);
4967             if(pdwHelpContext)
4968               *pdwHelpContext=pVDesc->HelpContext;
4969             return S_OK;
4970         }
4971     }
4972     return TYPE_E_ELEMENTNOTFOUND;
4973 }
4974
4975 /*  ITypeInfo::GetDllEntry
4976  *
4977  * Retrieves a description or specification of an entry point for a function
4978  * in a DLL.
4979  */
4980 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4981         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
4982         WORD  *pwOrdinal)
4983 {
4984     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4985     TLBFuncDesc *pFDesc;
4986
4987     FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4988
4989     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4990         if(pFDesc->funcdesc.memid==memid){
4991             dump_TypeInfo(This);
4992             dump_TLBFuncDescOne(pFDesc);
4993
4994             /* FIXME: This is wrong, but how do you find that out? */
4995             if (pBstrDllName) {
4996                 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4997                 *pBstrDllName = SysAllocString(oleaut32W);
4998             }
4999
5000             if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5001                 if (pBstrName)
5002                     *pBstrName = SysAllocString(pFDesc->Entry);
5003                 if (pwOrdinal)
5004                     *pwOrdinal = -1;
5005                 return S_OK;
5006             }
5007             if (pBstrName)
5008                 *pBstrName = NULL;
5009             if (pwOrdinal)
5010                 *pwOrdinal = (DWORD)pFDesc->Entry;
5011             return S_OK;
5012         }
5013     return E_FAIL;
5014 }
5015
5016 /* ITypeInfo::GetRefTypeInfo
5017  *
5018  * If a type description references other type descriptions, it retrieves
5019  * the referenced type descriptions.
5020  */
5021 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5022         ITypeInfo2 *iface,
5023         HREFTYPE hRefType,
5024         ITypeInfo  **ppTInfo)
5025 {
5026     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5027     HRESULT result = E_FAIL;
5028
5029
5030     if (hRefType == -1 &&
5031         (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
5032         (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
5033     {
5034           /* when we meet a DUAL dispinterface, we must create the interface
5035           * version of it.
5036           */
5037           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5038
5039
5040           /* the interface version contains the same information as the dispinterface
5041            * copy the contents of the structs.
5042            */
5043           *pTypeInfoImpl = *This;
5044           pTypeInfoImpl->ref = 1;
5045
5046           /* change the type to interface */
5047           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5048
5049           *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5050
5051           ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5052
5053           result = S_OK;
5054
5055     } else {
5056         TLBRefType *pRefType;
5057         for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5058             if(pRefType->reference == hRefType)
5059                 break;
5060         }
5061         if(!pRefType)
5062           FIXME("Can't find pRefType for ref %lx\n", hRefType);
5063         if(pRefType && hRefType != -1) {
5064             ITypeLib *pTLib = NULL;
5065
5066             if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5067                 int Index;
5068                 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5069             } else {
5070                 if(pRefType->pImpTLInfo->pImpTypeLib) {
5071                     TRACE("typeinfo in imported typelib that is already loaded\n");
5072                     pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5073                     ITypeLib2_AddRef((ITypeLib*) pTLib);
5074                     result = S_OK;
5075                 } else {
5076                     TRACE("typeinfo in imported typelib that isn't already loaded\n");
5077                     result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5078                                              pRefType->pImpTLInfo->wVersionMajor,
5079                                              pRefType->pImpTLInfo->wVersionMinor,
5080                                              pRefType->pImpTLInfo->lcid,
5081                                              &pTLib);
5082
5083                     if(!SUCCEEDED(result)) {
5084                         BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5085                         result=LoadTypeLib(libnam, &pTLib);
5086                         SysFreeString(libnam);
5087                     }
5088                     if(SUCCEEDED(result)) {
5089                         pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5090                         ITypeLib2_AddRef(pTLib);
5091                     }
5092                 }
5093             }
5094             if(SUCCEEDED(result)) {
5095                 if(pRefType->index == TLB_REF_USE_GUID)
5096                     result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5097                                                          &pRefType->guid,
5098                                                          ppTInfo);
5099                 else
5100                     result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5101                                                    ppTInfo);
5102             }
5103             if (pTLib != NULL)
5104                 ITypeLib2_Release(pTLib);
5105         }
5106     }
5107
5108     TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5109           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5110     return result;
5111 }
5112
5113 /* ITypeInfo::AddressOfMember
5114  *
5115  * Retrieves the addresses of static functions or variables, such as those
5116  * defined in a DLL.
5117  */
5118 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5119         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5120 {
5121     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5122     FIXME("(%p) stub!\n", This);
5123     return S_OK;
5124 }
5125
5126 /* ITypeInfo::CreateInstance
5127  *
5128  * Creates a new instance of a type that describes a component object class
5129  * (coclass).
5130  */
5131 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5132         IUnknown *pUnk, REFIID riid, VOID  **ppvObj)
5133 {
5134     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5135     FIXME("(%p) stub!\n", This);
5136     return S_OK;
5137 }
5138
5139 /* ITypeInfo::GetMops
5140  *
5141  * Retrieves marshalling information.
5142  */
5143 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5144                                 BSTR  *pBstrMops)
5145 {
5146     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5147     FIXME("(%p) stub!\n", This);
5148     return S_OK;
5149 }
5150
5151 /* ITypeInfo::GetContainingTypeLib
5152  *
5153  * Retrieves the containing type library and the index of the type description
5154  * within that type library.
5155  */
5156 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5157         ITypeLib  * *ppTLib, UINT  *pIndex)
5158 {
5159     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5160     
5161     /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5162     if (pIndex) {
5163       *pIndex=This->index;
5164       TRACE("returning pIndex=%d\n", *pIndex);
5165     }
5166     
5167     if (ppTLib) {
5168       *ppTLib=(LPTYPELIB )(This->pTypeLib);
5169       ITypeLib2_AddRef(*ppTLib);
5170       TRACE("returning ppTLib=%p\n", *ppTLib);
5171     }
5172     
5173     return S_OK;
5174 }
5175
5176 /* ITypeInfo::ReleaseTypeAttr
5177  *
5178  * Releases a TYPEATTR previously returned by GetTypeAttr.
5179  *
5180  */
5181 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5182         TYPEATTR* pTypeAttr)
5183 {
5184     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185     TRACE("(%p)->(%p)\n", This, pTypeAttr);
5186 }
5187
5188 /* ITypeInfo::ReleaseFuncDesc
5189  *
5190  * Releases a FUNCDESC previously returned by GetFuncDesc. *
5191  */
5192 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5193         ITypeInfo2 *iface,
5194         FUNCDESC *pFuncDesc)
5195 {
5196     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5197     TRACE("(%p)->(%p)\n", This, pFuncDesc);
5198 }
5199
5200 /* ITypeInfo::ReleaseVarDesc
5201  *
5202  * Releases a VARDESC previously returned by GetVarDesc.
5203  */
5204 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5205         VARDESC *pVarDesc)
5206 {
5207     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5208     TRACE("(%p)->(%p)\n", This, pVarDesc);
5209 }
5210
5211 /* ITypeInfo2::GetTypeKind
5212  *
5213  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5214  *
5215  */
5216 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5217     TYPEKIND *pTypeKind)
5218 {
5219     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5220     *pTypeKind=This->TypeAttr.typekind;
5221     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5222     return S_OK;
5223 }
5224
5225 /* ITypeInfo2::GetTypeFlags
5226  *
5227  * Returns the type flags without any allocations. This returns a DWORD type
5228  * flag, which expands the type flags without growing the TYPEATTR (type
5229  * attribute).
5230  *
5231  */
5232 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5233 {
5234     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5235     *pTypeFlags=This->TypeAttr.wTypeFlags;
5236     TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5237     return S_OK;
5238 }
5239
5240 /* ITypeInfo2::GetFuncIndexOfMemId
5241  * Binds to a specific member based on a known DISPID, where the member name
5242  * is not known (for example, when binding to a default member).
5243  *
5244  */
5245 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5246     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5247 {
5248     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5249     TLBFuncDesc *pFuncInfo;
5250     int i;
5251     HRESULT result;
5252     /* FIXME: should check for invKind??? */
5253     for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5254             memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5255     if(pFuncInfo){
5256         *pFuncIndex=i;
5257         result= S_OK;
5258     }else{
5259         *pFuncIndex=0;
5260         result=E_INVALIDARG;
5261     }
5262     TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5263           memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5264     return result;
5265 }
5266
5267 /* TypeInfo2::GetVarIndexOfMemId
5268  *
5269  * Binds to a specific member based on a known DISPID, where the member name
5270  * is not known (for example, when binding to a default member).
5271  *
5272  */
5273 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5274     MEMBERID memid, UINT *pVarIndex)
5275 {
5276     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5277     TLBVarDesc *pVarInfo;
5278     int i;
5279     HRESULT result;
5280     for(i=0, pVarInfo=This->varlist; pVarInfo &&
5281             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5282         ;
5283     if(pVarInfo){
5284         *pVarIndex=i;
5285         result= S_OK;
5286     }else{
5287         *pVarIndex=0;
5288         result=E_INVALIDARG;
5289     }
5290     TRACE("(%p) memid 0x%08lx -> %s\n", This,
5291           memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5292     return result;
5293 }
5294
5295 /* ITypeInfo2::GetCustData
5296  *
5297  * Gets the custom data
5298  */
5299 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5300         ITypeInfo2 * iface,
5301         REFGUID guid,
5302         VARIANT *pVarVal)
5303 {
5304     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5305     TLBCustData *pCData;
5306
5307     for(pCData=This->pCustData; pCData; pCData = pCData->next)
5308         if( IsEqualIID(guid, &pCData->guid)) break;
5309
5310     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5311
5312     if(pCData)
5313     {
5314         VariantInit( pVarVal);
5315         VariantCopy( pVarVal, &pCData->data);
5316         return S_OK;
5317     }
5318     return E_INVALIDARG;  /* FIXME: correct? */
5319 }
5320
5321 /* ITypeInfo2::GetFuncCustData
5322  *
5323  * Gets the custom data
5324  */
5325 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5326         ITypeInfo2 * iface,
5327         UINT index,
5328         REFGUID guid,
5329         VARIANT *pVarVal)
5330 {
5331     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5332     TLBCustData *pCData=NULL;
5333     TLBFuncDesc * pFDesc;
5334     int i;
5335     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5336             pFDesc=pFDesc->next);
5337
5338     if(pFDesc)
5339         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5340             if( IsEqualIID(guid, &pCData->guid)) break;
5341
5342     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5343
5344     if(pCData){
5345         VariantInit( pVarVal);
5346         VariantCopy( pVarVal, &pCData->data);
5347         return S_OK;
5348     }
5349     return E_INVALIDARG;  /* FIXME: correct? */
5350 }
5351
5352 /* ITypeInfo2::GetParamCustData
5353  *
5354  * Gets the custom data
5355  */
5356 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5357         ITypeInfo2 * iface,
5358         UINT indexFunc,
5359         UINT indexParam,
5360         REFGUID guid,
5361         VARIANT *pVarVal)
5362 {
5363     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5364     TLBCustData *pCData=NULL;
5365     TLBFuncDesc * pFDesc;
5366     int i;
5367
5368     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5369
5370     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5371         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5372                 pCData = pCData->next)
5373             if( IsEqualIID(guid, &pCData->guid)) break;
5374
5375     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5376
5377     if(pCData)
5378     {
5379         VariantInit( pVarVal);
5380         VariantCopy( pVarVal, &pCData->data);
5381         return S_OK;
5382     }
5383     return E_INVALIDARG;  /* FIXME: correct? */
5384 }
5385
5386 /* ITypeInfo2::GetVarCustData
5387  *
5388  * Gets the custom data
5389  */
5390 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5391         ITypeInfo2 * iface,
5392         UINT index,
5393         REFGUID guid,
5394         VARIANT *pVarVal)
5395 {
5396     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5397     TLBCustData *pCData=NULL;
5398     TLBVarDesc * pVDesc;
5399     int i;
5400
5401     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5402
5403     if(pVDesc)
5404     {
5405       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5406       {
5407         if( IsEqualIID(guid, &pCData->guid)) break;
5408       }
5409     }
5410
5411     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5412
5413     if(pCData)
5414     {
5415         VariantInit( pVarVal);
5416         VariantCopy( pVarVal, &pCData->data);
5417         return S_OK;
5418     }
5419     return E_INVALIDARG;  /* FIXME: correct? */
5420 }
5421
5422 /* ITypeInfo2::GetImplCustData
5423  *
5424  * Gets the custom data
5425  */
5426 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5427         ITypeInfo2 * iface,
5428         UINT index,
5429         REFGUID guid,
5430         VARIANT *pVarVal)
5431 {
5432     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5433     TLBCustData *pCData=NULL;
5434     TLBImplType * pRDesc;
5435     int i;
5436
5437     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5438
5439     if(pRDesc)
5440     {
5441       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5442       {
5443         if( IsEqualIID(guid, &pCData->guid)) break;
5444       }
5445     }
5446
5447     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5448
5449     if(pCData)
5450     {
5451         VariantInit( pVarVal);
5452         VariantCopy( pVarVal, &pCData->data);
5453         return S_OK;
5454     }
5455     return E_INVALIDARG;  /* FIXME: correct? */
5456 }
5457
5458 /* ITypeInfo2::GetDocumentation2
5459  *
5460  * Retrieves the documentation string, the complete Help file name and path,
5461  * the localization context to use, and the context ID for the library Help
5462  * topic in the Help file.
5463  *
5464  */
5465 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5466         ITypeInfo2 * iface,
5467         MEMBERID memid,
5468         LCID lcid,
5469         BSTR *pbstrHelpString,
5470         DWORD *pdwHelpStringContext,
5471         BSTR *pbstrHelpStringDll)
5472 {
5473     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5474     TLBFuncDesc * pFDesc;
5475     TLBVarDesc * pVDesc;
5476     TRACE("(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
5477           "HelpStringContext(%p) HelpStringDll(%p)\n",
5478           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5479           pbstrHelpStringDll );
5480     /* the help string should be obtained from the helpstringdll,
5481      * using the _DLLGetDocumentation function, based on the supplied
5482      * lcid. Nice to do sometime...
5483      */
5484     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5485         if(pbstrHelpString)
5486             *pbstrHelpString=SysAllocString(This->Name);
5487         if(pdwHelpStringContext)
5488             *pdwHelpStringContext=This->dwHelpStringContext;
5489         if(pbstrHelpStringDll)
5490             *pbstrHelpStringDll=
5491                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5492         return S_OK;
5493     }else {/* for a member */
5494     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5495         if(pFDesc->funcdesc.memid==memid){
5496              if(pbstrHelpString)
5497                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5498             if(pdwHelpStringContext)
5499                 *pdwHelpStringContext=pFDesc->HelpStringContext;
5500             if(pbstrHelpStringDll)
5501                 *pbstrHelpStringDll=
5502                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5503         return S_OK;
5504     }
5505     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5506         if(pVDesc->vardesc.memid==memid){
5507              if(pbstrHelpString)
5508                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5509             if(pdwHelpStringContext)
5510                 *pdwHelpStringContext=pVDesc->HelpStringContext;
5511             if(pbstrHelpStringDll)
5512                 *pbstrHelpStringDll=
5513                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5514             return S_OK;
5515         }
5516     }
5517     return TYPE_E_ELEMENTNOTFOUND;
5518 }
5519
5520 /* ITypeInfo2::GetAllCustData
5521  *
5522  * Gets all custom data items for the Type info.
5523  *
5524  */
5525 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5526         ITypeInfo2 * iface,
5527         CUSTDATA *pCustData)
5528 {
5529     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5530     TLBCustData *pCData;
5531     int i;
5532
5533     TRACE("(%p) returning %d items\n", This, This->ctCustData);
5534
5535     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5536     if(pCustData->prgCustData ){
5537         pCustData->cCustData=This->ctCustData;
5538         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5539             pCustData->prgCustData[i].guid=pCData->guid;
5540             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5541         }
5542     }else{
5543         ERR(" OUT OF MEMORY! \n");
5544         return E_OUTOFMEMORY;
5545     }
5546     return S_OK;
5547 }
5548
5549 /* ITypeInfo2::GetAllFuncCustData
5550  *
5551  * Gets all custom data items for the specified Function
5552  *
5553  */
5554 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5555         ITypeInfo2 * iface,
5556         UINT index,
5557         CUSTDATA *pCustData)
5558 {
5559     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5560     TLBCustData *pCData;
5561     TLBFuncDesc * pFDesc;
5562     int i;
5563     TRACE("(%p) index %d\n", This, index);
5564     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5565             pFDesc=pFDesc->next)
5566         ;
5567     if(pFDesc){
5568         pCustData->prgCustData =
5569             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5570         if(pCustData->prgCustData ){
5571             pCustData->cCustData=pFDesc->ctCustData;
5572             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5573                     pCData = pCData->next){
5574                 pCustData->prgCustData[i].guid=pCData->guid;
5575                 VariantCopy(& pCustData->prgCustData[i].varValue,
5576                         & pCData->data);
5577             }
5578         }else{
5579             ERR(" OUT OF MEMORY! \n");
5580             return E_OUTOFMEMORY;
5581         }
5582         return S_OK;
5583     }
5584     return TYPE_E_ELEMENTNOTFOUND;
5585 }
5586
5587 /* ITypeInfo2::GetAllParamCustData
5588  *
5589  * Gets all custom data items for the Functions
5590  *
5591  */
5592 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5593     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5594 {
5595     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5596     TLBCustData *pCData=NULL;
5597     TLBFuncDesc * pFDesc;
5598     int i;
5599     TRACE("(%p) index %d\n", This, indexFunc);
5600     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5601             pFDesc=pFDesc->next)
5602         ;
5603     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5604         pCustData->prgCustData =
5605             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5606                     sizeof(CUSTDATAITEM));
5607         if(pCustData->prgCustData ){
5608             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5609             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5610                     pCData; i++, pCData = pCData->next){
5611                 pCustData->prgCustData[i].guid=pCData->guid;
5612                 VariantCopy(& pCustData->prgCustData[i].varValue,
5613                         & pCData->data);
5614             }
5615         }else{
5616             ERR(" OUT OF MEMORY! \n");
5617             return E_OUTOFMEMORY;
5618         }
5619         return S_OK;
5620     }
5621     return TYPE_E_ELEMENTNOTFOUND;
5622 }
5623
5624 /* ITypeInfo2::GetAllVarCustData
5625  *
5626  * Gets all custom data items for the specified Variable
5627  *
5628  */
5629 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5630     UINT index, CUSTDATA *pCustData)
5631 {
5632     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5633     TLBCustData *pCData;
5634     TLBVarDesc * pVDesc;
5635     int i;
5636     TRACE("(%p) index %d\n", This, index);
5637     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5638             pVDesc=pVDesc->next)
5639         ;
5640     if(pVDesc){
5641         pCustData->prgCustData =
5642             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5643         if(pCustData->prgCustData ){
5644             pCustData->cCustData=pVDesc->ctCustData;
5645             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5646                     pCData = pCData->next){
5647                 pCustData->prgCustData[i].guid=pCData->guid;
5648                 VariantCopy(& pCustData->prgCustData[i].varValue,
5649                         & pCData->data);
5650             }
5651         }else{
5652             ERR(" OUT OF MEMORY! \n");
5653             return E_OUTOFMEMORY;
5654         }
5655         return S_OK;
5656     }
5657     return TYPE_E_ELEMENTNOTFOUND;
5658 }
5659
5660 /* ITypeInfo2::GetAllImplCustData
5661  *
5662  * Gets all custom data items for the specified implementation type
5663  *
5664  */
5665 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5666         ITypeInfo2 * iface,
5667         UINT index,
5668         CUSTDATA *pCustData)
5669 {
5670     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5671     TLBCustData *pCData;
5672     TLBImplType * pRDesc;
5673     int i;
5674     TRACE("(%p) index %d\n", This, index);
5675     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5676             pRDesc=pRDesc->next)
5677         ;
5678     if(pRDesc){
5679         pCustData->prgCustData =
5680             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5681         if(pCustData->prgCustData ){
5682             pCustData->cCustData=pRDesc->ctCustData;
5683             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5684                     pCData = pCData->next){
5685                 pCustData->prgCustData[i].guid=pCData->guid;
5686                 VariantCopy(& pCustData->prgCustData[i].varValue,
5687                         & pCData->data);
5688             }
5689         }else{
5690             ERR(" OUT OF MEMORY! \n");
5691             return E_OUTOFMEMORY;
5692         }
5693         return S_OK;
5694     }
5695     return TYPE_E_ELEMENTNOTFOUND;
5696 }
5697
5698 static ITypeInfo2Vtbl tinfvt =
5699 {
5700
5701     ITypeInfo_fnQueryInterface,
5702     ITypeInfo_fnAddRef,
5703     ITypeInfo_fnRelease,
5704
5705     ITypeInfo_fnGetTypeAttr,
5706     ITypeInfo_fnGetTypeComp,
5707     ITypeInfo_fnGetFuncDesc,
5708     ITypeInfo_fnGetVarDesc,
5709     ITypeInfo_fnGetNames,
5710     ITypeInfo_fnGetRefTypeOfImplType,
5711     ITypeInfo_fnGetImplTypeFlags,
5712     ITypeInfo_fnGetIDsOfNames,
5713     ITypeInfo_fnInvoke,
5714     ITypeInfo_fnGetDocumentation,
5715     ITypeInfo_fnGetDllEntry,
5716     ITypeInfo_fnGetRefTypeInfo,
5717     ITypeInfo_fnAddressOfMember,
5718     ITypeInfo_fnCreateInstance,
5719     ITypeInfo_fnGetMops,
5720     ITypeInfo_fnGetContainingTypeLib,
5721     ITypeInfo_fnReleaseTypeAttr,
5722     ITypeInfo_fnReleaseFuncDesc,
5723     ITypeInfo_fnReleaseVarDesc,
5724
5725     ITypeInfo2_fnGetTypeKind,
5726     ITypeInfo2_fnGetTypeFlags,
5727     ITypeInfo2_fnGetFuncIndexOfMemId,
5728     ITypeInfo2_fnGetVarIndexOfMemId,
5729     ITypeInfo2_fnGetCustData,
5730     ITypeInfo2_fnGetFuncCustData,
5731     ITypeInfo2_fnGetParamCustData,
5732     ITypeInfo2_fnGetVarCustData,
5733     ITypeInfo2_fnGetImplTypeCustData,
5734     ITypeInfo2_fnGetDocumentation2,
5735     ITypeInfo2_fnGetAllCustData,
5736     ITypeInfo2_fnGetAllFuncCustData,
5737     ITypeInfo2_fnGetAllParamCustData,
5738     ITypeInfo2_fnGetAllVarCustData,
5739     ITypeInfo2_fnGetAllImplTypeCustData,
5740 };
5741
5742 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5743 {
5744     ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5745
5746     return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5747 }
5748
5749 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5750 {
5751     ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5752
5753     return ITypeInfo_AddRef((ITypeInfo *)This);
5754 }
5755
5756 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5757 {
5758     ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5759
5760     return ITypeInfo_Release((ITypeInfo *)This);
5761 }
5762
5763 static HRESULT WINAPI ITypeComp_fnBind(
5764     ITypeComp * iface,
5765     OLECHAR * szName,
5766     unsigned long lHash,
5767     unsigned short wFlags,
5768     ITypeInfo ** ppTInfo,
5769     DESCKIND * pDescKind,
5770     BINDPTR * pBindPtr)
5771 {
5772     ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5773     TLBFuncDesc * pFDesc;
5774     TLBVarDesc * pVDesc;
5775
5776     TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5777
5778     for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5779         if (pFDesc->funcdesc.invkind & wFlags)
5780             if (!strcmpW(pFDesc->Name, szName)) {
5781                 break;
5782             }
5783
5784     if (pFDesc)
5785     {
5786         *pDescKind = DESCKIND_FUNCDESC;
5787         pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5788         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5789         return S_OK;
5790     } else {
5791         if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5792         {
5793             for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5794                 if (!strcmpW(pVDesc->Name, szName)) {
5795                     *pDescKind = DESCKIND_VARDESC;
5796                     pBindPtr->lpvardesc = &pVDesc->vardesc;
5797                     *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5798                     return S_OK;
5799                 }
5800             }
5801         }
5802     }
5803     /* not found, look for it in inherited interfaces */
5804     if (This->TypeAttr.cImplTypes &&
5805         (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5806         /* recursive search */
5807         ITypeInfo *pTInfo;
5808         ITypeComp *pTComp;
5809         HRESULT hr;
5810         hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5811         if (SUCCEEDED(hr))
5812         {
5813             hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5814             ITypeInfo_Release(pTInfo);
5815         }
5816         if (SUCCEEDED(hr))
5817         {
5818             hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5819             ITypeComp_Release(pTComp);
5820             return hr;
5821         }
5822         WARN("Could not search inherited interface!\n");
5823     }
5824     ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5825     *pDescKind = DESCKIND_NONE;
5826     pBindPtr->lpfuncdesc = NULL;
5827     *ppTInfo = NULL;
5828     return DISP_E_MEMBERNOTFOUND;
5829 }
5830
5831 static HRESULT WINAPI ITypeComp_fnBindType(
5832     ITypeComp * iface,
5833     OLECHAR * szName,
5834     unsigned long lHash,
5835     ITypeInfo ** ppTInfo,
5836     ITypeComp ** ppTComp)
5837 {
5838     TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5839
5840     /* strange behaviour (does nothing) but like the
5841      * original */
5842
5843     if (!ppTInfo || !ppTComp)
5844         return E_POINTER;
5845
5846     *ppTInfo = NULL;
5847     *ppTComp = NULL;
5848
5849     return S_OK;
5850 }
5851
5852 static ITypeCompVtbl tcompvt =
5853 {
5854
5855     ITypeComp_fnQueryInterface,
5856     ITypeComp_fnAddRef,
5857     ITypeComp_fnRelease,
5858
5859     ITypeComp_fnBind,
5860     ITypeComp_fnBindType
5861 };