d3drm: Implement D3DRMVectorRandom.
[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 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 wszPropPut[] = { 'p','r','o','p','p','u','t','\0' };
85 static const WCHAR wszPropGet[] = { 'p','r','o','p','g','e','t','\0' };
86 static const WCHAR wszPropPutRef[] = { 'p','r','o','p','p','u','t','r','e','f','\0' };
87 static const WCHAR wszPARAMFLAG_FIN[] = { 'i','n','\0' };
88 static const WCHAR wszPARAMFLAG_FOUT[] = { 'o','u','t','\0' };
89 static const WCHAR wszPARAMFLAG_FLCID[] = { 'c','i','d','\0' };
90 static const WCHAR wszPARAMFLAG_FRETVAL[] = { 'r','e','t','v','a','l','\0' };
91 static const WCHAR wszPARAMFLAG_FOPT[] = { 'o','p','t','i','o','n','a','l','\0' };
92 static const WCHAR wszPARAMFLAG_FHASCUSTDATA[]
93     = { 'h','a','s','c','u','s','t','d','a','t','a','\0' };
94 static const WCHAR wszDefaultValue[]
95     = { 'd','e','f','a','u','l','t','v','a','l','u','e','\0' };
96
97 static const WCHAR wszReadOnly[] = { 'r','e','a','d','o','n','l','y','\0' };
98 static const WCHAR wszConst[] = { 'c','o','n','s','t','\0' };
99
100 static void ShowLastError(void)
101 {
102     DWORD error = GetLastError();
103     LPWSTR lpMsgBuf;
104     WCHAR wszTitle[MAX_LOAD_STRING];
105
106     LoadString(globals.hMainInst, IDS_TYPELIBTITLE, wszTitle,
107             sizeof(WCHAR[MAX_LOAD_STRING]));
108     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
109             NULL, error, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
110     MessageBox(NULL, lpMsgBuf, wszTitle, MB_OK | MB_ICONERROR);
111     LocalFree(lpMsgBuf);
112     return;
113 }
114
115 static void SaveIdl(WCHAR *wszFileName)
116 {
117     HTREEITEM hIDL;
118     TVITEM tvi;
119     HANDLE hFile;
120     DWORD len, dwNumWrite;
121     char *wszIdl;
122     TYPELIB_DATA *data;
123
124     hIDL = TreeView_GetChild(typelib.hTree, TVI_ROOT);
125
126     memset(&tvi, 0, sizeof(TVITEM));
127     tvi.hItem = hIDL;
128
129     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
130     data = (TYPELIB_DATA *)tvi.lParam;
131
132     hFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
133                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
134     if(hFile == INVALID_HANDLE_VALUE)
135     {
136         ShowLastError();
137         return;
138     }
139
140     len = WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, NULL, 0, NULL, NULL );
141     wszIdl = HeapAlloc(GetProcessHeap(), 0, len);
142     WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, wszIdl, len, NULL, NULL );
143
144     if(!WriteFile(hFile, wszIdl, len, &dwNumWrite, NULL))
145         ShowLastError();
146
147     HeapFree(GetProcessHeap(), 0, wszIdl);
148     CloseHandle(hFile);
149 }
150
151 static void GetSaveIdlAsPath(void)
152 {
153     OPENFILENAME saveidl;
154     WCHAR *pFileName;
155     WCHAR wszPath[MAX_LOAD_STRING];
156     WCHAR wszDir[MAX_LOAD_STRING];
157     static const WCHAR wszDefaultExt[] = { 'i','d','l',0 };
158     static const WCHAR wszIdlFiles[] = { '*','.','i','d','l','\0','\0' };
159
160     memset(&saveidl, 0, sizeof(saveidl));
161
162     lstrcpyW(wszDir, typelib.wszFileName);
163     pFileName = wszDir + lstrlenW(wszDir);
164     while(*pFileName != '.' && *pFileName != '\\' && *pFileName != '/'
165             && pFileName > wszDir) pFileName -= 1;
166     if(*pFileName == '.')
167     {
168         *pFileName = '\0';
169         while(*pFileName != '\\' && *pFileName != '/' && pFileName > wszDir)
170             pFileName -= 1;
171     }
172     if(*pFileName == '\\' || *pFileName == '/') pFileName += 1;
173     lstrcpyW(wszPath, pFileName);
174
175     GetCurrentDirectory(MAX_LOAD_STRING, wszDir);
176
177     saveidl.lStructSize = sizeof(OPENFILENAME);
178     saveidl.hwndOwner = globals.hTypeLibWnd;
179     saveidl.hInstance = globals.hMainInst;
180     saveidl.lpstrFilter = wszIdlFiles;
181     saveidl.lpstrFile = wszPath;
182     saveidl.nMaxFile = MAX_LOAD_STRING;
183     saveidl.lpstrInitialDir = wszDir;
184     saveidl.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
185     saveidl.lpstrDefExt = wszDefaultExt;
186
187     if (GetSaveFileName(&saveidl))
188         SaveIdl(wszPath);
189 }
190
191 void AddToStrW(WCHAR *wszDest, const WCHAR *wszSource)
192 {
193     lstrcpyW(&wszDest[lstrlenW(wszDest)], wszSource);
194 }
195
196 void AddToTLDataStrW(TYPELIB_DATA *pTLData, const WCHAR *wszSource)
197 {
198     int SourceLen = lstrlenW(wszSource);
199
200     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
201             sizeof(WCHAR)*(pTLData->idlLen+SourceLen+1));
202
203     memcpy(&pTLData->idl[pTLData->idlLen], wszSource, sizeof(WCHAR)*(SourceLen+1));
204     pTLData->idlLen += SourceLen;
205 }
206
207 void AddToTLDataStrWithTabsW(TYPELIB_DATA *pTLData, WCHAR *wszSource)
208 {
209     int lineLen = lstrlenW(wszSource);
210     int newLinesNo = 0;
211     WCHAR *pSourcePos = (WCHAR *)wszSource;
212     WCHAR *pSourceBeg;
213
214     if(!lineLen) return;
215     while(*pSourcePos)
216     {
217         if(*pSourcePos == *wszNewLine) newLinesNo++;
218         pSourcePos += 1;
219     }
220     if(*(pSourcePos - 1) != *wszNewLine) newLinesNo++;
221
222     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
223             sizeof(WCHAR)*(pTLData->idlLen+lineLen+4*newLinesNo+1));
224
225     pSourcePos = (WCHAR *)wszSource;
226     pSourceBeg = (WCHAR *)wszSource;
227     while(newLinesNo)
228     {
229         if(*pSourcePos != *wszNewLine && *pSourcePos)
230         {
231             pSourcePos += 1;
232             continue;
233         }
234         newLinesNo--;
235
236         if(*pSourcePos)
237         {
238             *pSourcePos = '\0';
239             lineLen = lstrlenW(pSourceBeg)+1;
240             *pSourcePos = '\n';
241             pSourcePos += 1;
242         }
243         else lineLen = lstrlenW(pSourceBeg);
244
245         pTLData->idl[pTLData->idlLen] = *wszSpace;
246         pTLData->idl[pTLData->idlLen+1] = *wszSpace;
247         pTLData->idl[pTLData->idlLen+2] = *wszSpace;
248         pTLData->idl[pTLData->idlLen+3] = *wszSpace;
249         memcpy(&pTLData->idl[pTLData->idlLen+4], pSourceBeg, sizeof(WCHAR)*lineLen);
250         pTLData->idlLen += lineLen + 4;
251         pTLData->idl[pTLData->idlLen] = '\0';
252
253         pSourceBeg = pSourcePos;
254     }
255 }
256
257 static TYPELIB_DATA *InitializeTLData(void)
258 {
259     TYPELIB_DATA *pTLData;
260
261     pTLData = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPELIB_DATA));
262
263     memset(pTLData, 0, sizeof(TYPELIB_DATA));
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, int cFuncs, HTREEITEM hParent)
497 {
498     int i, j, tabSize;
499     unsigned namesNo;
500     TVINSERTSTRUCT tvis;
501     FUNCDESC *pFuncDesc;
502     BSTR bstrName, *bstrParamNames;
503     WCHAR wszText[MAX_LOAD_STRING];
504     WCHAR wszAfter[MAX_LOAD_STRING];
505     WCHAR szRhs[] = {'r','h','s',0};    /* Right-hand side of a propput */
506     BOOL bFirst;
507
508     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
509     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
510     tvis.hParent = hParent;
511
512     for(i=0; i<cFuncs; i++)
513     {
514         TYPELIB_DATA *tld;
515
516         if(FAILED(ITypeInfo_GetFuncDesc(pTypeInfo, i, &pFuncDesc))) continue;
517         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstrName,
518                 NULL, NULL, NULL))) continue;
519
520         bstrParamNames = HeapAlloc(GetProcessHeap(), 0,
521                 sizeof(BSTR*)*(pFuncDesc->cParams+1));
522         if(FAILED(ITypeInfo_GetNames(pTypeInfo, pFuncDesc->memid, bstrParamNames,
523                 pFuncDesc->cParams+1, &namesNo)))
524         {
525             HeapFree(GetProcessHeap(), 0, bstrParamNames);
526             continue;
527         }
528         SysFreeString(bstrParamNames[0]);
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)
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         CreateTypeInfo(wszText, wszAfter, pFuncDesc->elemdescFunc.tdesc, pTypeInfo);
549         switch(pFuncDesc->invkind)
550         {
551             case INVOKE_PROPERTYGET:
552                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
553                 else
554                 {
555                     AddToTLDataStrW(tld, wszComa);
556                     AddToTLDataStrW(tld, wszSpace);
557                 }
558                 bFirst = FALSE;
559                 AddToTLDataStrW(tld, wszPropGet);
560                 break;
561             case INVOKE_PROPERTYPUT:
562                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
563                 else
564                 {
565                     AddToTLDataStrW(tld, wszComa);
566                     AddToTLDataStrW(tld, wszSpace);
567                 }
568                 bFirst = FALSE;
569                 AddToTLDataStrW(tld, wszPropPut);
570                 break;
571             case INVOKE_PROPERTYPUTREF:
572                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
573                 else
574                 {
575                     AddToTLDataStrW(tld, wszComa);
576                     AddToTLDataStrW(tld, wszSpace);
577                 }
578                 bFirst = FALSE;
579                 AddToTLDataStrW(tld, wszPropPutRef);
580                 break;
581             default:;
582         }
583         if(!bFirst)
584         {
585             AddToTLDataStrW(tld, wszCloseBrackets1);
586             AddToTLDataStrW(tld, wszNewLine);
587         }
588         AddToTLDataStrW(tld, wszText);
589         AddToTLDataStrW(tld, wszAfter);
590         AddToTLDataStrW(tld, wszSpace);
591         if(pFuncDesc->memid >= MIN_FUNC_ID)
592         {
593             AddToTLDataStrW(tld, wszStdCall);
594             AddToTLDataStrW(tld, wszSpace);
595         }
596         tabSize = tld->idlLen;
597         AddToTLDataStrW(tld, bstrName);
598         AddToTLDataStrW(tld, wszOpenBrackets2);
599
600         for(j=0; j<pFuncDesc->cParams; j++)
601         {
602             if(j != 0) AddToTLDataStrW(tld, wszComa);
603             if(pFuncDesc->cParams != 1)
604             {
605                 AddToTLDataStrW(tld, wszNewLine);
606                 AddSpaces(tld, tabSize);
607             }
608             bFirst = TRUE;
609 #define ENUM_PARAM_FLAG(x)\
610             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & x) \
611             {\
612                 if(bFirst) AddToTLDataStrW(tld,\
613                         wszOpenBrackets1);\
614                 else\
615                 {\
616                     AddToTLDataStrW(tld, wszComa);\
617                     AddToTLDataStrW(tld, wszSpace);\
618                 }\
619                 bFirst = FALSE;\
620                 AddToTLDataStrW(tld, wsz##x);\
621             }
622             ENUM_PARAM_FLAG(PARAMFLAG_FIN);
623             ENUM_PARAM_FLAG(PARAMFLAG_FOUT);
624             ENUM_PARAM_FLAG(PARAMFLAG_FLCID);
625             ENUM_PARAM_FLAG(PARAMFLAG_FRETVAL);
626             ENUM_PARAM_FLAG(PARAMFLAG_FOPT);
627             ENUM_PARAM_FLAG(PARAMFLAG_FHASCUSTDATA);
628
629             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
630             {
631                 VARIANT var, *param=&U(pFuncDesc->lprgelemdescParam[j]).paramdesc.pparamdescex->varDefaultValue;
632                 VariantInit(&var);
633                 if(bFirst) AddToTLDataStrW(tld,
634                         wszOpenBrackets1);
635                 else
636                 {
637                     AddToTLDataStrW(tld, wszComa);
638                     AddToTLDataStrW(tld, wszSpace);
639                 }
640                 bFirst = FALSE;
641                 AddToTLDataStrW(tld, wszDefaultValue);
642                 AddToTLDataStrW(tld, wszOpenBrackets2);
643                 if (V_VT(param) == VT_BSTR)
644                 {
645                     AddToTLDataStrW(tld, wszInvertedComa);
646                     AddToTLDataStrW(tld, V_BSTR(&var));
647                     AddToTLDataStrW(tld, wszInvertedComa);
648                 } else if (VariantChangeType(&var, param, 0, VT_BSTR) == S_OK)
649                     AddToTLDataStrW(tld, V_BSTR(&var));
650                 AddToTLDataStrW(tld, wszCloseBrackets2);
651             }
652
653             if(!bFirst)
654             {
655                 AddToTLDataStrW(tld, wszCloseBrackets1);
656                 AddToTLDataStrW(tld, wszSpace);
657             }
658
659             memset(wszText, 0, sizeof(wszText));
660             memset(wszAfter, 0, sizeof(wszAfter));
661             CreateTypeInfo(wszText, wszAfter, pFuncDesc->lprgelemdescParam[j].tdesc,
662                     pTypeInfo);
663             AddToTLDataStrW(tld, wszText);
664             AddToTLDataStrW(tld, wszAfter);
665             AddToTLDataStrW(tld, wszSpace);
666             if (j+1 < namesNo) {
667                 AddToTLDataStrW(tld, bstrParamNames[j+1]);
668                 SysFreeString(bstrParamNames[j+1]);
669             } else {
670                 AddToTLDataStrW(tld, szRhs);
671             }
672         }
673         AddToTLDataStrW(tld, wszCloseBrackets2);
674         AddToTLDataStrW(tld, wszSemicolon);
675         AddToTLDataStrW(tld, wszNewLine);
676
677         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
678         HeapFree(GetProcessHeap(), 0, bstrParamNames);
679         SysFreeString(bstrName);
680         ITypeInfo_ReleaseFuncDesc(pTypeInfo, pFuncDesc);
681     }
682
683     return 0;
684 }
685
686 static int EnumImplTypes(ITypeInfo *pTypeInfo, int cImplTypes, HTREEITEM hParent)
687 {
688     int i;
689     TVINSERTSTRUCT tvis;
690     ITypeInfo *pRefTypeInfo;
691     HREFTYPE hRefType;
692     TYPEATTR *pTypeAttr;
693     BSTR bstrName;
694     WCHAR wszInheritedInterfaces[MAX_LOAD_STRING];
695
696     if(!cImplTypes) return 0;
697
698     LoadString(globals.hMainInst, IDS_INHERITINTERFACES, wszInheritedInterfaces,
699             sizeof(WCHAR[MAX_LOAD_STRING]));
700
701     U(tvis).item.mask = TVIF_TEXT;
702     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
703     U(tvis).item.pszText = wszInheritedInterfaces;
704     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
705     tvis.hParent = hParent;
706
707     tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
708
709     for(i=0; i<cImplTypes; i++)
710     {
711         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
712         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
713             continue;
714         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
715                 NULL, NULL, NULL))) continue;
716         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr))) continue;
717
718         U(tvis).item.cchTextMax = SysStringLen(bstrName);
719         U(tvis).item.pszText = bstrName;
720
721         hParent = TreeView_InsertItem(typelib.hTree, &tvis);
722         EnumVars(pRefTypeInfo, pTypeAttr->cVars, hParent);
723         EnumFuncs(pRefTypeInfo, pTypeAttr->cFuncs, hParent);
724         EnumImplTypes(pRefTypeInfo, pTypeAttr->cImplTypes, hParent);
725
726         SysFreeString(bstrName);
727         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
728         ITypeInfo_Release(pRefTypeInfo);
729     }
730
731     return 0;
732 }
733
734 static void AddIdlData(HTREEITEM hCur, TYPELIB_DATA *pTLData)
735 {
736     TVITEM tvi;
737
738     hCur = TreeView_GetChild(typelib.hTree, hCur);
739     memset(&tvi, 0, sizeof(TVITEM));
740     tvi.mask = TVIF_PARAM;
741
742     while(hCur)
743     {
744         tvi.hItem = hCur;
745         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
746         AddToTLDataStrW(pTLData, wszNewLine);
747         AddToTLDataStrWithTabsW(pTLData, ((TYPELIB_DATA*)(tvi.lParam))->idl);
748         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
749     }
750 }
751
752 static void AddPredefinitions(HTREEITEM hFirst, TYPELIB_DATA *pTLData)
753 {
754     HTREEITEM hCur;
755     TVITEM tvi;
756     WCHAR wszText[MAX_LOAD_STRING];
757     WCHAR wszPredefinition[] = { '/','/',' ','T','L','i','b',' ',':','\n',
758         '/','/',' ','F','o','r','w','a','r','d',' ','d','e','c','l','a','r','e',' ',
759         'a','l','l',' ','t','y','p','e','s',' ','d','e','f','i','n','e','d',' ',
760         'i','n',' ','t','h','i','s',' ','t','y','p','e','l','i','b','\0' };
761
762     hFirst = TreeView_GetChild(typelib.hTree, hFirst);
763
764     AddToTLDataStrWithTabsW(pTLData, wszPredefinition);
765     AddToTLDataStrW(pTLData, wszNewLine);
766
767     hCur = hFirst;
768     memset(&tvi, 0, sizeof(TVITEM));
769     tvi.mask = TVIF_TEXT|TVIF_PARAM;
770     tvi.cchTextMax = MAX_LOAD_STRING;
771     tvi.pszText = wszText;
772     while(hCur)
773     {
774         tvi.hItem = hCur;
775         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
776         if(((TYPELIB_DATA*)(tvi.lParam))->bPredefine)
777         {
778             AddToStrW(wszText, wszSemicolon);
779             AddToTLDataStrWithTabsW(pTLData, wszText);
780             AddToTLDataStrW(pTLData, wszNewLine);
781         }
782         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
783     }
784 }
785
786 static void CreateInterfaceInfo(ITypeInfo *pTypeInfo, int cImplTypes, WCHAR *wszName,
787         WCHAR *wszHelpString, unsigned long ulHelpContext, TYPEATTR *pTypeAttr,
788         TYPELIB_DATA *pTLData)
789 {
790     ITypeInfo *pRefTypeInfo;
791     HREFTYPE hRefType;
792     BSTR bstrName;
793     WCHAR wszGuid[MAX_LOAD_STRING];
794     WCHAR wszHelpContext[MAX_LOAD_STRING];
795
796     const WCHAR wszInterface[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
797     const WCHAR wszDispinterface[]
798         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
799     const WCHAR wszHelpstring[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
800     const WCHAR wszHelpcontext[] = { 'h','e','l','p','c','o','n','t','e','x','t','\0' };
801     const WCHAR wszTYPEFLAG_FAPPOBJECT[] = { 'a','p','p','o','b','j','e','c','t','\0' };
802     const WCHAR wszTYPEFLAG_FCANCREATE[] = { 'c','a','n','c','r','e','a','t','e','\0' };
803     const WCHAR wszTYPEFLAG_FLICENSED[] = { 'l','i','c','e','n','s','e','d','\0' };
804     const WCHAR wszTYPEFLAG_FPREDECLID[] = { 'p','r','e','d','e','c','l','i','d','\0' };
805     const WCHAR wszTYPEFLAG_FHIDDEN[] = { 'h','i','d','d','e','n','\0' };
806     const WCHAR wszTYPEFLAG_FCONTROL[] = { 'c','o','n','t','r','o','l','\0' };
807     const WCHAR wszTYPEFLAG_FDUAL[] = { 'd','u','a','l','\0' };
808     const WCHAR wszTYPEFLAG_FNONEXTENSIBLE[]
809         = { 'n','o','n','e','x','t','e','n','s','i','b','l','e','\0' };
810     const WCHAR wszTYPEFLAG_FOLEAUTOMATION[]
811         = { 'o','l','e','a','u','t','o','m','a','t','i','o','n','\0' };
812     const WCHAR wszTYPEFLAG_FRESTRICTED[]
813         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
814     const WCHAR wszTYPEFLAG_FAGGREGATABLE[]
815         = { 'a','g','g','r','e','g','a','t','a','b','l','e','\0' };
816     const WCHAR wszTYPEFLAG_FREPLACEABLE[]
817         = { 'r','e','p','l','a','c','a','b','l','e','\0' };
818     const WCHAR wszTYPEFLAG_FREVERSEBIND[]
819         = { 'r','e','v','e','r','s','e','b','i','n','d','\0' };
820     const WCHAR wszTYPEFLAG_FPROXY[] = { 'p','r','o','x','y','\0' };
821
822     AddToTLDataStrW(pTLData, wszOpenBrackets1);
823     AddToTLDataStrW(pTLData, wszNewLine);
824     if(pTypeAttr->typekind != TKIND_DISPATCH)
825     {
826         AddSpaces(pTLData, 4);
827         AddToTLDataStrW(pTLData, wszOdl);
828         AddToTLDataStrW(pTLData, wszComa);
829         AddToTLDataStrW(pTLData, wszNewLine);
830     }
831     AddSpaces(pTLData, 4);
832     AddToTLDataStrW(pTLData, wszUUID);
833     AddToTLDataStrW(pTLData, wszOpenBrackets2);
834     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
835     wszGuid[lstrlenW(wszGuid)-1] = '\0';
836     AddToTLDataStrW(pTLData, &wszGuid[1]);
837     AddToTLDataStrW(pTLData, wszCloseBrackets2);
838     if(wszHelpString)
839     {
840         AddToTLDataStrW(pTLData, wszComa);
841         AddToTLDataStrW(pTLData, wszNewLine);
842         AddSpaces(pTLData, 4);
843         AddToTLDataStrW(pTLData, wszHelpstring);
844         AddToTLDataStrW(pTLData, wszOpenBrackets2);
845         AddToTLDataStrW(pTLData, wszInvertedComa);
846         AddToTLDataStrW(pTLData, wszHelpString);
847         AddToTLDataStrW(pTLData, wszInvertedComa);
848         AddToTLDataStrW(pTLData, wszCloseBrackets2);
849     }
850     if(ulHelpContext)
851     {
852         AddToTLDataStrW(pTLData, wszComa);
853         AddToTLDataStrW(pTLData, wszNewLine);
854         AddSpaces(pTLData, 4);
855         AddToTLDataStrW(pTLData, wszHelpcontext);
856         AddToTLDataStrW(pTLData, wszOpenBrackets2);
857         wsprintfW(wszHelpContext, wszFormat, ulHelpContext);
858         AddToTLDataStrW(pTLData, wszHelpContext);
859         AddToTLDataStrW(pTLData, wszCloseBrackets2);
860     }
861     if(pTypeAttr->wTypeFlags)
862     {
863 #define ENUM_FLAGS(x) if(pTypeAttr->wTypeFlags & x &&\
864         (pTypeAttr->typekind != TKIND_DISPATCH || x != TYPEFLAG_FDISPATCHABLE))\
865         {\
866             AddToTLDataStrW(pTLData, wszComa);\
867             AddToTLDataStrW(pTLData, wszNewLine);\
868             AddSpaces(pTLData, 4);\
869             AddToTLDataStrW(pTLData, wsz##x);\
870         }
871         ENUM_FLAGS(TYPEFLAG_FAPPOBJECT);
872         ENUM_FLAGS(TYPEFLAG_FCANCREATE);
873         ENUM_FLAGS(TYPEFLAG_FLICENSED);
874         ENUM_FLAGS(TYPEFLAG_FPREDECLID);
875         ENUM_FLAGS(TYPEFLAG_FHIDDEN);
876         ENUM_FLAGS(TYPEFLAG_FCONTROL);
877         ENUM_FLAGS(TYPEFLAG_FDUAL);
878         ENUM_FLAGS(TYPEFLAG_FNONEXTENSIBLE);
879         ENUM_FLAGS(TYPEFLAG_FOLEAUTOMATION);
880         ENUM_FLAGS(TYPEFLAG_FRESTRICTED);
881         ENUM_FLAGS(TYPEFLAG_FAGGREGATABLE);
882         ENUM_FLAGS(TYPEFLAG_FREPLACEABLE);
883         ENUM_FLAGS(TYPEFLAG_FREVERSEBIND);
884         ENUM_FLAGS(TYPEFLAG_FPROXY);
885     }
886     AddToTLDataStrW(pTLData, wszNewLine);
887     AddToTLDataStrW(pTLData, wszCloseBrackets1);
888     AddToTLDataStrW(pTLData, wszNewLine);
889     if(pTypeAttr->typekind != TKIND_DISPATCH) AddToTLDataStrW(pTLData, wszInterface);
890     else AddToTLDataStrW(pTLData, wszDispinterface);
891     AddToTLDataStrW(pTLData, wszName);
892     AddToTLDataStrW(pTLData, wszSpace);
893     if(cImplTypes && pTypeAttr->typekind != TKIND_DISPATCH)
894     {
895         AddToTLDataStrW(pTLData, wszColon);
896         AddToTLDataStrW(pTLData, wszSpace);
897
898         ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &hRefType);
899         ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
900         ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
901                 NULL, NULL, NULL);
902         AddToTLDataStrW(pTLData, bstrName);
903         AddToTLDataStrW(pTLData, wszSpace);
904
905         SysFreeString(bstrName);
906         ITypeInfo_Release(pRefTypeInfo);
907     }
908     AddToTLDataStrW(pTLData, wszOpenBrackets3);
909     AddToTLDataStrW(pTLData, wszNewLine);
910
911     AddToStrW(pTLData->wszInsertAfter, wszCloseBrackets3);
912     AddToStrW(pTLData->wszInsertAfter, wszSemicolon);
913     AddToStrW(pTLData->wszInsertAfter, wszNewLine);
914 }
915
916 static void CreateTypedefHeader(ITypeInfo *pTypeInfo,
917         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
918 {
919     BOOL bFirst = TRUE;
920     WCHAR wszGuid[MAX_LOAD_STRING];
921     const WCHAR wszTypedef[] = { 't','y','p','e','d','e','f',' ','\0' };
922     const WCHAR wszPublic[] = { 'p','u','b','l','i','c','\0' };
923
924     AddToTLDataStrW(pTLData, wszTypedef);
925     if(memcmp(&pTypeAttr->guid, &GUID_NULL, sizeof(GUID)))
926     {
927         AddToTLDataStrW(pTLData, wszOpenBrackets1);
928         bFirst = FALSE;
929         AddToTLDataStrW(pTLData, wszUUID);
930         AddToTLDataStrW(pTLData, wszOpenBrackets2);
931         StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
932         wszGuid[lstrlenW(wszGuid)-1] = '\0';
933         AddToTLDataStrW(pTLData, &wszGuid[1]);
934         AddToTLDataStrW(pTLData, wszCloseBrackets2);
935     }
936     if(pTypeAttr->typekind == TKIND_ALIAS)
937     {
938         if(bFirst) AddToTLDataStrW(pTLData, wszOpenBrackets1);
939         else
940         {
941             AddToTLDataStrW(pTLData, wszComa);
942             AddToTLDataStrW(pTLData, wszSpace);
943         }
944         bFirst = FALSE;
945         AddToTLDataStrW(pTLData, wszPublic);
946     }
947     if(!bFirst)
948     {
949         AddToTLDataStrW(pTLData, wszCloseBrackets1);
950         AddToTLDataStrW(pTLData, wszNewLine);
951     }
952 }
953
954 static int PopulateTree(void)
955 {
956     TVINSERTSTRUCT tvis;
957     TVITEM tvi;
958     ITypeLib *pTypeLib;
959     TLIBATTR *pTLibAttr;
960     ITypeInfo *pTypeInfo, *pRefTypeInfo;
961     HREFTYPE hRefType;
962     TYPEATTR *pTypeAttr;
963     INT count, i;
964     ULONG ulHelpContext;
965     BSTR bstrName;
966     BSTR bstrData;
967     WCHAR wszText[MAX_LOAD_STRING];
968     WCHAR wszAfter[MAX_LOAD_STRING];
969     HRESULT hRes;
970     HTREEITEM hParent;
971     HTREEITEM hMain;
972     BOOL bInsert;
973     TYPELIB_DATA *tldDispatch;
974     TYPELIB_DATA *tld;
975
976     const WCHAR wszGeneratedInfo[] = { '/','/',' ','G','e','n','e','r','a','t','e','d',
977         ' ','.','I','D','L',' ','f','i','l','e',' ','(','b','y',' ','t','h','e',' ',
978         'O','L','E','/','C','O','M',' ','O','b','j','e','c','t',' ',
979         'V','i','e','w','e','r',')','\n','/','/','\n','/','/',' ',
980         't','y','p','e','l','i','b',' ','f','i','l','e','n','a','m','e',':',' ','\0'};
981
982     const WCHAR wszFormat[] = { '%','s',' ','(','%','s',')','\0' };
983     const WCHAR wszFormat2[] = { 'v','e','r','s','i','o','n',
984         '(','%','l','d','.','%','l','d',')','\0' };
985
986     const WCHAR wszTKIND_ENUM[] = { 't','y','p','e','d','e','f',' ','e','n','u','m',' ','\0' };
987     const WCHAR wszTKIND_RECORD[]
988         = { 't','y','p','e','d','e','f',' ','s','t','r','u','c','t',' ','\0' };
989     const WCHAR wszTKIND_MODULE[] = { 'm','o','d','u','l','e',' ','\0' };
990     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
991     const WCHAR wszTKIND_DISPATCH[]
992         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
993     const WCHAR wszTKIND_COCLASS[] = { 'c','o','c','l','a','s','s',' ','\0' };
994     const WCHAR wszTKIND_ALIAS[] = { 't','y','p','e','d','e','f',' ','\0' };
995     const WCHAR wszTKIND_UNION[]
996         = { 't','y','p','e','d','e','f',' ','u','n','i','o','n',' ','\0' };
997
998     const WCHAR wszHelpString[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
999     const WCHAR wszLibrary[] = { 'l','i','b','r','a','r','y',' ','\0' };
1000     const WCHAR wszTag[] = { 't','a','g','\0' };
1001
1002     WCHAR wszProperties[] = { 'p','r','o','p','e','r','t','i','e','s','\0' };
1003     WCHAR wszMethods[] = { 'm','e','t','h','o','d','s','\0' };
1004
1005     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
1006     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
1007     U(tvis).item.pszText = wszText;
1008     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
1009     tvis.hParent = TVI_ROOT;
1010
1011     if(FAILED((hRes = LoadTypeLib(typelib.wszFileName, &pTypeLib))))
1012     {
1013         WCHAR wszMessage[MAX_LOAD_STRING];
1014         WCHAR wszError[MAX_LOAD_STRING];
1015
1016         LoadString(globals.hMainInst, IDS_ERROR_LOADTYPELIB,
1017                 wszError, sizeof(WCHAR[MAX_LOAD_STRING]));
1018         wsprintfW(wszMessage, wszError, typelib.wszFileName, hRes);
1019         MessageBox(globals.hMainWnd, wszMessage, NULL, MB_OK|MB_ICONEXCLAMATION);
1020         return 1;
1021     }
1022     count = ITypeLib_GetTypeInfoCount(pTypeLib);
1023
1024     ITypeLib_GetDocumentation(pTypeLib, -1, &bstrName, &bstrData, NULL, NULL);
1025     ITypeLib_GetLibAttr(pTypeLib, &pTLibAttr);
1026
1027     tld = InitializeTLData();
1028     U(tvis).item.lParam = (LPARAM) tld;
1029     AddToTLDataStrW(tld, wszGeneratedInfo);
1030     AddToTLDataStrW(tld, typelib.wszFileName);
1031     AddToTLDataStrW(tld, wszNewLine);
1032     AddToTLDataStrW(tld, wszNewLine);
1033     AddToTLDataStrW(tld, wszOpenBrackets1);
1034     AddToTLDataStrW(tld, wszNewLine);
1035     AddSpaces(tld, 4);
1036     AddToTLDataStrW(tld, wszUUID);
1037     AddToTLDataStrW(tld, wszOpenBrackets2);
1038     StringFromGUID2(&(pTLibAttr->guid), wszText, MAX_LOAD_STRING);
1039     wszText[lstrlenW(wszText)-1] = '\0';
1040     AddToTLDataStrW(tld, &wszText[1]);
1041     AddToTLDataStrW(tld, wszCloseBrackets2);
1042     AddToTLDataStrW(tld, wszComa);
1043     AddToTLDataStrW(tld, wszNewLine);
1044     AddSpaces(tld, 4);
1045     wsprintfW(wszText, wszFormat2, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
1046     AddToTLDataStrW(tld, wszText);
1047     AddToTLDataStrW(tld, wszComa);
1048     AddToTLDataStrW(tld, wszNewLine);
1049     AddSpaces(tld, 4);
1050     AddToTLDataStrW(tld, wszHelpString);
1051     AddToTLDataStrW(tld, wszOpenBrackets2);
1052     AddToTLDataStrW(tld, wszInvertedComa);
1053     AddToTLDataStrW(tld, bstrData);
1054     AddToTLDataStrW(tld, wszInvertedComa);
1055     AddToTLDataStrW(tld, wszCloseBrackets2);
1056     AddToTLDataStrW(tld, wszNewLine);
1057     AddToTLDataStrW(tld, wszCloseBrackets1);
1058     AddToTLDataStrW(tld, wszNewLine);
1059     AddToTLDataStrW(tld, wszLibrary);
1060     AddToTLDataStrW(tld, bstrName);
1061     AddToTLDataStrW(tld, wszNewLine);
1062     AddToTLDataStrW(tld, wszOpenBrackets3);
1063     AddToTLDataStrW(tld, wszNewLine);
1064
1065     AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1066     AddToStrW(tld->wszInsertAfter, wszSemicolon);
1067
1068     wsprintfW(wszText, wszFormat, bstrName, bstrData);
1069     SysFreeString(bstrName);
1070     SysFreeString(bstrData);
1071     tvis.hParent = (HTREEITEM)SendMessage(typelib.hTree,
1072             TVM_INSERTITEM, 0, (LPARAM)&tvis);
1073
1074     for(i=0; i<count; i++)
1075     {
1076         bInsert = TRUE;
1077         ITypeLib_GetTypeInfo(pTypeLib, i, &pTypeInfo);
1078
1079         ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &bstrName, &bstrData,
1080                 &ulHelpContext, NULL);
1081         ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
1082
1083         memset(wszText, 0, sizeof(wszText));
1084         memset(wszAfter, 0, sizeof(wszAfter));
1085         tld = InitializeTLData();
1086         U(tvis).item.lParam = (LPARAM)tld;
1087         switch(pTypeAttr->typekind)
1088         {
1089             case TKIND_ENUM:
1090                 AddToStrW(wszText, wszTKIND_ENUM);
1091                 AddToStrW(wszText, bstrName);
1092
1093                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1094                 AddToTLDataStrW(tld, &wszTKIND_ENUM[lstrlenW(wszTKIND_ALIAS)]);
1095                 AddToTLDataStrW(tld, wszOpenBrackets3);
1096                 AddToTLDataStrW(tld,wszNewLine);
1097                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1098                 AddToStrW(tld->wszInsertAfter, wszSpace);
1099                 AddToStrW(tld->wszInsertAfter, bstrName);
1100                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1101                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1102
1103                 bInsert = FALSE;
1104                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1105                 EnumEnums(pTypeInfo, pTypeAttr->cVars, hParent);
1106                 AddChildrenData(hParent, tld);
1107                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1108                 break;
1109             case TKIND_RECORD:
1110                 AddToTLDataStrW(tld, wszTKIND_RECORD);
1111                 AddToTLDataStrW(tld, wszTag);
1112                 AddToTLDataStrW(tld, bstrName);
1113                 AddToTLDataStrW(tld, wszSpace);
1114                 AddToTLDataStrW(tld, wszOpenBrackets3);
1115                 AddToTLDataStrW(tld, wszNewLine);
1116
1117                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1118                 AddToStrW(tld->wszInsertAfter, wszSpace);
1119                 AddToStrW(tld->wszInsertAfter, bstrName);
1120                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1121                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1122
1123                 AddToStrW(wszText, wszTKIND_RECORD);
1124                 AddToStrW(wszText, bstrName);
1125                 break;
1126             case TKIND_MODULE:
1127                 AddToStrW(wszText, wszTKIND_MODULE);
1128                 AddToStrW(wszText, bstrName);
1129                 break;
1130             case TKIND_INTERFACE:
1131                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1132                         bstrData, ulHelpContext, pTypeAttr, tld);
1133                 tld->bPredefine = TRUE;
1134
1135                 AddToStrW(wszText, wszTKIND_INTERFACE);
1136                 AddToStrW(wszText, bstrName);
1137                 break;
1138             case TKIND_COCLASS:
1139                 AddToStrW(wszText, wszTKIND_COCLASS);
1140                 AddToStrW(wszText, bstrName);
1141                 break;
1142             case TKIND_UNION:
1143                 AddToStrW(wszText, wszTKIND_UNION);
1144                 AddToStrW(wszText, bstrName);
1145                 break;
1146             case TKIND_DISPATCH:
1147                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1148                         bstrData, ulHelpContext, pTypeAttr, tld);
1149                 tld->bPredefine = TRUE;
1150                 AddToStrW(wszText, wszTKIND_DISPATCH);
1151                 AddToStrW(wszText, bstrName);
1152
1153                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1154                 hMain = tvis.hParent;
1155                 tldDispatch = tld;
1156
1157                 lstrcpyW(wszText, wszProperties);
1158                 tvis.hParent = hParent;
1159                 tld = InitializeTLData();
1160                 U(tvis).item.lParam = (LPARAM) tld;
1161                 AddToTLDataStrW(tld, wszProperties);
1162                 AddToTLDataStrW(tld, wszColon);
1163                 AddToTLDataStrW(tld, wszNewLine);
1164                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1165                 EnumVars(pTypeInfo, pTypeAttr->cVars, tvis.hParent);
1166                 AddChildrenData(tvis.hParent, tld);
1167
1168                 lstrcpyW(wszText, wszMethods);
1169                 tvis.hParent = hParent;
1170                 tld = InitializeTLData();
1171                 U(tvis).item.lParam = (LPARAM) tld;
1172                 AddToTLDataStrW(tld, wszMethods);
1173                 AddToTLDataStrW(tld, wszColon);
1174                 AddToTLDataStrW(tld, wszNewLine);
1175                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1176                 EnumFuncs(pTypeInfo, pTypeAttr->cFuncs, tvis.hParent);
1177                 AddChildrenData(tvis.hParent, tld);
1178
1179                 EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1180                 AddChildrenData(hParent, tldDispatch);
1181                 AddToTLDataStrW(tldDispatch, tldDispatch->wszInsertAfter);
1182
1183                 bInsert = FALSE;
1184                 tvis.hParent = hMain;
1185
1186                 if(SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, -1, &hRefType)))
1187                 {
1188                     bInsert = TRUE;
1189
1190                     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1191                     SysFreeString(bstrName);
1192                     SysFreeString(bstrData);
1193
1194                     memset(wszText, 0, sizeof(wszText));
1195                     tld = InitializeTLData();
1196                     U(tvis).item.lParam = (LPARAM) tld;
1197
1198                     ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
1199                     ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1200                                 &bstrData, &ulHelpContext, NULL);
1201                     ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr);
1202
1203                     CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1204                             bstrData, ulHelpContext, pTypeAttr, tld);
1205                     tld->bPredefine = TRUE;
1206
1207                     AddToStrW(wszText, wszTKIND_INTERFACE);
1208                     AddToStrW(wszText, bstrName);
1209                     ITypeInfo_Release(pRefTypeInfo);
1210                 }
1211                 break;
1212             case TKIND_ALIAS:
1213                 AddToStrW(wszText, wszTKIND_ALIAS);
1214                 CreateTypeInfo(wszText, wszAfter, pTypeAttr->tdescAlias, pTypeInfo);
1215                 AddToStrW(wszText, wszSpace);
1216                 AddToStrW(wszText, bstrName);
1217                 AddToStrW(wszText, wszAfter);
1218
1219                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1220                 AddToTLDataStrW(tld, &wszText[lstrlenW(wszTKIND_ALIAS)]);
1221                 AddToTLDataStrW(tld, wszSemicolon);
1222                 AddToTLDataStrW(tld, wszNewLine);
1223                 break;
1224             default:
1225                 lstrcpyW(wszText, bstrName);
1226                 WINE_FIXME("pTypeAttr->typekind == %d not supported\n",
1227                         pTypeAttr->typekind);
1228         }
1229
1230         if(bInsert)
1231         {
1232             hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1233
1234             EnumVars(pTypeInfo, pTypeAttr->cVars, hParent);
1235             EnumFuncs(pTypeInfo, pTypeAttr->cFuncs, hParent);
1236             EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1237
1238             if(memcmp(bstrName, wszVT_UNKNOWN, sizeof(wszVT_UNKNOWN)))
1239                 AddChildrenData(hParent, tld);
1240             AddToTLDataStrW(tld, tld->wszInsertAfter);
1241         }
1242
1243         ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1244         ITypeInfo_Release(pTypeInfo);
1245         SysFreeString(bstrName);
1246         SysFreeString(bstrData);
1247     }
1248     SendMessage(typelib.hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
1249
1250     memset(&tvi, 0, sizeof(TVITEM));
1251     tvi.mask = TVIF_PARAM;
1252     tvi.hItem = tvis.hParent;
1253
1254     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1255     AddPredefinitions(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1256     AddIdlData(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1257     AddToTLDataStrW((TYPELIB_DATA*)(tvi.lParam),
1258             ((TYPELIB_DATA*)(tvi.lParam))->wszInsertAfter);
1259
1260     ITypeLib_Release(pTypeLib);
1261     return 0;
1262 }
1263
1264 void UpdateData(HTREEITEM item)
1265 {
1266     TVITEM tvi;
1267
1268     memset(&tvi, 0, sizeof(TVITEM));
1269     tvi.mask = TVIF_PARAM;
1270     tvi.hItem = item;
1271
1272     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1273     if(!tvi.lParam)
1274     {
1275         SetWindowText(typelib.hEdit, wszSpace);
1276         return;
1277     }
1278
1279     SetWindowText(typelib.hEdit, ((TYPELIB_DATA*)tvi.lParam)->idl);
1280 }
1281
1282 static void TypeLibResizeChild(void)
1283 {
1284     RECT client, stat;
1285
1286     MoveWindow(typelib.hStatusBar, 0, 0, 0, 0, TRUE);
1287
1288     if(IsWindowVisible(typelib.hStatusBar))
1289         GetClientRect(typelib.hStatusBar, &stat);
1290     else stat.bottom = 0;
1291
1292     GetClientRect(globals.hTypeLibWnd, &client);
1293     MoveWindow(typelib.hPaneWnd, 0, 0,
1294             client.right, client.bottom-stat.bottom, TRUE);
1295 }
1296
1297 static void TypeLibMenuCommand(WPARAM wParam, HWND hWnd)
1298 {
1299     BOOL vis;
1300
1301     switch(wParam)
1302     {
1303         case IDM_SAVEAS:
1304             GetSaveIdlAsPath();
1305             break;
1306         case IDM_STATUSBAR:
1307             vis = IsWindowVisible(typelib.hStatusBar);
1308             ShowWindow(typelib.hStatusBar, vis ? SW_HIDE : SW_SHOW);
1309             CheckMenuItem(GetMenu(hWnd), LOWORD(wParam),
1310                     vis ? MF_UNCHECKED : MF_CHECKED);
1311             TypeLibResizeChild();
1312             break;
1313         case IDM_CLOSE:
1314             DestroyWindow(hWnd);
1315             break;
1316     }
1317 }
1318
1319 static void UpdateTypeLibStatusBar(int itemID)
1320 {
1321     WCHAR info[MAX_LOAD_STRING];
1322
1323     if(!LoadString(globals.hMainInst, itemID, info, sizeof(WCHAR[MAX_LOAD_STRING])))
1324         LoadString(globals.hMainInst, IDS_READY, info, sizeof(WCHAR[MAX_LOAD_STRING]));
1325
1326     SendMessage(typelib.hStatusBar, SB_SETTEXT, 0, (LPARAM)info);
1327 }
1328
1329 static void EmptyTLTree(void)
1330 {
1331     HTREEITEM cur, del;
1332     TVITEM tvi;
1333
1334     tvi.mask = TVIF_PARAM;
1335     cur = TreeView_GetChild(typelib.hTree, TVI_ROOT);
1336
1337     while(TRUE)
1338     {
1339         del = cur;
1340         cur = TreeView_GetChild(typelib.hTree, del);
1341
1342         if(!cur) cur = TreeView_GetNextSibling(typelib.hTree, del);
1343         if(!cur) cur = TreeView_GetParent(typelib.hTree, del);
1344
1345         tvi.hItem = del;
1346         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1347         if(tvi.lParam)
1348         {
1349             HeapFree(GetProcessHeap(), 0, ((TYPELIB_DATA *)tvi.lParam)->idl);
1350             HeapFree(GetProcessHeap(), 0, (TYPELIB_DATA *)tvi.lParam);
1351         }
1352
1353         SendMessage(typelib.hTree, TVM_DELETEITEM, 0, (LPARAM)del);
1354
1355         if(!cur) break;
1356     }
1357 }
1358
1359 LRESULT CALLBACK TypeLibProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1360 {
1361     switch(uMsg)
1362     {
1363         case WM_CREATE:
1364         {
1365             if(!CreatePanedWindow(hWnd, &typelib.hPaneWnd, globals.hMainInst))
1366                 DestroyWindow(hWnd);
1367             typelib.hTree = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1368                     WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
1369                     0, 0, 0, 0, typelib.hPaneWnd, (HMENU)TYPELIB_TREE,
1370                     globals.hMainInst, NULL);
1371             typelib.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
1372                     WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|WS_HSCROLL|WS_VSCROLL,
1373                     0, 0, 0, 0, typelib.hPaneWnd, NULL, globals.hMainInst, NULL);
1374
1375             SetLeft(typelib.hPaneWnd, typelib.hTree);
1376             SetRight(typelib.hPaneWnd, typelib.hEdit);
1377
1378             if(PopulateTree()) DestroyWindow(hWnd);
1379             else SetFocus(typelib.hTree);
1380             break;
1381         }
1382         case WM_COMMAND:
1383             TypeLibMenuCommand(LOWORD(wParam), hWnd);
1384         case WM_MENUSELECT:
1385             UpdateTypeLibStatusBar(LOWORD(wParam));
1386             break;
1387         case WM_SETFOCUS:
1388             SetFocus(typelib.hTree);
1389             break;
1390         case WM_SIZE:
1391             if(wParam == SIZE_MINIMIZED) break;
1392             TypeLibResizeChild();
1393             break;
1394         case WM_DESTROY:
1395             EmptyTLTree();
1396             break;
1397         default:
1398             return DefWindowProc(hWnd, uMsg, wParam, lParam);
1399     }
1400     return 0;
1401 }
1402
1403 BOOL TypeLibRegisterClass(void)
1404 {
1405     WNDCLASS wcc;
1406
1407     memset(&wcc, 0, sizeof(WNDCLASS));
1408     wcc.lpfnWndProc = TypeLibProc;
1409     wcc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1410     wcc.lpszMenuName = MAKEINTRESOURCE(IDM_TYPELIB);
1411     wcc.lpszClassName = wszTypeLib;
1412
1413     if(!RegisterClass(&wcc))
1414         return FALSE;
1415
1416     return TRUE;
1417 }
1418
1419 BOOL CreateTypeLibWindow(HINSTANCE hInst, WCHAR *wszFileName)
1420 {
1421     WCHAR wszTitle[MAX_LOAD_STRING];
1422     LoadString(hInst, IDS_TYPELIBTITLE, wszTitle, sizeof(WCHAR[MAX_LOAD_STRING]));
1423
1424     if(wszFileName) lstrcpyW(typelib.wszFileName, wszFileName);
1425     else
1426     {
1427         TVITEM tvi;
1428
1429         memset(&tvi, 0, sizeof(TVITEM));
1430         tvi.hItem = TreeView_GetSelection(globals.hTree);
1431
1432         SendMessage(globals.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1433         lstrcpyW(typelib.wszFileName, ((ITEM_INFO*)tvi.lParam)->path);
1434     }
1435
1436     globals.hTypeLibWnd = CreateWindow(wszTypeLib, wszTitle,
1437             WS_OVERLAPPEDWINDOW|WS_VISIBLE,
1438             CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL);
1439     if(!globals.hTypeLibWnd) return FALSE;
1440
1441     typelib.hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD,
1442             (LPWSTR)wszTitle, globals.hTypeLibWnd, 0);
1443
1444     TypeLibResizeChild();
1445     return TRUE;
1446 }