msvcp100: Don't bother to clean up at process exit.
[wine.git] / programs / oleview / tree.c
blob241c32c66f76ad56382d3dc59e063041c7566473
1 /*
2 * OleView (tree.c)
4 * Copyright 2006 Piotr Caban
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.
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.
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
21 #include "main.h"
23 TREE tree;
24 static const WCHAR wszCLSID[] = { 'C','L','S','I','D','\\','\0' };
25 static const WCHAR wszInProcServer32[] =
26 { 'I','n','P','r','o','c','S','e','r','v','e','r','3','2','\0' };
27 static const WCHAR wszOle32dll[] = { 'o','l','e','3','2','.','d','l','l','\0' };
28 static const WCHAR wszOleAut32dll[] =
29 { 'o','l','e','a','u','t','3','2','.','d','l','l','\0' };
30 static const WCHAR wszImplementedCategories[] =
31 { 'I','m','p','l','e','m','e','n','t','e','d',' ',
32 'C','a','t','e','g','o','r','i','e','s','\0' };
33 static const WCHAR wszAppID[] = { 'A','p','p','I','D','\\','\0' };
34 static const WCHAR wszTypeLib[] = { 'T','y','p','e','L','i','b','\\','\0' };
35 static const WCHAR wszInterface[] = { 'I','n','t','e','r','f','a','c','e','\\','\0' };
36 static const WCHAR wszComponentCategories[] = { 'C','o','m','p','o','n','e','n','t',
37 ' ','C','a','t','e','g','o','r','i','e','s','\\','\0' };
38 static const WCHAR wszGetPath[] = { '0','\\','w','i','n','3','2','\0' };
40 static LPARAM CreateITEM_INFO(INT flag, const WCHAR *info, const WCHAR *clsid, const WCHAR *path)
42 ITEM_INFO *reg;
44 reg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITEM_INFO));
46 reg->cFlag = flag;
47 lstrcpyW(reg->info, info);
48 if(clsid) lstrcpyW(reg->clsid, clsid);
49 if(path) lstrcpyW(reg->path, path);
51 return (LPARAM)reg;
54 void CreateInst(HTREEITEM item, WCHAR *wszMachineName)
56 TVITEMW tvi;
57 HTREEITEM hCur;
58 TVINSERTSTRUCTW tvis;
59 WCHAR wszTitle[MAX_LOAD_STRING];
60 WCHAR wszMessage[MAX_LOAD_STRING];
61 WCHAR wszFlagName[MAX_LOAD_STRING];
62 WCHAR wszTreeName[MAX_LOAD_STRING];
63 WCHAR wszRegPath[MAX_LOAD_STRING];
64 const WCHAR wszFormat[] = { '\n','%','s',' ','(','$','%','x',')','\n','\0' };
65 CLSID clsid;
66 COSERVERINFO remoteInfo;
67 MULTI_QI qi;
68 IUnknown *obj, *unk;
69 HRESULT hRes;
71 memset(&tvi, 0, sizeof(TVITEMW));
72 tvi.mask = TVIF_TEXT;
73 tvi.hItem = item;
74 tvi.cchTextMax = MAX_LOAD_STRING;
75 tvi.pszText = wszTreeName;
77 memset(&tvis, 0, sizeof(TVINSERTSTRUCTW));
78 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
79 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
80 tvis.hInsertAfter = TVI_FIRST;
81 U(tvis).item.pszText = tvi.pszText;
82 tvis.hParent = item;
83 tvis.hInsertAfter = TVI_LAST;
85 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
87 if(!tvi.lParam || ((ITEM_INFO *)tvi.lParam)->loaded
88 || !(((ITEM_INFO *)tvi.lParam)->cFlag&SHOWALL)) return;
90 if(FAILED(CLSIDFromString(((ITEM_INFO *)tvi.lParam)->clsid, &clsid))) return;
92 if(wszMachineName)
94 remoteInfo.dwReserved1 = 0;
95 remoteInfo.dwReserved2 = 0;
96 remoteInfo.pAuthInfo = NULL;
97 remoteInfo.pwszName = wszMachineName;
99 qi.pIID = &IID_IUnknown;
101 CoCreateInstanceEx(&clsid, NULL, globals.dwClsCtx|CLSCTX_REMOTE_SERVER,
102 &remoteInfo, 1, &qi);
103 hRes = qi.hr;
104 obj = qi.pItf;
106 else hRes = CoCreateInstance(&clsid, NULL, globals.dwClsCtx,
107 &IID_IUnknown, (void **)&obj);
109 if(FAILED(hRes))
111 LoadStringW(globals.hMainInst, IDS_CGCOFAIL, wszMessage,
112 sizeof(wszMessage)/sizeof(wszMessage[0]));
113 LoadStringW(globals.hMainInst, IDS_ABOUT, wszTitle,
114 sizeof(wszTitle)/sizeof(wszTitle[0]));
116 #define CASE_ERR(i) case i: \
117 MultiByteToWideChar(CP_ACP, 0, #i, -1, wszFlagName, MAX_LOAD_STRING); \
118 break
120 switch(hRes)
122 CASE_ERR(REGDB_E_CLASSNOTREG);
123 CASE_ERR(E_NOINTERFACE);
124 CASE_ERR(REGDB_E_READREGDB);
125 CASE_ERR(REGDB_E_KEYMISSING);
126 CASE_ERR(CO_E_DLLNOTFOUND);
127 CASE_ERR(CO_E_APPNOTFOUND);
128 CASE_ERR(E_ACCESSDENIED);
129 CASE_ERR(CO_E_ERRORINDLL);
130 CASE_ERR(CO_E_APPDIDNTREG);
131 CASE_ERR(CLASS_E_CLASSNOTAVAILABLE);
132 default:
133 LoadStringW(globals.hMainInst, IDS_ERROR_UNKN, wszFlagName, sizeof(wszFlagName)/sizeof(wszFlagName[0]));
136 wsprintfW(&wszMessage[lstrlenW(wszMessage)], wszFormat,
137 wszFlagName, (unsigned)hRes);
138 MessageBoxW(globals.hMainWnd, wszMessage, wszTitle, MB_OK|MB_ICONEXCLAMATION);
139 return;
142 ((ITEM_INFO *)tvi.lParam)->loaded = 1;
143 ((ITEM_INFO *)tvi.lParam)->pU = obj;
145 tvi.mask = TVIF_STATE;
146 tvi.state = TVIS_BOLD;
147 tvi.stateMask = TVIS_BOLD;
148 SendMessageW(globals.hTree, TVM_SETITEMW, 0, (LPARAM)&tvi);
150 tvi.mask = TVIF_TEXT;
151 hCur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
152 TVGN_CHILD, (LPARAM)tree.hI);
154 while(hCur)
156 tvi.hItem = hCur;
157 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
159 if(!tvi.lParam)
161 hCur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
162 TVGN_NEXT, (LPARAM)hCur);
163 continue;
166 CLSIDFromString(((ITEM_INFO *)tvi.lParam)->clsid, &clsid);
167 hRes = IUnknown_QueryInterface(obj, &clsid, (void *)&unk);
169 if(SUCCEEDED(hRes))
171 IUnknown_Release(unk);
173 lstrcpyW(wszRegPath, wszInterface);
174 lstrcpyW(&wszRegPath[lstrlenW(wszRegPath)], ((ITEM_INFO *)tvi.lParam)->clsid);
175 U(tvis).item.lParam = CreateITEM_INFO(REGTOP|INTERFACE|REGPATH,
176 wszRegPath, ((ITEM_INFO *)tvi.lParam)->clsid, NULL);
177 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
179 hCur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
180 TVGN_NEXT, (LPARAM)hCur);
183 RefreshMenu(item);
184 RefreshDetails(item);
187 void ReleaseInst(HTREEITEM item)
189 TVITEMW tvi;
190 HTREEITEM cur;
191 IUnknown *pU;
193 memset(&tvi, 0, sizeof(TVITEMW));
194 tvi.hItem = item;
195 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
197 if(!tvi.lParam) return;
199 pU = ((ITEM_INFO *)tvi.lParam)->pU;
201 if(pU) IUnknown_Release(pU);
202 ((ITEM_INFO *)tvi.lParam)->loaded = 0;
204 SendMessageW(globals.hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)item);
206 cur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
207 TVGN_CHILD, (LPARAM)item);
208 while(cur)
210 SendMessageW(globals.hTree, TVM_DELETEITEM, 0, (LPARAM)cur);
211 cur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
212 TVGN_CHILD, (LPARAM)item);
215 tvi.mask = TVIF_CHILDREN|TVIF_STATE;
216 tvi.state = 0;
217 tvi.stateMask = TVIS_BOLD;
218 tvi.cChildren = 1;
219 SendMessageW(globals.hTree, TVM_SETITEMW, 0, (LPARAM)&tvi);
222 BOOL CreateRegPath(HTREEITEM item, WCHAR *buffer, int bufSize)
224 TVITEMW tvi;
225 int bufLen;
226 BOOL ret;
228 memset(buffer, 0, sizeof(WCHAR[bufSize]));
229 memset(&tvi, 0, sizeof(TVITEMW));
230 tvi.hItem = item;
232 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
233 ret = (tvi.lParam && ((ITEM_INFO *)tvi.lParam)->cFlag & REGPATH);
235 while(TRUE)
237 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
239 if(tvi.lParam && (((ITEM_INFO *)tvi.lParam)->cFlag & (REGPATH|REGTOP)))
241 bufLen = lstrlenW(((ITEM_INFO *)tvi.lParam)->info);
242 memmove(&buffer[bufLen], buffer, sizeof(WCHAR[bufSize-bufLen]));
243 memcpy(buffer, ((ITEM_INFO *)tvi.lParam)->info, sizeof(WCHAR[bufLen]));
246 if(tvi.lParam && ((ITEM_INFO *)tvi.lParam)->cFlag & REGTOP) break;
248 if(!tvi.lParam) return FALSE;
250 tvi.hItem = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
251 TVGN_PARENT, (LPARAM)tvi.hItem);
253 return ret;
256 static void AddCOMandAll(void)
258 TVINSERTSTRUCTW tvis;
259 TVITEMW tvi;
260 HTREEITEM curSearch;
261 HKEY hKey, hCurKey, hInfo;
262 WCHAR valName[MAX_LOAD_STRING];
263 WCHAR buffer[MAX_LOAD_STRING];
264 WCHAR wszComp[MAX_LOAD_STRING];
265 LONG lenBuffer;
266 int i=-1;
268 memset(&tvi, 0, sizeof(TVITEMW));
269 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_CHILDREN;
270 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
271 U(tvis).item.cChildren = 1;
272 tvis.hInsertAfter = TVI_FIRST;
274 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszCLSID, &hKey) != ERROR_SUCCESS) return;
276 while(TRUE)
278 i++;
280 if(RegEnumKeyW(hKey, i, valName, sizeof(valName)/sizeof(valName[0])) != ERROR_SUCCESS) break;
282 if(RegOpenKeyW(hKey, valName, &hCurKey) != ERROR_SUCCESS) continue;
284 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
285 tvis.hParent = tree.hAO;
287 if(RegOpenKeyW(hCurKey, wszInProcServer32, &hInfo) == ERROR_SUCCESS)
289 if(RegQueryValueW(hInfo, NULL, buffer, &lenBuffer) == ERROR_SUCCESS
290 && *buffer)
291 if(!memcmp(buffer, wszOle32dll, sizeof(WCHAR[9]))
292 ||!memcmp(buffer, wszOleAut32dll, sizeof(WCHAR[12])))
293 tvis.hParent = tree.hCLO;
295 RegCloseKey(hInfo);
298 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
300 if(RegQueryValueW(hCurKey, NULL, buffer, &lenBuffer) == ERROR_SUCCESS && *buffer)
301 U(tvis).item.pszText = buffer;
302 else U(tvis).item.pszText = valName;
304 U(tvis).item.lParam = CreateITEM_INFO(REGPATH|SHOWALL, valName, valName, NULL);
305 if(tvis.hParent) SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
307 if(RegOpenKeyW(hCurKey, wszImplementedCategories, &hInfo) == ERROR_SUCCESS)
309 if(RegEnumKeyW(hInfo, 0, wszComp, sizeof(wszComp)/sizeof(wszComp[0])) != ERROR_SUCCESS) break;
311 RegCloseKey(hInfo);
313 if(tree.hGBCC) curSearch = (HTREEITEM)SendMessageW(globals.hTree,
314 TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)tree.hGBCC);
315 else curSearch = (HTREEITEM)SendMessageW(globals.hTree,
316 TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT);
318 while(curSearch)
320 tvi.hItem = curSearch;
321 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
323 if(tvi.lParam && !lstrcmpW(((ITEM_INFO *)tvi.lParam)->info, wszComp))
325 tvis.hParent = curSearch;
327 memmove(&valName[6], valName, sizeof(WCHAR[MAX_LOAD_STRING-6]));
328 memmove(valName, wszCLSID, sizeof(WCHAR[6]));
329 U(tvis).item.lParam = CreateITEM_INFO(REGTOP|REGPATH|SHOWALL,
330 valName, &valName[6], NULL);
332 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
333 break;
335 curSearch = (HTREEITEM)SendMessageW(globals.hTree,
336 TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)curSearch);
339 RegCloseKey(hCurKey);
341 RegCloseKey(hKey);
343 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hCLO);
344 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hAO);
347 static void AddApplicationID(void)
349 TVINSERTSTRUCTW tvis;
350 HKEY hKey, hCurKey;
351 WCHAR valName[MAX_LOAD_STRING];
352 WCHAR buffer[MAX_LOAD_STRING];
353 LONG lenBuffer;
354 int i=-1;
356 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
357 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
358 tvis.hInsertAfter = TVI_FIRST;
359 tvis.hParent = tree.hAID;
361 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszAppID, &hKey) != ERROR_SUCCESS) return;
363 while(TRUE)
365 i++;
367 if(RegEnumKeyW(hKey, i, valName, sizeof(valName)/sizeof(valName[0])) != ERROR_SUCCESS) break;
369 if(RegOpenKeyW(hKey, valName, &hCurKey) != ERROR_SUCCESS) continue;
371 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
373 if(RegQueryValueW(hCurKey, NULL, buffer, &lenBuffer) == ERROR_SUCCESS && *buffer)
374 U(tvis).item.pszText = buffer;
375 else U(tvis).item.pszText = valName;
377 RegCloseKey(hCurKey);
379 U(tvis).item.lParam = CreateITEM_INFO(REGPATH, valName, valName, NULL);
380 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
382 RegCloseKey(hKey);
384 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hAID);
387 static void AddTypeLib(void)
389 TVINSERTSTRUCTW tvis;
390 HKEY hKey, hCurKey, hInfoKey, hPath;
391 WCHAR valName[MAX_LOAD_STRING];
392 WCHAR valParent[MAX_LOAD_STRING];
393 WCHAR buffer[MAX_LOAD_STRING];
394 WCHAR wszVer[MAX_LOAD_STRING];
395 WCHAR wszPath[MAX_LOAD_STRING];
396 const WCHAR wszFormat[] = { ' ','(','%','s',' ','%','s',')','\0' };
397 const WCHAR wszFormat2[] = { '%','s','\\','%','s','\0' };
398 LONG lenBuffer;
399 int i=-1, j;
401 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
402 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
403 tvis.hInsertAfter = TVI_FIRST;
404 tvis.hParent = tree.hTL;
406 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszTypeLib, &hKey) != ERROR_SUCCESS) return;
408 while(TRUE)
410 i++;
412 if(RegEnumKeyW(hKey, i, valParent, sizeof(valParent)/sizeof(valParent[0])) != ERROR_SUCCESS) break;
414 if(RegOpenKeyW(hKey, valParent, &hCurKey) != ERROR_SUCCESS) continue;
416 j = -1;
417 while(TRUE)
419 j++;
421 if(RegEnumKeyW(hCurKey, j, valName, sizeof(valName)/sizeof(valName[0])) != ERROR_SUCCESS) break;
423 if(RegOpenKeyW(hCurKey, valName, &hInfoKey) != ERROR_SUCCESS) continue;
425 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
427 if(RegQueryValueW(hInfoKey, NULL, buffer, &lenBuffer) == ERROR_SUCCESS
428 && *buffer)
430 LoadStringW(globals.hMainInst, IDS_TL_VER, wszVer,
431 sizeof(wszVer)/sizeof(wszVer[0]));
433 wsprintfW(&buffer[lstrlenW(buffer)], wszFormat, wszVer, valName);
434 U(tvis).item.pszText = buffer;
436 lenBuffer = MAX_LOAD_STRING;
437 RegOpenKeyW(hInfoKey, wszGetPath, &hPath);
438 RegQueryValueW(hPath, NULL, wszPath, &lenBuffer);
439 RegCloseKey(hPath);
441 else U(tvis).item.pszText = valName;
443 RegCloseKey(hInfoKey);
445 wsprintfW(wszVer, wszFormat2, valParent, valName);
446 U(tvis).item.lParam = CreateITEM_INFO(REGPATH, wszVer, valParent, wszPath);
448 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
450 RegCloseKey(hCurKey);
453 RegCloseKey(hKey);
455 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hTL);
458 static void AddInterfaces(void)
460 TVINSERTSTRUCTW tvis;
461 HKEY hKey, hCurKey;
462 WCHAR valName[MAX_LOAD_STRING];
463 WCHAR buffer[MAX_LOAD_STRING];
464 LONG lenBuffer;
465 int i=-1;
467 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
468 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
469 tvis.hInsertAfter = TVI_FIRST;
470 tvis.hParent = tree.hI;
472 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszInterface, &hKey) != ERROR_SUCCESS) return;
474 while(TRUE)
476 i++;
478 if(RegEnumKeyW(hKey, i, valName, sizeof(valName)/sizeof(valName[0])) != ERROR_SUCCESS) break;
480 if(RegOpenKeyW(hKey, valName, &hCurKey) != ERROR_SUCCESS) continue;
482 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
484 if(RegQueryValueW(hCurKey, NULL, buffer, &lenBuffer) == ERROR_SUCCESS && *buffer)
485 U(tvis).item.pszText = buffer;
486 else U(tvis).item.pszText = valName;
488 RegCloseKey(hCurKey);
490 U(tvis).item.lParam = CreateITEM_INFO(REGPATH|INTERFACE, valName, valName, NULL);
491 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
494 RegCloseKey(hKey);
496 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hI);
499 static void AddComponentCategories(void)
501 TVINSERTSTRUCTW tvis;
502 HKEY hKey, hCurKey;
503 WCHAR valName[MAX_LOAD_STRING];
504 WCHAR buffer[MAX_LOAD_STRING];
505 LONG lenBuffer;
506 DWORD lenBufferHlp;
507 int i=-1;
509 U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_CHILDREN;
510 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
511 tvis.hInsertAfter = TVI_FIRST;
512 if(tree.hGBCC) tvis.hParent = tree.hGBCC;
513 else tvis.hParent = TVI_ROOT;
514 U(tvis).item.cChildren = 1;
516 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszComponentCategories, &hKey) != ERROR_SUCCESS)
517 return;
519 while(TRUE)
521 i++;
523 if(RegEnumKeyW(hKey, i, valName, sizeof(valName)/sizeof(valName[0])) != ERROR_SUCCESS) break;
525 if(RegOpenKeyW(hKey, valName, &hCurKey) != ERROR_SUCCESS) continue;
527 lenBuffer = sizeof(WCHAR[MAX_LOAD_STRING]);
528 lenBufferHlp = sizeof(WCHAR[MAX_LOAD_STRING]);
530 if(RegQueryValueW(hCurKey, NULL, buffer, &lenBuffer) == ERROR_SUCCESS && *buffer)
531 U(tvis).item.pszText = buffer;
532 else if(RegEnumValueW(hCurKey, 0, NULL, NULL, NULL, NULL,
533 (LPBYTE)buffer, &lenBufferHlp) == ERROR_SUCCESS && *buffer)
534 U(tvis).item.pszText = buffer;
535 else continue;
537 RegCloseKey(hCurKey);
539 U(tvis).item.lParam = CreateITEM_INFO(REGTOP, valName, valName, NULL);
540 SendMessageW(globals.hTree, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
543 RegCloseKey(hKey);
545 SendMessageW(globals.hTree, TVM_SORTCHILDREN, FALSE, (LPARAM)tree.hGBCC);
548 static void AddBaseEntries(void)
550 TVINSERTSTRUCTW tvis;
551 WCHAR name[MAX_LOAD_STRING];
553 U(tvis).item.mask = TVIF_TEXT|TVIF_CHILDREN|TVIF_PARAM;
554 /* FIXME add TVIF_IMAGE */
555 U(tvis).item.pszText = name;
556 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
557 U(tvis).item.cChildren = 1;
558 tvis.hInsertAfter = TVI_FIRST;
559 tvis.hParent = TVI_ROOT;
561 LoadStringW(globals.hMainInst, IDS_TREE_I, U(tvis).item.pszText,
562 MAX_LOAD_STRING);
563 U(tvis).item.lParam = CreateITEM_INFO(REGTOP, wszInterface, NULL, NULL);
564 tree.hI = TreeView_InsertItemW(globals.hTree, &tvis);
566 LoadStringW(globals.hMainInst, IDS_TREE_TL, U(tvis).item.pszText,
567 MAX_LOAD_STRING);
568 U(tvis).item.lParam = CreateITEM_INFO(REGTOP, wszTypeLib, NULL, NULL);
569 tree.hTL = TreeView_InsertItemW(globals.hTree, &tvis);
571 LoadStringW(globals.hMainInst, IDS_TREE_AID, U(tvis).item.pszText,
572 MAX_LOAD_STRING);
573 U(tvis).item.lParam = CreateITEM_INFO(REGTOP|REGPATH, wszAppID, NULL, NULL);
574 tree.hAID = TreeView_InsertItemW(globals.hTree, &tvis);
576 LoadStringW(globals.hMainInst, IDS_TREE_OC, U(tvis).item.pszText,
577 MAX_LOAD_STRING);
578 U(tvis).item.lParam = 0;
579 tree.hOC = TreeView_InsertItemW(globals.hTree, &tvis);
582 tvis.hParent = tree.hOC;
583 LoadStringW(globals.hMainInst, IDS_TREE_AO, U(tvis).item.pszText,
584 MAX_LOAD_STRING);
585 U(tvis).item.lParam = CreateITEM_INFO(REGTOP, wszCLSID, NULL, NULL);
586 tree.hAO = TreeView_InsertItemW(globals.hTree, &tvis);
588 LoadStringW(globals.hMainInst, IDS_TREE_CLO, U(tvis).item.pszText,
589 MAX_LOAD_STRING);
590 tree.hCLO = TreeView_InsertItemW(globals.hTree, &tvis);
592 LoadStringW(globals.hMainInst, IDS_TREE_O1O, U(tvis).item.pszText,
593 MAX_LOAD_STRING);
594 U(tvis).item.lParam = 0;
595 tree.hO1O = TreeView_InsertItemW(globals.hTree, &tvis);
597 LoadStringW(globals.hMainInst, IDS_TREE_GBCC, U(tvis).item.pszText,
598 MAX_LOAD_STRING);
599 U(tvis).item.lParam = CreateITEM_INFO(REGTOP|REGPATH,
600 wszComponentCategories, NULL, NULL);
601 tree.hGBCC = TreeView_InsertItemW(globals.hTree, &tvis);
603 SendMessageW(globals.hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)tree.hOC);
606 void EmptyTree(void)
608 HTREEITEM cur, del;
609 TVITEMW tvi;
611 tvi.mask = TVIF_PARAM;
612 cur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
613 TVGN_CHILD, (LPARAM)TVI_ROOT);
615 while(TRUE)
617 del = cur;
618 cur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
619 TVGN_CHILD, (LPARAM)del);
621 if(!cur) cur = (HTREEITEM)SendMessageW(globals.hTree,
622 TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)del);
623 if(!cur)
625 cur = (HTREEITEM)SendMessageW(globals.hTree, TVM_GETNEXTITEM,
626 TVGN_PREVIOUS, (LPARAM)del);
627 if(!cur) cur = (HTREEITEM)SendMessageW(globals.hTree,
628 TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)del);
630 tvi.hItem = del;
631 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
633 if(tvi.lParam)
635 if(((ITEM_INFO *)tvi.lParam)->loaded) ReleaseInst(del);
636 HeapFree(GetProcessHeap(), 0, (ITEM_INFO *)tvi.lParam);
639 SendMessageW(globals.hTree, TVM_DELETEITEM, 0, (LPARAM)del);
641 if(!cur) break;
646 void AddTreeEx(void)
648 AddBaseEntries();
649 AddComponentCategories();
650 AddCOMandAll();
651 AddApplicationID();
652 AddTypeLib();
653 AddInterfaces();
656 void AddTree(void)
658 memset(&tree, 0, sizeof(TREE));
659 AddComponentCategories();
660 AddCOMandAll();
663 static LRESULT CALLBACK TreeProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
665 switch(uMsg)
667 case WM_CREATE:
668 globals.hTree = CreateWindowW(WC_TREEVIEWW, NULL,
669 WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
670 0, 0, 0, 0, hWnd, (HMENU)TREE_WINDOW, globals.hMainInst, NULL);
671 AddTreeEx();
672 break;
673 case WM_NOTIFY:
674 if((int)wParam != TREE_WINDOW) break;
675 switch(((LPNMHDR)lParam)->code)
677 case TVN_ITEMEXPANDINGW:
678 CreateInst(((NMTREEVIEWW *)lParam)->itemNew.hItem, NULL);
679 break;
680 case TVN_SELCHANGEDW:
681 RefreshMenu(((NMTREEVIEWW *)lParam)->itemNew.hItem);
682 RefreshDetails(((NMTREEVIEWW *)lParam)->itemNew.hItem);
683 break;
685 break;
686 case WM_SIZE:
687 MoveWindow(globals.hTree, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
688 break;
689 default:
690 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
692 return 0;
695 HWND CreateTreeWindow(HINSTANCE hInst)
697 WNDCLASSW wct;
698 const WCHAR wszTreeClass[] = { 'T','R','E','E','\0' };
700 memset(&wct, 0, sizeof(WNDCLASSW));
701 wct.lpfnWndProc = TreeProc;
702 wct.lpszClassName = wszTreeClass;
704 if(!RegisterClassW(&wct)) return NULL;
706 return CreateWindowExW(WS_EX_CLIENTEDGE, wszTreeClass, NULL, WS_CHILD|WS_VISIBLE,
707 0, 0, 0, 0, globals.hPaneWnd, NULL, hInst, NULL);