33#include < windows.h>
44
55#include < propkey.h>
6- #include < propvarutil.h>
76#include < shobjidl.h>
87
9- #include < atomic>
108#include < functional>
119#include < string>
1210
1614
1715namespace {
1816
19- const std::wstring& GetCustomAppUserModelID () {
17+ std::wstring_view GetCustomAppUserModelID () {
2018 static const std::wstring custom_appid = [] {
2119 auto hash = std::hash<std::wstring>{}(GetAppDir ());
22- wchar_t buf[48 ];
23- swprintf_s (buf, L" ChromePlusNext.%016llX" ,
24- static_cast <unsigned long long >(hash));
25- return std::wstring (buf);
20+ constexpr wchar_t hex[] = L" 0123456789ABCDEF" ;
21+ std::wstring result = L" CPN." ;
22+ for (int i = 60 ; i >= 0 ; i -= 4 ) {
23+ result += hex[(hash >> i) & 0xF ];
24+ }
25+ return result;
2626 }();
2727 return custom_appid;
2828}
2929
30- class PropertyStoreWrapper final : public IPropertyStore {
31- public:
32- explicit PropertyStoreWrapper (IPropertyStore* real_store)
33- : real_store_(real_store) {}
34-
35- ~PropertyStoreWrapper () {
36- if (real_store_) {
37- real_store_->Release ();
38- }
39- }
40-
41- PropertyStoreWrapper (const PropertyStoreWrapper&) = delete ;
42- PropertyStoreWrapper& operator =(const PropertyStoreWrapper&) = delete ;
43-
44- HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void ** ppv) override {
45- if (!ppv) {
46- return E_POINTER;
47- }
48- if (riid == IID_IUnknown || riid == IID_IPropertyStore) {
49- *ppv = static_cast <IPropertyStore*>(this );
50- AddRef ();
51- return S_OK;
52- }
53- return real_store_->QueryInterface (riid, ppv);
54- }
55-
56- ULONG STDMETHODCALLTYPE AddRef () override {
57- return ref_count_.fetch_add (1 , std::memory_order_relaxed) + 1 ;
58- }
59-
60- ULONG STDMETHODCALLTYPE Release () override {
61- auto count = ref_count_.fetch_sub (1 , std::memory_order_acq_rel) - 1 ;
62- if (count == 0 ) {
63- delete this ;
64- }
65- return count;
66- }
67-
68- HRESULT STDMETHODCALLTYPE GetCount (DWORD* cProps) override {
69- return real_store_->GetCount (cProps);
30+ PROPVARIANT MakeAppIdVariant () {
31+ const auto & src = GetCustomAppUserModelID ();
32+ auto len = src.size () + 1 ;
33+ PROPVARIANT pv{};
34+ pv.vt = VT_LPWSTR;
35+ pv.pwszVal = static_cast <LPWSTR>(CoTaskMemAlloc (len * sizeof (wchar_t )));
36+ if (pv.pwszVal ) {
37+ memcpy (pv.pwszVal , src.data (), len * sizeof (wchar_t ));
7038 }
71-
72- HRESULT STDMETHODCALLTYPE GetAt (DWORD iProp, PROPERTYKEY* pkey) override {
73- return real_store_->GetAt (iProp, pkey);
74- }
75-
76- HRESULT STDMETHODCALLTYPE GetValue (REFPROPERTYKEY key,
77- PROPVARIANT* pv) override {
78- if (IsEqualPropertyKey (key, PKEY_AppUserModel_ID)) {
79- return InitPropVariantFromString (GetCustomAppUserModelID ().c_str (), pv);
80- }
81- return real_store_->GetValue (key, pv);
82- }
83-
84- HRESULT STDMETHODCALLTYPE SetValue (REFPROPERTYKEY key,
85- REFPROPVARIANT propvar) override {
86- if (IsEqualPropertyKey (key, PKEY_AppUserModel_ID)) {
87- PROPVARIANT pv{};
88- if (auto hr =
89- InitPropVariantFromString (GetCustomAppUserModelID ().c_str (), &pv);
90- FAILED (hr)) {
91- return hr;
92- }
93- auto hr = real_store_->SetValue (key, pv);
94- PropVariantClear (&pv);
95- return hr;
96- }
97- return real_store_->SetValue (key, propvar);
98- }
99-
100- HRESULT STDMETHODCALLTYPE Commit () override { return real_store_->Commit (); }
101-
102- private:
103- IPropertyStore* real_store_;
104- std::atomic<ULONG> ref_count_{1 };
105- };
39+ return pv;
40+ }
10641
10742static auto RawSetCurrentProcessExplicitAppUserModelID =
10843 SetCurrentProcessExplicitAppUserModelID;
10944
11045HRESULT WINAPI MySetCurrentProcessExplicitAppUserModelID (PCWSTR appid) {
11146 return RawSetCurrentProcessExplicitAppUserModelID (
112- GetCustomAppUserModelID ().c_str ());
47+ GetCustomAppUserModelID ().data ());
48+ }
49+
50+ using SetValueFn = HRESULT(STDMETHODCALLTYPE*)(IPropertyStore*,
51+ REFPROPERTYKEY,
52+ REFPROPVARIANT);
53+ static SetValueFn RawPropertyStoreSetValue = nullptr ;
54+
55+ HRESULT STDMETHODCALLTYPE MyPropertyStoreSetValue (IPropertyStore* self,
56+ REFPROPERTYKEY key,
57+ REFPROPVARIANT propvar) {
58+ if (IsEqualPropertyKey (key, PKEY_AppUserModel_ID)) {
59+ auto pv = MakeAppIdVariant ();
60+ auto hr = RawPropertyStoreSetValue (self, key, pv);
61+ PropVariantClear (&pv);
62+ return hr;
63+ }
64+ return RawPropertyStoreSetValue (self, key, propvar);
11365}
11466
11567static auto RawSHGetPropertyStoreForWindow = SHGetPropertyStoreForWindow;
@@ -118,11 +70,17 @@ HRESULT WINAPI MySHGetPropertyStoreForWindow(HWND hwnd,
11870 REFIID riid,
11971 void ** ppv) {
12072 HRESULT hr = RawSHGetPropertyStoreForWindow (hwnd, riid, ppv);
121- if (SUCCEEDED (hr) && ppv && *ppv && riid == IID_IPropertyStore) {
122- auto * wrapper = new (std::nothrow)
123- PropertyStoreWrapper (static_cast <IPropertyStore*>(*ppv));
124- if (wrapper) {
125- *ppv = static_cast <IPropertyStore*>(wrapper);
73+ if (SUCCEEDED (hr) && ppv && *ppv && riid == IID_IPropertyStore &&
74+ !RawPropertyStoreSetValue) {
75+ auto ** vtable = *reinterpret_cast <void ***>(*ppv);
76+ RawPropertyStoreSetValue = reinterpret_cast <SetValueFn>(vtable[6 ]);
77+ DetourTransactionBegin ();
78+ DetourUpdateThread (GetCurrentThread ());
79+ DetourAttach (reinterpret_cast <LPVOID*>(&RawPropertyStoreSetValue),
80+ reinterpret_cast <void *>(MyPropertyStoreSetValue));
81+ auto status = DetourTransactionCommit ();
82+ if (status != NO_ERROR) {
83+ DebugLog (L" Hook PropertyStore::SetValue failed {}" , status);
12684 }
12785 }
12886 return hr;
0 commit comments