forked from FauxFaux/taglibhandler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dll.cpp
145 lines (116 loc) · 3.23 KB
/
Dll.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "dllregister.h"
// Reference count for the DLL
LONG g_cLocks = 0;
// Handle the the DLL's module
HMODULE g_hmodThis;
// Standard DLL functions
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD, LPVOID)
{
g_hmodThis = (HMODULE)hModule;
return TRUE;
}
STDAPI DllCanUnloadNow()
{
// Only allow the DLL to be unloaded after all outstanding references have been released
return (g_cLocks == 0) ? S_OK : S_FALSE;
}
void DllAddRef()
{
// Increment the reference count on the DLL
InterlockedIncrement(&g_cLocks);
}
void DllRelease()
{
// Decrement the reference count on the DLL
InterlockedDecrement(&g_cLocks);
}
// Constructor for CTagLibPropertyStore
HRESULT CTagLibPropertyStore_CreateInstance(REFIID riid, void **ppv);
// Class factory for CTagLibPropertyHandler
class CTagLibPropertyHandlerClassFactory : public IClassFactory
{
public:
// IUnknown methods
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = {
QITABENT(CTagLibPropertyHandlerClassFactory, IClassFactory),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) AddRef()
{
DllAddRef();
return 2; // Object's lifetime is tied to the DLL, so no need to track its refcount
}
IFACEMETHODIMP_(ULONG) Release()
{
DllRelease();
return 1; // Object's lifetime is tied to the DLL, so no need to track its refcount or manually delete it
}
// IClassFactory methods
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
// Aggregation is not supported
return pUnkOuter ? CLASS_E_NOAGGREGATION : CTagLibPropertyStore_CreateInstance(riid, ppv);
}
IFACEMETHODIMP LockServer(BOOL fLock)
{
if (fLock)
DllAddRef();
else
DllRelease();
return S_OK;
}
};
// Single global instance of the class factory object
CTagLibPropertyHandlerClassFactory g_cfDebugPropertyHandler;
// Export called by CoCreateInstance to obtain a class factory for the specified CLSID
STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
{
if (clsid == CLSID_US)
return g_cfDebugPropertyHandler.QueryInterface(riid, ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
// Registers this COM server
STDAPI DllRegisterServer()
{
HRESULT hr = E_FAIL;
WCHAR szModuleName[MAX_PATH];
if (!GetModuleFileNameW(g_hmodThis, szModuleName, ARRAYSIZE(szModuleName)))
hr = HRESULT_FROM_WIN32(GetLastError());
else
{
if (FAILED(hr = doRegistration(szModuleName)))
return hr;
// inform Explorer, et al of the new handler
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
}
return hr;
}
//
// Unregisters this COM server
//
STDAPI DllUnregisterServer()
{
HRESULT hr = S_OK;
// attempt to delete everything, even if some operations fail
DWORD dwCLSID = SHDeleteKeyW(HKEY_CLASSES_ROOT, L"CLSID\\" SZ_CLSID_US);
DWORD dwShellExtension = SHDeleteValueW(HKEY_LOCAL_MACHINE, SZ_APPROVEDSHELLEXTENSIONS, SZ_CLSID_US);
// return first error encountered as HRESULT
if (dwCLSID != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwCLSID);
}
else if (dwShellExtension != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwShellExtension);
}
if (SUCCEEDED(hr))
{
// inform Explorer, et al that the handler has been unregistered
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
}
return hr;
}