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
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
)
44 reg
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ITEM_INFO
));
47 lstrcpyW(reg
->info
, info
);
48 if(clsid
) lstrcpyW(reg
->clsid
, clsid
);
49 if(path
) lstrcpyW(reg
->path
, path
);
54 void CreateInst(HTREEITEM item
, WCHAR
*wszMachineName
)
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' };
66 COSERVERINFO remoteInfo
;
71 memset(&tvi
, 0, sizeof(TVITEM
));
74 tvi
.cchTextMax
= MAX_LOAD_STRING
;
75 tvi
.pszText
= wszTreeName
;
77 memset(&tvis
, 0, sizeof(TVINSERTSTRUCT
));
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
;
83 tvis
.hInsertAfter
= TVI_LAST
;
85 SendMessage(globals
.hTree
, TVM_GETITEM
, 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;
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
);
106 else hRes
= CoCreateInstance(&clsid
, NULL
, globals
.dwClsCtx
,
107 &IID_IUnknown
, (void **)&obj
);
111 LoadString(globals
.hMainInst
, IDS_CGCOFAIL
, wszMessage
,
112 sizeof(wszMessage
)/sizeof(wszMessage
[0]));
113 LoadString(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); \
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
);
133 LoadString(globals
.hMainInst
, IDS_ERROR_UNKN
, wszFlagName
, sizeof(wszFlagName
)/sizeof(wszFlagName
[0]));
136 wsprintfW(&wszMessage
[lstrlenW(wszMessage
)], wszFormat
,
137 wszFlagName
, (unsigned)hRes
);
138 MessageBox(globals
.hMainWnd
, wszMessage
, wszTitle
, MB_OK
|MB_ICONEXCLAMATION
);
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 SendMessage(globals
.hTree
, TVM_SETITEM
, 0, (LPARAM
)&tvi
);
150 tvi
.mask
= TVIF_TEXT
;
151 hCur
= TreeView_GetChild(globals
.hTree
, tree
.hI
);
156 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
160 hCur
= TreeView_GetNextSibling(globals
.hTree
, hCur
);
164 CLSIDFromString(((ITEM_INFO
*)tvi
.lParam
)->clsid
, &clsid
);
165 hRes
= IUnknown_QueryInterface(obj
, &clsid
, (void *)&unk
);
169 IUnknown_Release(unk
);
171 lstrcpyW(wszRegPath
, wszInterface
);
172 lstrcpyW(&wszRegPath
[lstrlenW(wszRegPath
)], ((ITEM_INFO
*)tvi
.lParam
)->clsid
);
173 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|INTERFACE
|REGPATH
,
174 wszRegPath
, ((ITEM_INFO
*)tvi
.lParam
)->clsid
, NULL
);
175 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
177 hCur
= TreeView_GetNextSibling(globals
.hTree
, hCur
);
181 RefreshDetails(item
);
184 void ReleaseInst(HTREEITEM item
)
190 memset(&tvi
, 0, sizeof(TVITEM
));
192 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
194 if(!tvi
.lParam
) return;
196 pU
= ((ITEM_INFO
*)tvi
.lParam
)->pU
;
198 if(pU
) IUnknown_Release(pU
);
199 ((ITEM_INFO
*)tvi
.lParam
)->loaded
= 0;
201 SendMessage(globals
.hTree
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)item
);
203 cur
= TreeView_GetChild(globals
.hTree
, item
);
206 SendMessage(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)cur
);
207 cur
= TreeView_GetChild(globals
.hTree
, item
);
210 tvi
.mask
= TVIF_CHILDREN
|TVIF_STATE
;
212 tvi
.stateMask
= TVIS_BOLD
;
214 SendMessage(globals
.hTree
, TVM_SETITEM
, 0, (LPARAM
)&tvi
);
217 BOOL
CreateRegPath(HTREEITEM item
, WCHAR
*buffer
, int bufSize
)
223 memset(buffer
, 0, sizeof(WCHAR
[bufSize
]));
224 memset(&tvi
, 0, sizeof(TVITEM
));
227 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
228 ret
= (tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGPATH
);
232 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
234 if(tvi
.lParam
&& (((ITEM_INFO
*)tvi
.lParam
)->cFlag
& (REGPATH
|REGTOP
)))
236 bufLen
= lstrlenW(((ITEM_INFO
*)tvi
.lParam
)->info
);
237 memmove(&buffer
[bufLen
], buffer
, sizeof(WCHAR
[bufSize
-bufLen
]));
238 memcpy(buffer
, ((ITEM_INFO
*)tvi
.lParam
)->info
, sizeof(WCHAR
[bufLen
]));
241 if(tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGTOP
) break;
243 if(!tvi
.lParam
) return FALSE
;
245 tvi
.hItem
= TreeView_GetParent(globals
.hTree
, tvi
.hItem
);
250 static void AddCOMandAll(void)
255 HKEY hKey
, hCurKey
, hInfo
;
256 WCHAR valName
[MAX_LOAD_STRING
];
257 WCHAR buffer
[MAX_LOAD_STRING
];
258 WCHAR wszComp
[MAX_LOAD_STRING
];
262 memset(&tvi
, 0, sizeof(TVITEM
));
263 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_CHILDREN
;
264 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
265 U(tvis
).item
.cChildren
= 1;
266 tvis
.hInsertAfter
= TVI_FIRST
;
268 if(RegOpenKey(HKEY_CLASSES_ROOT
, wszCLSID
, &hKey
) != ERROR_SUCCESS
) return;
274 if(RegEnumKey(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
276 if(RegOpenKey(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
278 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
279 tvis
.hParent
= tree
.hAO
;
281 if(RegOpenKey(hCurKey
, wszInProcServer32
, &hInfo
) == ERROR_SUCCESS
)
283 if(RegQueryValue(hInfo
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
285 if(!memcmp(buffer
, wszOle32dll
, sizeof(WCHAR
[9]))
286 ||!memcmp(buffer
, wszOleAut32dll
, sizeof(WCHAR
[12])))
287 tvis
.hParent
= tree
.hCLO
;
292 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
294 if(RegQueryValue(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
295 U(tvis
).item
.pszText
= buffer
;
296 else U(tvis
).item
.pszText
= valName
;
298 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
|SHOWALL
, valName
, valName
, NULL
);
299 if(tvis
.hParent
) SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
301 if(RegOpenKey(hCurKey
, wszImplementedCategories
, &hInfo
) == ERROR_SUCCESS
)
303 if(RegEnumKey(hInfo
, 0, wszComp
, sizeof(wszComp
)/sizeof(wszComp
[0])) != ERROR_SUCCESS
) break;
307 if(tree
.hGBCC
) curSearch
= TreeView_GetChild(globals
.hTree
, tree
.hGBCC
);
308 else curSearch
= TreeView_GetChild(globals
.hTree
, TVI_ROOT
);
312 tvi
.hItem
= curSearch
;
313 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
315 if(tvi
.lParam
&& !lstrcmpW(((ITEM_INFO
*)tvi
.lParam
)->info
, wszComp
))
317 tvis
.hParent
= curSearch
;
319 memmove(&valName
[6], valName
, sizeof(WCHAR
[MAX_LOAD_STRING
-6]));
320 memmove(valName
, wszCLSID
, sizeof(WCHAR
[6]));
321 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
|SHOWALL
,
322 valName
, &valName
[6], NULL
);
324 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
327 curSearch
= TreeView_GetNextSibling(globals
.hTree
, curSearch
);
330 RegCloseKey(hCurKey
);
334 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hCLO
);
335 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAO
);
338 static void AddApplicationID(void)
342 WCHAR valName
[MAX_LOAD_STRING
];
343 WCHAR buffer
[MAX_LOAD_STRING
];
347 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
348 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
349 tvis
.hInsertAfter
= TVI_FIRST
;
350 tvis
.hParent
= tree
.hAID
;
352 if(RegOpenKey(HKEY_CLASSES_ROOT
, wszAppID
, &hKey
) != ERROR_SUCCESS
) return;
358 if(RegEnumKey(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
360 if(RegOpenKey(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
362 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
364 if(RegQueryValue(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
365 U(tvis
).item
.pszText
= buffer
;
366 else U(tvis
).item
.pszText
= valName
;
368 RegCloseKey(hCurKey
);
370 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, valName
, valName
, NULL
);
371 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
375 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAID
);
378 static void AddTypeLib(void)
381 HKEY hKey
, hCurKey
, hInfoKey
, hPath
;
382 WCHAR valName
[MAX_LOAD_STRING
];
383 WCHAR valParent
[MAX_LOAD_STRING
];
384 WCHAR buffer
[MAX_LOAD_STRING
];
385 WCHAR wszVer
[MAX_LOAD_STRING
];
386 WCHAR wszPath
[MAX_LOAD_STRING
];
387 const WCHAR wszFormat
[] = { ' ','(','%','s',' ','%','s',')','\0' };
388 const WCHAR wszFormat2
[] = { '%','s','\\','%','s','\0' };
392 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
393 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
394 tvis
.hInsertAfter
= TVI_FIRST
;
395 tvis
.hParent
= tree
.hTL
;
397 if(RegOpenKey(HKEY_CLASSES_ROOT
, wszTypeLib
, &hKey
) != ERROR_SUCCESS
) return;
403 if(RegEnumKey(hKey
, i
, valParent
, sizeof(valParent
)/sizeof(valParent
[0])) != ERROR_SUCCESS
) break;
405 if(RegOpenKey(hKey
, valParent
, &hCurKey
) != ERROR_SUCCESS
) continue;
412 if(RegEnumKey(hCurKey
, j
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
414 if(RegOpenKey(hCurKey
, valName
, &hInfoKey
) != ERROR_SUCCESS
) continue;
416 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
418 if(RegQueryValue(hInfoKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
421 LoadString(globals
.hMainInst
, IDS_TL_VER
, wszVer
,
422 sizeof(wszVer
)/sizeof(wszVer
[0]));
424 wsprintfW(&buffer
[lstrlenW(buffer
)], wszFormat
, wszVer
, valName
);
425 U(tvis
).item
.pszText
= buffer
;
427 lenBuffer
= MAX_LOAD_STRING
;
428 RegOpenKey(hInfoKey
, wszGetPath
, &hPath
);
429 RegQueryValue(hPath
, NULL
, wszPath
, &lenBuffer
);
432 else U(tvis
).item
.pszText
= valName
;
434 RegCloseKey(hInfoKey
);
436 wsprintfW(wszVer
, wszFormat2
, valParent
, valName
);
437 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, wszVer
, valParent
, wszPath
);
439 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
441 RegCloseKey(hCurKey
);
446 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hTL
);
449 static void AddInterfaces(void)
453 WCHAR valName
[MAX_LOAD_STRING
];
454 WCHAR buffer
[MAX_LOAD_STRING
];
458 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
459 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
460 tvis
.hInsertAfter
= TVI_FIRST
;
461 tvis
.hParent
= tree
.hI
;
463 if(RegOpenKey(HKEY_CLASSES_ROOT
, wszInterface
, &hKey
) != ERROR_SUCCESS
) return;
469 if(RegEnumKey(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
471 if(RegOpenKey(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
473 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
475 if(RegQueryValue(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
476 U(tvis
).item
.pszText
= buffer
;
477 else U(tvis
).item
.pszText
= valName
;
479 RegCloseKey(hCurKey
);
481 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
|INTERFACE
, valName
, valName
, NULL
);
482 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
487 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hI
);
490 static void AddComponentCategories(void)
494 WCHAR valName
[MAX_LOAD_STRING
];
495 WCHAR buffer
[MAX_LOAD_STRING
];
500 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_CHILDREN
;
501 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
502 tvis
.hInsertAfter
= TVI_FIRST
;
503 if(tree
.hGBCC
) tvis
.hParent
= tree
.hGBCC
;
504 else tvis
.hParent
= TVI_ROOT
;
505 U(tvis
).item
.cChildren
= 1;
507 if(RegOpenKey(HKEY_CLASSES_ROOT
, wszComponentCategories
, &hKey
) != ERROR_SUCCESS
)
514 if(RegEnumKey(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
516 if(RegOpenKey(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
518 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
519 lenBufferHlp
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
521 if(RegQueryValue(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
522 U(tvis
).item
.pszText
= buffer
;
523 else if(RegEnumValue(hCurKey
, 0, NULL
, NULL
, NULL
, NULL
,
524 (LPBYTE
)buffer
, &lenBufferHlp
) == ERROR_SUCCESS
&& *buffer
)
525 U(tvis
).item
.pszText
= buffer
;
528 RegCloseKey(hCurKey
);
530 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, valName
, valName
, NULL
);
531 SendMessage(globals
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
536 SendMessage(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hGBCC
);
539 static void AddBaseEntries(void)
542 WCHAR name
[MAX_LOAD_STRING
];
544 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_CHILDREN
|TVIF_PARAM
;
545 /* FIXME add TVIF_IMAGE */
546 U(tvis
).item
.pszText
= name
;
547 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
548 U(tvis
).item
.cChildren
= 1;
549 tvis
.hInsertAfter
= TVI_FIRST
;
550 tvis
.hParent
= TVI_ROOT
;
552 LoadString(globals
.hMainInst
, IDS_TREE_I
, U(tvis
).item
.pszText
,
554 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszInterface
, NULL
, NULL
);
555 tree
.hI
= TreeView_InsertItem(globals
.hTree
, &tvis
);
557 LoadString(globals
.hMainInst
, IDS_TREE_TL
, U(tvis
).item
.pszText
,
559 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszTypeLib
, NULL
, NULL
);
560 tree
.hTL
= TreeView_InsertItem(globals
.hTree
, &tvis
);
562 LoadString(globals
.hMainInst
, IDS_TREE_AID
, U(tvis
).item
.pszText
,
564 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
, wszAppID
, NULL
, NULL
);
565 tree
.hAID
= TreeView_InsertItem(globals
.hTree
, &tvis
);
567 LoadString(globals
.hMainInst
, IDS_TREE_OC
, U(tvis
).item
.pszText
,
569 U(tvis
).item
.lParam
= 0;
570 tree
.hOC
= TreeView_InsertItem(globals
.hTree
, &tvis
);
573 tvis
.hParent
= tree
.hOC
;
574 LoadString(globals
.hMainInst
, IDS_TREE_AO
, U(tvis
).item
.pszText
,
576 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszCLSID
, NULL
, NULL
);
577 tree
.hAO
= TreeView_InsertItem(globals
.hTree
, &tvis
);
579 LoadString(globals
.hMainInst
, IDS_TREE_CLO
, U(tvis
).item
.pszText
,
581 tree
.hCLO
= TreeView_InsertItem(globals
.hTree
, &tvis
);
583 LoadString(globals
.hMainInst
, IDS_TREE_O1O
, U(tvis
).item
.pszText
,
585 U(tvis
).item
.lParam
= 0;
586 tree
.hO1O
= TreeView_InsertItem(globals
.hTree
, &tvis
);
588 LoadString(globals
.hMainInst
, IDS_TREE_GBCC
, U(tvis
).item
.pszText
,
590 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
,
591 wszComponentCategories
, NULL
, NULL
);
592 tree
.hGBCC
= TreeView_InsertItem(globals
.hTree
, &tvis
);
594 SendMessage(globals
.hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)tree
.hOC
);
602 tvi
.mask
= TVIF_PARAM
;
603 cur
= TreeView_GetChild(globals
.hTree
, TVI_ROOT
);
608 cur
= TreeView_GetChild(globals
.hTree
, del
);
610 if(!cur
) cur
= TreeView_GetNextSibling(globals
.hTree
, del
);
613 cur
= TreeView_GetPrevSibling(globals
.hTree
, del
);
614 if(!cur
) cur
= TreeView_GetParent(globals
.hTree
, del
);
617 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
621 if(((ITEM_INFO
*)tvi
.lParam
)->loaded
) ReleaseInst(del
);
622 HeapFree(GetProcessHeap(), 0, (ITEM_INFO
*)tvi
.lParam
);
625 SendMessage(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)del
);
635 AddComponentCategories();
644 memset(&tree
, 0, sizeof(TREE
));
645 AddComponentCategories();
649 static LRESULT CALLBACK
TreeProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
654 globals
.hTree
= CreateWindow(WC_TREEVIEW
, NULL
,
655 WS_CHILD
|WS_VISIBLE
|TVS_HASLINES
|TVS_HASBUTTONS
|TVS_LINESATROOT
,
656 0, 0, 0, 0, hWnd
, (HMENU
)TREE_WINDOW
, globals
.hMainInst
, NULL
);
660 if((int)wParam
!= TREE_WINDOW
) break;
661 switch(((LPNMHDR
)lParam
)->code
)
663 case TVN_ITEMEXPANDING
:
664 CreateInst(((NMTREEVIEW
*)lParam
)->itemNew
.hItem
, NULL
);
667 RefreshMenu(((NMTREEVIEW
*)lParam
)->itemNew
.hItem
);
668 RefreshDetails(((NMTREEVIEW
*)lParam
)->itemNew
.hItem
);
673 MoveWindow(globals
.hTree
, 0, 0, LOWORD(lParam
), HIWORD(lParam
), TRUE
);
676 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
681 HWND
CreateTreeWindow(HINSTANCE hInst
)
684 const WCHAR wszTreeClass
[] = { 'T','R','E','E','\0' };
686 memset(&wct
, 0, sizeof(WNDCLASS
));
687 wct
.lpfnWndProc
= TreeProc
;
688 wct
.lpszClassName
= wszTreeClass
;
690 if(!RegisterClass(&wct
)) return NULL
;
692 return CreateWindowEx(WS_EX_CLIENTEDGE
, wszTreeClass
, NULL
, WS_CHILD
|WS_VISIBLE
,
693 0, 0, 0, 0, globals
.hPaneWnd
, NULL
, hInst
, NULL
);