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 if (!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
)) return;
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
, ARRAY_SIZE(wszMessage
));
112 LoadStringW(globals
.hMainInst
, IDS_ABOUT
, wszTitle
, ARRAY_SIZE(wszTitle
));
114 #define CASE_ERR(i) case i: \
115 MultiByteToWideChar(CP_ACP, 0, #i, -1, wszFlagName, MAX_LOAD_STRING); \
120 CASE_ERR(REGDB_E_CLASSNOTREG
);
121 CASE_ERR(E_NOINTERFACE
);
122 CASE_ERR(REGDB_E_READREGDB
);
123 CASE_ERR(REGDB_E_KEYMISSING
);
124 CASE_ERR(CO_E_DLLNOTFOUND
);
125 CASE_ERR(CO_E_APPNOTFOUND
);
126 CASE_ERR(E_ACCESSDENIED
);
127 CASE_ERR(CO_E_ERRORINDLL
);
128 CASE_ERR(CO_E_APPDIDNTREG
);
129 CASE_ERR(CLASS_E_CLASSNOTAVAILABLE
);
131 LoadStringW(globals
.hMainInst
, IDS_ERROR_UNKN
, wszFlagName
, ARRAY_SIZE(wszFlagName
));
134 wsprintfW(&wszMessage
[lstrlenW(wszMessage
)], wszFormat
,
135 wszFlagName
, (unsigned)hRes
);
136 MessageBoxW(globals
.hMainWnd
, wszMessage
, wszTitle
, MB_OK
|MB_ICONEXCLAMATION
);
140 ((ITEM_INFO
*)tvi
.lParam
)->loaded
= 1;
141 ((ITEM_INFO
*)tvi
.lParam
)->pU
= obj
;
143 tvi
.mask
= TVIF_STATE
;
144 tvi
.state
= TVIS_BOLD
;
145 tvi
.stateMask
= TVIS_BOLD
;
146 SendMessageW(globals
.hTree
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
148 tvi
.mask
= TVIF_TEXT
;
149 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
150 TVGN_CHILD
, (LPARAM
)tree
.hI
);
155 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
) || !tvi
.lParam
)
157 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
158 TVGN_NEXT
, (LPARAM
)hCur
);
162 CLSIDFromString(((ITEM_INFO
*)tvi
.lParam
)->clsid
, &clsid
);
163 hRes
= IUnknown_QueryInterface(obj
, &clsid
, (void *)&unk
);
167 IUnknown_Release(unk
);
169 lstrcpyW(wszRegPath
, wszInterface
);
170 lstrcpyW(&wszRegPath
[lstrlenW(wszRegPath
)], ((ITEM_INFO
*)tvi
.lParam
)->clsid
);
171 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|INTERFACE
|REGPATH
,
172 wszRegPath
, ((ITEM_INFO
*)tvi
.lParam
)->clsid
, NULL
);
173 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
175 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
176 TVGN_NEXT
, (LPARAM
)hCur
);
180 RefreshDetails(item
);
183 void ReleaseInst(HTREEITEM item
)
189 memset(&tvi
, 0, sizeof(TVITEMW
));
191 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
) || !tvi
.lParam
) return;
193 pU
= ((ITEM_INFO
*)tvi
.lParam
)->pU
;
195 if(pU
) IUnknown_Release(pU
);
196 ((ITEM_INFO
*)tvi
.lParam
)->loaded
= 0;
198 SendMessageW(globals
.hTree
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)item
);
200 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
201 TVGN_CHILD
, (LPARAM
)item
);
204 SendMessageW(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)cur
);
205 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
206 TVGN_CHILD
, (LPARAM
)item
);
209 tvi
.mask
= TVIF_CHILDREN
|TVIF_STATE
;
211 tvi
.stateMask
= TVIS_BOLD
;
213 SendMessageW(globals
.hTree
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
216 BOOL
CreateRegPath(HTREEITEM item
, WCHAR
*buffer
, int bufSize
)
222 memset(buffer
, 0, bufSize
* sizeof(WCHAR
));
223 memset(&tvi
, 0, sizeof(TVITEMW
));
226 if (SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
))
227 ret
= (tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGPATH
);
231 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
)) break;
233 if(tvi
.lParam
&& (((ITEM_INFO
*)tvi
.lParam
)->cFlag
& (REGPATH
|REGTOP
)))
235 bufLen
= lstrlenW(((ITEM_INFO
*)tvi
.lParam
)->info
);
236 memmove(&buffer
[bufLen
], buffer
, (bufSize
- bufLen
) * sizeof(WCHAR
));
237 memcpy(buffer
, ((ITEM_INFO
*)tvi
.lParam
)->info
, bufLen
* sizeof(WCHAR
));
240 if(tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGTOP
) break;
242 if(!tvi
.lParam
) return FALSE
;
244 tvi
.hItem
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
245 TVGN_PARENT
, (LPARAM
)tvi
.hItem
);
250 static void AddCOMandAll(void)
252 TVINSERTSTRUCTW tvis
;
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(TVITEMW
));
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(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszCLSID
, &hKey
) != ERROR_SUCCESS
) return;
274 if(RegEnumKeyW(hKey
, i
, valName
, ARRAY_SIZE(valName
)) != ERROR_SUCCESS
) break;
276 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
278 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
279 tvis
.hParent
= tree
.hAO
;
281 if(RegOpenKeyW(hCurKey
, wszInProcServer32
, &hInfo
) == ERROR_SUCCESS
)
283 if(RegQueryValueW(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(RegQueryValueW(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
) SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
301 if(RegOpenKeyW(hCurKey
, wszImplementedCategories
, &hInfo
) == ERROR_SUCCESS
)
303 if(RegEnumKeyW(hInfo
, 0, wszComp
, ARRAY_SIZE(wszComp
)) != ERROR_SUCCESS
) break;
307 if(tree
.hGBCC
) curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
308 TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)tree
.hGBCC
);
309 else curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
310 TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)TVI_ROOT
);
314 tvi
.hItem
= curSearch
;
315 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
)) break;
317 if(tvi
.lParam
&& !lstrcmpW(((ITEM_INFO
*)tvi
.lParam
)->info
, wszComp
))
319 tvis
.hParent
= curSearch
;
321 memmove(&valName
[6], valName
, sizeof(WCHAR
[MAX_LOAD_STRING
-6]));
322 memmove(valName
, wszCLSID
, sizeof(WCHAR
[6]));
323 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
|SHOWALL
,
324 valName
, &valName
[6], NULL
);
326 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
329 curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
330 TVM_GETNEXTITEM
, TVGN_NEXT
, (LPARAM
)curSearch
);
333 RegCloseKey(hCurKey
);
337 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hCLO
);
338 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAO
);
341 static void AddApplicationID(void)
343 TVINSERTSTRUCTW tvis
;
345 WCHAR valName
[MAX_LOAD_STRING
];
346 WCHAR buffer
[MAX_LOAD_STRING
];
350 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
351 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
352 tvis
.hInsertAfter
= TVI_FIRST
;
353 tvis
.hParent
= tree
.hAID
;
355 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszAppID
, &hKey
) != ERROR_SUCCESS
) return;
361 if(RegEnumKeyW(hKey
, i
, valName
, ARRAY_SIZE(valName
)) != ERROR_SUCCESS
) break;
363 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
365 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
367 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
368 U(tvis
).item
.pszText
= buffer
;
369 else U(tvis
).item
.pszText
= valName
;
371 RegCloseKey(hCurKey
);
373 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, valName
, valName
, NULL
);
374 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
378 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAID
);
381 static void AddTypeLib(void)
383 TVINSERTSTRUCTW tvis
;
384 HKEY hKey
, hCurKey
, hInfoKey
, hPath
;
385 WCHAR valName
[MAX_LOAD_STRING
];
386 WCHAR valParent
[MAX_LOAD_STRING
];
387 WCHAR buffer
[MAX_LOAD_STRING
];
388 WCHAR wszVer
[MAX_LOAD_STRING
];
389 WCHAR wszPath
[MAX_LOAD_STRING
];
390 const WCHAR wszFormat
[] = { ' ','(','%','s',' ','%','s',')','\0' };
391 const WCHAR wszFormat2
[] = { '%','s','\\','%','s','\0' };
395 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
396 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
397 tvis
.hInsertAfter
= TVI_FIRST
;
398 tvis
.hParent
= tree
.hTL
;
400 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszTypeLib
, &hKey
) != ERROR_SUCCESS
) return;
406 if(RegEnumKeyW(hKey
, i
, valParent
, ARRAY_SIZE(valParent
)) != ERROR_SUCCESS
) break;
408 if(RegOpenKeyW(hKey
, valParent
, &hCurKey
) != ERROR_SUCCESS
) continue;
415 if(RegEnumKeyW(hCurKey
, j
, valName
, ARRAY_SIZE(valName
)) != ERROR_SUCCESS
) break;
417 if(RegOpenKeyW(hCurKey
, valName
, &hInfoKey
) != ERROR_SUCCESS
) continue;
419 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
421 if(RegQueryValueW(hInfoKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
424 LoadStringW(globals
.hMainInst
, IDS_TL_VER
, wszVer
, ARRAY_SIZE(wszVer
));
426 wsprintfW(&buffer
[lstrlenW(buffer
)], wszFormat
, wszVer
, valName
);
427 U(tvis
).item
.pszText
= buffer
;
429 lenBuffer
= MAX_LOAD_STRING
;
430 RegOpenKeyW(hInfoKey
, wszGetPath
, &hPath
);
431 RegQueryValueW(hPath
, NULL
, wszPath
, &lenBuffer
);
434 else U(tvis
).item
.pszText
= valName
;
436 RegCloseKey(hInfoKey
);
438 wsprintfW(wszVer
, wszFormat2
, valParent
, valName
);
439 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, wszVer
, valParent
, wszPath
);
441 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
443 RegCloseKey(hCurKey
);
448 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hTL
);
451 static void AddInterfaces(void)
453 TVINSERTSTRUCTW tvis
;
455 WCHAR valName
[MAX_LOAD_STRING
];
456 WCHAR buffer
[MAX_LOAD_STRING
];
460 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
461 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
462 tvis
.hInsertAfter
= TVI_FIRST
;
463 tvis
.hParent
= tree
.hI
;
465 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszInterface
, &hKey
) != ERROR_SUCCESS
) return;
471 if(RegEnumKeyW(hKey
, i
, valName
, ARRAY_SIZE(valName
)) != ERROR_SUCCESS
) break;
473 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
475 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
477 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
478 U(tvis
).item
.pszText
= buffer
;
479 else U(tvis
).item
.pszText
= valName
;
481 RegCloseKey(hCurKey
);
483 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
|INTERFACE
, valName
, valName
, NULL
);
484 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
489 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hI
);
492 static void AddComponentCategories(void)
494 TVINSERTSTRUCTW tvis
;
496 WCHAR keyName
[MAX_LOAD_STRING
];
497 WCHAR valName
[MAX_LOAD_STRING
];
498 WCHAR buffer
[MAX_LOAD_STRING
];
504 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_CHILDREN
;
505 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
506 tvis
.hInsertAfter
= TVI_FIRST
;
507 if(tree
.hGBCC
) tvis
.hParent
= tree
.hGBCC
;
508 else tvis
.hParent
= TVI_ROOT
;
509 U(tvis
).item
.cChildren
= 1;
511 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszComponentCategories
, &hKey
) != ERROR_SUCCESS
)
518 if(RegEnumKeyW(hKey
, i
, keyName
, ARRAY_SIZE(keyName
)) != ERROR_SUCCESS
) break;
520 if(RegOpenKeyW(hKey
, keyName
, &hCurKey
) != ERROR_SUCCESS
) continue;
522 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
523 lenBufferHlp
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
524 lenValName
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
526 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
527 U(tvis
).item
.pszText
= buffer
;
528 else if(RegEnumValueW(hCurKey
, 0, valName
, &lenValName
, NULL
, NULL
,
529 (LPBYTE
)buffer
, &lenBufferHlp
) == ERROR_SUCCESS
&& *buffer
)
530 U(tvis
).item
.pszText
= buffer
;
533 RegCloseKey(hCurKey
);
535 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, keyName
, keyName
, NULL
);
536 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
541 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hGBCC
);
544 static void AddBaseEntries(void)
546 TVINSERTSTRUCTW tvis
;
547 WCHAR name
[MAX_LOAD_STRING
];
549 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_CHILDREN
|TVIF_PARAM
;
550 /* FIXME add TVIF_IMAGE */
551 U(tvis
).item
.pszText
= name
;
552 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
553 U(tvis
).item
.cChildren
= 1;
554 tvis
.hInsertAfter
= TVI_FIRST
;
555 tvis
.hParent
= TVI_ROOT
;
557 LoadStringW(globals
.hMainInst
, IDS_TREE_I
, U(tvis
).item
.pszText
,
559 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszInterface
, NULL
, NULL
);
560 tree
.hI
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
562 LoadStringW(globals
.hMainInst
, IDS_TREE_TL
, U(tvis
).item
.pszText
,
564 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszTypeLib
, NULL
, NULL
);
565 tree
.hTL
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
567 LoadStringW(globals
.hMainInst
, IDS_TREE_AID
, U(tvis
).item
.pszText
,
569 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
, wszAppID
, NULL
, NULL
);
570 tree
.hAID
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
572 LoadStringW(globals
.hMainInst
, IDS_TREE_OC
, U(tvis
).item
.pszText
,
574 U(tvis
).item
.lParam
= 0;
575 tree
.hOC
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
578 tvis
.hParent
= tree
.hOC
;
579 LoadStringW(globals
.hMainInst
, IDS_TREE_AO
, U(tvis
).item
.pszText
,
581 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszCLSID
, NULL
, NULL
);
582 tree
.hAO
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
584 LoadStringW(globals
.hMainInst
, IDS_TREE_CLO
, U(tvis
).item
.pszText
,
586 tree
.hCLO
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
588 LoadStringW(globals
.hMainInst
, IDS_TREE_O1O
, U(tvis
).item
.pszText
,
590 U(tvis
).item
.lParam
= 0;
591 tree
.hO1O
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
593 LoadStringW(globals
.hMainInst
, IDS_TREE_GBCC
, U(tvis
).item
.pszText
,
595 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
,
596 wszComponentCategories
, NULL
, NULL
);
597 tree
.hGBCC
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
599 SendMessageW(globals
.hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)tree
.hOC
);
604 SendMessageW(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
610 AddComponentCategories();
619 memset(&tree
, 0, sizeof(TREE
));
620 AddComponentCategories();
624 static LRESULT CALLBACK
TreeProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
629 globals
.hTree
= CreateWindowW(WC_TREEVIEWW
, NULL
,
630 WS_CHILD
|WS_VISIBLE
|TVS_HASLINES
|TVS_HASBUTTONS
|TVS_LINESATROOT
,
631 0, 0, 0, 0, hWnd
, (HMENU
)TREE_WINDOW
, globals
.hMainInst
, NULL
);
635 if((int)wParam
!= TREE_WINDOW
) break;
636 switch(((LPNMHDR
)lParam
)->code
)
638 case TVN_ITEMEXPANDINGW
:
639 CreateInst(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
, NULL
);
641 case TVN_SELCHANGEDW
:
642 RefreshMenu(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
643 RefreshDetails(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
645 case TVN_DELETEITEMW
:
647 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lParam
;
648 ITEM_INFO
*info
= (ITEM_INFO
*)nm
->itemOld
.lParam
;
653 ReleaseInst(nm
->itemOld
.hItem
);
654 HeapFree(GetProcessHeap(), 0, info
);
661 MoveWindow(globals
.hTree
, 0, 0, LOWORD(lParam
), HIWORD(lParam
), TRUE
);
664 return DefWindowProcW(hWnd
, uMsg
, wParam
, lParam
);
669 HWND
CreateTreeWindow(HINSTANCE hInst
)
672 const WCHAR wszTreeClass
[] = { 'T','R','E','E','\0' };
674 memset(&wct
, 0, sizeof(WNDCLASSW
));
675 wct
.lpfnWndProc
= TreeProc
;
676 wct
.lpszClassName
= wszTreeClass
;
677 wct
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
678 wct
.hCursor
= LoadCursorW(0, (LPCWSTR
)IDC_ARROW
);
680 if(!RegisterClassW(&wct
)) return NULL
;
682 return CreateWindowExW(WS_EX_CLIENTEDGE
, wszTreeClass
, NULL
, WS_CHILD
|WS_VISIBLE
,
683 0, 0, 0, 0, globals
.hPaneWnd
, NULL
, hInst
, NULL
);