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
,
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 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
) || !tvi
.lParam
)
159 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
160 TVGN_NEXT
, (LPARAM
)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 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
177 hCur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
178 TVGN_NEXT
, (LPARAM
)hCur
);
182 RefreshDetails(item
);
185 void ReleaseInst(HTREEITEM item
)
191 memset(&tvi
, 0, sizeof(TVITEMW
));
193 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
) || !tvi
.lParam
) return;
195 pU
= ((ITEM_INFO
*)tvi
.lParam
)->pU
;
197 if(pU
) IUnknown_Release(pU
);
198 ((ITEM_INFO
*)tvi
.lParam
)->loaded
= 0;
200 SendMessageW(globals
.hTree
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)item
);
202 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
203 TVGN_CHILD
, (LPARAM
)item
);
206 SendMessageW(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)cur
);
207 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
208 TVGN_CHILD
, (LPARAM
)item
);
211 tvi
.mask
= TVIF_CHILDREN
|TVIF_STATE
;
213 tvi
.stateMask
= TVIS_BOLD
;
215 SendMessageW(globals
.hTree
, TVM_SETITEMW
, 0, (LPARAM
)&tvi
);
218 BOOL
CreateRegPath(HTREEITEM item
, WCHAR
*buffer
, int bufSize
)
224 memset(buffer
, 0, bufSize
* sizeof(WCHAR
));
225 memset(&tvi
, 0, sizeof(TVITEMW
));
228 if (SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
))
229 ret
= (tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGPATH
);
233 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
)) break;
235 if(tvi
.lParam
&& (((ITEM_INFO
*)tvi
.lParam
)->cFlag
& (REGPATH
|REGTOP
)))
237 bufLen
= lstrlenW(((ITEM_INFO
*)tvi
.lParam
)->info
);
238 memmove(&buffer
[bufLen
], buffer
, (bufSize
- bufLen
) * sizeof(WCHAR
));
239 memcpy(buffer
, ((ITEM_INFO
*)tvi
.lParam
)->info
, bufLen
* sizeof(WCHAR
));
242 if(tvi
.lParam
&& ((ITEM_INFO
*)tvi
.lParam
)->cFlag
& REGTOP
) break;
244 if(!tvi
.lParam
) return FALSE
;
246 tvi
.hItem
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
247 TVGN_PARENT
, (LPARAM
)tvi
.hItem
);
252 static void AddCOMandAll(void)
254 TVINSERTSTRUCTW tvis
;
257 HKEY hKey
, hCurKey
, hInfo
;
258 WCHAR valName
[MAX_LOAD_STRING
];
259 WCHAR buffer
[MAX_LOAD_STRING
];
260 WCHAR wszComp
[MAX_LOAD_STRING
];
264 memset(&tvi
, 0, sizeof(TVITEMW
));
265 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_CHILDREN
;
266 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
267 U(tvis
).item
.cChildren
= 1;
268 tvis
.hInsertAfter
= TVI_FIRST
;
270 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszCLSID
, &hKey
) != ERROR_SUCCESS
) return;
276 if(RegEnumKeyW(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
278 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
280 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
281 tvis
.hParent
= tree
.hAO
;
283 if(RegOpenKeyW(hCurKey
, wszInProcServer32
, &hInfo
) == ERROR_SUCCESS
)
285 if(RegQueryValueW(hInfo
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
287 if(!memcmp(buffer
, wszOle32dll
, sizeof(WCHAR
[9]))
288 ||!memcmp(buffer
, wszOleAut32dll
, sizeof(WCHAR
[12])))
289 tvis
.hParent
= tree
.hCLO
;
294 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
296 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
297 U(tvis
).item
.pszText
= buffer
;
298 else U(tvis
).item
.pszText
= valName
;
300 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
|SHOWALL
, valName
, valName
, NULL
);
301 if(tvis
.hParent
) SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
303 if(RegOpenKeyW(hCurKey
, wszImplementedCategories
, &hInfo
) == ERROR_SUCCESS
)
305 if(RegEnumKeyW(hInfo
, 0, wszComp
, sizeof(wszComp
)/sizeof(wszComp
[0])) != ERROR_SUCCESS
) break;
309 if(tree
.hGBCC
) curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
310 TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)tree
.hGBCC
);
311 else curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
312 TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)TVI_ROOT
);
316 tvi
.hItem
= curSearch
;
317 if(!SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
)) break;
319 if(tvi
.lParam
&& !lstrcmpW(((ITEM_INFO
*)tvi
.lParam
)->info
, wszComp
))
321 tvis
.hParent
= curSearch
;
323 memmove(&valName
[6], valName
, sizeof(WCHAR
[MAX_LOAD_STRING
-6]));
324 memmove(valName
, wszCLSID
, sizeof(WCHAR
[6]));
325 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
|SHOWALL
,
326 valName
, &valName
[6], NULL
);
328 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
331 curSearch
= (HTREEITEM
)SendMessageW(globals
.hTree
,
332 TVM_GETNEXTITEM
, TVGN_NEXT
, (LPARAM
)curSearch
);
335 RegCloseKey(hCurKey
);
339 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hCLO
);
340 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAO
);
343 static void AddApplicationID(void)
345 TVINSERTSTRUCTW tvis
;
347 WCHAR valName
[MAX_LOAD_STRING
];
348 WCHAR buffer
[MAX_LOAD_STRING
];
352 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
353 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
354 tvis
.hInsertAfter
= TVI_FIRST
;
355 tvis
.hParent
= tree
.hAID
;
357 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszAppID
, &hKey
) != ERROR_SUCCESS
) return;
363 if(RegEnumKeyW(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
365 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
367 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
369 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
370 U(tvis
).item
.pszText
= buffer
;
371 else U(tvis
).item
.pszText
= valName
;
373 RegCloseKey(hCurKey
);
375 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, valName
, valName
, NULL
);
376 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
380 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hAID
);
383 static void AddTypeLib(void)
385 TVINSERTSTRUCTW tvis
;
386 HKEY hKey
, hCurKey
, hInfoKey
, hPath
;
387 WCHAR valName
[MAX_LOAD_STRING
];
388 WCHAR valParent
[MAX_LOAD_STRING
];
389 WCHAR buffer
[MAX_LOAD_STRING
];
390 WCHAR wszVer
[MAX_LOAD_STRING
];
391 WCHAR wszPath
[MAX_LOAD_STRING
];
392 const WCHAR wszFormat
[] = { ' ','(','%','s',' ','%','s',')','\0' };
393 const WCHAR wszFormat2
[] = { '%','s','\\','%','s','\0' };
397 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
398 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
399 tvis
.hInsertAfter
= TVI_FIRST
;
400 tvis
.hParent
= tree
.hTL
;
402 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszTypeLib
, &hKey
) != ERROR_SUCCESS
) return;
408 if(RegEnumKeyW(hKey
, i
, valParent
, sizeof(valParent
)/sizeof(valParent
[0])) != ERROR_SUCCESS
) break;
410 if(RegOpenKeyW(hKey
, valParent
, &hCurKey
) != ERROR_SUCCESS
) continue;
417 if(RegEnumKeyW(hCurKey
, j
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
419 if(RegOpenKeyW(hCurKey
, valName
, &hInfoKey
) != ERROR_SUCCESS
) continue;
421 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
423 if(RegQueryValueW(hInfoKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
426 LoadStringW(globals
.hMainInst
, IDS_TL_VER
, wszVer
,
427 sizeof(wszVer
)/sizeof(wszVer
[0]));
429 wsprintfW(&buffer
[lstrlenW(buffer
)], wszFormat
, wszVer
, valName
);
430 U(tvis
).item
.pszText
= buffer
;
432 lenBuffer
= MAX_LOAD_STRING
;
433 RegOpenKeyW(hInfoKey
, wszGetPath
, &hPath
);
434 RegQueryValueW(hPath
, NULL
, wszPath
, &lenBuffer
);
437 else U(tvis
).item
.pszText
= valName
;
439 RegCloseKey(hInfoKey
);
441 wsprintfW(wszVer
, wszFormat2
, valParent
, valName
);
442 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
, wszVer
, valParent
, wszPath
);
444 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
446 RegCloseKey(hCurKey
);
451 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hTL
);
454 static void AddInterfaces(void)
456 TVINSERTSTRUCTW tvis
;
458 WCHAR valName
[MAX_LOAD_STRING
];
459 WCHAR buffer
[MAX_LOAD_STRING
];
463 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
464 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
465 tvis
.hInsertAfter
= TVI_FIRST
;
466 tvis
.hParent
= tree
.hI
;
468 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszInterface
, &hKey
) != ERROR_SUCCESS
) return;
474 if(RegEnumKeyW(hKey
, i
, valName
, sizeof(valName
)/sizeof(valName
[0])) != ERROR_SUCCESS
) break;
476 if(RegOpenKeyW(hKey
, valName
, &hCurKey
) != ERROR_SUCCESS
) continue;
478 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
480 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
481 U(tvis
).item
.pszText
= buffer
;
482 else U(tvis
).item
.pszText
= valName
;
484 RegCloseKey(hCurKey
);
486 U(tvis
).item
.lParam
= CreateITEM_INFO(REGPATH
|INTERFACE
, valName
, valName
, NULL
);
487 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
492 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hI
);
495 static void AddComponentCategories(void)
497 TVINSERTSTRUCTW tvis
;
499 WCHAR keyName
[MAX_LOAD_STRING
];
500 WCHAR valName
[MAX_LOAD_STRING
];
501 WCHAR buffer
[MAX_LOAD_STRING
];
507 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_CHILDREN
;
508 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
509 tvis
.hInsertAfter
= TVI_FIRST
;
510 if(tree
.hGBCC
) tvis
.hParent
= tree
.hGBCC
;
511 else tvis
.hParent
= TVI_ROOT
;
512 U(tvis
).item
.cChildren
= 1;
514 if(RegOpenKeyW(HKEY_CLASSES_ROOT
, wszComponentCategories
, &hKey
) != ERROR_SUCCESS
)
521 if(RegEnumKeyW(hKey
, i
, keyName
, sizeof(keyName
)/sizeof(keyName
[0])) != ERROR_SUCCESS
) break;
523 if(RegOpenKeyW(hKey
, keyName
, &hCurKey
) != ERROR_SUCCESS
) continue;
525 lenBuffer
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
526 lenBufferHlp
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
527 lenValName
= sizeof(WCHAR
[MAX_LOAD_STRING
]);
529 if(RegQueryValueW(hCurKey
, NULL
, buffer
, &lenBuffer
) == ERROR_SUCCESS
&& *buffer
)
530 U(tvis
).item
.pszText
= buffer
;
531 else if(RegEnumValueW(hCurKey
, 0, valName
, &lenValName
, NULL
, NULL
,
532 (LPBYTE
)buffer
, &lenBufferHlp
) == ERROR_SUCCESS
&& *buffer
)
533 U(tvis
).item
.pszText
= buffer
;
536 RegCloseKey(hCurKey
);
538 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, keyName
, keyName
, NULL
);
539 SendMessageW(globals
.hTree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
544 SendMessageW(globals
.hTree
, TVM_SORTCHILDREN
, FALSE
, (LPARAM
)tree
.hGBCC
);
547 static void AddBaseEntries(void)
549 TVINSERTSTRUCTW tvis
;
550 WCHAR name
[MAX_LOAD_STRING
];
552 U(tvis
).item
.mask
= TVIF_TEXT
|TVIF_CHILDREN
|TVIF_PARAM
;
553 /* FIXME add TVIF_IMAGE */
554 U(tvis
).item
.pszText
= name
;
555 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
556 U(tvis
).item
.cChildren
= 1;
557 tvis
.hInsertAfter
= TVI_FIRST
;
558 tvis
.hParent
= TVI_ROOT
;
560 LoadStringW(globals
.hMainInst
, IDS_TREE_I
, U(tvis
).item
.pszText
,
562 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszInterface
, NULL
, NULL
);
563 tree
.hI
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
565 LoadStringW(globals
.hMainInst
, IDS_TREE_TL
, U(tvis
).item
.pszText
,
567 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszTypeLib
, NULL
, NULL
);
568 tree
.hTL
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
570 LoadStringW(globals
.hMainInst
, IDS_TREE_AID
, U(tvis
).item
.pszText
,
572 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
, wszAppID
, NULL
, NULL
);
573 tree
.hAID
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
575 LoadStringW(globals
.hMainInst
, IDS_TREE_OC
, U(tvis
).item
.pszText
,
577 U(tvis
).item
.lParam
= 0;
578 tree
.hOC
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
581 tvis
.hParent
= tree
.hOC
;
582 LoadStringW(globals
.hMainInst
, IDS_TREE_AO
, U(tvis
).item
.pszText
,
584 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
, wszCLSID
, NULL
, NULL
);
585 tree
.hAO
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
587 LoadStringW(globals
.hMainInst
, IDS_TREE_CLO
, U(tvis
).item
.pszText
,
589 tree
.hCLO
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
591 LoadStringW(globals
.hMainInst
, IDS_TREE_O1O
, U(tvis
).item
.pszText
,
593 U(tvis
).item
.lParam
= 0;
594 tree
.hO1O
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
596 LoadStringW(globals
.hMainInst
, IDS_TREE_GBCC
, U(tvis
).item
.pszText
,
598 U(tvis
).item
.lParam
= CreateITEM_INFO(REGTOP
|REGPATH
,
599 wszComponentCategories
, NULL
, NULL
);
600 tree
.hGBCC
= TreeView_InsertItemW(globals
.hTree
, &tvis
);
602 SendMessageW(globals
.hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)tree
.hOC
);
610 tvi
.mask
= TVIF_PARAM
;
611 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
612 TVGN_CHILD
, (LPARAM
)TVI_ROOT
);
617 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
618 TVGN_CHILD
, (LPARAM
)del
);
620 if(!cur
) cur
= (HTREEITEM
)SendMessageW(globals
.hTree
,
621 TVM_GETNEXTITEM
, TVGN_NEXT
, (LPARAM
)del
);
624 cur
= (HTREEITEM
)SendMessageW(globals
.hTree
, TVM_GETNEXTITEM
,
625 TVGN_PREVIOUS
, (LPARAM
)del
);
626 if(!cur
) cur
= (HTREEITEM
)SendMessageW(globals
.hTree
,
627 TVM_GETNEXTITEM
, TVGN_PARENT
, (LPARAM
)del
);
630 if(SendMessageW(globals
.hTree
, TVM_GETITEMW
, 0, (LPARAM
)&tvi
) && tvi
.lParam
)
632 if(((ITEM_INFO
*)tvi
.lParam
)->loaded
) ReleaseInst(del
);
633 HeapFree(GetProcessHeap(), 0, (ITEM_INFO
*)tvi
.lParam
);
635 SendMessageW(globals
.hTree
, TVM_DELETEITEM
, 0, (LPARAM
)del
);
646 AddComponentCategories();
655 memset(&tree
, 0, sizeof(TREE
));
656 AddComponentCategories();
660 static LRESULT CALLBACK
TreeProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
665 globals
.hTree
= CreateWindowW(WC_TREEVIEWW
, NULL
,
666 WS_CHILD
|WS_VISIBLE
|TVS_HASLINES
|TVS_HASBUTTONS
|TVS_LINESATROOT
,
667 0, 0, 0, 0, hWnd
, (HMENU
)TREE_WINDOW
, globals
.hMainInst
, NULL
);
671 if((int)wParam
!= TREE_WINDOW
) break;
672 switch(((LPNMHDR
)lParam
)->code
)
674 case TVN_ITEMEXPANDINGW
:
675 CreateInst(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
, NULL
);
677 case TVN_SELCHANGEDW
:
678 RefreshMenu(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
679 RefreshDetails(((NMTREEVIEWW
*)lParam
)->itemNew
.hItem
);
684 MoveWindow(globals
.hTree
, 0, 0, LOWORD(lParam
), HIWORD(lParam
), TRUE
);
687 return DefWindowProcW(hWnd
, uMsg
, wParam
, lParam
);
692 HWND
CreateTreeWindow(HINSTANCE hInst
)
695 const WCHAR wszTreeClass
[] = { 'T','R','E','E','\0' };
697 memset(&wct
, 0, sizeof(WNDCLASSW
));
698 wct
.lpfnWndProc
= TreeProc
;
699 wct
.lpszClassName
= wszTreeClass
;
700 wct
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
701 wct
.hCursor
= LoadCursorW(0, (LPCWSTR
)IDC_ARROW
);
703 if(!RegisterClassW(&wct
)) return NULL
;
705 return CreateWindowExW(WS_EX_CLIENTEDGE
, wszTreeClass
, NULL
, WS_CHILD
|WS_VISIBLE
,
706 0, 0, 0, 0, globals
.hPaneWnd
, NULL
, hInst
, NULL
);