crypt32: ComparePublicKeyInfo must ignore the leading zero.
[wine] / programs / oleview / typelib.c
1 /*
2  * OleView (typelib.c)
3  *
4  * Copyright 2006 Piotr Caban
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "main.h"
22
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(oleview);
27
28 TYPELIB typelib;
29 static const WCHAR wszTypeLib[] = { 'T','Y','P','E','L','I','B','\0' };
30
31 static const WCHAR wszFailed[] = { '<','f','a','i','l','e','d','>','\0' };
32 static const WCHAR wszSpace[] = { ' ','\0' };
33 static const WCHAR wszAsterix[] = { '*','\0' };
34 static const WCHAR wszComa[] = { ',','\0' };
35 static const WCHAR wszEquals[] = { '=','\0' };
36 static const WCHAR wszSemicolon[] = { ';','\0' };
37 static const WCHAR wszNewLine[] = { '\n','\0' };
38 static const WCHAR wszOpenBrackets1[] = { '[','\0' };
39 static const WCHAR wszCloseBrackets1[] = { ']','\0' };
40 static const WCHAR wszOpenBrackets2[] = { '(','\0' };
41 static const WCHAR wszCloseBrackets2[] = { ')','\0' };
42 static const WCHAR wszOpenBrackets3[] = { '{','\0' };
43 static const WCHAR wszCloseBrackets3[] = { '}','\0' };
44 static const WCHAR wszInvertedComa[] = { '"','\0' };
45 static const WCHAR wszColon[] = { ':','\0' };
46
47 static const WCHAR wszUUID[] = { 'u','u','i','d','\0' };
48 static const WCHAR wszOdl[] = { 'o','d','l','\0' };
49
50 static const WCHAR wszVT_BOOL[]
51     = { 'V','A','R','I','A','N','T','_','B','O','O','L','\0' };
52 static const WCHAR wszVT_UI1[]
53     = { 'u','n','s','i','g','n','e','d',' ','c','h','a','r','\0' };
54 static const WCHAR wszVT_UI2[]
55     = { 'u','n','s','i','g','n','e','d',' ','s','h','o','r','t','\0' };
56 static const WCHAR wszVT_UI4[]
57     = { 'u','n','s','i','g','n','e','d',' ','l','o','n','g','\0' };
58 static const WCHAR wszVT_UI8[] = { 'u','i','n','t','6','4','\0' };
59 static const WCHAR wszVT_UINT[]
60     = { 'u','n','s','i','g','n','e','d',' ','i','n','t','\0' };
61 static const WCHAR wszVT_I1[] = { 'c','h','a','r','\0' };
62 static const WCHAR wszVT_I2[] = { 's','h','o','r','t','\0' };
63 static const WCHAR wszVT_I4[] = { 'l','o','n','g','\0' };
64 static const WCHAR wszVT_I8[] = { 'i','n','t','6','4','\0' };
65 static const WCHAR wszVT_R4[] = { 's','i','n','g','l','e','\0' };
66 static const WCHAR wszVT_INT[] = { 'i','n','t','\0' };
67 static const WCHAR wszVT_BSTR[] = { 'B','S','T','R','\0' };
68 static const WCHAR wszVT_CY[] = { 'C','U','R','R','E','N','C','Y','\0' };
69 static const WCHAR wszVT_VARIANT[] = { 'V','A','R','I','A','N','T','\0' };
70 static const WCHAR wszVT_VOID[] = { 'v','o','i','d','\0' };
71 static const WCHAR wszVT_ERROR[] = { 'S','C','O','D','E','\0' };
72 static const WCHAR wszVT_LPSTR[] = { 'L','P','S','T','R','\0' };
73 static const WCHAR wszVT_LPWSTR[] = { 'L','P','W','S','T','R','\0' };
74 static const WCHAR wszVT_HRESULT[] = { 'H','R','E','S','U','L','T','\0' };
75 static const WCHAR wszVT_UNKNOWN[] = { 'I','U','n','k','n','o','w','n','\0' };
76 static const WCHAR wszVT_DISPATCH[] = { 'I','D','i','s','p','a','t','c','h','\0' };
77 static const WCHAR wszVT_DATE[] = { 'D','A','T','E','\0' };
78 static const WCHAR wszVT_R8[] = { 'd','o','u','b','l','e','\0' };
79 static const WCHAR wszVT_SAFEARRAY[] = { 'S','A','F','E','A','R','R','A','Y','\0' };
80
81 static const WCHAR wszFormat[] = { '0','x','%','.','8','l','x','\0' };
82 static const WCHAR wszStdCall[] = { '_','s','t','d','c','a','l','l','\0' };
83 static const WCHAR wszId[] = { 'i','d','\0' };
84 static const WCHAR wszHelpstring[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
85 static const WCHAR wszPropPut[] = { 'p','r','o','p','p','u','t','\0' };
86 static const WCHAR wszPropGet[] = { 'p','r','o','p','g','e','t','\0' };
87 static const WCHAR wszPropPutRef[] = { 'p','r','o','p','p','u','t','r','e','f','\0' };
88 static const WCHAR wszPARAMFLAG_FIN[] = { 'i','n','\0' };
89 static const WCHAR wszPARAMFLAG_FOUT[] = { 'o','u','t','\0' };
90 static const WCHAR wszPARAMFLAG_FLCID[] = { 'c','i','d','\0' };
91 static const WCHAR wszPARAMFLAG_FRETVAL[] = { 'r','e','t','v','a','l','\0' };
92 static const WCHAR wszPARAMFLAG_FOPT[] = { 'o','p','t','i','o','n','a','l','\0' };
93 static const WCHAR wszPARAMFLAG_FHASCUSTDATA[]
94     = { 'h','a','s','c','u','s','t','d','a','t','a','\0' };
95 static const WCHAR wszDefaultValue[]
96     = { 'd','e','f','a','u','l','t','v','a','l','u','e','\0' };
97
98 static const WCHAR wszReadOnly[] = { 'r','e','a','d','o','n','l','y','\0' };
99 static const WCHAR wszConst[] = { 'c','o','n','s','t','\0' };
100
101 static void ShowLastError(void)
102 {
103     DWORD error = GetLastError();
104     LPWSTR lpMsgBuf;
105     WCHAR wszTitle[MAX_LOAD_STRING];
106
107     LoadString(globals.hMainInst, IDS_TYPELIBTITLE, wszTitle,
108             sizeof(WCHAR[MAX_LOAD_STRING]));
109     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
110             NULL, error, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
111     MessageBox(NULL, lpMsgBuf, wszTitle, MB_OK | MB_ICONERROR);
112     LocalFree(lpMsgBuf);
113     return;
114 }
115
116 static void SaveIdl(WCHAR *wszFileName)
117 {
118     HTREEITEM hIDL;
119     TVITEM tvi;
120     HANDLE hFile;
121     DWORD len, dwNumWrite;
122     char *wszIdl;
123     TYPELIB_DATA *data;
124
125     hIDL = TreeView_GetChild(typelib.hTree, TVI_ROOT);
126
127     memset(&tvi, 0, sizeof(TVITEM));
128     tvi.hItem = hIDL;
129
130     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
131     data = (TYPELIB_DATA *)tvi.lParam;
132
133     hFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
134                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
135     if(hFile == INVALID_HANDLE_VALUE)
136     {
137         ShowLastError();
138         return;
139     }
140
141     len = WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, NULL, 0, NULL, NULL );
142     wszIdl = HeapAlloc(GetProcessHeap(), 0, len);
143     WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, wszIdl, len, NULL, NULL );
144
145     if(!WriteFile(hFile, wszIdl, len, &dwNumWrite, NULL))
146         ShowLastError();
147
148     HeapFree(GetProcessHeap(), 0, wszIdl);
149     CloseHandle(hFile);
150 }
151
152 static void GetSaveIdlAsPath(void)
153 {
154     OPENFILENAME saveidl;
155     WCHAR *pFileName;
156     WCHAR wszPath[MAX_LOAD_STRING];
157     WCHAR wszDir[MAX_LOAD_STRING];
158     static const WCHAR wszDefaultExt[] = { 'i','d','l',0 };
159     static const WCHAR wszIdlFiles[] = { '*','.','i','d','l','\0','\0' };
160
161     memset(&saveidl, 0, sizeof(saveidl));
162
163     lstrcpyW(wszDir, typelib.wszFileName);
164     pFileName = wszDir + lstrlenW(wszDir);
165     while(*pFileName != '.' && *pFileName != '\\' && *pFileName != '/'
166             && pFileName > wszDir) pFileName -= 1;
167     if(*pFileName == '.')
168     {
169         *pFileName = '\0';
170         while(*pFileName != '\\' && *pFileName != '/' && pFileName > wszDir)
171             pFileName -= 1;
172     }
173     if(*pFileName == '\\' || *pFileName == '/') pFileName += 1;
174     lstrcpyW(wszPath, pFileName);
175
176     GetCurrentDirectory(MAX_LOAD_STRING, wszDir);
177
178     saveidl.lStructSize = sizeof(OPENFILENAME);
179     saveidl.hwndOwner = globals.hTypeLibWnd;
180     saveidl.hInstance = globals.hMainInst;
181     saveidl.lpstrFilter = wszIdlFiles;
182     saveidl.lpstrFile = wszPath;
183     saveidl.nMaxFile = MAX_LOAD_STRING;
184     saveidl.lpstrInitialDir = wszDir;
185     saveidl.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
186     saveidl.lpstrDefExt = wszDefaultExt;
187
188     if (GetSaveFileName(&saveidl))
189         SaveIdl(wszPath);
190 }
191
192 void AddToStrW(WCHAR *wszDest, const WCHAR *wszSource)
193 {
194     lstrcpyW(&wszDest[lstrlenW(wszDest)], wszSource);
195 }
196
197 void AddToTLDataStrW(TYPELIB_DATA *pTLData, const WCHAR *wszSource)
198 {
199     int SourceLen = lstrlenW(wszSource);
200
201     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
202             sizeof(WCHAR)*(pTLData->idlLen+SourceLen+1));
203
204     memcpy(&pTLData->idl[pTLData->idlLen], wszSource, sizeof(WCHAR)*(SourceLen+1));
205     pTLData->idlLen += SourceLen;
206 }
207
208 void AddToTLDataStrWithTabsW(TYPELIB_DATA *pTLData, WCHAR *wszSource)
209 {
210     int lineLen = lstrlenW(wszSource);
211     int newLinesNo = 0;
212     WCHAR *pSourcePos = (WCHAR *)wszSource;
213     WCHAR *pSourceBeg;
214
215     if(!lineLen) return;
216     while(*pSourcePos)
217     {
218         if(*pSourcePos == *wszNewLine) newLinesNo++;
219         pSourcePos += 1;
220     }
221     if(*(pSourcePos - 1) != *wszNewLine) newLinesNo++;
222
223     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
224             sizeof(WCHAR)*(pTLData->idlLen+lineLen+4*newLinesNo+1));
225
226     pSourcePos = (WCHAR *)wszSource;
227     pSourceBeg = (WCHAR *)wszSource;
228     while(newLinesNo)
229     {
230         if(*pSourcePos != *wszNewLine && *pSourcePos)
231         {
232             pSourcePos += 1;
233             continue;
234         }
235         newLinesNo--;
236
237         if(*pSourcePos)
238         {
239             *pSourcePos = '\0';
240             lineLen = lstrlenW(pSourceBeg)+1;
241             *pSourcePos = '\n';
242             pSourcePos += 1;
243         }
244         else lineLen = lstrlenW(pSourceBeg);
245
246         pTLData->idl[pTLData->idlLen] = *wszSpace;
247         pTLData->idl[pTLData->idlLen+1] = *wszSpace;
248         pTLData->idl[pTLData->idlLen+2] = *wszSpace;
249         pTLData->idl[pTLData->idlLen+3] = *wszSpace;
250         memcpy(&pTLData->idl[pTLData->idlLen+4], pSourceBeg, sizeof(WCHAR)*lineLen);
251         pTLData->idlLen += lineLen + 4;
252         pTLData->idl[pTLData->idlLen] = '\0';
253
254         pSourceBeg = pSourcePos;
255     }
256 }
257
258 static TYPELIB_DATA *InitializeTLData(void)
259 {
260     TYPELIB_DATA *pTLData;
261
262     pTLData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYPELIB_DATA));
263
264     pTLData->idl = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR));
265     pTLData->idl[0] = '\0';
266
267     return pTLData;
268 }
269
270 static void AddSpaces(TYPELIB_DATA *pTLData, int tabSize)
271 {
272     for(; tabSize>0; tabSize--)
273         AddToTLDataStrW(pTLData, wszSpace);
274 }
275
276 static void AddChildrenData(HTREEITEM hParent, TYPELIB_DATA *pData)
277 {
278     HTREEITEM hCur;
279     TVITEM tvi;
280
281     memset(&tvi, 0, sizeof(&tvi));
282
283     hCur = TreeView_GetChild(typelib.hTree, hParent);
284     if(!hCur) return;
285
286     do
287     {
288         tvi.hItem = hCur;
289         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
290         if(tvi.lParam && ((TYPELIB_DATA *)(tvi.lParam))->idlLen)
291             AddToTLDataStrWithTabsW(pData, ((TYPELIB_DATA *)(tvi.lParam))->idl);
292     }while((hCur = TreeView_GetNextSibling(typelib.hTree, hCur)));
293 }
294
295 static void CreateTypeInfo(WCHAR *wszAddTo, WCHAR *wszAddAfter, TYPEDESC tdesc, ITypeInfo *pTypeInfo)
296 {
297     int i;
298     BSTR bstrData;
299     HRESULT hRes;
300     ITypeInfo *pRefTypeInfo;
301     WCHAR wszBuf[MAX_LOAD_STRING];
302     WCHAR wszFormat[] = { '[','%','l','u',']','\0' };
303
304     switch(tdesc.vt&VT_TYPEMASK)
305     {
306 #define VTADDTOSTR(x) case x:\
307         AddToStrW(wszAddTo, wsz##x);\
308         break
309         VTADDTOSTR(VT_BOOL);
310         VTADDTOSTR(VT_UI1);
311         VTADDTOSTR(VT_UI2);
312         VTADDTOSTR(VT_UI4);
313         VTADDTOSTR(VT_UI8);
314         VTADDTOSTR(VT_UINT);
315         VTADDTOSTR(VT_I1);
316         VTADDTOSTR(VT_I2);
317         VTADDTOSTR(VT_I4);
318         VTADDTOSTR(VT_I8);
319         VTADDTOSTR(VT_R4);
320         VTADDTOSTR(VT_INT);
321         VTADDTOSTR(VT_BSTR);
322         VTADDTOSTR(VT_CY);
323         VTADDTOSTR(VT_VARIANT);
324         VTADDTOSTR(VT_VOID);
325         VTADDTOSTR(VT_ERROR);
326         VTADDTOSTR(VT_LPSTR);
327         VTADDTOSTR(VT_LPWSTR);
328         VTADDTOSTR(VT_HRESULT);
329         VTADDTOSTR(VT_UNKNOWN);
330         VTADDTOSTR(VT_DISPATCH);
331         VTADDTOSTR(VT_DATE);
332         VTADDTOSTR(VT_R8);
333         case VT_CARRAY:
334         for(i=0; i<U(tdesc).lpadesc->cDims; i++)
335         {
336             wsprintfW(wszBuf, wszFormat, U(tdesc).lpadesc->rgbounds[i].cElements);
337             AddToStrW(wszAddAfter, wszBuf);
338         }
339         CreateTypeInfo(wszAddTo, wszAddAfter, U(tdesc).lpadesc->tdescElem, pTypeInfo);
340         break;
341         case VT_SAFEARRAY:
342         AddToStrW(wszAddTo, wszVT_SAFEARRAY);
343         AddToStrW(wszAddTo, wszOpenBrackets2);
344         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
345         AddToStrW(wszAddTo, wszCloseBrackets2);
346         break;
347         case VT_PTR:
348         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
349         AddToStrW(wszAddTo, wszAsterix);
350         break;
351         case VT_USERDEFINED:
352         hRes = ITypeInfo_GetRefTypeInfo(pTypeInfo,
353                 U(tdesc).hreftype, &pRefTypeInfo);
354         if(SUCCEEDED(hRes))
355         {
356             ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL,
357                     &bstrData, NULL, NULL, NULL);
358             AddToStrW(wszAddTo, bstrData);
359             SysFreeString(bstrData);
360             ITypeInfo_Release(pRefTypeInfo);
361         }
362         else AddToStrW(wszAddTo, wszFailed);
363         break;
364         default:
365         WINE_FIXME("tdesc.vt&VT_TYPEMASK == %d not supported\n",
366                 tdesc.vt&VT_TYPEMASK);
367     }
368 }
369
370 static int EnumVars(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
371 {
372     int i;
373     TVINSERTSTRUCT tvis;
374     VARDESC *pVarDesc;
375     BSTR bstrName;
376     WCHAR wszText[MAX_LOAD_STRING];
377     WCHAR wszAfter[MAX_LOAD_STRING];
378
379     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
380     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
381     U(tvis).item.pszText = wszText;
382     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
383     tvis.hParent = hParent;
384
385     for(i=0; i<cVars; i++)
386     {
387         TYPELIB_DATA *tld;
388
389         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
390         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
391                 NULL, NULL, NULL))) continue;
392
393         tld = InitializeTLData();
394         U(tvis).item.lParam = (LPARAM) tld;
395         if(pVarDesc->memid < MIN_VAR_ID)
396         {
397
398             AddToTLDataStrW(tld, wszOpenBrackets1);
399             AddToTLDataStrW(tld, wszId);
400             AddToTLDataStrW(tld, wszOpenBrackets2);
401             wsprintfW(wszText, wszFormat, pVarDesc->memid);
402             AddToTLDataStrW(tld, wszText);
403             memset(wszText, 0, sizeof(wszText));
404             AddToTLDataStrW(tld, wszCloseBrackets2);
405
406             if(pVarDesc->wVarFlags & VARFLAG_FREADONLY)
407             {
408                 AddToTLDataStrW(tld, wszComa);
409                 AddToTLDataStrW(tld, wszSpace);
410                 AddToTLDataStrW(tld, wszReadOnly);
411             }
412             AddToTLDataStrW(tld, wszCloseBrackets1);
413             AddToTLDataStrW(tld, wszNewLine);
414         }
415
416         memset(wszText, 0, sizeof(wszText));
417         memset(wszAfter, 0, sizeof(wszAfter));
418         CreateTypeInfo(wszText, wszAfter, pVarDesc->elemdescVar.tdesc, pTypeInfo);
419         AddToStrW(wszText, wszSpace);
420         AddToStrW(wszText, bstrName);
421         AddToStrW(wszText, wszAfter);
422         AddToTLDataStrW(tld, wszText);
423         AddToTLDataStrW(tld, wszSemicolon);
424         AddToTLDataStrW(tld, wszNewLine);
425
426         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
427         SysFreeString(bstrName);
428         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
429     }
430
431     return 0;
432 }
433
434 static int EnumEnums(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
435 {
436     int i;
437     TVINSERTSTRUCT tvis;
438     VARDESC *pVarDesc;
439     BSTR bstrName;
440     WCHAR wszText[MAX_LOAD_STRING];
441     WCHAR wszAfter[MAX_LOAD_STRING];
442
443     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
444     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
445     U(tvis).item.pszText = wszText;
446     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
447     tvis.hParent = hParent;
448
449     for(i=0; i<cVars; i++)
450     {
451         TYPELIB_DATA *tld;
452
453         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
454         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
455                 NULL, NULL, NULL))) continue;
456
457         tld = InitializeTLData();
458         U(tvis).item.lParam = (LPARAM) tld;
459
460         memset(wszText, 0, sizeof(wszText));
461         memset(wszAfter, 0, sizeof(wszAfter));
462
463         if (pVarDesc->varkind == VAR_CONST)
464         {
465             VARIANT var;
466             VariantInit(&var);
467             if (VariantChangeType(&var, U(*pVarDesc).lpvarValue, 0, VT_BSTR) == S_OK)
468             {
469                 AddToStrW(wszText, wszConst);
470                 AddToStrW(wszText, wszSpace);
471                 AddToStrW(wszAfter, wszSpace);
472                 AddToStrW(wszAfter, wszEquals);
473                 AddToStrW(wszAfter, wszSpace);
474                 AddToStrW(wszAfter, V_BSTR(&var));
475             }
476         }
477
478         CreateTypeInfo(wszText, wszAfter, pVarDesc->elemdescVar.tdesc, pTypeInfo);
479         AddToStrW(wszText, wszSpace);
480         AddToStrW(wszText, bstrName);
481         AddToStrW(wszText, wszAfter);
482         AddToTLDataStrW(tld, bstrName);
483         AddToTLDataStrW(tld, wszAfter);
484         if (i<cVars-1)
485             AddToTLDataStrW(tld, wszComa);
486         AddToTLDataStrW(tld, wszNewLine);
487
488         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
489         SysFreeString(bstrName);
490         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
491     }
492
493     return 0;
494 }
495
496 static int EnumFuncs(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, HTREEITEM hParent)
497 {
498     int i, j;
499     int cFuncs;
500     unsigned namesNo;
501     TVINSERTSTRUCT tvis;
502     FUNCDESC *pFuncDesc;
503     BSTR bstrName, bstrHelpString, *bstrParamNames;
504     WCHAR wszText[MAX_LOAD_STRING];
505     WCHAR wszAfter[MAX_LOAD_STRING];
506     WCHAR szRhs[] = {'r','h','s',0};    /* Right-hand side of a propput */
507     BOOL bFirst;
508
509     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
510     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
511     tvis.hParent = hParent;
512
513     cFuncs = pTypeAttr->cFuncs;
514
515     i = 0;
516     if(pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL) { /* skip 7 members of IDispatch */
517         cFuncs += 7;
518         i += 7;
519     }
520
521     for(; i<cFuncs; i++)
522     {
523         TYPELIB_DATA *tld;
524
525         if(FAILED(ITypeInfo_GetFuncDesc(pTypeInfo, i, &pFuncDesc))) continue;
526
527         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstrName,
528                 &bstrHelpString, NULL, NULL))) continue;
529
530         memset(wszText, 0, sizeof(wszText));
531         memset(wszAfter, 0, sizeof(wszAfter));
532         tld = InitializeTLData();
533         U(tvis).item.cchTextMax = SysStringLen(bstrName);
534         U(tvis).item.pszText = bstrName;
535         U(tvis).item.lParam = (LPARAM) tld;
536         bFirst = TRUE;
537         if(pFuncDesc->memid < MIN_FUNC_ID || pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL)
538         {
539             AddToTLDataStrW(tld, wszOpenBrackets1);
540             bFirst = FALSE;
541             AddToTLDataStrW(tld, wszId);
542             AddToTLDataStrW(tld, wszOpenBrackets2);
543             wsprintfW(wszText, wszFormat, pFuncDesc->memid);
544             AddToTLDataStrW(tld, wszText);
545             AddToTLDataStrW(tld, wszCloseBrackets2);
546             memset(wszText, 0, sizeof(wszText));
547         }
548
549         CreateTypeInfo(wszText, wszAfter, pFuncDesc->elemdescFunc.tdesc, pTypeInfo);
550         switch(pFuncDesc->invkind)
551         {
552             case INVOKE_PROPERTYGET:
553                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
554                 else
555                 {
556                     AddToTLDataStrW(tld, wszComa);
557                     AddToTLDataStrW(tld, wszSpace);
558                 }
559                 bFirst = FALSE;
560                 AddToTLDataStrW(tld, wszPropGet);
561                 break;
562             case INVOKE_PROPERTYPUT:
563                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
564                 else
565                 {
566                     AddToTLDataStrW(tld, wszComa);
567                     AddToTLDataStrW(tld, wszSpace);
568                 }
569                 bFirst = FALSE;
570                 AddToTLDataStrW(tld, wszPropPut);
571                 break;
572             case INVOKE_PROPERTYPUTREF:
573                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
574                 else
575                 {
576                     AddToTLDataStrW(tld, wszComa);
577                     AddToTLDataStrW(tld, wszSpace);
578                 }
579                 bFirst = FALSE;
580                 AddToTLDataStrW(tld, wszPropPutRef);
581                 break;
582             default:;
583         }
584         if(SysStringLen(bstrHelpString))
585         {
586             if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
587             else
588             {
589                 AddToTLDataStrW(tld, wszComa);
590                 AddToTLDataStrW(tld, wszSpace);
591             }
592             bFirst = FALSE;
593             AddToTLDataStrW(tld, wszHelpstring);
594             AddToTLDataStrW(tld, wszOpenBrackets2);
595             AddToTLDataStrW(tld, wszInvertedComa);
596             AddToTLDataStrW(tld, bstrHelpString);
597             AddToTLDataStrW(tld, wszInvertedComa);
598             AddToTLDataStrW(tld, wszCloseBrackets2);
599         }
600         if(!bFirst)
601         {
602             AddToTLDataStrW(tld, wszCloseBrackets1);
603             AddToTLDataStrW(tld, wszNewLine);
604         }
605
606         if(pTypeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
607             AddToTLDataStrW(tld, wszVT_HRESULT);
608             if(strcmpW(wszText, wszVT_VOID)) pFuncDesc->cParams++;
609         }
610         else {
611             AddToTLDataStrW(tld, wszText);
612             AddToTLDataStrW(tld, wszAfter);
613         }
614
615         bstrParamNames = HeapAlloc(GetProcessHeap(), 0,
616                 sizeof(BSTR*)*(pFuncDesc->cParams+1));
617         if(FAILED(ITypeInfo_GetNames(pTypeInfo, pFuncDesc->memid, bstrParamNames,
618                 pFuncDesc->cParams+1, &namesNo)))
619         {
620             HeapFree(GetProcessHeap(), 0, bstrParamNames);
621             continue;
622         }
623         SysFreeString(bstrParamNames[0]);
624
625         AddToTLDataStrW(tld, wszSpace);
626         if(pFuncDesc->memid >= MIN_FUNC_ID)
627         {
628             AddToTLDataStrW(tld, wszStdCall);
629             AddToTLDataStrW(tld, wszSpace);
630         }
631         AddToTLDataStrW(tld, bstrName);
632         AddToTLDataStrW(tld, wszOpenBrackets2);
633
634         for(j=0; j<pFuncDesc->cParams; j++)
635         {
636             if(j != 0) AddToTLDataStrW(tld, wszComa);
637             if(pFuncDesc->cParams != 1)
638             {
639                 AddToTLDataStrW(tld, wszNewLine);
640                 AddSpaces(tld, TAB_SIZE);
641             }
642             bFirst = TRUE;
643 #define ENUM_PARAM_FLAG(x)\
644             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & x) \
645             {\
646                 if(bFirst) AddToTLDataStrW(tld,\
647                         wszOpenBrackets1);\
648                 else\
649                 {\
650                     AddToTLDataStrW(tld, wszComa);\
651                     AddToTLDataStrW(tld, wszSpace);\
652                 }\
653                 bFirst = FALSE;\
654                 AddToTLDataStrW(tld, wsz##x);\
655             }
656             ENUM_PARAM_FLAG(PARAMFLAG_FIN);
657             ENUM_PARAM_FLAG(PARAMFLAG_FOUT);
658             ENUM_PARAM_FLAG(PARAMFLAG_FLCID);
659             ENUM_PARAM_FLAG(PARAMFLAG_FRETVAL);
660             ENUM_PARAM_FLAG(PARAMFLAG_FOPT);
661             ENUM_PARAM_FLAG(PARAMFLAG_FHASCUSTDATA);
662
663             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
664             {
665                 VARIANT var, *param=&U(pFuncDesc->lprgelemdescParam[j]).paramdesc.pparamdescex->varDefaultValue;
666                 VariantInit(&var);
667                 if(bFirst) AddToTLDataStrW(tld,
668                         wszOpenBrackets1);
669                 else
670                 {
671                     AddToTLDataStrW(tld, wszComa);
672                     AddToTLDataStrW(tld, wszSpace);
673                 }
674                 bFirst = FALSE;
675                 AddToTLDataStrW(tld, wszDefaultValue);
676                 AddToTLDataStrW(tld, wszOpenBrackets2);
677                 if (V_VT(param) == VT_BSTR)
678                 {
679                     AddToTLDataStrW(tld, wszInvertedComa);
680                     AddToTLDataStrW(tld, V_BSTR(&var));
681                     AddToTLDataStrW(tld, wszInvertedComa);
682                 } else if (VariantChangeType(&var, param, 0, VT_BSTR) == S_OK)
683                     AddToTLDataStrW(tld, V_BSTR(&var));
684                 AddToTLDataStrW(tld, wszCloseBrackets2);
685             }
686
687             if(!bFirst)
688             {
689                 AddToTLDataStrW(tld, wszCloseBrackets1);
690                 AddToTLDataStrW(tld, wszSpace);
691             }
692
693             memset(wszText, 0, sizeof(wszText));
694             memset(wszAfter, 0, sizeof(wszAfter));
695             CreateTypeInfo(wszText, wszAfter, pFuncDesc->lprgelemdescParam[j].tdesc,
696                     pTypeInfo);
697             AddToTLDataStrW(tld, wszText);
698             AddToTLDataStrW(tld, wszAfter);
699             AddToTLDataStrW(tld, wszSpace);
700             if (j+1 < namesNo) {
701                 AddToTLDataStrW(tld, bstrParamNames[j+1]);
702                 SysFreeString(bstrParamNames[j+1]);
703             } else {
704                 AddToTLDataStrW(tld, szRhs);
705             }
706         }
707         AddToTLDataStrW(tld, wszCloseBrackets2);
708         AddToTLDataStrW(tld, wszSemicolon);
709         AddToTLDataStrW(tld, wszNewLine);
710
711         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
712         HeapFree(GetProcessHeap(), 0, bstrParamNames);
713         SysFreeString(bstrName);
714         SysFreeString(bstrHelpString);
715         ITypeInfo_ReleaseFuncDesc(pTypeInfo, pFuncDesc);
716     }
717
718     return 0;
719 }
720
721 static int EnumImplTypes(ITypeInfo *pTypeInfo, int cImplTypes, HTREEITEM hParent)
722 {
723     int i;
724     TVINSERTSTRUCT tvis;
725     ITypeInfo *pRefTypeInfo;
726     HREFTYPE hRefType;
727     TYPEATTR *pTypeAttr;
728     BSTR bstrName;
729     WCHAR wszInheritedInterfaces[MAX_LOAD_STRING];
730
731     if(!cImplTypes) return 0;
732
733     LoadString(globals.hMainInst, IDS_INHERITINTERFACES, wszInheritedInterfaces,
734             sizeof(WCHAR[MAX_LOAD_STRING]));
735
736     U(tvis).item.mask = TVIF_TEXT;
737     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
738     U(tvis).item.pszText = wszInheritedInterfaces;
739     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
740     tvis.hParent = hParent;
741
742     tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
743
744     for(i=0; i<cImplTypes; i++)
745     {
746         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
747         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
748             continue;
749         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
750                 NULL, NULL, NULL)))
751         {
752             ITypeInfo_Release(pRefTypeInfo);
753             continue;
754         }
755         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr)))
756         {
757             ITypeInfo_Release(pRefTypeInfo);
758             continue;
759         }
760
761         U(tvis).item.cchTextMax = SysStringLen(bstrName);
762         U(tvis).item.pszText = bstrName;
763
764         hParent = TreeView_InsertItem(typelib.hTree, &tvis);
765         EnumVars(pRefTypeInfo, pTypeAttr->cVars, hParent);
766         EnumFuncs(pRefTypeInfo, pTypeAttr, hParent);
767         EnumImplTypes(pRefTypeInfo, pTypeAttr->cImplTypes, hParent);
768
769         SysFreeString(bstrName);
770         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
771         ITypeInfo_Release(pRefTypeInfo);
772     }
773
774     return 0;
775 }
776
777 static void EnumCoclassImplTypes(ITypeInfo *pTypeInfo,
778         int cImplTypes, TYPELIB_DATA *pTLData)
779 {
780     int i;
781     ITypeInfo *pRefTypeInfo;
782     HREFTYPE hRefType;
783     TYPEATTR *pTypeAttr;
784     BSTR bstrName;
785     BOOL bFirst;
786     INT flags;
787     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
788     const WCHAR wszTKIND_DISPATCH[]
789         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
790     const WCHAR wszIMPLTYPEFLAG_FDEFAULT[]
791         = { 'd','e','f','a','u','l','t','\0' };
792     const WCHAR wszIMPLTYPEFLAG_FSOURCE[]
793         = { 's','o','u','r','c','e','\0' };
794     const WCHAR wszIMPLTYPEFLAG_FRESTRICTED[]
795         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
796
797     for(i=0; i<cImplTypes; i++)
798     {
799         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
800         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
801             continue;
802         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
803                         NULL, NULL, NULL)))
804         {
805             ITypeInfo_Release(pRefTypeInfo);
806             continue;
807         }
808         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr)))
809         {
810             ITypeInfo_Release(pRefTypeInfo);
811             continue;
812         }
813
814         AddSpaces(pTLData, TAB_SIZE);
815         ITypeInfo_GetImplTypeFlags(pTypeInfo, i, &flags);
816         bFirst = TRUE;
817 #define ENUM_IMPLTYPEFLAG(x)\
818         if(flags & x) \
819         {\
820             if(bFirst) AddToTLDataStrW(pTLData,\
821                     wszOpenBrackets1);\
822             else\
823             {\
824                 AddToTLDataStrW(pTLData, wszComa);\
825                 AddToTLDataStrW(pTLData, wszSpace);\
826             }\
827             bFirst = FALSE;\
828             AddToTLDataStrW(pTLData, wsz##x);\
829         }
830         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FDEFAULT);
831         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FSOURCE);
832         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FRESTRICTED);
833         if(!bFirst)
834         {
835             AddToTLDataStrW(pTLData, wszCloseBrackets1);
836             AddToTLDataStrW(pTLData, wszSpace);
837         }
838
839         if(pTypeAttr->typekind == TKIND_INTERFACE ||
840                 (pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL))
841             AddToTLDataStrW(pTLData, wszTKIND_INTERFACE);
842         else if(pTypeAttr->typekind == TKIND_DISPATCH)
843             AddToTLDataStrW(pTLData, wszTKIND_DISPATCH);
844         AddToTLDataStrW(pTLData, wszSpace);
845
846         AddToTLDataStrW(pTLData, bstrName);
847         AddToTLDataStrW(pTLData, wszSemicolon);
848         AddToTLDataStrW(pTLData, wszNewLine);
849
850         SysFreeString(bstrName);
851         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
852         ITypeInfo_Release(pRefTypeInfo);
853     }
854 }
855
856 static void AddIdlData(HTREEITEM hCur, TYPELIB_DATA *pTLData)
857 {
858     TVITEM tvi;
859
860     hCur = TreeView_GetChild(typelib.hTree, hCur);
861     memset(&tvi, 0, sizeof(TVITEM));
862     tvi.mask = TVIF_PARAM;
863
864     while(hCur)
865     {
866         tvi.hItem = hCur;
867         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
868         if(!((TYPELIB_DATA*)(tvi.lParam))->bHide) {
869             AddToTLDataStrW(pTLData, wszNewLine);
870             AddToTLDataStrWithTabsW(pTLData, ((TYPELIB_DATA*)(tvi.lParam))->idl);
871         }
872         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
873     }
874 }
875
876 static void AddPredefinitions(HTREEITEM hFirst, TYPELIB_DATA *pTLData)
877 {
878     HTREEITEM hCur;
879     TVITEM tvi;
880     WCHAR wszText[MAX_LOAD_STRING];
881     WCHAR wszPredefinition[] = { '/','/',' ','T','L','i','b',' ',':','\n',
882         '/','/',' ','F','o','r','w','a','r','d',' ','d','e','c','l','a','r','e',' ',
883         'a','l','l',' ','t','y','p','e','s',' ','d','e','f','i','n','e','d',' ',
884         'i','n',' ','t','h','i','s',' ','t','y','p','e','l','i','b','\0' };
885
886     hFirst = TreeView_GetChild(typelib.hTree, hFirst);
887
888     AddToTLDataStrWithTabsW(pTLData, wszPredefinition);
889     AddToTLDataStrW(pTLData, wszNewLine);
890
891     hCur = hFirst;
892     memset(&tvi, 0, sizeof(TVITEM));
893     tvi.mask = TVIF_TEXT|TVIF_PARAM;
894     tvi.cchTextMax = MAX_LOAD_STRING;
895     tvi.pszText = wszText;
896     while(hCur)
897     {
898         tvi.hItem = hCur;
899         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
900         if(((TYPELIB_DATA*)(tvi.lParam))->bPredefine &&
901                 !((TYPELIB_DATA*)(tvi.lParam))->bHide)
902         {
903             AddToStrW(wszText, wszSemicolon);
904             AddToTLDataStrWithTabsW(pTLData, wszText);
905             AddToTLDataStrW(pTLData, wszNewLine);
906         }
907         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
908     }
909 }
910
911 static void CreateInterfaceInfo(ITypeInfo *pTypeInfo, int cImplTypes, WCHAR *wszName,
912         WCHAR *wszHelpString, unsigned long ulHelpContext, TYPEATTR *pTypeAttr,
913         TYPELIB_DATA *pTLData)
914 {
915     ITypeInfo *pRefTypeInfo;
916     HREFTYPE hRefType;
917     BSTR bstrName;
918     WCHAR wszGuid[MAX_LOAD_STRING];
919     WCHAR wszHelpContext[MAX_LOAD_STRING];
920
921     const WCHAR wszInterface[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
922     const WCHAR wszDispinterface[]
923         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
924     const WCHAR wszHelpcontext[] = { 'h','e','l','p','c','o','n','t','e','x','t','\0' };
925     const WCHAR wszTYPEFLAG_FAPPOBJECT[] = { 'a','p','p','o','b','j','e','c','t','\0' };
926     const WCHAR wszTYPEFLAG_FCANCREATE[] = { 'c','a','n','c','r','e','a','t','e','\0' };
927     const WCHAR wszTYPEFLAG_FLICENSED[] = { 'l','i','c','e','n','s','e','d','\0' };
928     const WCHAR wszTYPEFLAG_FPREDECLID[] = { 'p','r','e','d','e','c','l','i','d','\0' };
929     const WCHAR wszTYPEFLAG_FHIDDEN[] = { 'h','i','d','d','e','n','\0' };
930     const WCHAR wszTYPEFLAG_FCONTROL[] = { 'c','o','n','t','r','o','l','\0' };
931     const WCHAR wszTYPEFLAG_FDUAL[] = { 'd','u','a','l','\0' };
932     const WCHAR wszTYPEFLAG_FNONEXTENSIBLE[]
933         = { 'n','o','n','e','x','t','e','n','s','i','b','l','e','\0' };
934     const WCHAR wszTYPEFLAG_FOLEAUTOMATION[]
935         = { 'o','l','e','a','u','t','o','m','a','t','i','o','n','\0' };
936     const WCHAR wszTYPEFLAG_FRESTRICTED[]
937         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
938     const WCHAR wszTYPEFLAG_FAGGREGATABLE[]
939         = { 'a','g','g','r','e','g','a','t','a','b','l','e','\0' };
940     const WCHAR wszTYPEFLAG_FREPLACEABLE[]
941         = { 'r','e','p','l','a','c','a','b','l','e','\0' };
942     const WCHAR wszTYPEFLAG_FREVERSEBIND[]
943         = { 'r','e','v','e','r','s','e','b','i','n','d','\0' };
944     const WCHAR wszTYPEFLAG_FPROXY[] = { 'p','r','o','x','y','\0' };
945
946     AddToTLDataStrW(pTLData, wszOpenBrackets1);
947     AddToTLDataStrW(pTLData, wszNewLine);
948     if(pTypeAttr->typekind != TKIND_DISPATCH)
949     {
950         AddSpaces(pTLData, TAB_SIZE);
951         AddToTLDataStrW(pTLData, wszOdl);
952         AddToTLDataStrW(pTLData, wszComa);
953         AddToTLDataStrW(pTLData, wszNewLine);
954     }
955     AddSpaces(pTLData, TAB_SIZE);
956     AddToTLDataStrW(pTLData, wszUUID);
957     AddToTLDataStrW(pTLData, wszOpenBrackets2);
958     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
959     wszGuid[lstrlenW(wszGuid)-1] = '\0';
960     AddToTLDataStrW(pTLData, &wszGuid[1]);
961     AddToTLDataStrW(pTLData, wszCloseBrackets2);
962     if(wszHelpString)
963     {
964         AddToTLDataStrW(pTLData, wszComa);
965         AddToTLDataStrW(pTLData, wszNewLine);
966         AddSpaces(pTLData, TAB_SIZE);
967         AddToTLDataStrW(pTLData, wszHelpstring);
968         AddToTLDataStrW(pTLData, wszOpenBrackets2);
969         AddToTLDataStrW(pTLData, wszInvertedComa);
970         AddToTLDataStrW(pTLData, wszHelpString);
971         AddToTLDataStrW(pTLData, wszInvertedComa);
972         AddToTLDataStrW(pTLData, wszCloseBrackets2);
973     }
974     if(ulHelpContext)
975     {
976         AddToTLDataStrW(pTLData, wszComa);
977         AddToTLDataStrW(pTLData, wszNewLine);
978         AddSpaces(pTLData, TAB_SIZE);
979         AddToTLDataStrW(pTLData, wszHelpcontext);
980         AddToTLDataStrW(pTLData, wszOpenBrackets2);
981         wsprintfW(wszHelpContext, wszFormat, ulHelpContext);
982         AddToTLDataStrW(pTLData, wszHelpContext);
983         AddToTLDataStrW(pTLData, wszCloseBrackets2);
984     }
985     if(pTypeAttr->wTypeFlags)
986     {
987 #define ENUM_FLAGS(x) if(pTypeAttr->wTypeFlags & x &&\
988         (pTypeAttr->typekind != TKIND_DISPATCH || x != TYPEFLAG_FDISPATCHABLE))\
989         {\
990             AddToTLDataStrW(pTLData, wszComa);\
991             AddToTLDataStrW(pTLData, wszNewLine);\
992             AddSpaces(pTLData, TAB_SIZE);\
993             AddToTLDataStrW(pTLData, wsz##x);\
994         }
995         ENUM_FLAGS(TYPEFLAG_FAPPOBJECT);
996         ENUM_FLAGS(TYPEFLAG_FCANCREATE);
997         ENUM_FLAGS(TYPEFLAG_FLICENSED);
998         ENUM_FLAGS(TYPEFLAG_FPREDECLID);
999         ENUM_FLAGS(TYPEFLAG_FHIDDEN);
1000         ENUM_FLAGS(TYPEFLAG_FCONTROL);
1001         ENUM_FLAGS(TYPEFLAG_FDUAL);
1002         ENUM_FLAGS(TYPEFLAG_FNONEXTENSIBLE);
1003         ENUM_FLAGS(TYPEFLAG_FOLEAUTOMATION);
1004         ENUM_FLAGS(TYPEFLAG_FRESTRICTED);
1005         ENUM_FLAGS(TYPEFLAG_FAGGREGATABLE);
1006         ENUM_FLAGS(TYPEFLAG_FREPLACEABLE);
1007         ENUM_FLAGS(TYPEFLAG_FREVERSEBIND);
1008         ENUM_FLAGS(TYPEFLAG_FPROXY);
1009     }
1010     AddToTLDataStrW(pTLData, wszNewLine);
1011     AddToTLDataStrW(pTLData, wszCloseBrackets1);
1012     AddToTLDataStrW(pTLData, wszNewLine);
1013     if(pTypeAttr->typekind != TKIND_DISPATCH) AddToTLDataStrW(pTLData, wszInterface);
1014     else AddToTLDataStrW(pTLData, wszDispinterface);
1015     AddToTLDataStrW(pTLData, wszName);
1016     AddToTLDataStrW(pTLData, wszSpace);
1017     if(cImplTypes && pTypeAttr->typekind != TKIND_DISPATCH)
1018     {
1019         AddToTLDataStrW(pTLData, wszColon);
1020         AddToTLDataStrW(pTLData, wszSpace);
1021
1022         ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &hRefType);
1023         if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
1024         {
1025             ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1026                 NULL, NULL, NULL);
1027             AddToTLDataStrW(pTLData, bstrName);
1028             AddToTLDataStrW(pTLData, wszSpace);
1029
1030             SysFreeString(bstrName);
1031             ITypeInfo_Release(pRefTypeInfo);
1032         }
1033         else
1034             AddToTLDataStrW(pTLData, wszFailed);
1035     }
1036     AddToTLDataStrW(pTLData, wszOpenBrackets3);
1037     AddToTLDataStrW(pTLData, wszNewLine);
1038
1039     AddToStrW(pTLData->wszInsertAfter, wszCloseBrackets3);
1040     AddToStrW(pTLData->wszInsertAfter, wszSemicolon);
1041     AddToStrW(pTLData->wszInsertAfter, wszNewLine);
1042 }
1043
1044 static void CreateTypedefHeader(ITypeInfo *pTypeInfo,
1045         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
1046 {
1047     BOOL bFirst = TRUE;
1048     WCHAR wszGuid[MAX_LOAD_STRING];
1049     const WCHAR wszTypedef[] = { 't','y','p','e','d','e','f',' ','\0' };
1050     const WCHAR wszPublic[] = { 'p','u','b','l','i','c','\0' };
1051
1052     AddToTLDataStrW(pTLData, wszTypedef);
1053     if(memcmp(&pTypeAttr->guid, &GUID_NULL, sizeof(GUID)))
1054     {
1055         AddToTLDataStrW(pTLData, wszOpenBrackets1);
1056         bFirst = FALSE;
1057         AddToTLDataStrW(pTLData, wszUUID);
1058         AddToTLDataStrW(pTLData, wszOpenBrackets2);
1059         StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
1060         wszGuid[lstrlenW(wszGuid)-1] = '\0';
1061         AddToTLDataStrW(pTLData, &wszGuid[1]);
1062         AddToTLDataStrW(pTLData, wszCloseBrackets2);
1063     }
1064     if(pTypeAttr->typekind == TKIND_ALIAS)
1065     {
1066         if(bFirst) AddToTLDataStrW(pTLData, wszOpenBrackets1);
1067         else
1068         {
1069             AddToTLDataStrW(pTLData, wszComa);
1070             AddToTLDataStrW(pTLData, wszSpace);
1071         }
1072         bFirst = FALSE;
1073         AddToTLDataStrW(pTLData, wszPublic);
1074     }
1075     if(!bFirst)
1076     {
1077         AddToTLDataStrW(pTLData, wszCloseBrackets1);
1078         AddToTLDataStrW(pTLData, wszNewLine);
1079     }
1080 }
1081
1082 static void CreateCoclassHeader(ITypeInfo *pTypeInfo,
1083         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
1084 {
1085     WCHAR wszGuid[MAX_LOAD_STRING];
1086     BSTR bstrHelpString;
1087     const WCHAR wszNoncreatable[]
1088         = { 'n','o','n','c','r','e','a','t','a','b','l','e','\0' };
1089
1090     AddToTLDataStrW(pTLData, wszOpenBrackets1);
1091     AddToTLDataStrW(pTLData, wszNewLine);
1092
1093     AddSpaces(pTLData, TAB_SIZE);
1094     AddToTLDataStrW(pTLData, wszUUID);
1095     AddToTLDataStrW(pTLData, wszOpenBrackets2);
1096     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
1097     wszGuid[lstrlenW(wszGuid)-1] = '\0';
1098     AddToTLDataStrW(pTLData, &wszGuid[1]);
1099     AddToTLDataStrW(pTLData, wszCloseBrackets2);
1100
1101     if(SUCCEEDED(ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, NULL,
1102             &bstrHelpString, NULL, NULL)))
1103     {
1104         if(SysStringLen(bstrHelpString))
1105         {
1106             AddToTLDataStrW(pTLData, wszComa);
1107             AddToTLDataStrW(pTLData, wszNewLine);
1108             AddSpaces(pTLData, TAB_SIZE);
1109             AddToTLDataStrW(pTLData, wszHelpstring);
1110             AddToTLDataStrW(pTLData, wszOpenBrackets2);
1111             AddToTLDataStrW(pTLData, wszInvertedComa);
1112             AddToTLDataStrW(pTLData, bstrHelpString);
1113             AddToTLDataStrW(pTLData, wszInvertedComa);
1114             AddToTLDataStrW(pTLData, wszCloseBrackets2);
1115         }
1116         SysFreeString(bstrHelpString);
1117     }
1118
1119     if(!(pTypeAttr->wTypeFlags & TYPEFLAG_FCANCREATE))
1120     {
1121         AddToTLDataStrW(pTLData, wszComa);
1122         AddToTLDataStrW(pTLData, wszNewLine);
1123         AddSpaces(pTLData, TAB_SIZE);
1124         AddToTLDataStrW(pTLData, wszNoncreatable);
1125     }
1126
1127     AddToTLDataStrW(pTLData, wszNewLine);
1128     AddToTLDataStrW(pTLData, wszCloseBrackets1);
1129     AddToTLDataStrW(pTLData, wszNewLine);
1130 }
1131
1132 static int PopulateTree(void)
1133 {
1134     TVINSERTSTRUCT tvis;
1135     TVITEM tvi;
1136     ITypeLib *pTypeLib;
1137     TLIBATTR *pTLibAttr;
1138     ITypeInfo *pTypeInfo, *pRefTypeInfo;
1139     HREFTYPE hRefType;
1140     TYPEATTR *pTypeAttr;
1141     INT count, i;
1142     ULONG ulHelpContext;
1143     BSTR bstrName;
1144     BSTR bstrData;
1145     WCHAR wszText[MAX_LOAD_STRING];
1146     WCHAR wszAfter[MAX_LOAD_STRING];
1147     HRESULT hRes;
1148     HTREEITEM hParent;
1149     HTREEITEM hMain;
1150     BOOL bInsert;
1151     TYPELIB_DATA *tldDispatch;
1152     TYPELIB_DATA *tld;
1153
1154     const WCHAR wszGeneratedInfo[] = { '/','/',' ','G','e','n','e','r','a','t','e','d',
1155         ' ','.','I','D','L',' ','f','i','l','e',' ','(','b','y',' ','t','h','e',' ',
1156         'O','L','E','/','C','O','M',' ','O','b','j','e','c','t',' ',
1157         'V','i','e','w','e','r',')','\n','/','/','\n','/','/',' ',
1158         't','y','p','e','l','i','b',' ','f','i','l','e','n','a','m','e',':',' ','\0'};
1159
1160     const WCHAR wszFormat[] = { '%','s',' ','(','%','s',')','\0' };
1161     const WCHAR wszFormat2[] = { 'v','e','r','s','i','o','n',
1162         '(','%','l','d','.','%','l','d',')','\0' };
1163
1164     const WCHAR wszTKIND_ENUM[] = { 't','y','p','e','d','e','f',' ','e','n','u','m',' ','\0' };
1165     const WCHAR wszTKIND_RECORD[]
1166         = { 't','y','p','e','d','e','f',' ','s','t','r','u','c','t',' ','\0' };
1167     const WCHAR wszTKIND_MODULE[] = { 'm','o','d','u','l','e',' ','\0' };
1168     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
1169     const WCHAR wszTKIND_DISPATCH[]
1170         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
1171     const WCHAR wszTKIND_COCLASS[] = { 'c','o','c','l','a','s','s',' ','\0' };
1172     const WCHAR wszTKIND_ALIAS[] = { 't','y','p','e','d','e','f',' ','\0' };
1173     const WCHAR wszTKIND_UNION[]
1174         = { 't','y','p','e','d','e','f',' ','u','n','i','o','n',' ','\0' };
1175
1176     const WCHAR wszLibrary[] = { 'l','i','b','r','a','r','y',' ','\0' };
1177     const WCHAR wszTag[] = { 't','a','g','\0' };
1178
1179     WCHAR wszProperties[] = { 'p','r','o','p','e','r','t','i','e','s','\0' };
1180     WCHAR wszMethods[] = { 'm','e','t','h','o','d','s','\0' };
1181
1182     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
1183     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
1184     U(tvis).item.pszText = wszText;
1185     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
1186     tvis.hParent = TVI_ROOT;
1187
1188     if(FAILED((hRes = LoadTypeLib(typelib.wszFileName, &pTypeLib))))
1189     {
1190         WCHAR wszMessage[MAX_LOAD_STRING];
1191         WCHAR wszError[MAX_LOAD_STRING];
1192
1193         LoadString(globals.hMainInst, IDS_ERROR_LOADTYPELIB,
1194                 wszError, sizeof(WCHAR[MAX_LOAD_STRING]));
1195         wsprintfW(wszMessage, wszError, typelib.wszFileName, hRes);
1196         MessageBox(globals.hMainWnd, wszMessage, NULL, MB_OK|MB_ICONEXCLAMATION);
1197         return 1;
1198     }
1199     count = ITypeLib_GetTypeInfoCount(pTypeLib);
1200
1201     ITypeLib_GetDocumentation(pTypeLib, -1, &bstrName, &bstrData, NULL, NULL);
1202     ITypeLib_GetLibAttr(pTypeLib, &pTLibAttr);
1203
1204     tld = InitializeTLData();
1205     U(tvis).item.lParam = (LPARAM) tld;
1206     AddToTLDataStrW(tld, wszGeneratedInfo);
1207     AddToTLDataStrW(tld, typelib.wszFileName);
1208     AddToTLDataStrW(tld, wszNewLine);
1209     AddToTLDataStrW(tld, wszNewLine);
1210     AddToTLDataStrW(tld, wszOpenBrackets1);
1211     AddToTLDataStrW(tld, wszNewLine);
1212     AddSpaces(tld, TAB_SIZE);
1213     AddToTLDataStrW(tld, wszUUID);
1214     AddToTLDataStrW(tld, wszOpenBrackets2);
1215     StringFromGUID2(&(pTLibAttr->guid), wszText, MAX_LOAD_STRING);
1216     wszText[lstrlenW(wszText)-1] = '\0';
1217     AddToTLDataStrW(tld, &wszText[1]);
1218     AddToTLDataStrW(tld, wszCloseBrackets2);
1219     AddToTLDataStrW(tld, wszComa);
1220     AddToTLDataStrW(tld, wszNewLine);
1221     AddSpaces(tld, TAB_SIZE);
1222     wsprintfW(wszText, wszFormat2, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
1223     AddToTLDataStrW(tld, wszText);
1224     AddToTLDataStrW(tld, wszComa);
1225     AddToTLDataStrW(tld, wszNewLine);
1226     AddSpaces(tld, TAB_SIZE);
1227     AddToTLDataStrW(tld, wszHelpstring);
1228     AddToTLDataStrW(tld, wszOpenBrackets2);
1229     AddToTLDataStrW(tld, wszInvertedComa);
1230     AddToTLDataStrW(tld, bstrData);
1231     AddToTLDataStrW(tld, wszInvertedComa);
1232     AddToTLDataStrW(tld, wszCloseBrackets2);
1233     AddToTLDataStrW(tld, wszNewLine);
1234     AddToTLDataStrW(tld, wszCloseBrackets1);
1235     AddToTLDataStrW(tld, wszNewLine);
1236     AddToTLDataStrW(tld, wszLibrary);
1237     AddToTLDataStrW(tld, bstrName);
1238     AddToTLDataStrW(tld, wszNewLine);
1239     AddToTLDataStrW(tld, wszOpenBrackets3);
1240     AddToTLDataStrW(tld, wszNewLine);
1241
1242     AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1243     AddToStrW(tld->wszInsertAfter, wszSemicolon);
1244
1245     wsprintfW(wszText, wszFormat, bstrName, bstrData);
1246     SysFreeString(bstrName);
1247     SysFreeString(bstrData);
1248     tvis.hParent = (HTREEITEM)SendMessage(typelib.hTree,
1249             TVM_INSERTITEM, 0, (LPARAM)&tvis);
1250
1251     for(i=0; i<count; i++)
1252     {
1253         bInsert = TRUE;
1254         ITypeLib_GetTypeInfo(pTypeLib, i, &pTypeInfo);
1255
1256         ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &bstrName, &bstrData,
1257                 &ulHelpContext, NULL);
1258         ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
1259
1260         memset(wszText, 0, sizeof(wszText));
1261         memset(wszAfter, 0, sizeof(wszAfter));
1262         tld = InitializeTLData();
1263         U(tvis).item.lParam = (LPARAM)tld;
1264         switch(pTypeAttr->typekind)
1265         {
1266             case TKIND_ENUM:
1267                 AddToStrW(wszText, wszTKIND_ENUM);
1268                 AddToStrW(wszText, bstrName);
1269
1270                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1271                 AddToTLDataStrW(tld, &wszTKIND_ENUM[lstrlenW(wszTKIND_ALIAS)]);
1272                 AddToTLDataStrW(tld, wszOpenBrackets3);
1273                 AddToTLDataStrW(tld,wszNewLine);
1274                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1275                 AddToStrW(tld->wszInsertAfter, wszSpace);
1276                 AddToStrW(tld->wszInsertAfter, bstrName);
1277                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1278                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1279
1280                 bInsert = FALSE;
1281                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1282                 EnumEnums(pTypeInfo, pTypeAttr->cVars, hParent);
1283                 AddChildrenData(hParent, tld);
1284                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1285                 break;
1286             case TKIND_RECORD:
1287                 AddToTLDataStrW(tld, wszTKIND_RECORD);
1288                 AddToTLDataStrW(tld, wszTag);
1289                 AddToTLDataStrW(tld, bstrName);
1290                 AddToTLDataStrW(tld, wszSpace);
1291                 AddToTLDataStrW(tld, wszOpenBrackets3);
1292                 AddToTLDataStrW(tld, wszNewLine);
1293
1294                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1295                 AddToStrW(tld->wszInsertAfter, wszSpace);
1296                 AddToStrW(tld->wszInsertAfter, bstrName);
1297                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1298                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1299
1300                 AddToStrW(wszText, wszTKIND_RECORD);
1301                 AddToStrW(wszText, bstrName);
1302                 break;
1303             case TKIND_MODULE:
1304                 AddToStrW(wszText, wszTKIND_MODULE);
1305                 AddToStrW(wszText, bstrName);
1306                 break;
1307             case TKIND_INTERFACE:
1308                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1309                         bstrData, ulHelpContext, pTypeAttr, tld);
1310                 tld->bPredefine = TRUE;
1311
1312                 AddToStrW(wszText, wszTKIND_INTERFACE);
1313                 AddToStrW(wszText, bstrName);
1314                 break;
1315             case TKIND_COCLASS:
1316                 AddToStrW(wszText, wszTKIND_COCLASS);
1317                 AddToStrW(wszText, bstrName);
1318
1319                 CreateCoclassHeader(pTypeInfo, pTypeAttr, tld);
1320                 AddToTLDataStrW(tld, wszTKIND_COCLASS);
1321                 AddToTLDataStrW(tld, bstrName);
1322                 AddToTLDataStrW(tld, wszSpace);
1323                 AddToTLDataStrW(tld, wszOpenBrackets3);
1324                 AddToTLDataStrW(tld, wszNewLine);
1325
1326                 EnumCoclassImplTypes(pTypeInfo, pTypeAttr->cImplTypes, tld);
1327
1328                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1329                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1330                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1331
1332                 bInsert = FALSE;
1333                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1334                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1335                 break;
1336             case TKIND_UNION:
1337                 AddToStrW(wszText, wszTKIND_UNION);
1338                 AddToStrW(wszText, bstrName);
1339                 break;
1340             case TKIND_DISPATCH:
1341                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1342                         bstrData, ulHelpContext, pTypeAttr, tld);
1343                 tld->bPredefine = TRUE;
1344                 if(pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL)
1345                     tld->bHide = TRUE;
1346                 AddToStrW(wszText, wszTKIND_DISPATCH);
1347                 AddToStrW(wszText, bstrName);
1348
1349                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1350                 hMain = tvis.hParent;
1351                 tldDispatch = tld;
1352
1353                 lstrcpyW(wszText, wszProperties);
1354                 tvis.hParent = hParent;
1355                 tld = InitializeTLData();
1356                 U(tvis).item.lParam = (LPARAM) tld;
1357                 AddToTLDataStrW(tld, wszProperties);
1358                 AddToTLDataStrW(tld, wszColon);
1359                 AddToTLDataStrW(tld, wszNewLine);
1360                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1361                 EnumVars(pTypeInfo, pTypeAttr->cVars, tvis.hParent);
1362                 AddChildrenData(tvis.hParent, tld);
1363
1364                 lstrcpyW(wszText, wszMethods);
1365                 tvis.hParent = hParent;
1366                 tld = InitializeTLData();
1367                 U(tvis).item.lParam = (LPARAM) tld;
1368                 AddToTLDataStrW(tld, wszMethods);
1369                 AddToTLDataStrW(tld, wszColon);
1370                 AddToTLDataStrW(tld, wszNewLine);
1371                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1372                 EnumFuncs(pTypeInfo, pTypeAttr, tvis.hParent);
1373                 AddChildrenData(tvis.hParent, tld);
1374
1375                 EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1376                 AddChildrenData(hParent, tldDispatch);
1377                 AddToTLDataStrW(tldDispatch, tldDispatch->wszInsertAfter);
1378
1379                 bInsert = FALSE;
1380                 tvis.hParent = hMain;
1381
1382                 if(SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, -1, &hRefType)))
1383                 {
1384                     bInsert = TRUE;
1385
1386                     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1387                     SysFreeString(bstrName);
1388                     SysFreeString(bstrData);
1389
1390                     memset(wszText, 0, sizeof(wszText));
1391                     tld = InitializeTLData();
1392                     U(tvis).item.lParam = (LPARAM) tld;
1393
1394                     ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
1395                     ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1396                                 &bstrData, &ulHelpContext, NULL);
1397                     ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr);
1398
1399                     CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1400                             bstrData, ulHelpContext, pTypeAttr, tld);
1401                     tld->bPredefine = TRUE;
1402
1403                     AddToStrW(wszText, wszTKIND_INTERFACE);
1404                     AddToStrW(wszText, bstrName);
1405                     ITypeInfo_Release(pRefTypeInfo);
1406                 }
1407                 break;
1408             case TKIND_ALIAS:
1409                 AddToStrW(wszText, wszTKIND_ALIAS);
1410                 CreateTypeInfo(wszText, wszAfter, pTypeAttr->tdescAlias, pTypeInfo);
1411                 AddToStrW(wszText, wszSpace);
1412                 AddToStrW(wszText, bstrName);
1413                 AddToStrW(wszText, wszAfter);
1414
1415                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1416                 AddToTLDataStrW(tld, &wszText[lstrlenW(wszTKIND_ALIAS)]);
1417                 AddToTLDataStrW(tld, wszSemicolon);
1418                 AddToTLDataStrW(tld, wszNewLine);
1419                 break;
1420             default:
1421                 lstrcpyW(wszText, bstrName);
1422                 WINE_FIXME("pTypeAttr->typekind == %d not supported\n",
1423                         pTypeAttr->typekind);
1424         }
1425
1426         if(bInsert)
1427         {
1428             hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1429
1430             EnumVars(pTypeInfo, pTypeAttr->cVars, hParent);
1431             EnumFuncs(pTypeInfo, pTypeAttr, hParent);
1432             EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1433
1434             if(memcmp(bstrName, wszVT_UNKNOWN, sizeof(wszVT_UNKNOWN)))
1435                 AddChildrenData(hParent, tld);
1436             AddToTLDataStrW(tld, tld->wszInsertAfter);
1437         }
1438
1439         ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1440         ITypeInfo_Release(pTypeInfo);
1441         SysFreeString(bstrName);
1442         SysFreeString(bstrData);
1443     }
1444     SendMessage(typelib.hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
1445
1446     memset(&tvi, 0, sizeof(TVITEM));
1447     tvi.mask = TVIF_PARAM;
1448     tvi.hItem = tvis.hParent;
1449
1450     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1451     AddPredefinitions(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1452     AddIdlData(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1453     AddToTLDataStrW((TYPELIB_DATA*)(tvi.lParam),
1454             ((TYPELIB_DATA*)(tvi.lParam))->wszInsertAfter);
1455
1456     ITypeLib_Release(pTypeLib);
1457     return 0;
1458 }
1459
1460 void UpdateData(HTREEITEM item)
1461 {
1462     TVITEM tvi;
1463
1464     memset(&tvi, 0, sizeof(TVITEM));
1465     tvi.mask = TVIF_PARAM;
1466     tvi.hItem = item;
1467
1468     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1469     if(!tvi.lParam)
1470     {
1471         SetWindowText(typelib.hEdit, wszSpace);
1472         return;
1473     }
1474
1475     SetWindowText(typelib.hEdit, ((TYPELIB_DATA*)tvi.lParam)->idl);
1476 }
1477
1478 static void TypeLibResizeChild(void)
1479 {
1480     RECT client, stat;
1481
1482     MoveWindow(typelib.hStatusBar, 0, 0, 0, 0, TRUE);
1483
1484     if(IsWindowVisible(typelib.hStatusBar))
1485         GetClientRect(typelib.hStatusBar, &stat);
1486     else stat.bottom = 0;
1487
1488     GetClientRect(globals.hTypeLibWnd, &client);
1489     MoveWindow(typelib.hPaneWnd, 0, 0,
1490             client.right, client.bottom-stat.bottom, TRUE);
1491 }
1492
1493 static void TypeLibMenuCommand(WPARAM wParam, HWND hWnd)
1494 {
1495     BOOL vis;
1496
1497     switch(wParam)
1498     {
1499         case IDM_SAVEAS:
1500             GetSaveIdlAsPath();
1501             break;
1502         case IDM_STATUSBAR:
1503             vis = IsWindowVisible(typelib.hStatusBar);
1504             ShowWindow(typelib.hStatusBar, vis ? SW_HIDE : SW_SHOW);
1505             CheckMenuItem(GetMenu(hWnd), LOWORD(wParam),
1506                     vis ? MF_UNCHECKED : MF_CHECKED);
1507             TypeLibResizeChild();
1508             break;
1509         case IDM_CLOSE:
1510             DestroyWindow(hWnd);
1511             break;
1512     }
1513 }
1514
1515 static void UpdateTypeLibStatusBar(int itemID)
1516 {
1517     WCHAR info[MAX_LOAD_STRING];
1518
1519     if(!LoadString(globals.hMainInst, itemID, info, sizeof(WCHAR[MAX_LOAD_STRING])))
1520         LoadString(globals.hMainInst, IDS_READY, info, sizeof(WCHAR[MAX_LOAD_STRING]));
1521
1522     SendMessage(typelib.hStatusBar, SB_SETTEXT, 0, (LPARAM)info);
1523 }
1524
1525 static void EmptyTLTree(void)
1526 {
1527     HTREEITEM cur, del;
1528     TVITEM tvi;
1529
1530     tvi.mask = TVIF_PARAM;
1531     cur = TreeView_GetChild(typelib.hTree, TVI_ROOT);
1532
1533     while(TRUE)
1534     {
1535         del = cur;
1536         cur = TreeView_GetChild(typelib.hTree, del);
1537
1538         if(!cur) cur = TreeView_GetNextSibling(typelib.hTree, del);
1539         if(!cur) cur = TreeView_GetParent(typelib.hTree, del);
1540
1541         tvi.hItem = del;
1542         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1543         if(tvi.lParam)
1544         {
1545             HeapFree(GetProcessHeap(), 0, ((TYPELIB_DATA *)tvi.lParam)->idl);
1546             HeapFree(GetProcessHeap(), 0, (TYPELIB_DATA *)tvi.lParam);
1547         }
1548
1549         SendMessage(typelib.hTree, TVM_DELETEITEM, 0, (LPARAM)del);
1550
1551         if(!cur) break;
1552     }
1553 }
1554
1555 LRESULT CALLBACK TypeLibProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1556 {
1557     switch(uMsg)
1558     {
1559         case WM_CREATE:
1560         {
1561             if(!CreatePanedWindow(hWnd, &typelib.hPaneWnd, globals.hMainInst))
1562                 DestroyWindow(hWnd);
1563             typelib.hTree = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1564                     WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
1565                     0, 0, 0, 0, typelib.hPaneWnd, (HMENU)TYPELIB_TREE,
1566                     globals.hMainInst, NULL);
1567             typelib.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
1568                     WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|WS_HSCROLL|WS_VSCROLL,
1569                     0, 0, 0, 0, typelib.hPaneWnd, NULL, globals.hMainInst, NULL);
1570
1571             SetLeft(typelib.hPaneWnd, typelib.hTree);
1572             SetRight(typelib.hPaneWnd, typelib.hEdit);
1573
1574             if(PopulateTree()) DestroyWindow(hWnd);
1575             else SetFocus(typelib.hTree);
1576             break;
1577         }
1578         case WM_COMMAND:
1579             TypeLibMenuCommand(LOWORD(wParam), hWnd);
1580         case WM_MENUSELECT:
1581             UpdateTypeLibStatusBar(LOWORD(wParam));
1582             break;
1583         case WM_SETFOCUS:
1584             SetFocus(typelib.hTree);
1585             break;
1586         case WM_SIZE:
1587             if(wParam == SIZE_MINIMIZED) break;
1588             TypeLibResizeChild();
1589             break;
1590         case WM_DESTROY:
1591             EmptyTLTree();
1592             break;
1593         default:
1594             return DefWindowProc(hWnd, uMsg, wParam, lParam);
1595     }
1596     return 0;
1597 }
1598
1599 BOOL TypeLibRegisterClass(void)
1600 {
1601     WNDCLASS wcc;
1602
1603     memset(&wcc, 0, sizeof(WNDCLASS));
1604     wcc.lpfnWndProc = TypeLibProc;
1605     wcc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1606     wcc.lpszMenuName = MAKEINTRESOURCE(IDM_TYPELIB);
1607     wcc.lpszClassName = wszTypeLib;
1608
1609     if(!RegisterClass(&wcc))
1610         return FALSE;
1611
1612     return TRUE;
1613 }
1614
1615 BOOL CreateTypeLibWindow(HINSTANCE hInst, WCHAR *wszFileName)
1616 {
1617     WCHAR wszTitle[MAX_LOAD_STRING];
1618     LoadString(hInst, IDS_TYPELIBTITLE, wszTitle, sizeof(WCHAR[MAX_LOAD_STRING]));
1619
1620     if(wszFileName) lstrcpyW(typelib.wszFileName, wszFileName);
1621     else
1622     {
1623         TVITEM tvi;
1624
1625         memset(&tvi, 0, sizeof(TVITEM));
1626         tvi.hItem = TreeView_GetSelection(globals.hTree);
1627
1628         SendMessage(globals.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1629         lstrcpyW(typelib.wszFileName, ((ITEM_INFO*)tvi.lParam)->path);
1630     }
1631
1632     globals.hTypeLibWnd = CreateWindow(wszTypeLib, wszTitle,
1633             WS_OVERLAPPEDWINDOW|WS_VISIBLE,
1634             CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL);
1635     if(!globals.hTypeLibWnd) return FALSE;
1636
1637     typelib.hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD,
1638             (LPWSTR)wszTitle, globals.hTypeLibWnd, 0);
1639
1640     TypeLibResizeChild();
1641     return TRUE;
1642 }