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(TVITEMW
));
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
;
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;
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 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); \
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 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
);
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
);
157 SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
161 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
162 TVGN_NEXT
, (LPARAM
)hCur
);
166 CLSIDFromString(((ITEM_INFO
*)tvi
.lParam
)->clsid
, &clsid
);
167 hRes
= IUnknown_QueryInterface(obj
, &clsid
, (void *)&unk
);
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
);
184 RefreshDetails(item
);
187 void ReleaseInst(HTREEITEM item
)
193 memset(&tvi
, 0, sizeof(TVITEMW
));
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
);
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
;
217 tvi
.stateMask
= TVIS_BOLD
;
219 SendMessageW(globals
.hTree
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
222 BOOL
CreateRegPath(HTREEITEM item
, WCHAR
*buffer
, int bufSize
)
228 memset(buffer
, 0, bufSize
* sizeof(WCHAR
));
229 memset(&tvi
, 0, sizeof(TVITEMW
));
232 SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
233 ret
= (tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGPATH
);
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
, (bufSize
- bufLen
) * sizeof(WCHAR
));
243 memcpy(buffer
, ((ITEM_INFO
*)tvi
.lParam
)->info
, bufLen
* sizeof(WCHAR
));
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
);
256 static void AddCOMandAll(void)
258 TVINSERTSTRUCTW tvis
;
261 HKEY hKey
, hCurKey
, hInfo
;
262 WCHAR valName
[MAX_LOAD_STRING
];
263 WCHAR buffer
[MAX_LOAD_STRING
];
264 WCHAR wszComp
[MAX_LOAD_STRING
];
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;
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
291 if(!memcmp(buffer
, wszOle32dll
, sizeof(WCHAR
[9]))
292 ||!memcmp(buffer
, wszOleAut32dll
, sizeof(WCHAR
[12])))
293 tvis
.hParent
= tree
.hCLO
;
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;
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
);
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
);
335 curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
336 TVM_GETNEXTITEM
, TVGN_NEXT
, (LPARAM
)curSearch
);
339 RegCloseKey(hCurKey
);
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
;
351 WCHAR valName
[MAX_LOAD_STRING
];
352 WCHAR buffer
[MAX_LOAD_STRING
];
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;
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
);
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' };
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;
412 if(RegEnumKeyW(hKey
, i
, valParent
, sizeof(valParent
)/sizeof(valParent
[0])) != ERROR_SUCCESS
) break;
414 if(RegOpenKeyW(hKey
, valParent
, &hCurKey
) != ERROR_SUCCESS
) continue;
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
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
);
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
);
455 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hTL
);
458 static void AddInterfaces(void)
460 TVINSERTSTRUCTW tvis
;
462 WCHAR valName
[MAX_LOAD_STRING
];
463 WCHAR buffer
[MAX_LOAD_STRING
];
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;
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
);
496 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hI
);
499 static void AddComponentCategories(void)
501 TVINSERTSTRUCTW tvis
;
503 WCHAR valName
[MAX_LOAD_STRING
];
504 WCHAR buffer
[MAX_LOAD_STRING
];
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
)
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
;
537 RegCloseKey(hCurKey
);
539 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, valName
, valName
, NULL
);
540 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
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
,
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
,
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
,
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
,
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
,
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
,
590 tree
.hCLO
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
592 LoadStringW(globals
.hMainInst
, IDS_TREE_O1O
, U(tvis
).item
.pszText
,
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
,
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
);
611 tvi
.mask
= TVIF_PARAM
;
612 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
613 TVGN_CHILD
, (LPARAM
)TVI_ROOT
);
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
);
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
);
631 SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
);
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
);
649 AddComponentCategories();
658 memset(&tree
, 0, sizeof(TREE
));
659 AddComponentCategories();
663 static LRESULT CALLBACK
TreeProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
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
);
674 if((int)wParam
!= TREE_WINDOW
) break;
675 switch(((LPNMHDR
)lParam
)->code
)
677 case TVN_ITEMEXPANDINGW
:
678 CreateInst(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
, NULL
);
680 case TVN_SELCHANGEDW
:
681 RefreshMenu(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
682 RefreshDetails(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
687 MoveWindow(globals
.hTree
, 0, 0, LOWORD(lParam
), HIWORD(lParam
), TRUE
);
690 return DefWindowProcW(hWnd
, uMsg
, wParam
, lParam
);
695 HWND
CreateTreeWindow(HINSTANCE hInst
)
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
);