-
Notifications
You must be signed in to change notification settings - Fork 0
/
show-properties.cpp
92 lines (73 loc) · 2.15 KB
/
show-properties.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#define WIN32_LEAN_AND_MEAN // Disables inclusion of many large headers
#define _WIN32_WINNT 0x0601 // Defines the version of Windows for <windows.h>
// clang-format off
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <string>
#include <iostream>
// clang-format on
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
/**
* This class is used to keep the program running while showing the Properties
* dialog. Without it the dialog closes as soon as the `showProperties()`
* function returns. See https://devblogs.microsoft.com/oldnewthing/?p=22163.
*/
class ProcessReference : public IUnknown {
public:
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IUnknown) {
*ppv = static_cast<IUnknown *>(this);
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) Release() {
LONG lRef = InterlockedDecrement(&m_cRef);
if (lRef == 0) {
PostThreadMessage(m_dwThread, WM_NULL, 0, 0);
}
return lRef;
}
ProcessReference() : m_cRef(1), m_dwThread(GetCurrentThreadId()) {
SHSetInstanceExplorer(this);
}
~ProcessReference() {
SHSetInstanceExplorer(NULL);
Release();
MSG msg;
while (m_cRef && GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
private:
LONG m_cRef;
DWORD m_dwThread;
};
void showProperties(char *path) {
// Keeps the executable alive until the dialog is closed
ProcessReference ref;
// Create the info struct and fill it
SHELLEXECUTEINFO info = {sizeof(info)};
info.fMask = SEE_MASK_INVOKEIDLIST;
info.nShow = SW_SHOWNORMAL;
info.lpVerb = "properties";
info.lpFile = path;
// Show the properties by executing with the info struct
ShellExecuteEx(&info);
}
int main(int argc, char *argv[]) {
if (argc == 1) {
std::cout << "file or directory path is required to show properties"
<< std::endl;
std::cout << "usage: show-properties.exe <path to file or directory>";
return 1;
}
showProperties(argv[1]);
return 0;
}