├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── WMIExp
├── AboutDlg.cpp
├── AboutDlg.h
├── AppSettings.h
├── MainFrm.cpp
├── MainFrm.h
├── SecurityHelper.cpp
├── SecurityHelper.h
├── Settings.cpp
├── Settings.h
├── WMIExp.cpp
├── WMIExp.h
├── WMIExp.rc
├── WMIExp.vcxproj
├── WMIExp.vcxproj.filters
├── WMIHelper.cpp
├── WMIHelper.h
├── packages.config
├── pch.cpp
├── pch.h
├── res
│ ├── Refresh.ico
│ ├── WMIExp.ico
│ ├── class.ico
│ ├── copy.ico
│ ├── enum.ico
│ ├── method.ico
│ ├── namespace.ico
│ ├── object.ico
│ ├── properties-info.ico
│ └── properties.ico
└── resource.h
├── WMIExplorer.sln
└── WTLHelper
├── ClipboardHelper.cpp
├── ClipboardHelper.h
├── ColumnManager.cpp
├── ColumnManager.h
├── DialogHelper.h
├── IconHelper.cpp
├── IconHelper.h
├── IniFile.cpp
├── IniFile.h
├── ListViewhelper.cpp
├── ListViewhelper.h
├── SortHelper.cpp
├── SortHelper.h
├── StringHelper.cpp
├── StringHelper.h
├── VersionResourceHelper.cpp
├── VersionResourceHelper.h
├── VirtualListView.h
├── WTLHelper.cpp
├── WTLHelper.vcxproj
├── WTLHelper.vcxproj.filters
├── packages.config
├── pch.cpp
└── pch.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Pavel Yosifovich
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WMI Explorer
2 |
3 | Simple WMI Class/objects/property explorer (work in progress).
4 |
--------------------------------------------------------------------------------
/WMIExp/AboutDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "resource.h"
3 | #include "AboutDlg.h"
4 | #include "VersionResourceHelper.h"
5 |
6 | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
7 | CenterWindow(GetParent());
8 |
9 | SetDialogIcon(IDR_MAINFRAME);
10 | WCHAR path[MAX_PATH];
11 | ::GetModuleFileName(nullptr, path, _countof(path));
12 | VersionResourceHelper vr(path);
13 | auto version = vr.GetValue(L"ProductVersion");
14 | auto copyright = vr.GetValue(L"LegalCopyright");
15 | SetDlgItemText(IDC_VERSION, vr.GetValue(L"ProductName") + L" v" + version);
16 | SetDlgItemText(IDC_COPYRIGHT, copyright);
17 |
18 | return TRUE;
19 | }
20 |
21 | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
22 | EndDialog(wID);
23 | return 0;
24 | }
25 |
26 | LRESULT CAboutDlg::OnClickSyslink(int, LPNMHDR hdr, BOOL&) const {
27 | CString text;
28 | GetDlgItem(IDC_LINK).GetWindowText(text);
29 | text.Replace(L"", L"");
30 | text.Replace(L"", L"");
31 | ::ShellExecute(nullptr, L"open", text, nullptr, nullptr, SW_SHOWDEFAULT);
32 | return 0;
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/WMIExp/AboutDlg.h:
--------------------------------------------------------------------------------
1 | // aboutdlg.h : interface of the CAboutDlg class
2 | //
3 | /////////////////////////////////////////////////////////////////////////////
4 |
5 | #pragma once
6 |
7 | #include "DialogHelper.h"
8 |
9 | class CAboutDlg :
10 | public CDialogImpl,
11 | public CDialogHelper {
12 | public:
13 | enum { IDD = IDD_ABOUTBOX };
14 |
15 | BEGIN_MSG_MAP(CAboutDlg)
16 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
17 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
18 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
19 | END_MSG_MAP()
20 |
21 | // Handler prototypes (uncomment arguments if needed):
22 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
23 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
24 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
25 |
26 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
27 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
28 | LRESULT OnClickSyslink(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) const;
29 | };
30 |
--------------------------------------------------------------------------------
/WMIExp/AppSettings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Settings.h"
4 |
5 | struct AppSettings : Settings {
6 | BEGIN_SETTINGS(AppSettings)
7 | SETTING(MainWindowPlacement, WINDOWPLACEMENT{}, SettingType::Binary);
8 | SETTING(AlwaysOnTop, 0, SettingType::Bool);
9 | SETTING(SingleInstance, 0, SettingType::Bool);
10 | SETTING(ViewSystemClasses, 0, SettingType::Bool);
11 | SETTING(ViewSystemProperties, 1, SettingType::Bool);
12 | SETTING(ShowNamespacesInList, 0, SettingType::Bool);
13 | END_SETTINGS
14 |
15 | DEF_SETTING(AlwaysOnTop, int)
16 | DEF_SETTING(MainWindowPlacement, WINDOWPLACEMENT)
17 | DEF_SETTING(SingleInstance, int)
18 | DEF_SETTING(ViewSystemClasses, int)
19 | DEF_SETTING(ViewSystemProperties, int)
20 | DEF_SETTING(ShowNamespacesInList, int)
21 | };
22 |
--------------------------------------------------------------------------------
/WMIExp/MainFrm.cpp:
--------------------------------------------------------------------------------
1 | // MainFrm.cpp : implmentation of the CMainFrame class
2 | //
3 | /////////////////////////////////////////////////////////////////////////////
4 |
5 | #include "pch.h"
6 | #include "resource.h"
7 | #include "AboutDlg.h"
8 | #include "MainFrm.h"
9 | #include "SecurityHelper.h"
10 | #include "AppSettings.h"
11 | #include "IconHelper.h"
12 | #include "WMIHelper.h"
13 |
14 | BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) {
15 | return CFrameWindowImpl::PreTranslateMessage(pMsg);
16 | }
17 |
18 | BOOL CMainFrame::OnIdle() {
19 | UIUpdateToolBar();
20 | return FALSE;
21 | }
22 |
23 | CString CMainFrame::GetColumnText(HWND h, int row, int col) const {
24 | if (h == m_List) {
25 | auto& item = m_Items[row];
26 | switch (GetColumnManager(h)->GetColumnTag(col)) {
27 | case ColumnType::Name: return item.Name.c_str();
28 | case ColumnType::Type: return NodeTypeToText(item.Type);
29 | case ColumnType::CimType:
30 | if (item.Type == NodeType::Property) {
31 | auto text = CimTypeToString(item.CimType);
32 | return text;
33 | }
34 | break;
35 |
36 | case ColumnType::Value: return GetObjectValue(item);
37 | case ColumnType::Details: return GetObjectDetails(item);
38 | }
39 | }
40 | return L"";
41 | }
42 |
43 | int CMainFrame::GetRowImage(HWND h, int row) const {
44 | if (h == m_List) {
45 | switch (m_Items[row].Type) {
46 | case NodeType::Namespace: return 0;
47 | case NodeType::Class: return 1;
48 | case NodeType::Instance: return 5;
49 | case NodeType::Property:
50 | return m_Items[row].Name.substr(0, 2) == L"__" ? 4 : 2;
51 |
52 | case NodeType::Method: return 3;
53 | }
54 | }
55 | return -1;
56 | }
57 |
58 | DWORD CMainFrame::OnPrePaint(int, LPNMCUSTOMDRAW cd) {
59 | if (cd->hdr.hwndFrom != m_List)
60 | return CDRF_DODEFAULT;
61 |
62 | return CDRF_NOTIFYITEMDRAW;
63 | }
64 |
65 | DWORD CMainFrame::OnItemPrePaint(int, LPNMCUSTOMDRAW cd) {
66 | int index = (int)cd->dwItemSpec;
67 | auto& item = m_Items[index];
68 | if (item.Type != NodeType::Instance)
69 | return CDRF_DODEFAULT;
70 |
71 | CDCHandle dc(cd->hdc);
72 | dc.SetBkMode(TRANSPARENT);
73 | bool selected = m_List.GetItemState(index, LVIS_SELECTED) > 0;
74 | auto& rc = cd->rc;
75 | dc.FillSolidRect(&rc, ::GetSysColor(selected ? COLOR_HIGHLIGHT : COLOR_WINDOW));
76 | dc.SetTextColor(::GetSysColor(selected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
77 | CRect rcIcon(CPoint(rc.left + 2, rc.top + 2), CSize(16, 16));
78 | m_List.GetImageList(LVSIL_SMALL).DrawEx(5, dc, rcIcon, CLR_NONE, CLR_NONE, ILD_NORMAL);
79 | rc.left += 24;
80 | dc.DrawText(item.Name.c_str(), -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
81 |
82 | return CDRF_SKIPDEFAULT;
83 | }
84 |
85 | LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
86 | auto& settings = AppSettings::Get();
87 |
88 | settings.Load(L"Software\\ScorpioSoftware\\WmiExp");
89 | m_hSingleInstMutex = ::CreateMutex(nullptr, FALSE, L"WmiExpSingleInstanceMutex");
90 | if (settings.SingleInstance() && m_hSingleInstMutex) {
91 | if (::GetLastError() == ERROR_ALREADY_EXISTS) {
92 | //
93 | // not first instance
94 | //
95 | auto hMainWnd = ::FindWindow(GetWndClassName(), nullptr);
96 | if (hMainWnd) {
97 | ::SetActiveWindow(hMainWnd);
98 | ::SetForegroundWindow(hMainWnd);
99 | return -1;
100 | }
101 | }
102 | }
103 |
104 | CMenuHandle menu = GetMenu();
105 | if (SecurityHelper::IsRunningElevated()) {
106 | auto fileMenu = menu.GetSubMenu(0);
107 | fileMenu.DeleteMenu(0, MF_BYPOSITION);
108 | fileMenu.DeleteMenu(0, MF_BYPOSITION);
109 | CString text;
110 | GetWindowText(text);
111 | text += L" (Administrator)";
112 | SetWindowText(text);
113 | }
114 |
115 | HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, nullptr, ATL_SIMPLE_CMDBAR_PANE_STYLE);
116 |
117 | m_CmdBar.SetAlphaImages(true);
118 | m_CmdBar.AttachMenu(menu);
119 | InitCommandBar();
120 |
121 | UIAddMenu(menu);
122 | SetMenu(nullptr);
123 |
124 | CToolBarCtrl tb;
125 | tb.Create(m_hWnd, nullptr, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE, 0, ATL_IDW_TOOLBAR);
126 | InitToolBar(tb, 24);
127 | UIAddToolBar(tb);
128 |
129 | CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
130 | AddSimpleReBarBand(hWndCmdBar);
131 | AddSimpleReBarBand(tb, nullptr, TRUE);
132 |
133 | CReBarCtrl rb(m_hWndToolBar);
134 | rb.LockBands(true);
135 |
136 | CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP | SBT_TOOLTIPS);
137 | m_StatusBar.SubclassWindow(m_hWndStatusBar);
138 | // int panes[] = { 24, 1300 };
139 | // m_StatusBar.SetParts(_countof(panes), panes);
140 |
141 | m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, nullptr,
142 | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
143 |
144 | m_Tree.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
145 | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE, TreeId);
146 | m_Tree.SetExtendedStyle(TVS_EX_DOUBLEBUFFER | TVS_EX_RICHTOOLTIP, 0);
147 |
148 | m_DetailSplitter.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
149 | m_DetailSplitter.SetSplitterPosPct(50);
150 |
151 | CImageList images;
152 | images.Create(16, 16, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 10, 4);
153 | UINT icons[] = {
154 | IDI_NAMESPACE, IDI_CLASS, IDI_PROPERTY, IDI_METHOD, IDI_PROPERTY2,
155 | IDI_OBJECT
156 | };
157 | for (auto icon : icons)
158 | images.AddIcon(AtlLoadIconImage(icon, 0, 16, 16));
159 | m_Tree.SetImageList(images, TVSIL_NORMAL);
160 | //::SetWindowTheme(m_Tree, L"Explorer", nullptr);
161 |
162 | m_List.Create(m_DetailSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
163 | | LVS_OWNERDATA | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS, WS_EX_CLIENTEDGE);
164 | m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP);
165 | m_List.SetImageList(images, LVSIL_SMALL);
166 | //::SetWindowTheme(m_List, L"Explorer", nullptr);
167 |
168 | auto cm = GetColumnManager(m_List);
169 | cm->AddColumn(L"Name", LVCFMT_LEFT, 220, ColumnType::Name);
170 | cm->AddColumn(L"Type", LVCFMT_LEFT, 110, ColumnType::Type);
171 | //cm->AddColumn(L"Size", LVCFMT_RIGHT, 70, ColumnType::Size);
172 | cm->AddColumn(L"Value", LVCFMT_LEFT, 250, ColumnType::Value);
173 | cm->AddColumn(L"CIM Type", LVCFMT_LEFT, 120, ColumnType::CimType);
174 | cm->AddColumn(L"Details", LVCFMT_LEFT, 250, ColumnType::Details);
175 | cm->UpdateColumns();
176 |
177 | m_InstanceList.Create(m_DetailSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
178 | | LVS_OWNERDATA | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS, WS_EX_CLIENTEDGE);
179 | m_InstanceList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP);
180 | cm = GetColumnManager(m_InstanceList);
181 | cm->AddColumn(L"Property", LVCFMT_LEFT, 150, ColumnType::Name);
182 | cm->AddColumn(L"Value", LVCFMT_LEFT, 350, ColumnType::Value);
183 |
184 | m_Splitter.SetSplitterPanes(m_Tree, m_DetailSplitter);
185 | m_DetailSplitter.SetSplitterPanes(m_List, m_InstanceList);
186 |
187 | m_Splitter.SetSplitterPosPct(25);
188 | m_Splitter.UpdateSplitterLayout();
189 |
190 | auto pLoop = _Module.GetMessageLoop();
191 | ATLASSERT(pLoop != NULL);
192 | pLoop->AddMessageFilter(this);
193 | pLoop->AddIdleHandler(this);
194 |
195 | //
196 | // update UI based on settings
197 | //
198 | UISetCheck(ID_OPTIONS_ALWAYSONTOP, settings.AlwaysOnTop());
199 | UISetCheck(ID_OPTIONS_SINGLEINSTANCE, settings.SingleInstance());
200 | UISetCheck(ID_VIEW_SYSTEMPROPERTIES, settings.ViewSystemProperties());
201 | UISetCheck(ID_VIEW_SYSTEMCLASSES, settings.ViewSystemClasses());
202 | UISetCheck(ID_VIEW_NAMESPACESINLIST, settings.ShowNamespacesInList());
203 |
204 | if (settings.AlwaysOnTop())
205 | SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
206 |
207 | UpdateLayout();
208 | // UpdateUI();
209 | InitTree();
210 |
211 | return 0;
212 | }
213 |
214 | LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
215 | // unregister message filtering and idle updates
216 | CMessageLoop* pLoop = _Module.GetMessageLoop();
217 | ATLASSERT(pLoop != NULL);
218 | pLoop->RemoveMessageFilter(this);
219 | pLoop->RemoveIdleHandler(this);
220 |
221 | bHandled = FALSE;
222 | return 1;
223 | }
224 |
225 | LRESULT CMainFrame::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) {
226 | if (id == 2) {
227 | KillTimer(id);
228 | TreeItemSelected(nullptr);
229 | }
230 | return 0;
231 | }
232 |
233 | LRESULT CMainFrame::OnAddInstances(UINT, WPARAM, LPARAM lp, BOOL& bHandled) {
234 | auto cb = reinterpret_cast(lp);
235 | ATLASSERT(cb);
236 |
237 | auto count = cb->GetObjectCount();
238 | for(auto i = 0; i < count; i++) {
239 | WmiItem item;
240 | item.Type = NodeType::Instance;
241 | item.Object = cb->GetItem(i);
242 | CComBSTR text;
243 | item.Object->GetObjectText(0, &text);
244 | item.Name = text;
245 | m_Items.push_back(std::move(item));
246 | }
247 | cb->Release();
248 | RefreshList();
249 |
250 | return 0;
251 | }
252 |
253 | LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
254 | PostMessage(WM_CLOSE);
255 | return 0;
256 | }
257 |
258 | LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
259 | static BOOL bVisible = TRUE; // initially visible
260 | bVisible = !bVisible;
261 | CReBarCtrl rebar = m_hWndToolBar;
262 | int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band
263 | rebar.ShowBand(nBandIndex, bVisible);
264 | UISetCheck(wID, bVisible);
265 | UpdateLayout();
266 | return 0;
267 | }
268 |
269 | LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
270 | BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
271 | ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
272 | UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
273 | UpdateLayout();
274 | return 0;
275 | }
276 |
277 | LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
278 | CAboutDlg dlg;
279 | dlg.DoModal();
280 | return 0;
281 | }
282 |
283 | LRESULT CMainFrame::OnTreeItemExpanding(int, LPNMHDR hdr, BOOL&) {
284 | auto tv = reinterpret_cast(hdr);
285 | auto hItem = tv->itemNew.hItem;
286 | CString text;
287 | if (m_Tree.GetItemText(m_Tree.GetChildItem(hItem), text) && text != L"\\\\")
288 | return 0;
289 |
290 | auto path = GetFullPath(hItem);
291 | CComPtr spNamespace;
292 | auto hr = m_spWmi->OpenNamespace(CComBSTR(path), 0, nullptr, &spNamespace, nullptr);
293 | if (SUCCEEDED(hr)) {
294 | CWaitCursor wait;
295 | m_NamespacePath = L"ROOT\\" + path;
296 | m_Tree.DeleteItem(m_Tree.GetChildItem(hItem));
297 | m_spCurrentNamespace = spNamespace;
298 | BuildTree(spNamespace, hItem);
299 | }
300 | return 0;
301 | }
302 |
303 | LRESULT CMainFrame::OnTreeSelChanged(int, LPNMHDR, BOOL&) {
304 | SetTimer(2, 200, nullptr);
305 | return 0;
306 | }
307 |
308 | LRESULT CMainFrame::OnViewSystemClasses(WORD, WORD id, HWND, BOOL&) {
309 | bool view;
310 | AppSettings::Get().ViewSystemClasses(view = !AppSettings::Get().ViewSystemClasses());
311 | UISetCheck(id, view);
312 | UpdateList();
313 | return 0;
314 | }
315 |
316 | LRESULT CMainFrame::OnViewSystemProperties(WORD, WORD id, HWND, BOOL&) {
317 | bool view;
318 | AppSettings::Get().ViewSystemProperties(view = !AppSettings::Get().ViewSystemProperties());
319 | UISetCheck(id, view);
320 | UpdateList();
321 | return 0;
322 | }
323 |
324 | LRESULT CMainFrame::OnViewNamespacesInList(WORD, WORD id, HWND, BOOL&) {
325 | bool view;
326 | AppSettings::Get().ShowNamespacesInList(view = !AppSettings::Get().ShowNamespacesInList());
327 | UISetCheck(id, view);
328 | UpdateList();
329 | return 0;
330 | }
331 |
332 | PCWSTR CMainFrame::NodeTypeToText(NodeType type) {
333 | switch (type) {
334 | case NodeType::Class: return L"Class";
335 | case NodeType::Namespace: return L"Namespace";
336 | case NodeType::Method: return L"Method";
337 | case NodeType::Property: return L"Property";
338 | case NodeType::Instance: return L"Object";
339 | }
340 | return L"";
341 | }
342 |
343 | CString CMainFrame::CimTypeToString(CIMTYPE type) {
344 | CString text;
345 | switch (type & 0xff) {
346 | case CIM_EMPTY: text = L"Empty"; break;
347 | case CIM_SINT8: text = L"Signed Byte (8 bit)"; break;
348 | case CIM_UINT8: text = L"Byte (8 bit)"; break;
349 | case CIM_SINT16: text = L"Signed Word (16 bit)"; break;
350 | case CIM_UINT16: text = L"Word (16 bit)"; break;
351 | case CIM_SINT32: text = L"Signed Int (32 bit)"; break;
352 | case CIM_UINT32: text = L"Int (32 bit)"; break;
353 | case CIM_SINT64: text = L"Signed QWord (64 bit)"; break;
354 | case CIM_UINT64: text = L"QWord (64 bit)"; break;
355 | case CIM_REAL32: text = L"Real (32 bit)"; break;
356 | case CIM_REAL64: text = L"Real (64 bit)"; break;
357 | case CIM_BOOLEAN: text = L"Boolean"; break;
358 | case CIM_STRING: text = L"String"; break;
359 | case CIM_DATETIME: text = L"Date Time"; break;
360 | case CIM_REFERENCE: text = L"Reference"; break;
361 | case CIM_CHAR16: text = L"Character"; break;
362 | case CIM_OBJECT: text = L"Object"; break;
363 | }
364 | if (type & CIM_FLAG_ARRAY)
365 | text += L" [Array]";
366 | return text;
367 | }
368 |
369 | CString CMainFrame::GetArrayValue(CComVariant& value, CIMTYPE type) {
370 | CString text;
371 | switch (type & 0xff) {
372 | case CIM_STRING:
373 | {
374 | // string array
375 | CComSafeArray arr(value.parray);
376 | auto count = arr.GetCount();
377 | for (ULONG i = 0; i < count; i++)
378 | text += CString(arr.GetAt(i).m_str) + L", ";
379 | if (!text.IsEmpty())
380 | text = text.Left(text.GetLength() - 2);
381 | break;
382 | }
383 |
384 | case CIM_SINT8:
385 | case CIM_UINT8:
386 | {
387 | BYTE* data;
388 | CComSafeArray arr(value.parray);
389 | auto count = std::min(arr.GetCount(), (ULONG)64);
390 | if (SUCCEEDED(::SafeArrayAccessData(value.parray, reinterpret_cast(&data)))) {
391 | for (ULONG i = 0; i < count; i++) {
392 | CString str;
393 | str.Format(L"%02X ", data[i]);
394 | text += str;
395 | }
396 | ::SafeArrayUnaccessData(value.parray);
397 | }
398 | break;
399 | }
400 | }
401 | return text;
402 | }
403 |
404 | void CMainFrame::InitCommandBar() {
405 | struct {
406 | UINT id, icon;
407 | HICON hIcon = nullptr;
408 | } cmds[] = {
409 | { ID_FILE_RUNASADMINISTRATOR, 0, IconHelper::GetShieldIcon() },
410 | { ID_EDIT_COPY, IDI_COPY },
411 | //{ ID_VIEW_REFRESH, IDI_REFRESH },
412 | //{ ID_EDIT_CUT, IDI_CUT },
413 | //{ ID_EDIT_DELETE, IDI_DELETE },
414 | //{ ID_EDIT_FIND, IDI_FIND },
415 | };
416 | for (auto& cmd : cmds) {
417 | HICON hIcon = cmd.hIcon;
418 | if (!hIcon) {
419 | hIcon = AtlLoadIconImage(cmd.icon, 0, 16, 16);
420 | ATLASSERT(hIcon);
421 | }
422 | m_CmdBar.AddIcon(cmd.icon ? hIcon : cmd.hIcon, cmd.id);
423 | }
424 | }
425 |
426 | void CMainFrame::InitToolBar(CToolBarCtrl& tb, int size) {
427 | CImageList tbImages;
428 | tbImages.Create(size, size, ILC_COLOR32, 8, 4);
429 | tb.SetImageList(tbImages);
430 |
431 | const struct {
432 | UINT id;
433 | int image;
434 | BYTE style = BTNS_BUTTON;
435 | PCWSTR text = nullptr;
436 | } buttons[] = {
437 | { ID_VIEW_REFRESH, IDI_REFRESH },
438 | { 0 },
439 | { ID_EDIT_COPY, IDI_COPY },
440 | };
441 | for (auto& b : buttons) {
442 | if (b.id == 0)
443 | tb.AddSeparator(0);
444 | else {
445 | auto hIcon = AtlLoadIconImage(b.image, 0, size, size);
446 | ATLASSERT(hIcon);
447 | int image = tbImages.AddIcon(hIcon);
448 | tb.AddButton(b.id, b.style, TBSTATE_ENABLED, image, b.text, 0);
449 | }
450 | }
451 | }
452 |
453 | void CMainFrame::InitTree() {
454 | WMIHelper::Init(nullptr, L"ROOT", &m_spWmi);
455 | m_spCurrentNamespace = m_spWmi;
456 | m_Tree.LockWindowUpdate();
457 | m_hRoot = InsertTreeItem(L"ROOT", 0, TVI_ROOT, NodeType::Namespace);
458 | if (m_spWmi) {
459 | BuildTree(m_spWmi, m_hRoot);
460 | m_Tree.Expand(m_hRoot, TVE_EXPAND);
461 | }
462 | m_Tree.LockWindowUpdate(FALSE);
463 | m_Tree.SelectItem(m_hRoot);
464 | m_Tree.SetFocus();
465 | }
466 |
467 | void CMainFrame::BuildTree(IWbemServices* pWmi, HTREEITEM hParent) {
468 | auto classes = WMIHelper::EnumClasses(pWmi, true, AppSettings::Get().ViewSystemClasses());
469 | for (auto& spObj : classes) {
470 | auto name = WMIHelper::GetStringProperty(spObj, L"__CLASS");
471 | auto hItem = InsertTreeItem(name, 1, hParent, NodeType::Class);
472 | }
473 |
474 | auto ns = WMIHelper::EnumNamespaces(pWmi);
475 | for (auto& spObj : ns) {
476 | auto name = WMIHelper::GetStringProperty(spObj, L"NAME");
477 | ATLTRACE(L"Namespace: %s\n", (PCWSTR)name);
478 | auto hItem = InsertTreeItem(name, 0, hParent, NodeType::Namespace);
479 | CComPtr spNamespace;
480 | auto hr = pWmi->OpenNamespace(CComBSTR(name), 0, nullptr, &spNamespace, nullptr);
481 | if (FAILED(hr))
482 | continue;
483 |
484 | if (IsChildNamespaceOrClass(spNamespace)) {
485 | InsertTreeItem(L"\\\\", 0, hItem, NodeType::HasChildren);
486 | }
487 | }
488 | //m_Tree.SortChildren(hParent);
489 | }
490 |
491 | bool CMainFrame::IsChildNamespaceOrClass(IWbemServices* pWmi) const {
492 | CComPtr spEnum;
493 | pWmi->CreateInstanceEnum(CComBSTR(L"__NAMESPACE"), 0, nullptr, &spEnum);
494 | return spEnum != nullptr;
495 | }
496 |
497 | void CMainFrame::UpdateList() {
498 | m_List.SetItemCount(0);
499 | m_Items.clear();
500 |
501 | auto& settings = AppSettings::Get();
502 | if (m_spCurrentClass) {
503 | CString name;
504 | m_Tree.GetItemText(m_Tree.GetSelectedItem(), name);
505 | for (auto& prop : WMIHelper::EnumProperties(m_spCurrentClass)) {
506 | if (!settings.ViewSystemProperties() && CString(prop.Name).Left(2) == L"__")
507 | continue;
508 | WmiItem item;
509 | item.Name = prop.Name;
510 | item.Type = NodeType::Property;
511 | item.CimType = prop.Type;
512 | item.Value = prop.Value;
513 | m_Items.push_back(std::move(item));
514 | }
515 | for (auto& method : WMIHelper::EnumMethods(m_spCurrentClass)) {
516 | WmiItem item;
517 | item.Name = method.Name;
518 | item.Type = NodeType::Method;
519 | item.Object = method.spInParams;
520 | item.Object2 = method.spOutParams;
521 | item.Value = method.ClassName.c_str();
522 | m_Items.push_back(std::move(item));
523 | }
524 | WMIHelper::EnumInstancesAsync(m_hWnd, WM_INSTANCES, name, m_spCurrentNamespace, false);
525 | }
526 | else {
527 | if (m_spCurrentNamespace == nullptr)
528 | return;
529 |
530 | if (settings.ShowNamespacesInList()) {
531 | for (auto& ns : WMIHelper::EnumNamespaces(m_spCurrentNamespace)) {
532 | WmiItem item;
533 | CComBSTR name;
534 | item.Name = WMIHelper::GetStringProperty(ns, L"NAME");
535 | item.Object = ns;
536 | item.Type = NodeType::Namespace;
537 | m_Items.push_back(std::move(item));
538 | }
539 | }
540 | for (auto& cls : WMIHelper::EnumClasses(m_spCurrentNamespace, true)) {
541 | WmiItem item;
542 | CComBSTR name;
543 | item.Name = WMIHelper::GetStringProperty(cls, L"__CLASS");
544 | item.Object = cls;
545 | item.Type = NodeType::Class;
546 | m_Items.push_back(std::move(item));
547 | }
548 | }
549 | RefreshList();
550 | }
551 |
552 | CString CMainFrame::GetObjectDetails(WmiItem const& item) const {
553 | switch (item.Type) {
554 | case NodeType::Method:
555 | return L"Class: " + CString(item.Value.bstrVal);
556 | }
557 | return L"";
558 | }
559 |
560 | CString CMainFrame::GetObjectValue(WmiItem const& item) const {
561 | switch (item.Type) {
562 | case NodeType::Property:
563 | CComVariant value(item.Value);
564 | if (value.vt == VT_NULL)
565 | return L"";
566 |
567 | if ((item.CimType & CIM_FLAG_ARRAY) && value.parray) {
568 | return GetArrayValue(value, item.CimType);
569 | }
570 | if (value.vt == VT_BOOL)
571 | return value.boolVal ? L"True" : L"False";
572 | if(SUCCEEDED(value.ChangeType(VT_BSTR)))
573 | return CString(value.bstrVal);
574 | break;
575 | }
576 | return L"";
577 | }
578 |
579 | void CMainFrame::TreeItemSelected(HTREEITEM /* hItem */) {
580 | auto hItem = m_Tree.GetSelectedItem();
581 | if (hItem == nullptr) {
582 | m_spCurrentClass = nullptr;
583 | m_spCurrentNamespace = nullptr;
584 | return;
585 | }
586 | auto path = GetFullPath(hItem);
587 | auto type = GetTreeNodeType(hItem);
588 | CString name;
589 | m_Tree.GetItemText(hItem, name);
590 | switch (type) {
591 | case NodeType::Namespace:
592 | {
593 | if (hItem == m_hRoot) {
594 | m_NamespacePath = L"ROOT";
595 | m_spCurrentNamespace = m_spWmi;
596 | }
597 | else {
598 | CComPtr spNamespace;
599 | m_spWmi->OpenNamespace(CComBSTR(path), 0, nullptr, &spNamespace, nullptr);
600 | if (spNamespace) {
601 | m_spCurrentNamespace = spNamespace;
602 | m_NamespacePath = L"ROOT\\" + path;
603 | }
604 | }
605 | m_spCurrentClass = nullptr;
606 | break;
607 | }
608 | case NodeType::Class:
609 | m_spCurrentClass = nullptr;
610 | m_spCurrentNamespace->GetObject(CComBSTR(name), 0, nullptr, &m_spCurrentClass, nullptr);
611 | break;
612 |
613 | default:
614 | ATLASSERT(false);
615 | return;
616 | }
617 |
618 | UpdateList();
619 | }
620 |
621 | void CMainFrame::RefreshList() {
622 | m_List.SetItemCountEx(static_cast(m_Items.size()), LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
623 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage());
624 | }
625 |
626 | CString CMainFrame::GetFullPath(HTREEITEM hItem) const {
627 | CString path, text;
628 | while (hItem) {
629 | m_Tree.GetItemText(hItem, text);
630 | if (text == L"ROOT")
631 | break;
632 | path = text + L"\\" + path;
633 | hItem = m_Tree.GetParentItem(hItem);
634 | }
635 | return path.TrimRight(L"\\");
636 | }
637 |
638 | HTREEITEM CMainFrame::InsertTreeItem(PCWSTR text, int image, HTREEITEM hParent, NodeType type) {
639 | auto hItem = m_Tree.InsertItem(text, image, image, hParent, TVI_SORT);
640 | ATLASSERT(hItem);
641 | m_Tree.SetItemData(hItem, static_cast(type));
642 | return hItem;
643 | }
644 |
645 | CMainFrame::NodeType CMainFrame::GetTreeNodeType(HTREEITEM hItem) const {
646 | return static_cast(m_Tree.GetItemData(hItem));
647 | }
648 |
--------------------------------------------------------------------------------
/WMIExp/MainFrm.h:
--------------------------------------------------------------------------------
1 | // MainFrm.h : interface of the CMainFrame class
2 | //
3 | /////////////////////////////////////////////////////////////////////////////
4 |
5 | #pragma once
6 |
7 | #include "VirtualListView.h"
8 |
9 | class CMainFrame :
10 | public CFrameWindowImpl,
11 | public CAutoUpdateUI,
12 | public CVirtualListView,
13 | public CCustomDraw,
14 | public CMessageFilter,
15 | public CIdleHandler {
16 | public:
17 | DECLARE_FRAME_WND_CLASS(L"WMIEXPWNDCLASS", IDR_MAINFRAME)
18 |
19 | const UINT WM_INSTANCES = WM_APP + 6;
20 |
21 | enum { TreeId = 123, ListId };
22 |
23 | virtual BOOL PreTranslateMessage(MSG* pMsg);
24 | virtual BOOL OnIdle();
25 |
26 | CString GetColumnText(HWND, int row, int col) const;
27 | int GetRowImage(HWND, int row) const;
28 |
29 | DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW cd);
30 | DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW cd);
31 |
32 | BEGIN_MSG_MAP(CMainFrame)
33 | MESSAGE_HANDLER(WM_TIMER, OnTimer)
34 | NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnTreeItemExpanding)
35 | NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnTreeSelChanged)
36 | MESSAGE_HANDLER(WM_INSTANCES, OnAddInstances)
37 | MESSAGE_HANDLER(WM_CREATE, OnCreate)
38 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
39 | COMMAND_ID_HANDLER(ID_VIEW_SYSTEMCLASSES, OnViewSystemClasses)
40 | COMMAND_ID_HANDLER(ID_VIEW_SYSTEMPROPERTIES, OnViewSystemProperties)
41 | COMMAND_ID_HANDLER(ID_VIEW_NAMESPACESINLIST, OnViewNamespacesInList)
42 | COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
43 | COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
44 | COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
45 | COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
46 | CHAIN_MSG_MAP(CAutoUpdateUI)
47 | CHAIN_MSG_MAP(CVirtualListView)
48 | CHAIN_MSG_MAP(CFrameWindowImpl)
49 | CHAIN_MSG_MAP(CCustomDraw)
50 | END_MSG_MAP()
51 |
52 | // Handler prototypes (uncomment arguments if needed):
53 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
54 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
55 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
56 |
57 | private:
58 | enum class ColumnType {
59 | Name, Value, Type, Size, CimType, Details
60 | };
61 | enum class NodeType {
62 | Computer, Namespace, Class, Property, Method, Instance, HasChildren = 0x80
63 | };
64 | struct WmiItem {
65 | std::wstring Name;
66 | wil::com_ptr Object, Object2;
67 | CIMTYPE CimType;
68 | NodeType Type;
69 | CComVariant Value;
70 | };
71 |
72 | static PCWSTR NodeTypeToText(NodeType type);
73 | static CString CimTypeToString(CIMTYPE type);
74 | static CString GetArrayValue(CComVariant& value, CIMTYPE type);
75 |
76 | void InitCommandBar();
77 | void InitToolBar(CToolBarCtrl& tb, int size = 24);
78 | void InitTree();
79 | void BuildTree(IWbemServices* pWmi, HTREEITEM hParent);
80 | bool IsChildNamespaceOrClass(IWbemServices* pWmi) const;
81 | void UpdateList();
82 | CString GetObjectDetails(WmiItem const& item) const;
83 | CString GetObjectValue(WmiItem const& item) const;
84 | void TreeItemSelected(HTREEITEM hItem);
85 | void RefreshList();
86 |
87 | CString GetFullPath(HTREEITEM hItem) const;
88 |
89 | HTREEITEM InsertTreeItem(PCWSTR text, int image, HTREEITEM hParent, NodeType type);
90 | NodeType GetTreeNodeType(HTREEITEM hItem) const;
91 |
92 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
93 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
94 | LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
95 | LRESULT OnAddInstances(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
96 | LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
97 | LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
98 | LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
99 | LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
100 | LRESULT OnTreeItemExpanding(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
101 | LRESULT OnTreeSelChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
102 | LRESULT OnViewSystemClasses(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
103 | LRESULT OnViewSystemProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
104 | LRESULT OnViewNamespacesInList(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
105 |
106 | CCommandBarCtrl m_CmdBar;
107 | CSplitterWindow m_Splitter;
108 | CHorSplitterWindow m_DetailSplitter;
109 | CTreeViewCtrlEx m_Tree;
110 | CPaneContainer m_TreePane;
111 | CListViewCtrl m_List;
112 | CListViewCtrl m_InstanceList;
113 | CMultiPaneStatusBarCtrl m_StatusBar;
114 | std::vector m_Items;
115 | HANDLE m_hSingleInstMutex;
116 | HTREEITEM m_hRoot;
117 | CString m_NamespacePath;
118 | CComPtr m_spWmi;
119 | CComPtr m_spCurrentNamespace;
120 | CComPtr m_spCurrentClass;
121 | };
122 |
--------------------------------------------------------------------------------
/WMIExp/SecurityHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "SecurityHelper.h"
3 |
4 | bool SecurityHelper::IsRunningElevated() {
5 | static bool runningElevated = false;
6 | static bool runningElevatedCheck = false;
7 | if (runningElevatedCheck)
8 | return runningElevated;
9 |
10 | runningElevatedCheck = true;
11 | HANDLE hToken;
12 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
13 | return false;
14 |
15 | TOKEN_ELEVATION te;
16 | DWORD len;
17 | if (::GetTokenInformation(hToken, TokenElevation, &te, sizeof(te), &len)) {
18 | runningElevated = te.TokenIsElevated ? true : false;
19 | }
20 | ::CloseHandle(hToken);
21 | return runningElevated;
22 | }
23 |
24 | bool SecurityHelper::RunElevated() {
25 | WCHAR path[MAX_PATH];
26 | ::GetModuleFileName(nullptr, path, _countof(path));
27 | return (INT_PTR)::ShellExecute(nullptr, L"runas", path, nullptr, nullptr, SW_SHOWDEFAULT) > 31;
28 | }
29 |
30 | bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) {
31 | HANDLE hToken;
32 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
33 | return false;
34 |
35 | bool result = false;
36 | TOKEN_PRIVILEGES tp;
37 | tp.PrivilegeCount = 1;
38 | tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
39 | if (::LookupPrivilegeValue(nullptr, privName,
40 | &tp.Privileges[0].Luid)) {
41 | if (::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp),
42 | nullptr, nullptr))
43 | result = ::GetLastError() == ERROR_SUCCESS;
44 | }
45 | ::CloseHandle(hToken);
46 | return result;
47 | }
48 |
--------------------------------------------------------------------------------
/WMIExp/SecurityHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct SecurityHelper abstract final {
4 | static bool IsRunningElevated();
5 | static bool RunElevated();
6 | static bool EnablePrivilege(PCWSTR privName, bool enable);
7 | };
8 |
--------------------------------------------------------------------------------
/WMIExp/Settings.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Settings.h"
3 |
4 | bool Settings::Load(PCWSTR registryPath) {
5 | if (registryPath == nullptr)
6 | registryPath = _path.c_str();
7 | else
8 | _path = registryPath;
9 |
10 | ATLASSERT(registryPath);
11 | if (registryPath == nullptr)
12 | return false;
13 |
14 | CRegKey key;
15 | if (ERROR_SUCCESS != key.Open(HKEY_CURRENT_USER, registryPath))
16 | return false;
17 |
18 | WCHAR name[64];
19 | BYTE value[1024];
20 | DWORD type;
21 | for (DWORD i = 0;; ++i) {
22 | DWORD lname = _countof(name), lvalue = _countof(value);
23 | if (ERROR_SUCCESS != ::RegEnumValue(key, i, name, &lname, nullptr, &type, value, &lvalue))
24 | break;
25 | auto it = _settings.find(name);
26 | if (it == _settings.end())
27 | _settings.insert({ name, Setting(name, (BYTE*)value, lvalue, (SettingType)type) });
28 | else
29 | it->second.Set(value, lvalue);
30 | }
31 | return true;
32 | }
33 |
34 | bool Settings::Save(PCWSTR registryPath) const {
35 | if (registryPath == nullptr)
36 | registryPath = _path.c_str();
37 |
38 | ATLASSERT(registryPath);
39 | if (registryPath == nullptr)
40 | return false;
41 |
42 | CRegKey key;
43 | key.Create(HKEY_CURRENT_USER, registryPath, nullptr, 0, KEY_WRITE);
44 | if (!key)
45 | return false;
46 |
47 | for (auto& [name, setting] : _settings) {
48 | key.SetValue(name.c_str(), (DWORD)setting.Type, setting.Buffer.get(), setting.Size);
49 | }
50 | return true;
51 | }
52 |
53 | void Settings::Set(PCWSTR name, int value) {
54 | return Set(name, value, SettingType::Int32);
55 | }
56 |
57 | void Settings::SetString(PCWSTR name, PCWSTR value) {
58 | auto it = _settings.find(name);
59 | if (it != _settings.end()) {
60 | it->second.SetString(value);
61 | }
62 | else {
63 | Setting s(name, value);
64 | _settings.insert({ name, std::move(s) });
65 | }
66 | }
67 |
68 | std::wstring Settings::GetString(PCWSTR name) const {
69 | auto it = _settings.find(name);
70 | if (it == _settings.end())
71 | return L"";
72 | return (PCWSTR)it->second.Buffer.get();
73 | }
74 |
75 | int Settings::GetInt32(PCWSTR name) const {
76 | return GetValue(name);
77 | }
78 |
79 | void Setting::SetString(PCWSTR value) {
80 | Buffer = std::make_unique(Size = (1 + (int)::wcslen(value)) * sizeof(wchar_t));
81 | ::memcpy(Buffer.get(), value, Size);
82 | Type = SettingType::String;
83 | }
84 |
--------------------------------------------------------------------------------
/WMIExp/Settings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum class SettingType {
4 | String = REG_SZ,
5 | Int32 = REG_DWORD,
6 | Int64 = REG_QWORD,
7 | Binary = REG_BINARY,
8 | Bool = REG_DWORD,
9 | };
10 |
11 | struct Setting {
12 | std::wstring Name;
13 | SettingType Type{ SettingType::String };
14 | std::unique_ptr Buffer;
15 | int Size;
16 |
17 | Setting(std::wstring name, const std::wstring& value) : Name(std::move(name)) {
18 | Buffer = std::make_unique(Size = (1 + (int)value.size()) * sizeof(wchar_t));
19 | ::memcpy(Buffer.get(), value.data(), Size);
20 | }
21 | template
22 | Setting(std::wstring name, const T& value, SettingType type) : Name(std::move(name)), Type(type) {
23 | Buffer = std::make_unique(Size = sizeof(T));
24 | ::memcpy(Buffer.get(), &value, Size);
25 | }
26 |
27 | Setting(std::wstring name, const void* value, int size, SettingType type = SettingType::Binary) : Name(std::move(name)), Type(type) {
28 | Buffer = std::make_unique(Size = size);
29 | ::memcpy(Buffer.get(), value, Size);
30 | }
31 |
32 | template
33 | void Set(const T& value) {
34 | Buffer = std::make_unique(sizeof(T));
35 | memcpy(Buffer.get(), &value, sizeof(T));
36 | }
37 |
38 | void SetString(PCWSTR value);
39 |
40 | void Set(const void* value, int size) {
41 | Buffer = std::make_unique(Size = size);
42 | memcpy(Buffer.get(), value, size);
43 | }
44 | };
45 |
46 | #define BEGIN_SETTINGS(className) \
47 | className() { \
48 | InitSettings(); \
49 | } \
50 | static className& Get() { \
51 | static className _instance; \
52 | return _instance; \
53 | } \
54 | void InitSettings() { \
55 |
56 | #define END_SETTINGS }
57 |
58 | #define SETTING_STRING(name, value) _settings.insert({ L""#name, Setting(L""#name, value) })
59 | #define SETTING(name, value, type) _settings.insert({ L""#name, Setting(L""#name, value, type) })
60 | #define DEF_SETTING_STRING(name) \
61 | std::wstring name() const { return GetString(L""#name); } \
62 | void name(const std::wstring& value) { SetString(L""#name, value.c_str()); }
63 |
64 | #define DEF_SETTING(name, type) \
65 | type name() const { return GetValueOrDefault(L""#name); } \
66 | void name(const type& value) { Set(L""#name, value); }
67 |
68 | #define DEF_SETTING_REF(name, type) \
69 | type& name() const { return GetValueRef(L""#name); }
70 |
71 | class Settings {
72 | public:
73 | Settings() = default;
74 |
75 | bool Load(PCWSTR registryPath = nullptr);
76 | bool Save(PCWSTR registryPath = nullptr) const;
77 |
78 | template
79 | void Set(const std::wstring& name, const T& value, SettingType type = SettingType::Binary) {
80 | auto it = _settings.find(name);
81 | if (it != _settings.end()) {
82 | it->second.Set(value);
83 | }
84 | else {
85 | Setting s(name, value, type);
86 | _settings.insert({ name, std::move(s) });
87 | }
88 | }
89 |
90 | void Set(PCWSTR name, int value);
91 | void SetString(PCWSTR name, PCWSTR value);
92 |
93 | std::wstring GetString(PCWSTR name) const;
94 |
95 | template
96 | T GetValue(PCWSTR name) const {
97 | auto it = _settings.find(name);
98 | ATLASSERT(it != _settings.end());
99 | ATLASSERT(it->second.Size == sizeof(T));
100 | return *(T*)it->second.Buffer.get();
101 | }
102 |
103 | template
104 | T& GetValueRef(PCWSTR name) const {
105 | auto it = _settings.find(name);
106 | ATLASSERT(it != _settings.end());
107 | ATLASSERT(it->second.Size == sizeof(T));
108 | return *(T*)it->second.Buffer.get();
109 | }
110 |
111 | template
112 | T GetValueOrDefault(PCWSTR name, const T& def = T()) const {
113 | auto it = _settings.find(name);
114 | if (it == _settings.end())
115 | return def;
116 | ATLASSERT(it->second.Size == sizeof(T));
117 | return *(T*)it->second.Buffer.get();
118 | }
119 |
120 | int GetInt32(PCWSTR name) const;
121 |
122 | template
123 | T* GetBinary(PCWSTR name) const {
124 | auto it = _settings.find(name);
125 | if (it == _settings.end())
126 | return nullptr;
127 | ATLASSERT(it->second.Size == sizeof(T));
128 | return (T*)it->second.Buffer.get();
129 | }
130 |
131 | protected:
132 | struct LessNoCase {
133 | bool operator()(const std::wstring& s1, const std::wstring& s2) const {
134 | return ::_wcsicmp(s1.c_str(), s2.c_str()) < 0;
135 | }
136 | };
137 | std::map _settings;
138 | std::wstring _path;
139 | };
140 |
141 |
--------------------------------------------------------------------------------
/WMIExp/WMIExp.cpp:
--------------------------------------------------------------------------------
1 | // WMIExp.cpp : main source file for WMIExp.exe
2 | //
3 |
4 | #include "pch.h"
5 | #include "resource.h"
6 | #include "MainFrm.h"
7 |
8 | CAppModule _Module;
9 |
10 | int Run(LPTSTR /*lpstrCmdLine*/ = nullptr, int nCmdShow = SW_SHOWDEFAULT) {
11 | CMessageLoop theLoop;
12 | _Module.AddMessageLoop(&theLoop);
13 |
14 | CMainFrame wndMain;
15 |
16 | if (wndMain.CreateEx() == nullptr) {
17 | ATLTRACE(_T("Main window creation failed!\n"));
18 | return 0;
19 | }
20 |
21 | wndMain.ShowWindow(nCmdShow);
22 |
23 | int nRet = theLoop.Run();
24 |
25 | _Module.RemoveMessageLoop();
26 | return nRet;
27 | }
28 |
29 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) {
30 | auto hr = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
31 | ATLASSERT(SUCCEEDED(hr));
32 |
33 | //
34 | // needed to prevent access denied errors from WMI
35 | //
36 | hr = ::CoInitializeSecurity(
37 | nullptr,
38 | -1, // COM authentication
39 | nullptr, // Authentication services
40 | nullptr, // Reserved
41 | RPC_C_AUTHN_LEVEL_DEFAULT,
42 | RPC_C_IMP_LEVEL_DELEGATE,
43 | nullptr, // Authentication info
44 | EOAC_NONE, // Additional capabilities
45 | nullptr);
46 | ATLASSERT(SUCCEEDED(hr));
47 |
48 | AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES);
49 |
50 | hr = _Module.Init(nullptr, hInstance);
51 | ATLASSERT(SUCCEEDED(hr));
52 |
53 | int nRet = Run(lpstrCmdLine, nCmdShow);
54 |
55 | _Module.Term();
56 | ::CoUninitialize();
57 |
58 | return nRet;
59 | }
60 |
--------------------------------------------------------------------------------
/WMIExp/WMIExp.h:
--------------------------------------------------------------------------------
1 | // WMIExp.h
2 |
--------------------------------------------------------------------------------
/WMIExp/WMIExp.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zodiacon/WMIExplorer/f8e4aef4769fd1dd9f00d7848d64dcc8578aae0e/WMIExp/WMIExp.rc
--------------------------------------------------------------------------------
/WMIExp/WMIExp.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {AA7F6FBE-6964-4D88-B8D1-08F906FFFD4A}
24 | 10.0
25 |
26 |
27 |
28 | Application
29 | true
30 | v143
31 | Unicode
32 |
33 |
34 | Application
35 | false
36 | v143
37 | Unicode
38 |
39 |
40 | Application
41 | true
42 | v143
43 | Unicode
44 |
45 |
46 | Application
47 | false
48 | v143
49 | Unicode
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 |
72 |
73 | true
74 |
75 |
76 | false
77 |
78 |
79 | false
80 |
81 |
82 |
83 | Use
84 | Level3
85 | MultiThreadedDebug
86 | EditAndContinue
87 | EnableFastChecks
88 | Disabled
89 | WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions)
90 | pch.h
91 | ..\WTLHelper
92 | stdcpp20
93 |
94 |
95 | Windows
96 | true
97 |
98 |
99 | 0x0409
100 | $(IntDir);%(AdditionalIncludeDirectories)
101 | _DEBUG;%(PreprocessorDefinitions)
102 |
103 |
104 | false
105 | Win32
106 | _DEBUG;%(PreprocessorDefinitions)
107 | WMIExp.h
108 | WMIExp_i.c
109 | WMIExp_p.c
110 | true
111 | $(IntDir)/WMIExp.tlb
112 |
113 |
114 |
115 |
116 |
117 | Use
118 | Level3
119 | MultiThreadedDebug
120 | EditAndContinue
121 | EnableFastChecks
122 | Disabled
123 | _WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions)
124 | pch.h
125 | ..\WTLHelper
126 | stdcpp20
127 |
128 |
129 | Windows
130 | true
131 |
132 |
133 | 0x0409
134 | $(IntDir);%(AdditionalIncludeDirectories)
135 | _DEBUG;%(PreprocessorDefinitions)
136 |
137 |
138 | false
139 | _DEBUG;%(PreprocessorDefinitions)
140 | WMIExp.h
141 | WMIExp_i.c
142 | WMIExp_p.c
143 | true
144 | $(IntDir)/WMIExp.tlb
145 |
146 |
147 |
148 |
149 |
150 | Use
151 | Level3
152 | MultiThreaded
153 | Sync
154 |
155 | WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)
156 | pch.h
157 | ..\WTLHelper
158 | stdcpp20
159 |
160 |
161 | Windows
162 |
163 |
164 | 0x0409
165 | $(IntDir);%(AdditionalIncludeDirectories)
166 | NDEBUG;%(PreprocessorDefinitions)
167 |
168 |
169 | false
170 | Win32
171 | NDEBUG;%(PreprocessorDefinitions)
172 | WMIExp.h
173 | WMIExp_i.c
174 | WMIExp_p.c
175 | true
176 | $(IntDir)/WMIExp.tlb
177 |
178 |
179 |
180 |
181 |
182 | Use
183 | Level3
184 | MultiThreaded
185 | Sync
186 |
187 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)
188 | pch.h
189 | ..\WTLHelper
190 | stdcpp20
191 |
192 |
193 | Windows
194 |
195 |
196 | 0x0409
197 | $(IntDir);%(AdditionalIncludeDirectories)
198 | NDEBUG;%(PreprocessorDefinitions)
199 |
200 |
201 | false
202 | NDEBUG;%(PreprocessorDefinitions)
203 | WMIExp.h
204 | WMIExp_i.c
205 | WMIExp_p.c
206 | true
207 | $(IntDir)/WMIExp.tlb
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | Create
216 | Create
217 | Create
218 | Create
219 |
220 |
221 |
222 |
223 | CppCode
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 | {be107d73-39aa-4ea8-b7ba-b0e26c018b98}
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
266 |
267 |
268 |
269 |
--------------------------------------------------------------------------------
/WMIExp/WMIExp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {82cbe054-888b-4cc6-a3c6-edec663ab069}
6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm
7 |
8 |
9 | {3c7a8add-394a-4480-879f-24013b753445}
10 | h;hpp;hxx;hm;inl;inc
11 |
12 |
13 | {4a923535-423a-4c75-beaa-441613545488}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest
15 |
16 |
17 | {1f37ca0a-7425-4fab-aac4-4bf51b9d183d}
18 |
19 |
20 | {ca9049d8-69a1-4c74-835a-0b3541a1b2a8}
21 |
22 |
23 | {abd1dcba-2af0-4dd2-a8c5-f9232767cfe7}
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 | Dialogs
38 |
39 |
40 | Helpers
41 |
42 |
43 | Source Files
44 |
45 |
46 | Helpers
47 |
48 |
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 | Resource Files
58 |
59 |
60 | Dialogs
61 |
62 |
63 | Helpers
64 |
65 |
66 | Header Files
67 |
68 |
69 | Header Files
70 |
71 |
72 | Helpers
73 |
74 |
75 |
76 |
77 | Resource Files
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | Resource Files\Icons
86 |
87 |
88 | Resource Files\Icons
89 |
90 |
91 | Resource Files\Icons
92 |
93 |
94 | Resource Files\Icons
95 |
96 |
97 | Resource Files\Icons
98 |
99 |
100 | Resource Files\Icons
101 |
102 |
103 | Resource Files\Icons
104 |
105 |
106 | Resource Files\Icons
107 |
108 |
109 | Resource Files\Icons
110 |
111 |
112 |
--------------------------------------------------------------------------------
/WMIExp/WMIHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "WMIHelper.h"
3 |
4 | class CObjectSink :
5 | public IObjectsCallback,
6 | public CComObjectRoot,
7 | public IWbemObjectSink {
8 | public:
9 | BEGIN_COM_MAP(CObjectSink)
10 | COM_INTERFACE_ENTRY(IWbemObjectSink)
11 | END_COM_MAP()
12 |
13 | void Init(HWND hWnd, UINT msg) {
14 | m_hWnd = hWnd;
15 | m_Msg = msg;
16 | }
17 |
18 | int GetObjectCount() const override {
19 | return (int)m_Objects.size();
20 | }
21 | CComPtr GetItem(int i) const override {
22 | return m_Objects[i];
23 | }
24 |
25 | private:
26 | // Inherited via IWbemObjectSink
27 | HRESULT __stdcall Indicate(long lObjectCount, IWbemClassObject** apObjArray) override {
28 | for (int i = 0; i < lObjectCount; i++)
29 | m_Objects.push_back(apObjArray[i]);
30 | return S_OK;
31 | }
32 | HRESULT __stdcall SetStatus(long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject* pObjParam) override {
33 | if (lFlags == WBEM_STATUS_COMPLETE && !m_Objects.empty()) {
34 | AddRef();
35 | ::PostMessage(m_hWnd, m_Msg, 0, reinterpret_cast(static_cast(this)));
36 | }
37 | return S_OK;
38 | }
39 |
40 | HWND m_hWnd;
41 | UINT m_Msg;
42 | std::vector> m_Objects;
43 | };
44 |
45 | HRESULT WMIHelper::Init(PCWSTR computerName, PCWSTR ns, IWbemServices** ppWmi) {
46 | CComPtr spLocator;
47 | auto hr = spLocator.CoCreateInstance(__uuidof(WbemLocator));
48 | if (FAILED(hr))
49 | return hr;
50 |
51 | return spLocator->ConnectServer(CComBSTR(ns),
52 | nullptr, nullptr, nullptr, WBEM_FLAG_CONNECT_USE_MAX_WAIT, nullptr, nullptr, ppWmi);
53 | }
54 |
55 | std::vector> WMIHelper::EnumNamespaces(IWbemServices* pWmi) {
56 | std::vector> ns;
57 | CComPtr spEnum;
58 | //auto hr = pWmi->ExecQuery(CComBSTR(L"WQL"), CComBSTR(L"SELECT * FROM __NAMESPACE"), 0, nullptr, &spEnum);
59 | auto hr = pWmi->CreateInstanceEnum(CComBSTR(L"__NAMESPACE"), 0, nullptr, &spEnum);
60 | if (FAILED(hr))
61 | return ns;
62 |
63 | CComPtr spObj;
64 | ULONG count;
65 | while (S_OK == spEnum->Next(WBEM_INFINITE, 1, &spObj, &count)) {
66 | ns.push_back(spObj);
67 | spObj.Release();
68 | }
69 | return ns;
70 | }
71 |
72 | std::vector> WMIHelper::EnumClasses(IWbemServices* pSvc, bool deep, bool includeSystemClasses) {
73 | std::vector> classes;
74 | CComPtr spEnum;
75 | auto hr = pSvc->CreateClassEnum(nullptr, (deep ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW) | WBEM_FLAG_FORWARD_ONLY, nullptr, &spEnum);
76 | if (FAILED(hr))
77 | return classes;
78 |
79 | CComPtr spObj;
80 | ULONG count;
81 | while (S_OK == spEnum->Next(WBEM_INFINITE, 1, &spObj, &count)) {
82 | if (!includeSystemClasses) {
83 | auto dynasty = GetStringProperty(spObj, L"__DYNASTY");
84 | if (dynasty.CompareNoCase(L"__SystemClass") == 0) {
85 | spObj.Release();
86 | continue;
87 | }
88 | }
89 | classes.push_back(spObj);
90 | spObj.Release();
91 | }
92 | return classes;
93 | }
94 |
95 | std::vector> WMIHelper::EnumInstances(PCWSTR name, IWbemServices* pSvc, bool deep) {
96 | std::vector> instances;
97 | CComPtr spEnum;
98 | auto hr = pSvc->CreateInstanceEnum(CComBSTR(name), (deep ? WBEM_FLAG_DEEP : 0) | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &spEnum);
99 | if (FAILED(hr))
100 | return instances;
101 |
102 | CComPtr spObj;
103 | ULONG count;
104 | while (S_OK == spEnum->Next(WBEM_INFINITE, 1, &spObj, &count)) {
105 | instances.push_back(spObj);
106 | spObj.Release();
107 | }
108 | return instances;
109 | }
110 |
111 | bool WMIHelper::EnumInstancesAsync(HWND hWnd, UINT msg, PCWSTR name, IWbemServices* pSvc, bool deep) {
112 | CComObject* pSink;
113 | pSink->CreateInstance(&pSink);
114 | pSink->Init(hWnd, msg);
115 | auto hr = pSvc->CreateInstanceEnumAsync(CComBSTR(name), (deep ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW), nullptr, pSink);
116 | if (FAILED(hr))
117 | return false;
118 |
119 | return true;
120 | }
121 |
122 | std::vector WMIHelper::EnumProperties(IWbemClassObject* pObj) {
123 | std::vector props;
124 | pObj->BeginEnumeration(0);
125 | WMIProperty prop;
126 | while (S_OK == pObj->Next(0, &prop.Name, &prop.Value, &prop.Type, &prop.Flavor)) {
127 | props.push_back(std::move(prop));
128 | prop.Value.Clear();
129 | }
130 | pObj->EndEnumeration();
131 | return props;
132 | }
133 |
134 | std::vector WMIHelper::EnumMethods(IWbemClassObject* pObj, bool localOnly, bool inheritedOnly) {
135 | std::vector methods;
136 | pObj->BeginMethodEnumeration((localOnly ? WBEM_FLAG_LOCAL_ONLY : 0) | (inheritedOnly ? WBEM_FLAG_PROPAGATED_ONLY : 0));
137 | CComBSTR name;
138 | WMIMethod method;
139 | while (S_OK == pObj->NextMethod(0, &name, method.spInParams.addressof(), method.spOutParams.addressof())) {
140 | method.Name = name.m_str;
141 | pObj->GetMethodOrigin(method.Name.c_str(), &name);
142 | method.ClassName = name.m_str;
143 | methods.push_back(std::move(method));
144 | }
145 | pObj->EndMethodEnumeration();
146 | return methods;
147 | }
148 |
149 | std::vector WMIHelper::GetNames(IWbemClassObject* pObj) {
150 | std::vector names;
151 | SAFEARRAY* sa;
152 | pObj->GetNames(nullptr, 0, nullptr, &sa);
153 | auto count = sa->cbElements;
154 | for (ULONG i = 0; i < count; i++) {
155 | LONG index = i;
156 | BSTR name;
157 | ::SafeArrayGetElement(sa, &index, &name);
158 | CComBSTR bname;
159 | bname.Attach(name);
160 | names.push_back(bname);
161 | }
162 | ::SafeArrayDestroy(sa);
163 | return names;
164 | }
165 |
166 | CString WMIHelper::GetStringProperty(IWbemClassObject* pObj, PCWSTR name) {
167 | CComVariant value;
168 | if (FAILED(pObj->Get(name, 0, &value, nullptr, nullptr)))
169 | return L"";
170 |
171 | if (value.vt != VT_BSTR)
172 | return L"";
173 | return value.bstrVal;
174 | }
175 |
--------------------------------------------------------------------------------
/WMIExp/WMIHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | struct WMIProperty {
6 | CComBSTR Name;
7 | CComVariant Value;
8 | CIMTYPE Type;
9 | long Flavor;
10 | };
11 |
12 | struct WMIMethod {
13 | std::wstring Name;
14 | wil::com_ptr spInParams, spOutParams;
15 | std::wstring ClassName;
16 | };
17 |
18 | struct IObjectsCallback {
19 | virtual int GetObjectCount() const = 0;
20 | virtual CComPtr GetItem(int i) const = 0;
21 | virtual ULONG Release() = 0;
22 | };
23 |
24 | struct WMIHelper abstract final {
25 | static HRESULT Init(PCWSTR computerName, PCWSTR ns, IWbemServices** ppWmi);
26 | static CString GetStringProperty(IWbemClassObject* pObj, PCWSTR name);
27 | static std::vector> EnumNamespaces(IWbemServices* pWmi);
28 | static std::vector> EnumClasses(IWbemServices* pSvc, bool deep, bool includeSystemClasses = false);
29 | static std::vector> EnumInstances(PCWSTR name, IWbemServices* pSvc, bool deep);
30 | static bool EnumInstancesAsync(HWND hWnd, UINT msg, PCWSTR name, IWbemServices* pSvc, bool deep);
31 | static std::vector EnumProperties(IWbemClassObject* pObj);
32 | static std::vector EnumMethods(IWbemClassObject* pObj, bool localOnly = false, bool inheritedOnly = false);
33 | static std::vector GetNames(IWbemClassObject* pObj);
34 | };
35 |
--------------------------------------------------------------------------------
/WMIExp/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/WMIExp/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp : source file that includes just the standard includes
2 | // WMIExp.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "pch.h"
6 |
--------------------------------------------------------------------------------
/WMIExp/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Change these values to use different versions
4 | #define WINVER 0x0601
5 | #define _WIN32_WINNT 0x0601
6 | #define _WIN32_IE 0x0700
7 | #define _RICHEDIT_VER 0x0500
8 | #define NOMINMAX
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | extern CAppModule _Module;
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include