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