4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
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.
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.
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
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
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.
34 * - locale stuff is partially implemented but hasn't been tested.
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.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
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
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.
63 #include "winnls.h" /* for PRIMARYLANGID */
64 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
67 #include "wine/unicode.h"
68 #include "wine/obj_base.h"
72 #include "wine/debug.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
78 /****************************************************************************
79 * QueryPathOfRegTypeLib [TYPELIB.14]
81 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
86 QueryPathOfRegTypeLib16(
87 REFGUID guid
, /* [in] referenced guid */
88 WORD wMaj
, /* [in] major version */
89 WORD wMin
, /* [in] minor version */
90 LCID lcid
, /* [in] locale id */
91 LPBSTR16 path
/* [out] path of typelib */
94 char typelibkey
[100],pathname
[260];
100 sprintf( typelibkey
, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
101 guid
->Data1
, guid
->Data2
, guid
->Data3
,
102 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
103 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
106 sprintf(xguid
,"<guid 0x%08lx>",(DWORD
)guid
);
107 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid
,wMaj
,wMin
,(DWORD
)lcid
,path
);
110 plen
= sizeof(pathname
);
111 if (RegQueryValueA(HKEY_LOCAL_MACHINE
,typelibkey
,pathname
,&plen
)) {
112 /* try again without lang specific id */
114 return QueryPathOfRegTypeLib16(guid
,wMaj
,wMin
,PRIMARYLANGID(lcid
),path
);
115 FIXME("key %s not found\n",typelibkey
);
118 *path
= SysAllocString16(pathname
);
122 /****************************************************************************
123 * QueryPathOfRegTypeLib [OLEAUT32.164]
128 QueryPathOfRegTypeLib(
129 REFGUID guid
, /* [in] referenced guid */
130 WORD wMaj
, /* [in] major version */
131 WORD wMin
, /* [in] minor version */
132 LCID lcid
, /* [in] locale id */
133 LPBSTR path
) /* [out] path of typelib */
135 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
136 string termination character on output strings */
140 DWORD dwPathLen
= _MAX_PATH
;
144 char szTypeLibKey
[100];
145 char szPath
[dwPathLen
];
153 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
159 sprintf(szTypeLibKey
,
160 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
161 guid
->Data1
, guid
->Data2
, guid
->Data3
,
162 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
163 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
168 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
172 else if (myLCID
== lcid
)
174 /* try with sub-langid */
175 myLCID
= SUBLANGID(lcid
);
177 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
179 /* try with system langid */
189 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
190 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
192 MultiByteToWideChar(CP_ACP
,
204 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
209 /******************************************************************************
210 * CreateTypeLib [OLEAUT32.160] creates a typelib
216 HRESULT WINAPI
CreateTypeLib(
217 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
219 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
222 /******************************************************************************
223 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
225 * Docs: OLECHAR FAR* szFile
226 * Docs: iTypeLib FAR* FAR* pptLib
232 HRESULT WINAPI
LoadTypeLib16(
233 LPOLESTR szFile
, /* [in] Name of file to load from */
234 ITypeLib
** pptLib
) /* [out] Pointer to pointer to loaded type library */
236 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR
)szFile
),pptLib
);
244 /******************************************************************************
245 * LoadTypeLib [OLEAUT32.161]
246 * Loads and registers a type library
248 * Docs: OLECHAR FAR* szFile
249 * Docs: iTypeLib FAR* FAR* pptLib
255 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
257 HRESULT WINAPI
LoadTypeLib(
258 const OLECHAR
*szFile
,/* [in] Name of file to load from */
259 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
262 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
265 /******************************************************************************
266 * LoadTypeLibEx [OLEAUT32.183]
267 * Loads and optionally registers a type library
273 HRESULT WINAPI
LoadTypeLibEx(
274 LPCOLESTR szFile
, /* [in] Name of file to load from */
275 REGKIND regkind
, /* [in] Specify kind of registration */
276 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
278 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
282 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
284 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
287 /* Look for a trailing '\\' followed by an index */
288 pIndexStr
= strrchrW(szFile
, '\\');
289 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
290 index
= wcstol(pIndexStr
, NULL
, 10);
291 memcpy(szFileCopy
, szFile
,
292 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
293 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
294 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
296 return TYPE_E_CANTLOADLIBRARY
;
297 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
298 return TYPE_E_CANTLOADLIBRARY
;
300 return TYPE_E_CANTLOADLIBRARY
;
303 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
305 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
310 case REGKIND_DEFAULT
:
311 /* FIXME: is this correct? */
312 if (!szFile
|| !szFile
[0] ||
313 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
315 /* else fall-through */
316 case REGKIND_REGISTER
:
317 /* FIXME: Help path? */
318 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
320 IUnknown_Release(*pptLib
);
328 TRACE(" returns %08lx\n",res
);
332 /******************************************************************************
333 * LoadRegTypeLib [OLEAUT32.162]
335 HRESULT WINAPI
LoadRegTypeLib(
336 REFGUID rguid
, /* [in] referenced guid */
337 WORD wVerMajor
, /* [in] major version */
338 WORD wVerMinor
, /* [in] minor version */
339 LCID lcid
, /* [in] locale id */
340 ITypeLib
**ppTLib
) /* [out] path of typelib */
343 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
347 res
= LoadTypeLib(bstr
, ppTLib
);
351 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
357 /******************************************************************************
358 * RegisterTypeLib [OLEAUT32.163]
359 * Adds information about a type library to the System Registry
361 * Docs: ITypeLib FAR * ptlib
362 * Docs: OLECHAR FAR* szFullPath
363 * Docs: OLECHAR FAR* szHelpDir
369 HRESULT WINAPI
RegisterTypeLib(
370 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
371 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
372 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
383 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
385 if (ptlib
== NULL
|| szFullPath
== NULL
)
388 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
391 StringFromGUID2(&attr
->guid
, guid
, 80);
392 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
393 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
394 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
395 HeapFree(GetProcessHeap(), 0, guidA
);
398 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
399 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
403 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
405 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
406 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
414 /* FIXME: This *seems* to be 0 always, not sure though */
415 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
416 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
418 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
419 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
427 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
428 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
431 /* FIXME: is %u correct? */
432 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
433 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
434 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
442 /* register OLE Automation-compatible interfaces for this typelib */
443 types
= ITypeLib_GetTypeInfoCount(ptlib
);
444 for (tidx
=0; tidx
<types
; tidx
++) {
445 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
446 LPOLESTR name
= NULL
;
447 ITypeInfo
*tinfo
= NULL
;
449 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
451 case TKIND_INTERFACE
:
452 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
453 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
456 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
457 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
460 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
461 /* coclasses should probably not be registered? */
464 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
468 TYPEATTR
*tattr
= NULL
;
469 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
471 TRACE_(typelib
)("guid=%s, flags=%04x\n",
472 debugstr_guid(&tattr
->guid
),
474 if (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
) {
475 /* register interface<->typelib coupling */
476 StringFromGUID2(&tattr
->guid
, guid
, 80);
477 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
478 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
479 HeapFree(GetProcessHeap(), 0, guidA
);
481 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
482 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
484 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
485 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
487 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
488 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
489 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
493 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
494 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
495 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
500 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
501 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
503 StringFromGUID2(&attr
->guid
, guid
, 80);
504 snprintf(ver
, sizeof(ver
), "%x.%x",
505 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
506 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
507 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
508 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
515 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
517 ITypeInfo_Release(tinfo
);
524 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
530 /******************************************************************************
531 * UnRegisterTypeLib [OLEAUT32.186]
532 * Removes information about a type library from the System Registry
539 HRESULT WINAPI
UnRegisterTypeLib(
540 REFGUID libid
, /* [in] Guid of the library */
541 WORD wVerMajor
, /* [in] major version */
542 WORD wVerMinor
, /* [in] minor version */
543 LCID lcid
, /* [in] locale id */
546 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
547 return S_OK
; /* FIXME: pretend everything is OK */
550 /****************************************************************************
551 * OaBuildVersion (TYPELIB.15)
553 * known TYPELIB.DLL versions:
555 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
556 * OLE 2.02 1993-94 02 3002
559 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
560 * OLE 2.1 NT 1993-95 ?? ???
561 * OLE 2.3.1 W95 23 700
562 * OLE2 4.0 NT4SP6 1993-98 40 4277
564 DWORD WINAPI
OaBuildVersion16(void)
566 /* FIXME: I'd like to return the highest currently known version value
567 * in case the user didn't force a --winver, but I don't know how
568 * to retrieve the "versionForced" info from misc/version.c :(
569 * (this would be useful in other places, too) */
570 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
571 switch(GetVersion() & 0x8000ffff) /* mask off build number */
573 case 0x80000a03: /* WIN31 */
574 return MAKELONG(3027, 3); /* WfW 3.11 */
575 case 0x80000004: /* WIN95 */
576 return MAKELONG(700, 23); /* Win95A */
577 case 0x80000a04: /* WIN98 */
578 return MAKELONG(3024, 10); /* W98 SE */
579 case 0x00000004: /* NT4 */
580 return MAKELONG(4277, 40); /* NT4 SP6 */
582 FIXME("Version value not known yet. Please investigate it!\n");
587 /* for better debugging info leave the static out for the time being */
590 /*======================= ITypeLib implementation =======================*/
592 typedef struct tagTLBCustData
596 struct tagTLBCustData
* next
;
599 /* data structure for import typelibs */
600 typedef struct tagTLBImpLib
602 int offset
; /* offset in the file (MSFT)
603 offset in nametable (SLTG)
604 just used to identify library while reading
606 GUID guid
; /* libid */
607 BSTR name
; /* name */
609 LCID lcid
; /* lcid of imported typelib */
611 WORD wVersionMajor
; /* major version number */
612 WORD wVersionMinor
; /* minor version number */
614 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
615 NULL if not yet loaded */
616 struct tagTLBImpLib
* next
;
619 /* internal ITypeLib data */
620 typedef struct tagITypeLibImpl
622 ICOM_VFIELD(ITypeLib2
);
624 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
626 /* strings can be stored in tlb as multibyte strings BUT they are *always*
627 * exported to the application as a UNICODE string.
633 unsigned long dwHelpContext
;
634 int TypeInfoCount
; /* nr of typeinfo's in librarry */
635 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
636 int ctCustData
; /* number of items in cust data list */
637 TLBCustData
* pCustData
; /* linked list to cust data */
638 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
639 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
640 libary. Only used while read MSFT
644 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
646 /* ITypeLib methods */
647 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
648 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
650 /*======================= ITypeInfo implementation =======================*/
652 /* data for refernced types */
653 typedef struct tagTLBRefType
655 INT index
; /* Type index for internal ref or for external ref
656 it the format is SLTG. -2 indicates to
659 GUID guid
; /* guid of the referenced type */
660 /* if index == TLB_REF_USE_GUID */
662 HREFTYPE reference
; /* The href of this ref */
663 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
664 TLB_REF_INTERNAL for internal refs
665 TLB_REF_NOT_FOUND for broken refs */
667 struct tagTLBRefType
* next
;
670 #define TLB_REF_USE_GUID -2
672 #define TLB_REF_INTERNAL (void*)-2
673 #define TLB_REF_NOT_FOUND (void*)-1
675 /* internal Parameter data */
676 typedef struct tagTLBParDesc
680 TLBCustData
* pCustData
; /* linked list to cust data */
683 /* internal Function data */
684 typedef struct tagTLBFuncDesc
686 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
687 BSTR Name
; /* the name of this function */
688 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
690 int HelpStringContext
;
692 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
694 TLBCustData
* pCustData
; /* linked list to cust data; */
695 struct tagTLBFuncDesc
* next
;
698 /* internal Variable data */
699 typedef struct tagTLBVarDesc
701 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
702 BSTR Name
; /* the name of this variable */
704 int HelpStringContext
; /* FIXME: where? */
707 TLBCustData
* pCustData
;/* linked list to cust data; */
708 struct tagTLBVarDesc
* next
;
711 /* internal implemented interface data */
712 typedef struct tagTLBImplType
714 HREFTYPE hRef
; /* hRef of interface */
715 int implflags
; /* IMPLFLAG_*s */
717 TLBCustData
* pCustData
;/* linked list to custom data; */
718 struct tagTLBImplType
*next
;
721 /* internal TypeInfo data */
722 typedef struct tagITypeInfoImpl
724 ICOM_VFIELD(ITypeInfo2
);
726 TYPEATTR TypeAttr
; /* _lots_ of type information. */
727 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
728 int index
; /* index in this typelib; */
729 /* type libs seem to store the doc strings in ascii
730 * so why should we do it in unicode?
734 unsigned long dwHelpContext
;
735 unsigned long dwHelpStringContext
;
738 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
741 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
743 /* Implemented Interfaces */
744 TLBImplType
* impltypelist
;
746 TLBRefType
* reflist
;
748 TLBCustData
* pCustData
; /* linked list to cust data; */
749 struct tagITypeInfoImpl
* next
;
752 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
754 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
756 typedef struct tagTLBContext
758 unsigned int oStart
; /* start of TLB in file */
759 unsigned int pos
; /* current pos */
760 unsigned int length
; /* total length */
761 void *mapping
; /* memory mapping */
762 MSFT_SegDir
* pTblDir
;
763 ITypeLibImpl
* pLibInfo
;
767 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
772 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
773 /* FIXME : we could have better trace here, depending on the VARTYPE
776 if (vt
& VT_RESERVED
)
777 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
779 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
781 szVarType
+= strlen(strcpy(szVarType
, "array of "));
783 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
784 switch(vt
& VT_TYPEMASK
) {
785 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
786 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
787 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
788 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
789 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
790 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
791 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
792 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
793 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
794 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
795 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
796 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
797 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
798 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
799 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
800 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
801 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
802 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
803 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
804 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
805 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
809 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
810 if (pTD
->vt
& VT_RESERVED
)
811 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
812 if (pTD
->vt
& VT_BYREF
)
813 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
814 if (pTD
->vt
& VT_ARRAY
)
815 szVarType
+= strlen(strcpy(szVarType
, "array of "));
816 if (pTD
->vt
& VT_VECTOR
)
817 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
818 switch(pTD
->vt
& VT_TYPEMASK
) {
819 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
820 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
821 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
822 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
823 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
824 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
825 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
826 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
827 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
828 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
829 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
830 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
831 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
832 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
833 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
834 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
835 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
836 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
837 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
838 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
839 pTD
->u
.hreftype
); break;
840 case VT_PTR
: sprintf(szVarType
, "ptr to ");
841 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
843 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
844 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
846 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
847 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
848 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
851 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
855 static void dump_ELEMDESC(ELEMDESC
*edesc
) {
857 dump_TypeDesc(&edesc
->tdesc
,buf
);
858 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
859 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
860 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
862 static void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
864 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
865 for (i
=0;i
<funcdesc
->cParams
;i
++) {
866 MESSAGE("Param %d:\n",i
);
867 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
869 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
870 switch (funcdesc
->funckind
) {
871 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
872 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
873 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
874 case FUNC_STATIC
: MESSAGE("static");break;
875 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
876 default: MESSAGE("unknown");break;
878 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
879 switch (funcdesc
->invkind
) {
880 case INVOKE_FUNC
: MESSAGE("func");break;
881 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
882 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
883 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
885 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
886 switch (funcdesc
->callconv
) {
887 case CC_CDECL
: MESSAGE("cdecl");break;
888 case CC_PASCAL
: MESSAGE("pascal");break;
889 case CC_STDCALL
: MESSAGE("stdcall");break;
890 case CC_SYSCALL
: MESSAGE("syscall");break;
893 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
894 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
895 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
897 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
900 if (!TRACE_ON(typelib
))
902 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
903 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
904 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
907 dump_FUNCDESC(&(pfd
->funcdesc
));
909 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
910 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
912 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
916 dump_TLBFuncDescOne(pfd
);
920 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
924 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
929 static void dump_TLBImpLib(TLBImpLib
*import
)
931 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
932 debugstr_w(import
->name
));
933 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
934 import
->wVersionMinor
, import
->lcid
, import
->offset
);
937 static void dump_TLBRefType(TLBRefType
* prt
)
941 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
943 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
945 TRACE_(typelib
)("type no: %d\n", prt
->index
);
947 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
948 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
949 TRACE_(typelib
)("in lib\n");
950 dump_TLBImpLib(prt
->pImpTLInfo
);
956 static void dump_TLBImplType(TLBImplType
* impl
)
960 "implementing/inheriting interface hRef = %lx implflags %x\n",
961 impl
->hRef
, impl
->implflags
);
966 static void dump_Variant(VARIANT
* pvar
)
971 TRACE("(%p)\n", pvar
);
975 ZeroMemory(szVarType
, sizeof(szVarType
));
977 /* FIXME : we could have better trace here, depending on the VARTYPE
980 dump_VarType(V_VT(pvar
),szVarType
);
982 TRACE("VARTYPE: %s\n", szVarType
);
984 if (V_VT(pvar
) & VT_BYREF
) {
985 ref
= V_UNION(pvar
, byref
);
988 else ref
= &V_UNION(pvar
, cVal
);
990 if (V_VT(pvar
) & VT_ARRAY
) {
994 if (V_VT(pvar
) & VT_VECTOR
) {
1002 TRACE("%d\n", *(short*)ref
);
1006 TRACE("%d\n", *(INT
*)ref
);
1010 TRACE("%3.3e\n", *(float*)ref
);
1014 TRACE("%3.3e\n", *(double*)ref
);
1018 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1022 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1027 TRACE("%p\n", *(LPVOID
*)ref
);
1031 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1035 TRACE("(?)%ld\n", *(long*)ref
);
1040 static void dump_DispParms(DISPPARAMS
* pdp
)
1044 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1046 while (index
< pdp
->cArgs
)
1048 dump_Variant( &pdp
->rgvarg
[index
] );
1053 static char * typekind_desc
[] =
1066 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1068 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1069 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1070 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1071 TRACE("fct:%u var:%u impl:%u\n",
1072 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1073 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1074 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1075 dump_TLBFuncDesc(pty
->funclist
);
1076 dump_TLBVarDesc(pty
->varlist
);
1077 dump_TLBImplType(pty
->impltypelist
);
1080 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1082 /* VT_LPWSTR is largest type that */
1083 /* may appear in type description*/
1084 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1085 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1086 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1087 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1088 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1089 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1093 static void TLB_abort()
1097 static void * TLB_Alloc(unsigned size
)
1100 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1102 ERR("cannot allocate memory\n");
1107 static void TLB_Free(void * ptr
)
1109 HeapFree(GetProcessHeap(), 0, ptr
);
1113 /**********************************************************************
1115 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1118 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1120 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1121 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1123 if (where
!= DO_NOT_SEEK
)
1125 where
+= pcx
->oStart
;
1126 if (where
> pcx
->length
)
1129 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1134 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1135 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1140 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1142 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1144 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1145 memset(pGuid
,0, sizeof(GUID
));
1148 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1151 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1154 MSFT_NameIntro niName
;
1156 WCHAR
* pwstring
= NULL
;
1157 BSTR bstrName
= NULL
;
1159 MSFT_Read(&niName
, sizeof(niName
), pcx
,
1160 pcx
->pTblDir
->pNametab
.offset
+offset
);
1161 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1162 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1163 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1164 name
[niName
.namelen
& 0xff]='\0';
1166 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1169 /* no invalid characters in string */
1172 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1174 /* don't check for invalid character since this has been done previously */
1175 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1177 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1178 lengthInChars
= SysStringLen(bstrName
);
1179 HeapFree(GetProcessHeap(), 0, pwstring
);
1182 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1186 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1193 if(offset
<0) return NULL
;
1194 MSFT_Read(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1195 if(length
<= 0) return 0;
1196 string
=TLB_Alloc(length
+1);
1197 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1198 string
[length
]='\0';
1200 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1201 string
, -1, NULL
, 0);
1203 /* no invalid characters in string */
1206 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1208 /* don't check for invalid character since this has been done previously */
1209 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1211 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1212 lengthInChars
= SysStringLen(bstr
);
1213 HeapFree(GetProcessHeap(), 0, pwstring
);
1216 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1220 * read a value and fill a VARIANT structure
1222 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1226 TRACE_(typelib
)("\n");
1228 if(offset
<0) { /* data are packed in here */
1229 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1230 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1233 MSFT_Read(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1234 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1235 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1236 switch (V_VT(pVar
)){
1237 case VT_EMPTY
: /* FIXME: is this right? */
1238 case VT_NULL
: /* FIXME: is this right? */
1239 case VT_I2
: /* this should not happen */
1250 case VT_VOID
: /* FIXME: is this right? */
1258 case VT_DECIMAL
: /* FIXME: is this right? */
1261 /* pointer types with known behaviour */
1264 MSFT_Read(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1266 FIXME("BSTR length = %d?\n", size
);
1268 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1269 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1270 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1271 /* FIXME: do we need a AtoW conversion here? */
1272 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1273 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1278 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1285 case VT_USERDEFINED
:
1291 case VT_STREAMED_OBJECT
:
1292 case VT_STORED_OBJECT
:
1293 case VT_BLOB_OBJECT
:
1298 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1302 if(size
>0) /* (big|small) endian correct? */
1303 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1307 * create a linked list with custom data
1309 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1315 TRACE_(typelib
)("\n");
1319 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1320 MSFT_Read(&entry
, sizeof(entry
), pcx
,
1321 pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1322 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1323 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1324 /* add new custom data at head of the list */
1325 pNew
->next
=*ppCustData
;
1327 offset
= entry
.next
;
1332 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1336 pTd
->vt
=type
& VT_TYPEMASK
;
1338 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1340 if(pTd
->vt
== VT_USERDEFINED
)
1341 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1343 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1347 MSFT_DoFuncs(TLBContext
* pcx
,
1352 TLBFuncDesc
** pptfd
)
1355 * member information is stored in a data structure at offset
1356 * indicated by the memoffset field of the typeinfo structure
1357 * There are several distinctive parts.
1358 * the first part starts with a field that holds the total length
1359 * of this (first) part excluding this field. Then follow the records,
1360 * for each member there is one record.
1362 * First entry is always the length of the record (excluding this
1364 * Rest of the record depends on the type of the member. If there is
1365 * a field indicating the member type (function variable intereface etc)
1366 * I have not found it yet. At this time we depend on the information
1367 * in the type info and the usual order how things are stored.
1369 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1372 * Third is a equal sized array with file offsets to the name entry
1375 * Forth and last (?) part is an array with offsets to the records in the
1376 * first part of this file segment.
1379 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1380 int recoffset
= offset
+ sizeof(INT
);
1383 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1385 TRACE_(typelib
)("\n");
1387 MSFT_Read(&infolen
, sizeof(INT
), pcx
, offset
);
1389 for ( i
= 0; i
< cFuncs
; i
++ )
1391 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1393 /* name, eventually add to a hash table */
1394 MSFT_Read(&nameoffset
,
1397 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1399 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1401 /* read the function information record */
1402 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1406 MSFT_Read(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1408 /* do the attributes */
1409 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1412 if ( nrattributes
> 0 )
1414 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1416 if ( nrattributes
> 1 )
1418 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1419 pFuncRec
->OptAttr
[1]) ;
1421 if ( nrattributes
> 2 )
1423 if ( pFuncRec
->FKCCIC
& 0x2000 )
1425 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1429 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1430 pFuncRec
->OptAttr
[2]);
1432 if( nrattributes
> 5 )
1434 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1436 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1439 pFuncRec
->OptAttr
[6],
1440 &(*pptfd
)->pCustData
);
1447 /* fill the FuncDesc Structure */
1448 MSFT_Read( & (*pptfd
)->funcdesc
.memid
,
1450 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1452 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1453 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1454 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1455 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1456 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1457 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1458 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1462 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1465 /* do the parameters/arguments */
1466 if(pFuncRec
->nrargs
)
1469 MSFT_ParameterInfo paraminfo
;
1471 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1472 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1474 (*pptfd
)->pParamDesc
=
1475 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1477 MSFT_Read(¶minfo
,
1480 recoffset
+ reclength
-
1481 pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1483 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1485 TYPEDESC
* lpArgTypeDesc
= 0;
1489 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1492 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1494 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1496 /* SEEK value = jump to offset,
1497 * from there jump to the end of record,
1498 * go back by (j-1) arguments
1500 MSFT_Read( ¶minfo
,
1501 sizeof(MSFT_ParameterInfo
), pcx
,
1502 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1503 * sizeof(MSFT_ParameterInfo
)));
1505 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1507 while ( lpArgTypeDesc
!= NULL
)
1509 switch ( lpArgTypeDesc
->vt
)
1512 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1516 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1519 case VT_USERDEFINED
:
1520 MSFT_DoRefType(pcx
, pTI
,
1521 lpArgTypeDesc
->u
.hreftype
);
1523 lpArgTypeDesc
= NULL
;
1527 lpArgTypeDesc
= NULL
;
1533 /* parameter is the return value! */
1534 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1536 TYPEDESC
* lpArgTypeDesc
;
1538 (*pptfd
)->funcdesc
.elemdescFunc
=
1539 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1541 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1543 while ( lpArgTypeDesc
!= NULL
)
1545 switch ( lpArgTypeDesc
->vt
)
1548 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1552 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1556 case VT_USERDEFINED
:
1559 lpArgTypeDesc
->u
.hreftype
);
1561 lpArgTypeDesc
= NULL
;
1565 lpArgTypeDesc
= NULL
;
1570 /* second time around */
1571 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1574 (*pptfd
)->pParamDesc
[j
].Name
=
1575 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1578 if ( (PARAMFLAG_FHASDEFAULT
&
1579 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1580 ((pFuncRec
->FKCCIC
) & 0x1000) )
1582 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1584 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1586 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1588 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1589 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1591 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1595 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1598 pFuncRec
->OptAttr
[7+j
],
1599 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1604 /* scode is not used: archaic win16 stuff FIXME: right? */
1605 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1606 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1608 pptfd
= & ((*pptfd
)->next
);
1609 recoffset
+= reclength
;
1612 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1613 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1615 int infolen
, nameoffset
, reclength
;
1617 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1621 TRACE_(typelib
)("\n");
1623 MSFT_Read(&infolen
,sizeof(INT
), pcx
, offset
);
1624 MSFT_Read(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1625 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1626 recoffset
+= offset
+sizeof(INT
);
1627 for(i
=0;i
<cVars
;i
++){
1628 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1629 /* name, eventually add to a hash table */
1630 MSFT_Read(&nameoffset
, sizeof(INT
), pcx
,
1631 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1632 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1633 /* read the variable information record */
1634 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1636 MSFT_Read(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1638 if(reclength
>(6*sizeof(INT
)) )
1639 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1640 if(reclength
>(7*sizeof(INT
)) )
1641 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1642 if(reclength
>(8*sizeof(INT
)) )
1643 if(reclength
>(9*sizeof(INT
)) )
1644 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1645 /* fill the VarDesc Structure */
1646 MSFT_Read(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1647 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1648 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1649 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1650 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1651 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1652 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1653 if(pVarRec
->VarKind
== VAR_CONST
){
1654 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1655 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1656 pVarRec
->OffsValue
, pcx
);
1658 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1659 pptvd
=&((*pptvd
)->next
);
1660 recoffset
+= reclength
;
1663 /* fill in data for a hreftype (offset). When the refernced type is contained
1664 * in the typelib, it's just an (file) offset in the type info base dir.
1665 * If comes from import, it's an offset+1 in the ImpInfo table
1667 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1671 TLBRefType
**ppRefType
= &pTI
->reflist
;
1673 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1676 if((*ppRefType
)->reference
== offset
)
1678 ppRefType
= &(*ppRefType
)->next
;
1681 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1682 sizeof(**ppRefType
));
1684 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1685 /* external typelib */
1686 MSFT_ImpInfo impinfo
;
1687 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1689 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1691 MSFT_Read(&impinfo
, sizeof(impinfo
), pcx
,
1692 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1693 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1694 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1695 pImpLib
=pImpLib
->next
;
1698 (*ppRefType
)->reference
=offset
;
1699 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1700 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1701 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1703 ERR("Cannot find a reference\n");
1704 (*ppRefType
)->reference
=-1;
1705 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1708 /* in this typelib */
1709 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1710 (*ppRefType
)->reference
=offset
;
1711 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1715 /* process Implemented Interfaces of a com class */
1716 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1720 MSFT_RefRecord refrec
;
1721 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1723 TRACE_(typelib
)("\n");
1725 for(i
=0;i
<count
;i
++){
1726 if(offset
<0) break; /* paranoia */
1727 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1728 MSFT_Read(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1729 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1730 (*ppImpl
)->hRef
= refrec
.reftype
;
1731 (*ppImpl
)->implflags
=refrec
.flags
;
1732 (*ppImpl
)->ctCustData
=
1733 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1734 offset
=refrec
.onext
;
1735 ppImpl
=&((*ppImpl
)->next
);
1739 * process a typeinfo record
1741 ITypeInfoImpl
* MSFT_DoTypeInfo(
1744 ITypeLibImpl
* pLibInfo
)
1746 MSFT_TypeInfoBase tiBase
;
1747 ITypeInfoImpl
*ptiRet
;
1749 TRACE_(typelib
)("count=%u\n", count
);
1751 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1752 MSFT_Read(&tiBase
, sizeof(tiBase
) ,pcx
,
1753 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1754 /* this is where we are coming from */
1755 ptiRet
->pTypeLib
= pLibInfo
;
1756 ITypeLib2_AddRef((ITypeLib2
*)pLibInfo
);
1757 ptiRet
->index
=count
;
1758 /* fill in the typeattr fields */
1759 FIXME("Assign constructor/destructor memid\n");
1761 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1762 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1763 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1764 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1765 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1766 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1767 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1768 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1769 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1770 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1771 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1772 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1773 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1774 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1775 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1776 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1777 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1778 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1781 /* IDLDESC idldescType; *//* never saw this one != zero */
1783 /* name, eventually add to a hash table */
1784 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1785 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1787 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1788 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1789 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1790 /* note: InfoType's Help file and HelpStringDll come from the containing
1791 * library. Further HelpString and Docstring appear to be the same thing :(
1794 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1795 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1796 ptiRet
->TypeAttr
.cVars
,
1797 tiBase
.memoffset
, & ptiRet
->funclist
);
1799 if(ptiRet
->TypeAttr
.cVars
>0 )
1800 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1801 ptiRet
->TypeAttr
.cVars
,
1802 tiBase
.memoffset
, & ptiRet
->varlist
);
1803 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1804 switch(ptiRet
->TypeAttr
.typekind
)
1807 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1810 case TKIND_DISPATCH
:
1811 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1813 if (tiBase
.datatype1
!= -1)
1815 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1816 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1819 { /* FIXME: This is a really bad hack to add IDispatch */
1820 char* szStdOle
= "stdole2.tlb\0";
1821 int nStdOleLen
= strlen(szStdOle
);
1822 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1825 if((*ppRef
)->reference
== -1)
1827 ppRef
= &(*ppRef
)->next
;
1830 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1831 (*ppRef
)->guid
= IID_IDispatch
;
1832 (*ppRef
)->reference
= -1;
1833 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1834 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1835 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1836 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1839 MultiByteToWideChar(CP_ACP
,
1843 (*ppRef
)->pImpTLInfo
->name
,
1844 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1846 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1847 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1848 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1853 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1854 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1855 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1860 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1862 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1863 debugstr_w(ptiRet
->Name
),
1864 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1865 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1870 /****************************************************************************
1873 * find the type of the typelib file and map the typelib resource into
1876 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1877 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1878 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
1880 int ret
= TYPE_E_CANTLOADLIBRARY
;
1881 DWORD dwSignature
= 0;
1884 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
1888 /* check the signature of the file */
1889 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1890 if (INVALID_HANDLE_VALUE
!= hFile
)
1892 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
1895 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
1898 /* retrieve file size */
1899 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
1901 /* first try to load as *.tlb */
1902 dwSignature
= *((DWORD
*) pBase
);
1903 if ( dwSignature
== MSFT_SIGNATURE
)
1905 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1907 else if ( dwSignature
== SLTG_SIGNATURE
)
1909 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1911 UnmapViewOfFile(pBase
);
1913 CloseHandle(hMapping
);
1918 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
1920 /* find the typelibrary resource*/
1921 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
1922 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
1925 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
1929 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
1932 LPVOID pBase
= LockResource(hGlobal
);
1933 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
1937 /* try to load as incore resource */
1938 dwSignature
= *((DWORD
*) pBase
);
1939 if ( dwSignature
== MSFT_SIGNATURE
)
1941 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1943 else if ( dwSignature
== SLTG_SIGNATURE
)
1945 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1949 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
1952 FreeResource( hGlobal
);
1955 FreeLibrary(hinstDLL
);
1962 ERR("Loading of typelib %s failed with error %ld\n",
1963 debugstr_w(pszFileName
), GetLastError());
1968 /*================== ITypeLib(2) Methods ===================================*/
1970 /****************************************************************************
1971 * ITypeLib2_Constructor_MSFT
1973 * loading an MSFT typelib from an in-memory image
1975 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
1979 MSFT_Header tlbHeader
;
1980 MSFT_SegDir tlbSegDir
;
1981 ITypeLibImpl
* pTypeLibImpl
;
1983 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
1985 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
1986 if (!pTypeLibImpl
) return NULL
;
1988 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
1989 pTypeLibImpl
->ref
= 1;
1991 /* get pointer to beginning of typelib data */
1995 cx
.pLibInfo
= pTypeLibImpl
;
1996 cx
.length
= dwTLBLength
;
1999 MSFT_Read((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2001 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2002 if (memcmp(&tlbHeader
.magic1
,TLBMAGIC2
,4)) {
2003 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2006 /* there is a small amount of information here until the next important
2008 * the segment directory . Try to calculate the amount of data */
2009 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2011 /* now read the segment directory */
2012 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2013 MSFT_Read((void*)&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2014 cx
.pTblDir
= &tlbSegDir
;
2016 /* just check two entries */
2017 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2019 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2020 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2024 /* now fill our internal data */
2025 /* TLIBATTR fields */
2026 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2028 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2029 /* Windows seems to have zero here, is this correct? */
2030 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2031 pTypeLibImpl
->LibAttr
.lcid
= PRIMARYLANGID(tlbHeader
.lcid
);
2033 pTypeLibImpl
->LibAttr
.lcid
= 0;
2035 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2036 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2037 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2038 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2040 /* name, eventually add to a hash table */
2041 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2044 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2045 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2047 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2050 MSFT_Read(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2051 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2054 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2057 if(tlbHeader
.CustomDataOffset
>= 0)
2059 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2062 /* fill in typedescriptions */
2063 if(tlbSegDir
.pTypdescTab
.length
> 0)
2065 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2067 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2068 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2071 /* FIXME: add several sanity checks here */
2072 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2073 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2075 /* FIXME: check safearray */
2077 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2079 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2081 else if(td
[0] == VT_CARRAY
)
2083 /* array descr table here */
2084 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2086 else if(td
[0] == VT_USERDEFINED
)
2088 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2090 if(++i
<cTD
) MSFT_Read(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2093 /* second time around to fill the array subscript info */
2096 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2097 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2099 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2100 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2103 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2105 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2107 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2109 for(j
= 0; j
<td
[2]; j
++)
2111 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2112 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2113 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2114 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2119 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2120 ERR("didn't find array description data\n");
2125 /* imported type libs */
2126 if(tlbSegDir
.pImpFiles
.offset
>0)
2128 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2129 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2132 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2134 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2135 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2136 MSFT_Read(&oGuid
, sizeof(INT
), &cx
, offset
);
2138 MSFT_Read(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2139 MSFT_Read(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2140 MSFT_Read(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2141 MSFT_Read(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2144 (*ppImpLib
)->name
= TLB_Alloc(size
+1);
2145 MSFT_Read((*ppImpLib
)->name
, size
, &cx
, DO_NOT_SEEK
);
2146 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2147 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & 0xfffffffc;
2149 ppImpLib
= &(*ppImpLib
)->next
;
2154 if(tlbHeader
.nrtypeinfos
>= 0 )
2156 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2157 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2160 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2162 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2164 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2165 ppTI
= &((*ppTI
)->next
);
2166 (pTypeLibImpl
->TypeInfoCount
)++;
2170 TRACE("(%p)\n", pTypeLibImpl
);
2171 return (ITypeLib2
*) pTypeLibImpl
;
2175 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2181 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2182 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2183 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2184 ret
= SysAllocString(nameW
);
2185 HeapFree(GetProcessHeap(), 0, nameW
);
2189 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2195 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2196 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2200 guid
->Data4
[0] = s
>> 8;
2201 guid
->Data4
[1] = s
& 0xff;
2204 for(i
= 0; i
< 6; i
++) {
2205 memcpy(b
, str
+ 24 + 2 * i
, 2);
2206 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2211 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2218 bytelen
= *(WORD
*)ptr
;
2219 if(bytelen
== 0xffff) return 2;
2220 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2221 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2222 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2223 *pBstr
= SysAllocStringLen(nameW
, len
);
2224 HeapFree(GetProcessHeap(), 0, nameW
);
2228 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2233 bytelen
= *(WORD
*)ptr
;
2234 if(bytelen
== 0xffff) return 2;
2235 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2236 memcpy(*str
, ptr
+ 2, bytelen
);
2237 (*str
)[bytelen
] = '\0';
2241 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2243 char *ptr
= pLibBlk
;
2246 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2247 FIXME("libblk magic = %04x\n", w
);
2252 if((w
= *(WORD
*)ptr
) != 0xffff) {
2253 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2258 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2260 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2262 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2265 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2268 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2271 ptr
+= 4; /* skip res12 */
2273 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2276 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2279 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2282 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2283 ptr
+= sizeof(GUID
);
2285 return ptr
- (char*)pLibBlk
;
2288 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2291 TYPEDESC
*pTD
= &pElem
->tdesc
;
2293 /* Handle [in/out] first */
2294 if((*pType
& 0xc000) == 0xc000)
2295 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2296 else if(*pType
& 0x8000)
2297 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2298 else if(*pType
& 0x4000)
2299 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2301 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2304 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2307 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2310 if((*pType
& 0xe00) == 0xe00) {
2312 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2314 pTD
= pTD
->u
.lptdesc
;
2316 switch(*pType
& 0x7f) {
2319 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2321 pTD
= pTD
->u
.lptdesc
;
2324 case VT_USERDEFINED
:
2325 pTD
->vt
= VT_USERDEFINED
;
2326 pTD
->u
.hreftype
= *(++pType
) / 4;
2332 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2335 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2337 pTD
->vt
= VT_CARRAY
;
2338 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2340 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2341 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2342 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2343 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2345 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2351 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2355 pTD
->vt
= VT_SAFEARRAY
;
2356 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2358 pTD
= pTD
->u
.lptdesc
;
2362 pTD
->vt
= *pType
& 0x7f;
2372 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2377 TLBRefType
**ppRefType
;
2379 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2380 FIXME("Ref magic = %x\n", pRef
->magic
);
2383 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2385 ppRefType
= &pTI
->reflist
;
2386 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2388 unsigned int lib_offs
, type_num
;
2390 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2391 sizeof(**ppRefType
));
2393 name
+= SLTG_ReadStringA(name
, &refname
);
2394 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2395 FIXME("Can't sscanf ref\n");
2396 if(lib_offs
!= 0xffff) {
2397 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2400 if((*import
)->offset
== lib_offs
)
2402 import
= &(*import
)->next
;
2405 char fname
[MAX_PATH
+1];
2408 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2410 (*import
)->offset
= lib_offs
;
2411 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2413 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2414 &(*import
)->wVersionMajor
,
2415 &(*import
)->wVersionMinor
,
2416 &(*import
)->lcid
, fname
) != 4) {
2417 FIXME("can't sscanf ref %s\n",
2418 pNameTable
+ lib_offs
+ 40);
2420 len
= strlen(fname
);
2421 if(fname
[len
-1] != '#')
2422 FIXME("fname = %s\n", fname
);
2423 fname
[len
-1] = '\0';
2424 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2426 (*ppRefType
)->pImpTLInfo
= *import
;
2427 } else { /* internal ref */
2428 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2430 (*ppRefType
)->reference
= ref
;
2431 (*ppRefType
)->index
= type_num
;
2433 HeapFree(GetProcessHeap(), 0, refname
);
2434 ppRefType
= &(*ppRefType
)->next
;
2436 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2437 FIXME("End of ref block magic = %x\n", *name
);
2438 dump_TLBRefType(pTI
->reflist
);
2441 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2444 SLTG_ImplInfo
*info
;
2445 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2446 /* I don't really get this structure, usually it's 0x16 bytes
2447 long, but iuser.tlb contains some that are 0x18 bytes long.
2448 That's ok because we can use the next ptr to jump to the next
2449 one. But how do we know the length of the last one? The WORD
2450 at offs 0x8 might be the clue. For now I'm just assuming that
2451 the last one is the regular 0x16 bytes. */
2453 info
= (SLTG_ImplInfo
*)pBlk
;
2455 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2456 sizeof(**ppImplType
));
2457 (*ppImplType
)->hRef
= info
->ref
;
2458 (*ppImplType
)->implflags
= info
->impltypeflags
;
2459 pTI
->TypeAttr
.cImplTypes
++;
2460 ppImplType
= &(*ppImplType
)->next
;
2462 if(info
->next
== 0xffff)
2465 FIXME("Interface inheriting more than one interface\n");
2466 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2468 info
++; /* see comment at top of function */
2472 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2475 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2476 SLTG_MemberHeader
*pMemHeader
;
2477 char *pFirstItem
, *pNextItem
;
2479 if(pTIHeader
->href_table
!= 0xffffffff) {
2480 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2485 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2487 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2489 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2490 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2493 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2497 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2500 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2501 SLTG_MemberHeader
*pMemHeader
;
2502 SLTG_Function
*pFunc
;
2503 char *pFirstItem
, *pNextItem
;
2504 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2507 if(pTIHeader
->href_table
!= 0xffffffff) {
2508 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2512 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2514 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2516 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2517 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2520 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2521 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2526 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2527 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2528 FIXME("func magic = %02x\n", pFunc
->magic
);
2531 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2532 sizeof(**ppFuncDesc
));
2533 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2535 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2536 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2537 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2538 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2539 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2540 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2542 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2543 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2545 if(pFunc
->retnextopt
& 0x80)
2546 pType
= &pFunc
->rettype
;
2548 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2551 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2553 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2554 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2555 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2556 (*ppFuncDesc
)->pParamDesc
=
2557 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2558 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2560 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2562 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2563 char *paramName
= pNameTable
+ *pArg
;
2565 /* If arg type follows then paramName points to the 2nd
2566 letter of the name, else the next WORD is an offset to
2567 the arg type and paramName points to the first letter.
2568 So let's take one char off paramName and see if we're
2569 pointing at an alpha-numeric char. However if *pArg is
2570 0xffff or 0xfffe then the param has no name, the former
2571 meaning that the next WORD is the type, the latter
2572 meaning the the next WORD is an offset to the type. */
2577 else if(*pArg
== 0xfffe) {
2581 else if(!isalnum(*(paramName
-1)))
2586 if(HaveOffs
) { /* the next word is an offset to type */
2587 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2588 SLTG_DoType(pType
, pFirstItem
,
2589 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2594 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2595 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2598 /* Are we an optional param ? */
2599 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2600 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2601 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2604 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2605 TLB_MultiByteToBSTR(paramName
);
2609 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2610 if(pFunc
->next
== 0xffff) break;
2612 pTI
->TypeAttr
.cFuncs
= num
;
2613 dump_TLBFuncDesc(pTI
->funclist
);
2614 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2617 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2620 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2621 SLTG_MemberHeader
*pMemHeader
;
2622 SLTG_RecordItem
*pItem
;
2624 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2629 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2631 pFirstItem
= (char*)(pMemHeader
+ 1);
2632 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2633 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2634 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2635 FIXME("record magic = %02x\n", pItem
->magic
);
2638 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2639 sizeof(**ppVarDesc
));
2640 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2641 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2642 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2643 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2645 if(pItem
->typepos
== 0x02)
2646 pType
= &pItem
->type
;
2647 else if(pItem
->typepos
== 0x00)
2648 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2650 FIXME("typepos = %02x\n", pItem
->typepos
);
2654 SLTG_DoType(pType
, pFirstItem
,
2655 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2657 /* FIXME("helpcontext, helpstring\n"); */
2659 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2661 ppVarDesc
= &((*ppVarDesc
)->next
);
2662 if(pItem
->next
== 0xffff) break;
2664 pTI
->TypeAttr
.cVars
= num
;
2665 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2668 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2671 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2672 SLTG_MemberHeader
*pMemHeader
;
2673 SLTG_EnumItem
*pItem
;
2675 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2678 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2680 pFirstItem
= (char*)(pMemHeader
+ 1);
2681 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2682 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2683 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2684 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2687 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2688 sizeof(**ppVarDesc
));
2689 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2690 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2691 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2693 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2694 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2695 *(INT
*)(pItem
->value
+ pFirstItem
);
2696 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2697 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2698 /* FIXME("helpcontext, helpstring\n"); */
2700 ppVarDesc
= &((*ppVarDesc
)->next
);
2701 if(pItem
->next
== 0xffff) break;
2703 pTI
->TypeAttr
.cVars
= num
;
2704 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2707 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2708 managable copy of it into this */
2721 } SLTG_InternalOtherTypeInfo
;
2723 /****************************************************************************
2724 * ITypeLib2_Constructor_SLTG
2726 * loading a SLTG typelib from an in-memory image
2728 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2730 ITypeLibImpl
*pTypeLibImpl
;
2731 SLTG_Header
*pHeader
;
2732 SLTG_BlkEntry
*pBlkEntry
;
2736 LPVOID pBlk
, pFirstBlk
;
2737 SLTG_LibBlk
*pLibBlk
;
2738 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2739 char *pAfterOTIBlks
= NULL
;
2740 char *pNameTable
, *ptr
;
2743 ITypeInfoImpl
**ppTypeInfoImpl
;
2745 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2747 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2748 if (!pTypeLibImpl
) return NULL
;
2750 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2751 pTypeLibImpl
->ref
= 1;
2756 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2757 pHeader
->nrOfFileBlks
);
2758 if (memcmp(&pHeader
->SLTG_magic
, TLBMAGIC1
, 4)) {
2759 FIXME("Header type magic 0x%08lx not supported.\n",
2760 pHeader
->SLTG_magic
);
2764 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2765 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2767 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2768 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2770 /* Next we have a magic block */
2771 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2773 /* Let's see if we're still in sync */
2774 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2775 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2776 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2779 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2780 sizeof(SLTG_DIR_MAGIC
))) {
2781 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2785 pIndex
= (SLTG_Index
*)(pMagic
+1);
2787 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
2789 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
2791 /* We'll set up a ptr to the main library block, which is the last one. */
2793 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2794 pBlkEntry
[order
].next
!= 0;
2795 order
= pBlkEntry
[order
].next
- 1, i
++) {
2796 pBlk
+= pBlkEntry
[order
].len
;
2800 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
2802 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2807 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2809 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2810 sizeof(*pOtherTypeInfoBlks
) *
2811 pTypeLibImpl
->TypeInfoCount
);
2814 ptr
= (char*)pLibBlk
+ len
;
2816 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
2820 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
2822 w
= *(WORD
*)(ptr
+ 2);
2825 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
2827 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
2828 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
2830 w
= *(WORD
*)(ptr
+ 4 + len
);
2832 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
2834 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
2836 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
2837 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
2839 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
2840 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
2841 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
2843 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
2845 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
2848 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
2849 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
2850 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
2851 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
2852 len
+= sizeof(SLTG_OtherTypeInfo
);
2856 pAfterOTIBlks
= ptr
;
2858 /* Skip this WORD and get the next DWORD */
2859 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
2861 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2862 magic dust and we should be pointing at the beginning of the name
2865 pNameTable
= (char*)pLibBlk
+ len
+ 0x216;
2869 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
2871 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
2874 /* Hopefully we now have enough ptrs set up to actually read in
2875 some TypeInfos. It's not clear which order to do them in, so
2876 I'll just follow the links along the BlkEntry chain and read
2877 them in in the order in which they're in the file */
2879 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
2881 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2882 pBlkEntry
[order
].next
!= 0;
2883 order
= pBlkEntry
[order
].next
- 1, i
++) {
2885 SLTG_TypeInfoHeader
*pTIHeader
;
2886 SLTG_TypeInfoTail
*pTITail
;
2888 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
2889 pOtherTypeInfoBlks
[i
].index_name
)) {
2890 FIXME("Index strings don't match\n");
2895 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
2896 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
2899 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
2900 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
2901 ITypeLib2_AddRef((ITypeLib2
*)pTypeLibImpl
);
2902 (*ppTypeInfoImpl
)->index
= i
;
2903 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
2904 pOtherTypeInfoBlks
[i
].name_offs
+
2906 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
2907 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
2909 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
2910 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
2911 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
2912 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
2913 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
2915 if((pTIHeader
->typeflags1
& 7) != 2)
2916 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
2917 if(pTIHeader
->typeflags3
!= 2)
2918 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
2920 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2921 debugstr_w((*ppTypeInfoImpl
)->Name
),
2922 typekind_desc
[pTIHeader
->typekind
],
2923 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
2924 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
2926 switch(pTIHeader
->typekind
) {
2928 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2932 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2935 case TKIND_INTERFACE
:
2936 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2940 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2944 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
2950 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
2951 but we've already set those */
2952 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
2953 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
2954 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
2956 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
2957 pBlk
+= pBlkEntry
[order
].len
;
2960 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
2961 FIXME("Somehow processed %d TypeInfos\n", i
);
2965 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
2966 return (ITypeLib2
*)pTypeLibImpl
;
2969 /* ITypeLib::QueryInterface
2971 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
2976 ICOM_THIS( ITypeLibImpl
, iface
);
2978 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
2981 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2982 IsEqualIID(riid
,&IID_ITypeLib
)||
2983 IsEqualIID(riid
,&IID_ITypeLib2
))
2990 ITypeLib2_AddRef(iface
);
2991 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
2994 TRACE("-- Interface: E_NOINTERFACE\n");
2995 return E_NOINTERFACE
;
3000 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3002 ICOM_THIS( ITypeLibImpl
, iface
);
3004 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3006 return ++(This
->ref
);
3009 /* ITypeLib::Release
3011 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3013 ICOM_THIS( ITypeLibImpl
, iface
);
3017 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3021 /* FIXME destroy child objects */
3023 TRACE(" destroying ITypeLib(%p)\n",This
);
3027 SysFreeString(This
->Name
);
3031 if (This
->DocString
)
3033 SysFreeString(This
->DocString
);
3034 This
->DocString
= NULL
;
3039 SysFreeString(This
->HelpFile
);
3040 This
->HelpFile
= NULL
;
3043 if (This
->HelpStringDll
)
3045 SysFreeString(This
->HelpStringDll
);
3046 This
->HelpStringDll
= NULL
;
3049 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3050 HeapFree(GetProcessHeap(),0,This
);
3057 /* ITypeLib::GetTypeInfoCount
3059 * Returns the number of type descriptions in the type library
3061 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3063 ICOM_THIS( ITypeLibImpl
, iface
);
3064 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3065 return This
->TypeInfoCount
;
3068 /* ITypeLib::GetTypeInfo
3070 * retrieves the specified type description in the library.
3072 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3075 ITypeInfo
**ppTInfo
)
3079 ICOM_THIS( ITypeLibImpl
, iface
);
3080 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3082 TRACE("(%p)->(index=%d) \n", This
, index
);
3084 if (!ppTInfo
) return E_INVALIDARG
;
3086 /* search element n in list */
3087 for(i
=0; i
< index
; i
++)
3089 pTypeInfo
= pTypeInfo
->next
;
3092 TRACE("-- element not found\n");
3093 return TYPE_E_ELEMENTNOTFOUND
;
3097 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3099 ITypeInfo_AddRef(*ppTInfo
);
3100 TRACE("-- found (%p)\n",*ppTInfo
);
3105 /* ITypeLibs::GetTypeInfoType
3107 * Retrieves the type of a type description.
3109 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3114 ICOM_THIS( ITypeLibImpl
, iface
);
3116 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3118 TRACE("(%p) index %d \n",This
, index
);
3120 if(!pTKind
) return E_INVALIDARG
;
3122 /* search element n in list */
3123 for(i
=0; i
< index
; i
++)
3127 TRACE("-- element not found\n");
3128 return TYPE_E_ELEMENTNOTFOUND
;
3130 pTInfo
= pTInfo
->next
;
3133 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3134 TRACE("-- found Type (%d)\n", *pTKind
);
3138 /* ITypeLib::GetTypeInfoOfGuid
3140 * Retrieves the type description that corresponds to the specified GUID.
3143 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3146 ITypeInfo
**ppTInfo
)
3148 ICOM_THIS( ITypeLibImpl
, iface
);
3149 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3151 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3153 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3155 /* search linked list for guid */
3156 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3158 pTypeInfo
= pTypeInfo
->next
;
3162 /* end of list reached */
3163 TRACE("-- element not found\n");
3164 return TYPE_E_ELEMENTNOTFOUND
;
3168 TRACE("-- found (%p, %s)\n",
3170 debugstr_w(pTypeInfo
->Name
));
3172 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3173 ITypeInfo_AddRef(*ppTInfo
);
3177 /* ITypeLib::GetLibAttr
3179 * Retrieves the structure that contains the library's attributes.
3182 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3184 LPTLIBATTR
*ppTLibAttr
)
3186 ICOM_THIS( ITypeLibImpl
, iface
);
3187 TRACE("(%p)\n",This
);
3188 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3189 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3193 /* ITypeLib::GetTypeComp
3195 * Enables a client compiler to bind to a library's types, variables,
3196 * constants, and global functions.
3199 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3201 ITypeComp
**ppTComp
)
3203 ICOM_THIS( ITypeLibImpl
, iface
);
3204 FIXME("(%p): stub!\n",This
);
3208 /* ITypeLib::GetDocumentation
3210 * Retrieves the library's documentation string, the complete Help file name
3211 * and path, and the context identifier for the library Help topic in the Help
3214 * On a successful return all non-null BSTR pointers will have been set,
3217 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3221 BSTR
*pBstrDocString
,
3222 DWORD
*pdwHelpContext
,
3223 BSTR
*pBstrHelpFile
)
3225 ICOM_THIS( ITypeLibImpl
, iface
);
3227 HRESULT result
= E_INVALIDARG
;
3232 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3234 pBstrName
, pBstrDocString
,
3235 pdwHelpContext
, pBstrHelpFile
);
3239 /* documentation for the typelib */
3243 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3249 if (This
->DocString
)
3250 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3251 else if (This
->Name
)
3252 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3254 *pBstrDocString
= NULL
;
3258 *pdwHelpContext
= This
->dwHelpContext
;
3263 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3265 *pBstrHelpFile
= NULL
;
3272 /* for a typeinfo */
3273 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3275 if(SUCCEEDED(result
))
3277 result
= ITypeInfo_GetDocumentation(pTInfo
,
3281 pdwHelpContext
, pBstrHelpFile
);
3283 ITypeInfo_Release(pTInfo
);
3288 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3290 if (pBstrName
) SysFreeString (*pBstrName
);
3292 return STG_E_INSUFFICIENTMEMORY
;
3297 * Indicates whether a passed-in string contains the name of a type or member
3298 * described in the library.
3301 static HRESULT WINAPI
ITypeLib2_fnIsName(
3307 ICOM_THIS( ITypeLibImpl
, iface
);
3308 ITypeInfoImpl
*pTInfo
;
3309 TLBFuncDesc
*pFInfo
;
3312 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3314 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3318 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3319 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3320 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3321 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3322 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3323 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3324 goto ITypeLib2_fnIsName_exit
;
3326 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3327 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3332 ITypeLib2_fnIsName_exit
:
3333 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3334 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3339 /* ITypeLib::FindName
3341 * Finds occurrences of a type description in a type library. This may be used
3342 * to quickly verify that a name exists in a type library.
3345 static HRESULT WINAPI
ITypeLib2_fnFindName(
3349 ITypeInfo
**ppTInfo
,
3353 ICOM_THIS( ITypeLibImpl
, iface
);
3354 ITypeInfoImpl
*pTInfo
;
3355 TLBFuncDesc
*pFInfo
;
3359 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3361 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3362 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3363 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3364 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3365 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3366 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3367 goto ITypeLib2_fnFindName_exit
;
3369 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3370 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3372 ITypeLib2_fnFindName_exit
:
3373 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3374 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3377 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3378 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3385 /* ITypeLib::ReleaseTLibAttr
3387 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3390 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3392 TLIBATTR
*pTLibAttr
)
3394 ICOM_THIS( ITypeLibImpl
, iface
);
3395 TRACE("freeing (%p)\n",This
);
3396 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3400 /* ITypeLib2::GetCustData
3402 * gets the custom data
3404 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3409 ICOM_THIS( ITypeLibImpl
, iface
);
3410 TLBCustData
*pCData
;
3412 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3414 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3417 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3421 VariantInit( pVarVal
);
3422 VariantCopy( pVarVal
, &pCData
->data
);
3425 return E_INVALIDARG
; /* FIXME: correct? */
3428 /* ITypeLib2::GetLibStatistics
3430 * Returns statistics about a type library that are required for efficient
3431 * sizing of hash tables.
3434 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3436 ULONG
*pcUniqueNames
,
3437 ULONG
*pcchUniqueNames
)
3439 ICOM_THIS( ITypeLibImpl
, iface
);
3441 FIXME("(%p): stub!\n", This
);
3443 if(pcUniqueNames
) *pcUniqueNames
=1;
3444 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3448 /* ITypeLib2::GetDocumentation2
3450 * Retrieves the library's documentation string, the complete Help file name
3451 * and path, the localization context to use, and the context ID for the
3452 * library Help topic in the Help file.
3455 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3459 BSTR
*pbstrHelpString
,
3460 DWORD
*pdwHelpStringContext
,
3461 BSTR
*pbstrHelpStringDll
)
3463 ICOM_THIS( ITypeLibImpl
, iface
);
3467 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3469 /* the help string should be obtained from the helpstringdll,
3470 * using the _DLLGetDocumentation function, based on the supplied
3471 * lcid. Nice to do sometime...
3475 /* documentation for the typelib */
3477 *pbstrHelpString
=SysAllocString(This
->DocString
);
3478 if(pdwHelpStringContext
)
3479 *pdwHelpStringContext
=This
->dwHelpContext
;
3480 if(pbstrHelpStringDll
)
3481 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3487 /* for a typeinfo */
3488 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3490 if(SUCCEEDED(result
))
3492 ITypeInfo2
* pTInfo2
;
3493 result
= ITypeInfo_QueryInterface(pTInfo
,
3495 (LPVOID
*) &pTInfo2
);
3497 if(SUCCEEDED(result
))
3499 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3503 pdwHelpStringContext
,
3504 pbstrHelpStringDll
);
3506 ITypeInfo2_Release(pTInfo2
);
3509 ITypeInfo_Release(pTInfo
);
3515 /* ITypeLib2::GetAllCustData
3517 * Gets all custom data items for the library.
3520 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3522 CUSTDATA
*pCustData
)
3524 ICOM_THIS( ITypeLibImpl
, iface
);
3525 TLBCustData
*pCData
;
3527 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3528 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3529 if(pCustData
->prgCustData
){
3530 pCustData
->cCustData
=This
->ctCustData
;
3531 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3532 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3533 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3536 ERR(" OUT OF MEMORY! \n");
3537 return E_OUTOFMEMORY
;
3542 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3543 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3544 ITypeLib2_fnQueryInterface
,
3546 ITypeLib2_fnRelease
,
3547 ITypeLib2_fnGetTypeInfoCount
,
3548 ITypeLib2_fnGetTypeInfo
,
3549 ITypeLib2_fnGetTypeInfoType
,
3550 ITypeLib2_fnGetTypeInfoOfGuid
,
3551 ITypeLib2_fnGetLibAttr
,
3552 ITypeLib2_fnGetTypeComp
,
3553 ITypeLib2_fnGetDocumentation
,
3555 ITypeLib2_fnFindName
,
3556 ITypeLib2_fnReleaseTLibAttr
,
3558 ITypeLib2_fnGetCustData
,
3559 ITypeLib2_fnGetLibStatistics
,
3560 ITypeLib2_fnGetDocumentation2
,
3561 ITypeLib2_fnGetAllCustData
3564 /*================== ITypeInfo(2) Methods ===================================*/
3565 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3567 ITypeInfoImpl
* pTypeInfoImpl
;
3569 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3572 ICOM_VTBL(pTypeInfoImpl
) = &tinfvt
;
3573 pTypeInfoImpl
->ref
=1;
3575 TRACE("(%p)\n", pTypeInfoImpl
);
3576 return (ITypeInfo2
*) pTypeInfoImpl
;
3579 /* ITypeInfo::QueryInterface
3581 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3586 ICOM_THIS( ITypeLibImpl
, iface
);
3588 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3591 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3592 IsEqualIID(riid
,&IID_ITypeInfo
)||
3593 IsEqualIID(riid
,&IID_ITypeInfo2
))
3597 ITypeInfo_AddRef(iface
);
3598 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3601 TRACE("-- Interface: E_NOINTERFACE\n");
3602 return E_NOINTERFACE
;
3605 /* ITypeInfo::AddRef
3607 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3609 ICOM_THIS( ITypeInfoImpl
, iface
);
3613 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3617 /* ITypeInfo::Release
3619 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3621 ICOM_THIS( ITypeInfoImpl
, iface
);
3625 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3629 FIXME("destroy child objects\n");
3631 TRACE("destroying ITypeInfo(%p)\n",This
);
3634 SysFreeString(This
->Name
);
3638 if (This
->DocString
)
3640 SysFreeString(This
->DocString
);
3641 This
->DocString
= 0;
3646 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3649 HeapFree(GetProcessHeap(),0,This
);
3655 /* ITypeInfo::GetTypeAttr
3657 * Retrieves a TYPEATTR structure that contains the attributes of the type
3661 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3662 LPTYPEATTR
*ppTypeAttr
)
3664 ICOM_THIS( ITypeInfoImpl
, iface
);
3665 TRACE("(%p)\n",This
);
3666 /* FIXME: must do a copy here */
3667 *ppTypeAttr
=&This
->TypeAttr
;
3671 /* ITypeInfo::GetTypeComp
3673 * Retrieves the ITypeComp interface for the type description, which enables a
3674 * client compiler to bind to the type description's members.
3677 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
3678 ITypeComp
* *ppTComp
)
3680 ICOM_THIS( ITypeInfoImpl
, iface
);
3681 FIXME("(%p) stub!\n", This
);
3685 /* ITypeInfo::GetFuncDesc
3687 * Retrieves the FUNCDESC structure that contains information about a
3688 * specified function.
3691 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
3692 LPFUNCDESC
*ppFuncDesc
)
3694 ICOM_THIS( ITypeInfoImpl
, iface
);
3696 TLBFuncDesc
* pFDesc
;
3697 TRACE("(%p) index %d\n", This
, index
);
3698 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
3701 /* FIXME: must do a copy here */
3702 *ppFuncDesc
=&pFDesc
->funcdesc
;
3705 return E_INVALIDARG
;
3708 /* ITypeInfo::GetVarDesc
3710 * Retrieves a VARDESC structure that describes the specified variable.
3713 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
3714 LPVARDESC
*ppVarDesc
)
3716 ICOM_THIS( ITypeInfoImpl
, iface
);
3718 TLBVarDesc
* pVDesc
;
3719 TRACE("(%p) index %d\n", This
, index
);
3720 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
3723 /* FIXME: must do a copy here */
3724 *ppVarDesc
=&pVDesc
->vardesc
;
3727 return E_INVALIDARG
;
3730 /* ITypeInfo_GetNames
3732 * Retrieves the variable with the specified member ID (or the name of the
3733 * property or method and its parameters) that correspond to the specified
3736 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
3737 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
3739 ICOM_THIS( ITypeInfoImpl
, iface
);
3740 TLBFuncDesc
* pFDesc
;
3741 TLBVarDesc
* pVDesc
;
3743 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
3744 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
3747 /* function found, now return function and parameter names */
3748 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
3751 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
3753 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
3759 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
3762 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
3767 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
3769 /* recursive search */
3772 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
3774 if(SUCCEEDED(result
))
3776 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
3777 ITypeInfo_Release(pTInfo
);
3780 WARN("Could not search inherited interface!\n");
3784 WARN("no names found\n");
3787 return TYPE_E_ELEMENTNOTFOUND
;
3794 /* ITypeInfo::GetRefTypeOfImplType
3796 * If a type description describes a COM class, it retrieves the type
3797 * description of the implemented interface types. For an interface,
3798 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3802 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
3807 ICOM_THIS( ITypeInfoImpl
, iface
);
3809 TLBImplType
*pImpl
= This
->impltypelist
;
3811 TRACE("(%p) index %d\n", This
, index
);
3812 dump_TypeInfo(This
);
3816 /* only valid on dual interfaces;
3817 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3819 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
3821 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
3822 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
3828 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3829 *pRefType
= pImpl
->hRef
;
3834 /* get element n from linked list */
3835 for(i
=0; pImpl
&& i
<index
; i
++)
3837 pImpl
= pImpl
->next
;
3840 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3842 *pRefType
= pImpl
->hRef
;
3844 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
3851 /* ITypeInfo::GetImplTypeFlags
3853 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3854 * or base interface in a type description.
3856 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
3857 UINT index
, INT
*pImplTypeFlags
)
3859 ICOM_THIS( ITypeInfoImpl
, iface
);
3863 TRACE("(%p) index %d\n", This
, index
);
3864 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
3865 i
++, pImpl
=pImpl
->next
)
3867 if(i
==index
&& pImpl
){
3868 *pImplTypeFlags
=pImpl
->implflags
;
3872 return TYPE_E_ELEMENTNOTFOUND
;
3876 * Maps between member names and member IDs, and parameter names and
3879 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
3880 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
3882 ICOM_THIS( ITypeInfoImpl
, iface
);
3883 TLBFuncDesc
* pFDesc
;
3884 TLBVarDesc
* pVDesc
;
3887 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
3889 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
3891 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
3892 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
3893 for(i
=1; i
< cNames
; i
++){
3894 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
3895 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
3897 if( j
<pFDesc
->funcdesc
.cParams
)
3900 ret
=DISP_E_UNKNOWNNAME
;
3905 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
3906 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
3907 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
3911 /* not found, see if this is and interface with an inheritance */
3912 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
3913 This
->TypeAttr
.cImplTypes
){
3914 /* recursive search */
3916 ret
=ITypeInfo_GetRefTypeInfo(iface
,
3917 This
->impltypelist
->hRef
, &pTInfo
);
3919 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
3920 ITypeInfo_Release(pTInfo
);
3923 WARN("Could not search inherited interface!\n");
3925 WARN("no names found\n");
3926 return DISP_E_UNKNOWNNAME
;
3929 /* ITypeInfo::Invoke
3931 * Invokes a method, or accesses a property of an object, that implements the
3932 * interface described by the type description.
3935 _invoke(LPVOID func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
3938 if (TRACE_ON(ole
)) {
3940 MESSAGE("Calling %p(",func
);
3941 for (i
=0;i
<nrargs
;i
++) MESSAGE("%08lx,",args
[i
]);
3950 DWORD (WINAPI
*xfunc
)() = func
;
3955 DWORD (WINAPI
*xfunc
)(DWORD
) = func
;
3956 res
= xfunc(args
[0]);
3960 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
) = func
;
3961 res
= xfunc(args
[0],args
[1]);
3965 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
) = func
;
3966 res
= xfunc(args
[0],args
[1],args
[2]);
3970 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
) = func
;
3971 res
= xfunc(args
[0],args
[1],args
[2],args
[3]);
3975 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
3976 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4]);
3980 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
3981 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
3985 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
3986 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
3990 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
3996 FIXME("unsupported calling convention %d\n",callconv
);
4000 TRACE("returns %08lx\n",res
);
4004 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4009 DISPPARAMS
*pDispParams
,
4010 VARIANT
*pVarResult
,
4011 EXCEPINFO
*pExcepInfo
,
4014 ICOM_THIS( ITypeInfoImpl
, iface
);
4015 TLBFuncDesc
* pFDesc
;
4016 TLBVarDesc
* pVDesc
;
4019 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4020 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4022 dump_DispParms(pDispParams
);
4024 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4025 if (pFDesc
->funcdesc
.memid
== memid
) {
4026 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4030 dump_TLBFuncDescOne(pFDesc
);
4031 switch (pFDesc
->funcdesc
.funckind
) {
4032 case FUNC_PUREVIRTUAL
:
4033 case FUNC_VIRTUAL
: {
4035 DWORD
*args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
+1));
4036 DWORD
*args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
));
4037 args
[0] = (DWORD
)pIUnk
;
4039 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4040 if (i
<pDispParams
->cArgs
) {
4041 TRACE("set %d to disparg type %d vs %d\n",i
,
4042 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1]),
4043 pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
4045 args
[i
+1] = V_UNION(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1],lVal
);
4047 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4048 TRACE("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4049 /*FIXME: give pointers for the rest, so propertyget works*/
4050 args
[i
+1] = (DWORD
)&args2
[i
];
4052 /* If pointer to variant, pass reference to variant
4053 * in result variant array.
4055 if ((tdesc
->vt
== VT_PTR
) &&
4056 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4059 args
[i
+1] = (DWORD
)(pVarResult
+(i
-pDispParams
->cArgs
));
4062 if (pFDesc
->funcdesc
.cParamsOpt
)
4063 FIXME("Does not support optional parameters (%d)\n",
4064 pFDesc
->funcdesc
.cParamsOpt
4067 res
= _invoke((*(DWORD
***)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4068 pFDesc
->funcdesc
.callconv
,
4069 pFDesc
->funcdesc
.cParams
+1,
4072 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4073 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4074 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4075 /* If we are a pointer to a variant, we are done already */
4076 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4079 VariantInit(&pVarResult
[i
]);
4080 V_UNION(pVarResult
+i
,intVal
) = args2
[i
+pDispParams
->cArgs
];
4082 if (tdesc
->vt
== VT_PTR
)
4083 tdesc
= tdesc
->u
.lptdesc
;
4084 V_VT(pVarResult
+i
) = tdesc
->vt
;
4086 /* HACK: VB5 likes this.
4087 * I do not know why. There is 1 example in MSDN which uses
4088 * this which appears broken (mixes int vals and
4091 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4092 V_VT(pVarResult
+i
) = VT_DISPATCH
;
4093 TRACE("storing into variant: [%d]\n", i
);
4094 dump_Variant(pVarResult
+i
);
4097 HeapFree(GetProcessHeap(),0,args2
);
4098 HeapFree(GetProcessHeap(),0,args
);
4101 case FUNC_DISPATCH
: {
4105 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4107 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4110 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4111 hr
= IDispatch_Invoke(
4112 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4113 pVarResult
,pExcepInfo
,pArgErr
4116 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4117 IDispatch_Release(disp
);
4121 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4125 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4126 if (pVDesc
->vardesc
.memid
== memid
) {
4127 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4128 dump_TLBVarDesc(pVDesc
);
4133 /* not found, look for it in inherited interfaces */
4134 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4135 /* recursive search */
4138 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4140 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4141 ITypeInfo_Release(pTInfo
);
4144 WARN("Could not search inherited interface!\n");
4146 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4147 return DISP_E_MEMBERNOTFOUND
;
4150 /* ITypeInfo::GetDocumentation
4152 * Retrieves the documentation string, the complete Help file name and path,
4153 * and the context ID for the Help topic for a specified type description.
4155 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4156 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4157 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4159 ICOM_THIS( ITypeInfoImpl
, iface
);
4160 TLBFuncDesc
* pFDesc
;
4161 TLBVarDesc
* pVDesc
;
4162 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4163 " HelpContext(%p) HelpFile(%p)\n",
4164 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4165 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4167 *pBstrName
=SysAllocString(This
->Name
);
4169 *pBstrDocString
=SysAllocString(This
->DocString
);
4171 *pdwHelpContext
=This
->dwHelpContext
;
4173 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4175 }else {/* for a member */
4176 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4177 if(pFDesc
->funcdesc
.memid
==memid
){
4179 *pBstrName
= SysAllocString(pFDesc
->Name
);
4181 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4183 *pdwHelpContext
=pFDesc
->helpcontext
;
4186 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4187 if(pVDesc
->vardesc
.memid
==memid
){
4188 FIXME("Not implemented\n");
4192 return TYPE_E_ELEMENTNOTFOUND
;
4195 /* ITypeInfo::GetDllEntry
4197 * Retrieves a description or specification of an entry point for a function
4200 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4201 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4204 ICOM_THIS( ITypeInfoImpl
, iface
);
4205 FIXME("(%p) stub!\n", This
);
4209 /* ITypeInfo::GetRefTypeInfo
4211 * If a type description references other type descriptions, it retrieves
4212 * the referenced type descriptions.
4214 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4217 ITypeInfo
**ppTInfo
)
4219 ICOM_THIS( ITypeInfoImpl
, iface
);
4220 HRESULT result
= E_FAIL
;
4223 if (hRefType
== -1 &&
4224 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4225 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4227 /* when we meet a DUAL dispinterface, we must create the interface
4230 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4233 /* the interface version contains the same information as the dispinterface
4234 * copy the contents of the structs.
4236 *pTypeInfoImpl
= *This
;
4237 pTypeInfoImpl
->ref
= 1;
4239 /* change the type to interface */
4240 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4242 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4244 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4249 TLBRefType
*pRefType
;
4250 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4251 if(pRefType
->reference
== hRefType
)
4255 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4256 if(pRefType
&& hRefType
!= -1) {
4257 ITypeLib
*pTLib
= NULL
;
4259 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4261 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4263 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4264 TRACE("typeinfo in imported typelib that is already loaded\n");
4265 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4266 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4269 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4270 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4271 pRefType
->pImpTLInfo
->wVersionMajor
,
4272 pRefType
->pImpTLInfo
->wVersionMinor
,
4273 pRefType
->pImpTLInfo
->lcid
,
4276 if(!SUCCEEDED(result
)) {
4277 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4278 result
=LoadTypeLib(libnam
, &pTLib
);
4279 SysFreeString(libnam
);
4281 if(SUCCEEDED(result
)) {
4282 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4283 ITypeLib2_AddRef(pTLib
);
4287 if(SUCCEEDED(result
)) {
4288 if(pRefType
->index
== TLB_REF_USE_GUID
)
4289 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4293 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4297 ITypeLib2_Release(pTLib
);
4301 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4302 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4306 /* ITypeInfo::AddressOfMember
4308 * Retrieves the addresses of static functions or variables, such as those
4311 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4312 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4314 ICOM_THIS( ITypeInfoImpl
, iface
);
4315 FIXME("(%p) stub!\n", This
);
4319 /* ITypeInfo::CreateInstance
4321 * Creates a new instance of a type that describes a component object class
4324 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4325 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4327 ICOM_THIS( ITypeInfoImpl
, iface
);
4328 FIXME("(%p) stub!\n", This
);
4332 /* ITypeInfo::GetMops
4334 * Retrieves marshaling information.
4336 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4339 ICOM_THIS( ITypeInfoImpl
, iface
);
4340 FIXME("(%p) stub!\n", This
);
4344 /* ITypeInfo::GetContainingTypeLib
4346 * Retrieves the containing type library and the index of the type description
4347 * within that type library.
4349 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4350 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4352 ICOM_THIS( ITypeInfoImpl
, iface
);
4354 return E_INVALIDARG
;
4355 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4356 *pIndex
=This
->index
;
4357 ITypeLib2_AddRef(*ppTLib
);
4358 TRACE("(%p) returns (%p) index %d!\n", This
, *ppTLib
, *pIndex
);
4362 /* ITypeInfo::ReleaseTypeAttr
4364 * Releases a TYPEATTR previously returned by GetTypeAttr.
4367 static HRESULT WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4368 TYPEATTR
* pTypeAttr
)
4370 ICOM_THIS( ITypeInfoImpl
, iface
);
4371 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4375 /* ITypeInfo::ReleaseFuncDesc
4377 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4379 static HRESULT WINAPI
ITypeInfo_fnReleaseFuncDesc(
4381 FUNCDESC
*pFuncDesc
)
4383 ICOM_THIS( ITypeInfoImpl
, iface
);
4384 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4388 /* ITypeInfo::ReleaseVarDesc
4390 * Releases a VARDESC previously returned by GetVarDesc.
4392 static HRESULT WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4395 ICOM_THIS( ITypeInfoImpl
, iface
);
4396 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4400 /* ITypeInfo2::GetTypeKind
4402 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4405 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
4406 TYPEKIND
*pTypeKind
)
4408 ICOM_THIS( ITypeInfoImpl
, iface
);
4409 *pTypeKind
=This
->TypeAttr
.typekind
;
4410 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
4414 /* ITypeInfo2::GetTypeFlags
4416 * Returns the type flags without any allocations. This returns a DWORD type
4417 * flag, which expands the type flags without growing the TYPEATTR (type
4421 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
* iface
,
4424 ICOM_THIS( ITypeInfoImpl
, iface
);
4425 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
4426 TRACE("(%p) flags 0x%04x\n", This
,*pTypeFlags
);
4430 /* ITypeInfo2::GetFuncIndexOfMemId
4431 * Binds to a specific member based on a known DISPID, where the member name
4432 * is not known (for example, when binding to a default member).
4435 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
4436 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
4438 ICOM_THIS( ITypeInfoImpl
, iface
);
4439 TLBFuncDesc
*pFuncInfo
;
4442 /* FIXME: should check for invKind??? */
4443 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
4444 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
4450 result
=E_INVALIDARG
;
4452 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
4453 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4457 /* TypeInfo2::GetVarIndexOfMemId
4459 * Binds to a specific member based on a known DISPID, where the member name
4460 * is not known (for example, when binding to a default member).
4463 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
4464 MEMBERID memid
, UINT
*pVarIndex
)
4466 ICOM_THIS( ITypeInfoImpl
, iface
);
4467 TLBVarDesc
*pVarInfo
;
4470 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
4471 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
4478 result
=E_INVALIDARG
;
4480 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
4481 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4485 /* ITypeInfo2::GetCustData
4487 * Gets the custom data
4489 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
4494 ICOM_THIS( ITypeInfoImpl
, iface
);
4495 TLBCustData
*pCData
;
4497 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4498 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4500 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4504 VariantInit( pVarVal
);
4505 VariantCopy( pVarVal
, &pCData
->data
);
4508 return E_INVALIDARG
; /* FIXME: correct? */
4511 /* ITypeInfo2::GetFuncCustData
4513 * Gets the custom data
4515 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
4521 ICOM_THIS( ITypeInfoImpl
, iface
);
4522 TLBCustData
*pCData
=NULL
;
4523 TLBFuncDesc
* pFDesc
;
4525 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4526 pFDesc
=pFDesc
->next
);
4529 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4530 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4532 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4535 VariantInit( pVarVal
);
4536 VariantCopy( pVarVal
, &pCData
->data
);
4539 return E_INVALIDARG
; /* FIXME: correct? */
4542 /* ITypeInfo2::GetParamCustData
4544 * Gets the custom data
4546 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
4553 ICOM_THIS( ITypeInfoImpl
, iface
);
4554 TLBCustData
*pCData
=NULL
;
4555 TLBFuncDesc
* pFDesc
;
4558 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
4560 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
4561 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
4562 pCData
= pCData
->next
)
4563 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4565 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4569 VariantInit( pVarVal
);
4570 VariantCopy( pVarVal
, &pCData
->data
);
4573 return E_INVALIDARG
; /* FIXME: correct? */
4576 /* ITypeInfo2::GetVarCustData
4578 * Gets the custom data
4580 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
4586 ICOM_THIS( ITypeInfoImpl
, iface
);
4587 TLBCustData
*pCData
=NULL
;
4588 TLBVarDesc
* pVDesc
;
4591 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
4595 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4597 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4601 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4605 VariantInit( pVarVal
);
4606 VariantCopy( pVarVal
, &pCData
->data
);
4609 return E_INVALIDARG
; /* FIXME: correct? */
4612 /* ITypeInfo2::GetImplCustData
4614 * Gets the custom data
4616 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
4622 ICOM_THIS( ITypeInfoImpl
, iface
);
4623 TLBCustData
*pCData
=NULL
;
4624 TLBImplType
* pRDesc
;
4627 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
4631 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4633 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4637 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4641 VariantInit( pVarVal
);
4642 VariantCopy( pVarVal
, &pCData
->data
);
4645 return E_INVALIDARG
; /* FIXME: correct? */
4648 /* ITypeInfo2::GetDocumentation2
4650 * Retrieves the documentation string, the complete Help file name and path,
4651 * the localization context to use, and the context ID for the library Help
4652 * topic in the Help file.
4655 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
4659 BSTR
*pbstrHelpString
,
4660 DWORD
*pdwHelpStringContext
,
4661 BSTR
*pbstrHelpStringDll
)
4663 ICOM_THIS( ITypeInfoImpl
, iface
);
4664 TLBFuncDesc
* pFDesc
;
4665 TLBVarDesc
* pVDesc
;
4666 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4667 "HelpStringContext(%p) HelpStringDll(%p)\n",
4668 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
4669 pbstrHelpStringDll
);
4670 /* the help string should be obtained from the helpstringdll,
4671 * using the _DLLGetDocumentation function, based on the supplied
4672 * lcid. Nice to do sometime...
4674 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4676 *pbstrHelpString
=SysAllocString(This
->Name
);
4677 if(pdwHelpStringContext
)
4678 *pdwHelpStringContext
=This
->dwHelpStringContext
;
4679 if(pbstrHelpStringDll
)
4680 *pbstrHelpStringDll
=
4681 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4683 }else {/* for a member */
4684 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4685 if(pFDesc
->funcdesc
.memid
==memid
){
4687 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
4688 if(pdwHelpStringContext
)
4689 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
4690 if(pbstrHelpStringDll
)
4691 *pbstrHelpStringDll
=
4692 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4695 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4696 if(pVDesc
->vardesc
.memid
==memid
){
4698 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
4699 if(pdwHelpStringContext
)
4700 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
4701 if(pbstrHelpStringDll
)
4702 *pbstrHelpStringDll
=
4703 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4707 return TYPE_E_ELEMENTNOTFOUND
;
4710 /* ITypeInfo2::GetAllCustData
4712 * Gets all custom data items for the Type info.
4715 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
4717 CUSTDATA
*pCustData
)
4719 ICOM_THIS( ITypeInfoImpl
, iface
);
4720 TLBCustData
*pCData
;
4723 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4725 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4726 if(pCustData
->prgCustData
){
4727 pCustData
->cCustData
=This
->ctCustData
;
4728 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4729 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4730 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4733 ERR(" OUT OF MEMORY! \n");
4734 return E_OUTOFMEMORY
;
4739 /* ITypeInfo2::GetAllFuncCustData
4741 * Gets all custom data items for the specified Function
4744 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
4747 CUSTDATA
*pCustData
)
4749 ICOM_THIS( ITypeInfoImpl
, iface
);
4750 TLBCustData
*pCData
;
4751 TLBFuncDesc
* pFDesc
;
4753 TRACE("(%p) index %d\n", This
, index
);
4754 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4755 pFDesc
=pFDesc
->next
)
4758 pCustData
->prgCustData
=
4759 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4760 if(pCustData
->prgCustData
){
4761 pCustData
->cCustData
=pFDesc
->ctCustData
;
4762 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
4763 pCData
= pCData
->next
){
4764 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4765 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4769 ERR(" OUT OF MEMORY! \n");
4770 return E_OUTOFMEMORY
;
4774 return TYPE_E_ELEMENTNOTFOUND
;
4777 /* ITypeInfo2::GetAllParamCustData
4779 * Gets all custom data items for the Functions
4782 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
4783 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
4785 ICOM_THIS( ITypeInfoImpl
, iface
);
4786 TLBCustData
*pCData
=NULL
;
4787 TLBFuncDesc
* pFDesc
;
4789 TRACE("(%p) index %d\n", This
, indexFunc
);
4790 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
4791 pFDesc
=pFDesc
->next
)
4793 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
4794 pCustData
->prgCustData
=
4795 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
4796 sizeof(CUSTDATAITEM
));
4797 if(pCustData
->prgCustData
){
4798 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
4799 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
4800 pCData
; i
++, pCData
= pCData
->next
){
4801 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4802 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4806 ERR(" OUT OF MEMORY! \n");
4807 return E_OUTOFMEMORY
;
4811 return TYPE_E_ELEMENTNOTFOUND
;
4814 /* ITypeInfo2::GetAllVarCustData
4816 * Gets all custom data items for the specified Variable
4819 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
4820 UINT index
, CUSTDATA
*pCustData
)
4822 ICOM_THIS( ITypeInfoImpl
, iface
);
4823 TLBCustData
*pCData
;
4824 TLBVarDesc
* pVDesc
;
4826 TRACE("(%p) index %d\n", This
, index
);
4827 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
4828 pVDesc
=pVDesc
->next
)
4831 pCustData
->prgCustData
=
4832 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4833 if(pCustData
->prgCustData
){
4834 pCustData
->cCustData
=pVDesc
->ctCustData
;
4835 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
4836 pCData
= pCData
->next
){
4837 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4838 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4842 ERR(" OUT OF MEMORY! \n");
4843 return E_OUTOFMEMORY
;
4847 return TYPE_E_ELEMENTNOTFOUND
;
4850 /* ITypeInfo2::GetAllImplCustData
4852 * Gets all custom data items for the specified implementation type
4855 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
4858 CUSTDATA
*pCustData
)
4860 ICOM_THIS( ITypeInfoImpl
, iface
);
4861 TLBCustData
*pCData
;
4862 TLBImplType
* pRDesc
;
4864 TRACE("(%p) index %d\n", This
, index
);
4865 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
4866 pRDesc
=pRDesc
->next
)
4869 pCustData
->prgCustData
=
4870 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4871 if(pCustData
->prgCustData
){
4872 pCustData
->cCustData
=pRDesc
->ctCustData
;
4873 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
4874 pCData
= pCData
->next
){
4875 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4876 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4880 ERR(" OUT OF MEMORY! \n");
4881 return E_OUTOFMEMORY
;
4885 return TYPE_E_ELEMENTNOTFOUND
;
4888 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
4890 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4892 ITypeInfo_fnQueryInterface
,
4894 ITypeInfo_fnRelease
,
4896 ITypeInfo_fnGetTypeAttr
,
4897 ITypeInfo_fnGetTypeComp
,
4898 ITypeInfo_fnGetFuncDesc
,
4899 ITypeInfo_fnGetVarDesc
,
4900 ITypeInfo_fnGetNames
,
4901 ITypeInfo_fnGetRefTypeOfImplType
,
4902 ITypeInfo_fnGetImplTypeFlags
,
4903 ITypeInfo_fnGetIDsOfNames
,
4905 ITypeInfo_fnGetDocumentation
,
4906 ITypeInfo_fnGetDllEntry
,
4907 ITypeInfo_fnGetRefTypeInfo
,
4908 ITypeInfo_fnAddressOfMember
,
4909 ITypeInfo_fnCreateInstance
,
4910 ITypeInfo_fnGetMops
,
4911 ITypeInfo_fnGetContainingTypeLib
,
4912 ITypeInfo_fnReleaseTypeAttr
,
4913 ITypeInfo_fnReleaseFuncDesc
,
4914 ITypeInfo_fnReleaseVarDesc
,
4916 ITypeInfo2_fnGetTypeKind
,
4917 ITypeInfo2_fnGetTypeFlags
,
4918 ITypeInfo2_fnGetFuncIndexOfMemId
,
4919 ITypeInfo2_fnGetVarIndexOfMemId
,
4920 ITypeInfo2_fnGetCustData
,
4921 ITypeInfo2_fnGetFuncCustData
,
4922 ITypeInfo2_fnGetParamCustData
,
4923 ITypeInfo2_fnGetVarCustData
,
4924 ITypeInfo2_fnGetImplTypeCustData
,
4925 ITypeInfo2_fnGetDocumentation2
,
4926 ITypeInfo2_fnGetAllCustData
,
4927 ITypeInfo2_fnGetAllFuncCustData
,
4928 ITypeInfo2_fnGetAllParamCustData
,
4929 ITypeInfo2_fnGetAllVarCustData
,
4930 ITypeInfo2_fnGetAllImplTypeCustData
,