OSDN Git Service

Wix3.6に対応した
[completeeraser/CompleteEraser.git] / ShellExtension / ContextMenu.cpp
1 #include "ContextMenu.h"\r
2 #include "resource.h"\r
3 \r
4 #define EXEPATH L"CompleteEraser.EXE"\r
5 \r
6 HANDLE CContextMenu::m_hMapping;\r
7 \r
8 CContextMenu::CContextMenu()\r
9 {\r
10         m_cRef = 1;\r
11 \r
12         WCHAR wszLocale[MAX_PATH];\r
13         GetLocaleInfoW(GetThreadLocale(),\r
14                                 LOCALE_SABBREVLANGNAME,wszLocale,MAX_PATH);\r
15         _wsetlocale(LC_ALL,wszLocale);\r
16 \r
17         LockModule(TRUE);\r
18 }\r
19 \r
20 CContextMenu::~CContextMenu()\r
21 {\r
22         LockModule(FALSE);\r
23 }\r
24 \r
25 STDMETHODIMP_(ULONG) CContextMenu::AddRef()\r
26 {\r
27         return InterlockedIncrement(&m_cRef);\r
28 }\r
29 \r
30 STDMETHODIMP_(ULONG) CContextMenu::Release()\r
31 {\r
32         if (InterlockedDecrement(&m_cRef) == 0) {       \r
33                 delete this;\r
34                 return 0;\r
35         }\r
36 \r
37         return m_cRef;\r
38 }\r
39 \r
40 STDMETHODIMP CContextMenu::QueryInterface(REFIID riid, void **ppvObject)\r
41 {\r
42         *ppvObject = NULL;\r
43 \r
44         if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IContextMenu))\r
45                 *ppvObject = static_cast<IContextMenu *>(this);\r
46         else if (IsEqualIID(riid, IID_IShellExtInit))\r
47                 *ppvObject = static_cast<IShellExtInit *>(this);\r
48         else\r
49                 return E_NOINTERFACE;\r
50 \r
51         AddRef();\r
52 \r
53         return S_OK;\r
54 }\r
55 \r
56 STDMETHODIMP CContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)\r
57 {\r
58         WCHAR* temp;\r
59         DWORD size;\r
60         ::RegQueryValueEx(hkeyProgID,L"",NULL,NULL,NULL,&size);\r
61         temp = new WCHAR[size];\r
62         ::RegQueryValueEx(hkeyProgID,L"",NULL,NULL,(LPBYTE)temp,&size);\r
63         std::wstring value(temp);\r
64 \r
65         if(value == L"Recycle Bin")\r
66         {\r
67                 menutype = ClearRecyleBin;\r
68                 return S_OK;\r
69         }\r
70 \r
71         FORMATETC fetc = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
72 \r
73         STGMEDIUM medium;\r
74         HRESULT hr = pdtobj->GetData(&fetc, &medium);\r
75         if(FAILED(hr))\r
76                 return hr;\r
77 \r
78         HDROP DropData = (HDROP)GlobalLock(medium.hGlobal);     //\83\8d\83b\83N\82µ\82È\82¢\82Æ\97\8e\82¿\82é\82±\82Æ\82ª\82 \82é\r
79 \r
80         UINT count = DragQueryFile(DropData,0xFFFFFFFF,NULL,0);\r
81 \r
82         for(UINT i = 0; i < count; i++)\r
83         {\r
84                 WCHAR file[_MAX_PATH];\r
85                 DragQueryFile((HDROP)medium.hGlobal, i, file, sizeof(file));\r
86                 this->strs.append(file);\r
87                 this->strs.append(L"\n");\r
88         }\r
89 \r
90         GlobalUnlock(DropData);\r
91 \r
92         ReleaseStgMedium(&medium);\r
93 \r
94         menutype = ClearFileNames;\r
95 \r
96         return S_OK;\r
97 }\r
98 \r
99 STDMETHODIMP CContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)\r
100 {\r
101         MENUITEMINFO mii;\r
102         \r
103         if (uFlags & CMF_DEFAULTONLY)\r
104                 return MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 0);\r
105 \r
106         mii.cbSize     = sizeof(MENUITEMINFO);\r
107         mii.fMask      = MIIM_ID | MIIM_TYPE;\r
108         mii.fType      = MFT_STRING;\r
109         mii.wID        = idCmdFirst;\r
110 \r
111         if(menutype == ClearFileNames)\r
112         {\r
113                 std::wstring str;\r
114                 MyLoadString(str,MENUITEMNAME);\r
115                 mii.dwTypeData = const_cast<LPWSTR>(str.c_str());\r
116                 InsertMenuItem(hmenu, indexMenu, TRUE, &mii);\r
117         }else if(menutype == ClearRecyleBin){\r
118                 std::wstring str;\r
119                 MyLoadString(str,MENUITEMNAME_RECYLEBIN);\r
120                 mii.dwTypeData = const_cast<LPWSTR>(str.c_str());\r
121 \r
122                 SHQUERYRBINFO sqrbi;\r
123                 ZeroMemory(&sqrbi, sizeof(sqrbi));\r
124                 sqrbi.cbSize = sizeof(sqrbi);\r
125                 if(SUCCEEDED(SHQueryRecycleBin(NULL, &sqrbi)))\r
126                 {\r
127                         mii.fState |= (sqrbi.i64NumItems != 0) ? MFS_ENABLED : MFS_DISABLED;\r
128                 }\r
129 \r
130                 InsertMenuItem(hmenu, indexMenu, TRUE, &mii);\r
131         }\r
132         \r
133         return MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 2);\r
134 }\r
135 \r
136 STDMETHODIMP CContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)\r
137 {\r
138         UINT idCmd = LOWORD(pici->lpVerb);\r
139 \r
140         if (HIWORD(pici->lpVerb) != 0)\r
141                 return E_INVALIDARG;\r
142 \r
143         if (idCmd != 0)\r
144                 return S_OK;\r
145 \r
146         std::wstring str;\r
147         MyLoadString(str,CONFIRMDELETE);\r
148         if(MessageBoxW(NULL,str.c_str(),NULL,MB_YESNO) == IDNO)\r
149                 return S_OK;\r
150 \r
151         if (menutype == ClearFileNames)\r
152         {\r
153                 UINT mapSize = this->strs.length() * sizeof(wchar_t);\r
154 \r
155                 m_hMapping = ::CreateFileMappingW(INVALID_HANDLE_VALUE,\r
156                         NULL,\r
157                         PAGE_READWRITE,\r
158                         0,\r
159                         mapSize,\r
160                         L"CompleteEraser.MemMap");\r
161                 if(m_hMapping == NULL)\r
162                         return E_FAIL;\r
163 \r
164                 void *m_pMappingView = MapViewOfFile(m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);\r
165                 if(m_pMappingView == NULL)\r
166                         return E_FAIL;\r
167 \r
168                 ::wcscat_s((LPWSTR)m_pMappingView,mapSize,this->strs.c_str());\r
169 \r
170                 UnmapViewOfFile(m_pMappingView);\r
171 \r
172                 DWORD dwID;\r
173                 CreateThread(NULL , 0 , ThreadFunc , (LPVOID)this , 0 , &dwID);\r
174         }\r
175         else if (menutype == ClearRecyleBin)\r
176         {\r
177                 RunCompleteEraer(L"/recylebin");\r
178         }\r
179 \r
180         return S_OK;\r
181 }\r
182 \r
183 STDMETHODIMP CContextMenu::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)\r
184 {\r
185         if (idCmd == 0) {\r
186                 std::wstring str;\r
187                 if (uFlags == GCS_HELPTEXTW)\r
188                 {\r
189                         MyLoadString(str,MENUHELPMSG);\r
190                         ::wcscpy_s((LPWSTR)pszName,cchMax,str.c_str());\r
191                 }\r
192                 else if (uFlags == GCS_VERBW)\r
193                 {\r
194                         MyLoadString(str,MENUITEMNAME);\r
195                         ::wcscpy_s((LPWSTR)pszName,cchMax,str.c_str());\r
196                 }\r
197         }\r
198         else\r
199                 return E_FAIL;\r
200 \r
201         return S_OK;\r
202 }\r
203 \r
204 DWORD WINAPI CContextMenu::ThreadFunc(LPVOID pParam)\r
205 {\r
206         HANDLE hProcess = RunCompleteEraer(L"");\r
207 \r
208         WaitForSingleObject(hProcess,INFINITE);\r
209 \r
210         CloseHandle(m_hMapping);\r
211 \r
212         return 0;\r
213 }\r
214 \r
215 HANDLE CContextMenu::RunCompleteEraer(LPTSTR cmdline)\r
216 {\r
217         WCHAR modPath[_MAX_PATH];\r
218         GetModulePath(modPath,_MAX_PATH);\r
219 \r
220         SHELLEXECUTEINFO info = {0};\r
221         info.cbSize = sizeof(info);\r
222         info.hwnd = NULL;\r
223         info.nShow = SW_SHOWNORMAL;\r
224         info.fMask = SEE_MASK_NOCLOSEPROCESS;\r
225         info.lpDirectory = modPath;\r
226         info.lpFile = EXEPATH;\r
227         info.lpParameters = cmdline;\r
228         ShellExecuteEx(&info);\r
229 \r
230         return info.hProcess;\r
231 }\r