main.cpp (c2c66aff) | main.cpp (7b718d36) |
---|---|
1/* Copyright (c) Mark Harmstone 2016-17 2 * 3 * This file is part of WinBtrfs. 4 * 5 * WinBtrfs is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public Licence as published by 7 * the Free Software Foundation, either version 3 of the Licence, or 8 * (at your option) any later version. --- 6 unchanged lines hidden (view full) --- 15 * You should have received a copy of the GNU Lesser General Public Licence 16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include "shellext.h" 19#include <windows.h> 20#include <commctrl.h> 21#include <strsafe.h> 22#include <stddef.h> | 1/* Copyright (c) Mark Harmstone 2016-17 2 * 3 * This file is part of WinBtrfs. 4 * 5 * WinBtrfs is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public Licence as published by 7 * the Free Software Foundation, either version 3 of the Licence, or 8 * (at your option) any later version. --- 6 unchanged lines hidden (view full) --- 15 * You should have received a copy of the GNU Lesser General Public Licence 16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include "shellext.h" 19#include <windows.h> 20#include <commctrl.h> 21#include <strsafe.h> 22#include <stddef.h> |
23#include <stdexcept> |
|
23#include "factory.h" 24#include "resource.h" 25 26static const GUID CLSID_ShellBtrfsIconHandler = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf0 } }; 27static const GUID CLSID_ShellBtrfsContextMenu = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf1 } }; 28static const GUID CLSID_ShellBtrfsPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf2 } }; 29static const GUID CLSID_ShellBtrfsVolPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf3 } }; 30 --- 10 unchanged lines hidden (view full) --- 41} PROCESS_DPI_AWARENESS; 42 43typedef ULONG (WINAPI *_RtlNtStatusToDosError)(NTSTATUS Status); 44typedef HRESULT (WINAPI *_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); 45 46HMODULE module; 47LONG objs_loaded = 0; 48 | 24#include "factory.h" 25#include "resource.h" 26 27static const GUID CLSID_ShellBtrfsIconHandler = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf0 } }; 28static const GUID CLSID_ShellBtrfsContextMenu = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf1 } }; 29static const GUID CLSID_ShellBtrfsPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf2 } }; 30static const GUID CLSID_ShellBtrfsVolPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf3 } }; 31 --- 10 unchanged lines hidden (view full) --- 42} PROCESS_DPI_AWARENESS; 43 44typedef ULONG (WINAPI *_RtlNtStatusToDosError)(NTSTATUS Status); 45typedef HRESULT (WINAPI *_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); 46 47HMODULE module; 48LONG objs_loaded = 0; 49 |
49void ShowError(HWND hwnd, ULONG err) { 50 WCHAR* buf; 51 52 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, 53 err, 0, (WCHAR*)&buf, 0, NULL) == 0) { 54 MessageBoxW(hwnd, L"FormatMessage failed", L"Error", MB_ICONERROR); 55 return; 56 } 57 58 MessageBoxW(hwnd, buf, L"Error", MB_ICONERROR); 59 60 LocalFree(buf); 61} 62 63void ShowStringError(HWND hwndDlg, int num, ...) { 64 WCHAR title[255], s[1024], t[1024]; 65 va_list ap; 66 67 if (!LoadStringW(module, IDS_ERROR, title, sizeof(title) / sizeof(WCHAR))) { 68 ShowError(hwndDlg, GetLastError()); 69 return; 70 } 71 72 if (!LoadStringW(module, num, s, sizeof(s) / sizeof(WCHAR))) { 73 ShowError(hwndDlg, GetLastError()); 74 return; 75 } 76 77 va_start(ap, num); 78#ifndef __REACTOS__ 79 vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); 80#else 81 vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); 82#endif 83 84 MessageBoxW(hwndDlg, t, title, MB_ICONERROR); 85 86 va_end(ap); 87} 88 89void ShowNtStatusError(HWND hwnd, NTSTATUS Status) { 90 _RtlNtStatusToDosError RtlNtStatusToDosError; 91 HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); 92 93 if (!ntdll) { 94 MessageBoxW(hwnd, L"Error loading ntdll.dll", L"Error", MB_ICONERROR); 95 return; 96 } 97 98 RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); 99 100 if (!RtlNtStatusToDosError) { 101 MessageBoxW(hwnd, L"Error loading RtlNtStatusToDosError in ntdll.dll", L"Error", MB_ICONERROR); 102 FreeLibrary(ntdll); 103 return; 104 } 105 106 ShowError(hwnd, RtlNtStatusToDosError(Status)); 107 108 FreeLibrary(ntdll); 109} 110 | |
111void set_dpi_aware() { 112 _SetProcessDpiAwareness SetProcessDpiAwareness; 113 HMODULE shcore = LoadLibraryW(L"shcore.dll"); 114 115 if (!shcore) 116 return; 117 118 SetProcessDpiAwareness = (_SetProcessDpiAwareness)GetProcAddress(shcore, "SetProcessDpiAwareness"); 119 120 if (!SetProcessDpiAwareness) 121 return; 122 123 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 124} 125 | 50void set_dpi_aware() { 51 _SetProcessDpiAwareness SetProcessDpiAwareness; 52 HMODULE shcore = LoadLibraryW(L"shcore.dll"); 53 54 if (!shcore) 55 return; 56 57 SetProcessDpiAwareness = (_SetProcessDpiAwareness)GetProcAddress(shcore, "SetProcessDpiAwareness"); 58 59 if (!SetProcessDpiAwareness) 60 return; 61 62 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 63} 64 |
126void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes) { 127 WCHAR nb[255], nb2[255], t[255], bytes[255]; 128 WCHAR kb[255]; | 65void format_size(uint64_t size, wstring& s, bool show_bytes) { 66 wstring t, bytes, kb, nb; 67 WCHAR nb2[255]; |
129 ULONG sr; 130 float f; 131 NUMBERFMTW fmt; | 68 ULONG sr; 69 float f; 70 NUMBERFMTW fmt; |
132 WCHAR thou[4], grouping[64], *c; | 71 WCHAR dec[2], thou[4], grouping[64], *c; 72#ifdef __REACTOS__ 73 WCHAR buffer[64]; 74#endif |
133 | 75 |
134 _i64tow(size, nb, 10); | 76#ifndef __REACTOS__ 77 nb = to_wstring(size); 78#else 79 swprintf(buffer, L"%I64d", size); 80 nb = wstring(buffer); 81#endif |
135 136 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thou, sizeof(thou) / sizeof(WCHAR)); 137 | 82 83 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thou, sizeof(thou) / sizeof(WCHAR)); 84 |
85 dec[0] = '.'; dec[1] = 0; // not used, but silences gcc warning 86 |
|
138 fmt.NumDigits = 0; 139 fmt.LeadingZero = 1; | 87 fmt.NumDigits = 0; 88 fmt.LeadingZero = 1; |
140 fmt.lpDecimalSep = (LPWSTR)L"."; // not used | 89 fmt.lpDecimalSep = dec; |
141 fmt.lpThousandSep = thou; 142 fmt.NegativeOrder = 0; 143 144 // Grouping code copied from dlls/shlwapi/string.c in Wine - thank you 145 146 fmt.Grouping = 0; 147 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping) / sizeof(WCHAR)); 148 --- 7 unchanged lines hidden (view full) --- 156 c++; 157 } 158 159 if (fmt.Grouping % 10 == 0) 160 fmt.Grouping /= 10; 161 else 162 fmt.Grouping *= 10; 163 | 90 fmt.lpThousandSep = thou; 91 fmt.NegativeOrder = 0; 92 93 // Grouping code copied from dlls/shlwapi/string.c in Wine - thank you 94 95 fmt.Grouping = 0; 96 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping) / sizeof(WCHAR)); 97 --- 7 unchanged lines hidden (view full) --- 105 c++; 106 } 107 108 if (fmt.Grouping % 10 == 0) 109 fmt.Grouping /= 10; 110 else 111 fmt.Grouping *= 10; 112 |
164 GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb, &fmt, nb2, sizeof(nb2) / sizeof(WCHAR)); | 113 GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb.c_str(), &fmt, nb2, sizeof(nb2) / sizeof(WCHAR)); |
165 166 if (size < 1024) { | 114 115 if (size < 1024) { |
167 if (!LoadStringW(module, size == 1 ? IDS_SIZE_BYTE : IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) { 168 ShowError(NULL, GetLastError()); 169 return; 170 } | 116 if (!load_string(module, size == 1 ? IDS_SIZE_BYTE : IDS_SIZE_BYTES, t)) 117 throw last_error(GetLastError()); |
171 | 118 |
172 if (StringCchPrintfW(s, len, t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) { 173 ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); 174 return; 175 } 176 | 119 wstring_sprintf(s, t, nb2); |
177 return; 178 } 179 180 if (show_bytes) { | 120 return; 121 } 122 123 if (show_bytes) { |
181 if (!LoadStringW(module, IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) { 182 ShowError(NULL, GetLastError()); 183 return; 184 } | 124 if (!load_string(module, IDS_SIZE_BYTES, t)) 125 throw last_error(GetLastError()); |
185 | 126 |
186 if (StringCchPrintfW(bytes, sizeof(bytes) / sizeof(WCHAR), t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) { 187 ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); 188 return; 189 } | 127 wstring_sprintf(bytes, t, nb2); |
190 } 191 192 if (size >= 1152921504606846976) { 193 sr = IDS_SIZE_EB; 194 f = (float)size / 1152921504606846976.0f; 195 } else if (size >= 1125899906842624) { 196 sr = IDS_SIZE_PB; 197 f = (float)size / 1125899906842624.0f; --- 6 unchanged lines hidden (view full) --- 204 } else if (size >= 1048576) { 205 sr = IDS_SIZE_MB; 206 f = (float)size / 1048576.0f; 207 } else { 208 sr = IDS_SIZE_KB; 209 f = (float)size / 1024.0f; 210 } 211 | 128 } 129 130 if (size >= 1152921504606846976) { 131 sr = IDS_SIZE_EB; 132 f = (float)size / 1152921504606846976.0f; 133 } else if (size >= 1125899906842624) { 134 sr = IDS_SIZE_PB; 135 f = (float)size / 1125899906842624.0f; --- 6 unchanged lines hidden (view full) --- 142 } else if (size >= 1048576) { 143 sr = IDS_SIZE_MB; 144 f = (float)size / 1048576.0f; 145 } else { 146 sr = IDS_SIZE_KB; 147 f = (float)size / 1024.0f; 148 } 149 |
212 if (!LoadStringW(module, sr, t, sizeof(t) / sizeof(WCHAR))) { 213 ShowError(NULL, GetLastError()); 214 return; 215 } | 150 if (!load_string(module, sr, t)) 151 throw last_error(GetLastError()); |
216 217 if (show_bytes) { | 152 153 if (show_bytes) { |
218 if (StringCchPrintfW(kb, sizeof(kb) / sizeof(WCHAR), t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) { 219 ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); 220 return; 221 } | 154 wstring_sprintf(kb, t, f); |
222 | 155 |
223 if (!LoadStringW(module, IDS_SIZE_LARGE, t, sizeof(t) / sizeof(WCHAR))) { 224 ShowError(NULL, GetLastError()); 225 return; 226 } | 156 if (!load_string(module, IDS_SIZE_LARGE, t)) 157 throw last_error(GetLastError()); |
227 | 158 |
228 if (StringCchPrintfW(s, len, t, kb, bytes) == STRSAFE_E_INSUFFICIENT_BUFFER) { 229 ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); 230 return; 231 } 232 } else { 233 if (StringCchPrintfW(s, len, t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) { 234 ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); 235 return; 236 } 237 } | 159 wstring_sprintf(s, t, kb.c_str(), bytes.c_str()); 160 } else 161 wstring_sprintf(s, t, f); |
238} 239 | 162} 163 |
240std::wstring format_message(ULONG last_error) { | 164wstring format_message(ULONG last_error) { |
241 WCHAR* buf; | 165 WCHAR* buf; |
242 std::wstring s; | 166 wstring s; |
243 | 167 |
244 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, 245 last_error, 0, (WCHAR*)&buf, 0, NULL) == 0) { | 168 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, 169 last_error, 0, (WCHAR*)&buf, 0, nullptr) == 0) { |
246 return L"(error retrieving message)"; 247 } 248 249 s = buf; 250 251 LocalFree(buf); 252 253 // remove trailing newline 254 while (s.length() > 0 && (s.substr(s.length() - 1, 1) == L"\r" || s.substr(s.length() - 1, 1) == L"\n")) 255 s = s.substr(0, s.length() - 1); 256 257 return s; 258} 259 | 170 return L"(error retrieving message)"; 171 } 172 173 s = buf; 174 175 LocalFree(buf); 176 177 // remove trailing newline 178 while (s.length() > 0 && (s.substr(s.length() - 1, 1) == L"\r" || s.substr(s.length() - 1, 1) == L"\n")) 179 s = s.substr(0, s.length() - 1); 180 181 return s; 182} 183 |
260std::wstring format_ntstatus(NTSTATUS Status) { | 184wstring format_ntstatus(NTSTATUS Status) { |
261 _RtlNtStatusToDosError RtlNtStatusToDosError; | 185 _RtlNtStatusToDosError RtlNtStatusToDosError; |
262 std::wstring s; | 186 wstring s; |
263 HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); 264 265 if (!ntdll) 266 return L"(error loading ntdll.dll)"; 267 268 RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); 269 270 if (!RtlNtStatusToDosError) { 271 FreeLibrary(ntdll); 272 return L"(error loading RtlNtStatusToDosError)"; 273 } 274 275 s = format_message(RtlNtStatusToDosError(Status)); 276 277 FreeLibrary(ntdll); 278 279 return s; 280} 281 | 187 HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); 188 189 if (!ntdll) 190 return L"(error loading ntdll.dll)"; 191 192 RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); 193 194 if (!RtlNtStatusToDosError) { 195 FreeLibrary(ntdll); 196 return L"(error loading RtlNtStatusToDosError)"; 197 } 198 199 s = format_message(RtlNtStatusToDosError(Status)); 200 201 FreeLibrary(ntdll); 202 203 return s; 204} 205 |
282#ifdef __cplusplus 283extern "C" { | 206bool load_string(HMODULE module, UINT id, wstring& s) { 207 int len; 208 LPWSTR retstr = nullptr; 209 210 len = LoadStringW(module, id, (LPWSTR)&retstr, 0); 211 212 if (len == 0) 213 return false; 214 215 s = wstring(retstr, len); 216 217 return true; 218} 219 220#ifdef _MSC_VER 221#pragma warning(push) 222#pragma warning(disable: 4996) |
284#endif 285 | 223#endif 224 |
286STDAPI DllCanUnloadNow(void) { | 225void wstring_sprintf(wstring& s, wstring fmt, ...) { 226 int len; 227 va_list args; 228 229 va_start(args, fmt); 230 len = _vsnwprintf(nullptr, 0, fmt.c_str(), args); 231 232 if (len == 0) 233 s = L""; 234 else { 235 s.resize(len); 236 _vsnwprintf((wchar_t*)s.c_str(), len, fmt.c_str(), args); 237 } 238 239 va_end(args); 240} 241 242#ifdef _MSC_VER 243#pragma warning(pop) 244#endif 245 246extern "C" STDAPI DllCanUnloadNow(void) { |
287 return objs_loaded == 0 ? S_OK : S_FALSE; 288} 289 | 247 return objs_loaded == 0 ? S_OK : S_FALSE; 248} 249 |
290STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { | 250extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { |
291 if (rclsid == CLSID_ShellBtrfsIconHandler) { 292 Factory* fact = new Factory; 293 if (!fact) 294 return E_OUTOFMEMORY; 295 else { 296 fact->type = FactoryIconHandler; 297 298 return fact->QueryInterface(riid, ppv); --- 25 unchanged lines hidden (view full) --- 324 325 return fact->QueryInterface(riid, ppv); 326 } 327 } 328 329 return CLASS_E_CLASSNOTAVAILABLE; 330} 331 | 251 if (rclsid == CLSID_ShellBtrfsIconHandler) { 252 Factory* fact = new Factory; 253 if (!fact) 254 return E_OUTOFMEMORY; 255 else { 256 fact->type = FactoryIconHandler; 257 258 return fact->QueryInterface(riid, ppv); --- 25 unchanged lines hidden (view full) --- 284 285 return fact->QueryInterface(riid, ppv); 286 } 287 } 288 289 return CLASS_E_CLASSNOTAVAILABLE; 290} 291 |
332static BOOL write_reg_key(HKEY root, const WCHAR* keyname, const WCHAR* val, DWORD type, const BYTE* data, DWORD datasize) { | 292static void write_reg_key(HKEY root, const wstring& keyname, const WCHAR* val, const wstring& data) { |
333 LONG l; 334 HKEY hk; 335 DWORD dispos; 336 | 293 LONG l; 294 HKEY hk; 295 DWORD dispos; 296 |
337 l = RegCreateKeyExW(root, keyname, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dispos); 338 if (l != ERROR_SUCCESS) { 339 WCHAR s[255]; 340 wsprintfW(s, L"RegCreateKey returned %08x", l); 341 MessageBoxW(0, s, NULL, MB_ICONERROR); | 297 l = RegCreateKeyExW(root, keyname.c_str(), 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hk, &dispos); 298 if (l != ERROR_SUCCESS) 299 throw string_error(IDS_REGCREATEKEY_FAILED, l); |
342 | 300 |
343 return FALSE; 344 } | 301 l = RegSetValueExW(hk, val, 0, REG_SZ, (const BYTE*)data.c_str(), (data.length() + 1) * sizeof(WCHAR)); 302 if (l != ERROR_SUCCESS) 303 throw string_error(IDS_REGSETVALUEEX_FAILED, l); |
345 | 304 |
346 l = RegSetValueExW(hk, val, 0, type, data, datasize); 347 if (l != ERROR_SUCCESS) { 348 WCHAR s[255]; 349 wsprintfW(s, L"RegSetValueEx returned %08x", l); 350 MessageBoxW(0, s, NULL, MB_ICONERROR); 351 352 return FALSE; 353 } 354 | |
355 l = RegCloseKey(hk); | 305 l = RegCloseKey(hk); |
356 if (l != ERROR_SUCCESS) { 357 WCHAR s[255]; 358 wsprintfW(s, L"RegCloseKey returned %08x", l); 359 MessageBoxW(0, s, NULL, MB_ICONERROR); 360 361 return FALSE; 362 } 363 364 return TRUE; | 306 if (l != ERROR_SUCCESS) 307 throw string_error(IDS_REGCLOSEKEY_FAILED, l); |
365} 366 | 308} 309 |
367static BOOL register_clsid(const GUID clsid, const WCHAR* description) { | 310static void register_clsid(const GUID clsid, const WCHAR* description) { |
368 WCHAR* clsidstring; | 311 WCHAR* clsidstring; |
369 WCHAR inproc[MAX_PATH], progid[MAX_PATH], clsidkeyname[MAX_PATH], dllpath[MAX_PATH]; 370 BOOL ret = FALSE; | 312 wstring inproc, progid, clsidkeyname; 313 WCHAR dllpath[MAX_PATH]; |
371 372 StringFromCLSID(clsid, &clsidstring); 373 | 314 315 StringFromCLSID(clsid, &clsidstring); 316 |
374 wsprintfW(inproc, L"CLSID\\%s\\InprocServer32", clsidstring); 375 wsprintfW(progid, L"CLSID\\%s\\ProgId", clsidstring); 376 wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); | 317 try { 318#ifndef __REACTOS__ 319 inproc = L"CLSID\\"s + clsidstring + L"\\InprocServer32"s; 320 progid = L"CLSID\\"s + clsidstring + L"\\ProgId"s; 321 clsidkeyname = L"CLSID\\"s + clsidstring; 322#else 323 inproc = wstring(L"CLSID\\") + clsidstring + wstring(L"\\InprocServer32"); 324 progid = wstring(L"CLSID\\") + clsidstring + wstring(L"\\ProgId"); 325 clsidkeyname = wstring(L"CLSID\\") + clsidstring; 326#endif |
377 | 327 |
378 if (!write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, NULL, REG_SZ, (BYTE*)description, (wcslen(description) + 1) * sizeof(WCHAR))) 379 goto end; | 328 write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, nullptr, description); |
380 | 329 |
381 GetModuleFileNameW(module, dllpath, sizeof(dllpath)); | 330 GetModuleFileNameW(module, dllpath, sizeof(dllpath)); |
382 | 331 |
383 if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, NULL, REG_SZ, (BYTE*)dllpath, (wcslen(dllpath) + 1) * sizeof(WCHAR))) 384 goto end; | 332 write_reg_key(HKEY_CLASSES_ROOT, inproc, nullptr, dllpath); |
385 | 333 |
386 if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", REG_SZ, (BYTE*)L"Apartment", (wcslen(L"Apartment") + 1) * sizeof(WCHAR))) 387 goto end; | 334 write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", L"Apartment"); 335 } catch (...) { 336 CoTaskMemFree(clsidstring); 337 throw; 338 } |
388 | 339 |
389 ret = TRUE; 390 391end: | |
392 CoTaskMemFree(clsidstring); | 340 CoTaskMemFree(clsidstring); |
393 394 return ret; | |
395} 396 | 341} 342 |
397static BOOL unregister_clsid(const GUID clsid) { | 343static void unregister_clsid(const GUID clsid) { |
398 WCHAR* clsidstring; | 344 WCHAR* clsidstring; |
399 WCHAR clsidkeyname[MAX_PATH]; 400 BOOL ret = FALSE; 401 LONG l; | |
402 403 StringFromCLSID(clsid, &clsidstring); | 345 346 StringFromCLSID(clsid, &clsidstring); |
404 wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); | |
405 | 347 |
406 l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname); | 348 try { 349 WCHAR clsidkeyname[MAX_PATH]; |
407 | 350 |
408 if (l != ERROR_SUCCESS) { 409 WCHAR s[255]; 410 wsprintfW(s, L"RegDeleteTree returned %08x", l); 411 MessageBoxW(0, s, NULL, MB_ICONERROR); | 351 wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); |
412 | 352 |
413 ret = FALSE; 414 } else 415 ret = TRUE; | 353 LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname); |
416 | 354 |
417 CoTaskMemFree(clsidstring); | 355 if (l != ERROR_SUCCESS) 356 throw string_error(IDS_REGDELETETREE_FAILED, l); 357 } catch (...) { 358 CoTaskMemFree(clsidstring); 359 throw; 360 } |
418 | 361 |
419 return ret; | 362 CoTaskMemFree(clsidstring); |
420} 421 | 363} 364 |
422static BOOL reg_icon_overlay(const GUID clsid, const WCHAR* name) { 423 WCHAR path[MAX_PATH]; | 365static void reg_icon_overlay(const GUID clsid, const wstring& name) { |
424 WCHAR* clsidstring; | 366 WCHAR* clsidstring; |
425 BOOL ret = FALSE; | |
426 427 StringFromCLSID(clsid, &clsidstring); 428 | 367 368 StringFromCLSID(clsid, &clsidstring); 369 |
429 wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"); 430 wcscat(path, name); | 370 try { 371#ifndef __REACTOS__ 372 wstring path = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name; 373#else 374 wstring path = wstring(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\") + name; 375#endif |
431 | 376 |
432 if (!write_reg_key(HKEY_LOCAL_MACHINE, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) 433 goto end; | 377 write_reg_key(HKEY_LOCAL_MACHINE, path, nullptr, clsidstring); 378 } catch (...) { 379 CoTaskMemFree(clsidstring); 380 throw; 381 } |
434 | 382 |
435 ret = TRUE; 436 437end: | |
438 CoTaskMemFree(clsidstring); | 383 CoTaskMemFree(clsidstring); |
439 440 return ret; | |
441} 442 | 384} 385 |
443static BOOL unreg_icon_overlay(const WCHAR* name) { 444 WCHAR path[MAX_PATH]; 445 LONG l; | 386static void unreg_icon_overlay(const wstring& name) { 387#ifndef __REACTOS__ 388 wstring path = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name; 389#else 390 wstring path = wstring(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\") + name; 391#endif |
446 | 392 |
447 wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"); 448 wcscat(path, name); | 393 LONG l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path.c_str()); |
449 | 394 |
450 l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path); 451 452 if (l != ERROR_SUCCESS) { 453 WCHAR s[255]; 454 wsprintfW(s, L"RegDeleteTree returned %08x", l); 455 MessageBoxW(0, s, NULL, MB_ICONERROR); 456 457 return FALSE; 458 } else 459 return TRUE; | 395 if (l != ERROR_SUCCESS) 396 throw string_error(IDS_REGDELETETREE_FAILED, l); |
460} 461 | 397} 398 |
462static BOOL reg_context_menu_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) { 463 WCHAR path[MAX_PATH]; | 399static void reg_context_menu_handler(const GUID clsid, const wstring& filetype, const wstring& name) { |
464 WCHAR* clsidstring; | 400 WCHAR* clsidstring; |
465 BOOL ret = FALSE; | |
466 467 StringFromCLSID(clsid, &clsidstring); 468 | 401 402 StringFromCLSID(clsid, &clsidstring); 403 |
469 wcscpy(path, filetype); 470 wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\"); 471 wcscat(path, name); | 404 try { 405#ifndef __REACTOS__ 406 wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name; 407#else 408 wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name; 409#endif |
472 | 410 |
473 if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) 474 goto end; 475 476 ret = TRUE; 477 478end: 479 CoTaskMemFree(clsidstring); 480 481 return ret; | 411 write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring); 412 } catch (...) { 413 CoTaskMemFree(clsidstring); 414 throw; 415 } |
482} 483 | 416} 417 |
484static BOOL unreg_context_menu_handler(const WCHAR* filetype, const WCHAR* name) { 485 WCHAR path[MAX_PATH]; 486 LONG l; | 418static void unreg_context_menu_handler(const wstring& filetype, const wstring& name) { 419#ifndef __REACTOS__ 420 wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name; 421#else 422 wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name; 423#endif |
487 | 424 |
488 wcscpy(path, filetype); 489 wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\"); 490 wcscat(path, name); | 425 LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str()); |
491 | 426 |
492 l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path); 493 494 if (l != ERROR_SUCCESS) { 495 WCHAR s[255]; 496 wsprintfW(s, L"RegDeleteTree returned %08x", l); 497 MessageBoxW(0, s, NULL, MB_ICONERROR); 498 499 return FALSE; 500 } else 501 return TRUE; | 427 if (l != ERROR_SUCCESS) 428 throw string_error(IDS_REGDELETETREE_FAILED, l); |
502} 503 | 429} 430 |
504static BOOL reg_prop_sheet_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) { 505 WCHAR path[MAX_PATH]; | 431static void reg_prop_sheet_handler(const GUID clsid, const wstring& filetype, const wstring& name) { |
506 WCHAR* clsidstring; | 432 WCHAR* clsidstring; |
507 BOOL ret = FALSE; | |
508 509 StringFromCLSID(clsid, &clsidstring); 510 | 433 434 StringFromCLSID(clsid, &clsidstring); 435 |
511 wcscpy(path, filetype); 512 wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\"); 513 wcscat(path, name); | 436 try { 437#ifndef __REACTOS__ 438 wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name; 439#else 440 wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name; 441#endif |
514 | 442 |
515 if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) 516 goto end; 517 518 ret = TRUE; 519 520end: 521 CoTaskMemFree(clsidstring); 522 523 return ret; | 443 write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring); 444 } catch (...) { 445 CoTaskMemFree(clsidstring); 446 throw; 447 } |
524} 525 | 448} 449 |
526static BOOL unreg_prop_sheet_handler(const WCHAR* filetype, const WCHAR* name) { 527 WCHAR path[MAX_PATH]; 528 LONG l; | 450static void unreg_prop_sheet_handler(const wstring& filetype, const wstring& name) { 451#ifndef __REACTOS__ 452 wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name; 453#else 454 wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name; 455#endif |
529 | 456 |
530 wcscpy(path, filetype); 531 wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\"); 532 wcscat(path, name); | 457 LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str()); |
533 | 458 |
534 l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path); 535 536 if (l != ERROR_SUCCESS) { 537 WCHAR s[255]; 538 wsprintfW(s, L"RegDeleteTree returned %08x", l); 539 MessageBoxW(0, s, NULL, MB_ICONERROR); 540 541 return FALSE; 542 } else 543 return TRUE; | 459 if (l != ERROR_SUCCESS) 460 throw string_error(IDS_REGDELETETREE_FAILED, l); |
544} 545 | 461} 462 |
546STDAPI DllRegisterServer(void) { 547 if (!register_clsid(CLSID_ShellBtrfsIconHandler, COM_DESCRIPTION_ICON_HANDLER)) 548 return E_FAIL; | 463extern "C" STDAPI DllRegisterServer(void) { 464 try { 465 register_clsid(CLSID_ShellBtrfsIconHandler, COM_DESCRIPTION_ICON_HANDLER); 466 register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU); 467 register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET); 468 register_clsid(CLSID_ShellBtrfsVolPropSheet, COM_DESCRIPTION_VOL_PROP_SHEET); |
549 | 469 |
550 if (!register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU)) 551 return E_FAIL; | 470 reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME); |
552 | 471 |
553 if (!register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET)) 554 return E_FAIL; | 472 reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME); 473 reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME); |
555 | 474 |
556 if (!register_clsid(CLSID_ShellBtrfsVolPropSheet, COM_DESCRIPTION_VOL_PROP_SHEET)) | 475 reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME); 476 reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"*", ICON_OVERLAY_NAME); 477 reg_prop_sheet_handler(CLSID_ShellBtrfsVolPropSheet, L"Drive", ICON_OVERLAY_NAME); 478 } catch (const exception& e) { 479 error_message(nullptr, e.what()); |
557 return E_FAIL; | 480 return E_FAIL; |
558 559 if (!reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME)) { 560 MessageBoxW(0, L"Failed to register icon overlay.", NULL, MB_ICONERROR); 561 return E_FAIL; | |
562 } 563 | 481 } 482 |
564 if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME)) { 565 MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR); 566 return E_FAIL; 567 } 568 569 if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME)) { 570 MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR); 571 return E_FAIL; 572 } 573 574 if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME)) { 575 MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR); 576 return E_FAIL; 577 } 578 579 if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"*", ICON_OVERLAY_NAME)) { 580 MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR); 581 return E_FAIL; 582 } 583 584 if (!reg_prop_sheet_handler(CLSID_ShellBtrfsVolPropSheet, L"Drive", ICON_OVERLAY_NAME)) { 585 MessageBoxW(0, L"Failed to register volume property sheet handler.", NULL, MB_ICONERROR); 586 return E_FAIL; 587 } 588 | |
589 return S_OK; 590} 591 | 483 return S_OK; 484} 485 |
592STDAPI DllUnregisterServer(void) { 593 unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME); 594 unreg_prop_sheet_handler(L"*", ICON_OVERLAY_NAME); 595 unreg_prop_sheet_handler(L"Drive", ICON_OVERLAY_NAME); 596 unreg_context_menu_handler(L"Folder", ICON_OVERLAY_NAME); 597 unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME); 598 unreg_icon_overlay(ICON_OVERLAY_NAME); | 486extern "C" STDAPI DllUnregisterServer(void) { 487 try { 488 unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME); 489 unreg_prop_sheet_handler(L"*", ICON_OVERLAY_NAME); 490 unreg_prop_sheet_handler(L"Drive", ICON_OVERLAY_NAME); 491 unreg_context_menu_handler(L"Folder", ICON_OVERLAY_NAME); 492 unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME); 493 unreg_icon_overlay(ICON_OVERLAY_NAME); |
599 | 494 |
600 if (!unregister_clsid(CLSID_ShellBtrfsVolPropSheet)) | 495 unregister_clsid(CLSID_ShellBtrfsVolPropSheet); 496 unregister_clsid(CLSID_ShellBtrfsPropSheet); 497 unregister_clsid(CLSID_ShellBtrfsContextMenu); 498 unregister_clsid(CLSID_ShellBtrfsIconHandler); 499 } catch (const exception& e) { 500 error_message(nullptr, e.what()); |
601 return E_FAIL; | 501 return E_FAIL; |
502 } |
|
602 | 503 |
603 if (!unregister_clsid(CLSID_ShellBtrfsPropSheet)) 604 return E_FAIL; 605 606 if (!unregister_clsid(CLSID_ShellBtrfsContextMenu)) 607 return E_FAIL; 608 609 if (!unregister_clsid(CLSID_ShellBtrfsIconHandler)) 610 return E_FAIL; 611 | |
612 return S_OK; 613} 614 | 504 return S_OK; 505} 506 |
615STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { | 507extern "C" STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { |
616 if (bInstall) 617 return DllRegisterServer(); 618 else 619 return DllUnregisterServer(); 620} 621 | 508 if (bInstall) 509 return DllRegisterServer(); 510 else 511 return DllUnregisterServer(); 512} 513 |
622BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { | 514extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { |
623 if (dwReason == DLL_PROCESS_ATTACH) 624 module = (HMODULE)hModule; 625 | 515 if (dwReason == DLL_PROCESS_ATTACH) 516 module = (HMODULE)hModule; 517 |
626 return TRUE; | 518 return true; |
627} 628 | 519} 520 |
629static void create_subvol(std::wstring fn) { | 521static void create_subvol(const wstring& fn) { |
630 size_t found = fn.rfind(L"\\"); | 522 size_t found = fn.rfind(L"\\"); |
631 std::wstring path, file; 632 HANDLE h; | 523 wstring path, file; 524 win_handle h; |
633 ULONG bcslen; 634 btrfs_create_subvol* bcs; 635 IO_STATUS_BLOCK iosb; 636 | 525 ULONG bcslen; 526 btrfs_create_subvol* bcs; 527 IO_STATUS_BLOCK iosb; 528 |
637 if (found == std::wstring::npos) { | 529 if (found == wstring::npos) { |
638 path = L""; 639 file = fn; 640 } else { 641 path = fn.substr(0, found); 642 file = fn.substr(found + 1); 643 } 644 path += L"\\"; 645 | 530 path = L""; 531 file = fn; 532 } else { 533 path = fn.substr(0, found); 534 file = fn.substr(found + 1); 535 } 536 path += L"\\"; 537 |
646 h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 538 h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); |
647 648 if (h == INVALID_HANDLE_VALUE) 649 return; 650 651 bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR)); 652 bcs = (btrfs_create_subvol*)malloc(bcslen); 653 | 539 540 if (h == INVALID_HANDLE_VALUE) 541 return; 542 543 bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR)); 544 bcs = (btrfs_create_subvol*)malloc(bcslen); 545 |
654 bcs->readonly = FALSE; 655 bcs->posix = FALSE; 656 bcs->namelen = file.length() * sizeof(WCHAR); | 546 bcs->readonly = false; 547 bcs->posix = false; 548 bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR)); |
657 memcpy(bcs->name, file.c_str(), bcs->namelen); 658 | 549 memcpy(bcs->name, file.c_str(), bcs->namelen); 550 |
659 NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0); 660 661 CloseHandle(h); | 551 NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0); |
662} 663 | 552} 553 |
664void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { 665 LPWSTR* args; 666 int num_args; | 554extern "C" void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { 555 vector<wstring> args; |
667 | 556 |
668 args = CommandLineToArgvW(lpszCmdLine, &num_args); | 557 command_line_to_args(lpszCmdLine, args); |
669 | 558 |
670 if (!args) 671 return; 672 673 if (num_args >= 1) | 559 if (args.size() >= 1) |
674 create_subvol(args[0]); | 560 create_subvol(args[0]); |
675 676 LocalFree(args); | |
677} 678 | 561} 562 |
679static void create_snapshot2(std::wstring source, std::wstring fn) { | 563static void create_snapshot2(const wstring& source, const wstring& fn) { |
680 size_t found = fn.rfind(L"\\"); | 564 size_t found = fn.rfind(L"\\"); |
681 std::wstring path, file; 682 HANDLE h, src; | 565 wstring path, file; 566 win_handle h, src; |
683 ULONG bcslen; 684 btrfs_create_snapshot* bcs; 685 IO_STATUS_BLOCK iosb; 686 | 567 ULONG bcslen; 568 btrfs_create_snapshot* bcs; 569 IO_STATUS_BLOCK iosb; 570 |
687 if (found == std::wstring::npos) { | 571 if (found == wstring::npos) { |
688 path = L""; 689 file = fn; 690 } else { 691 path = fn.substr(0, found); 692 file = fn.substr(found + 1); 693 } 694 path += L"\\"; 695 | 572 path = L""; 573 file = fn; 574 } else { 575 path = fn.substr(0, found); 576 file = fn.substr(found + 1); 577 } 578 path += L"\\"; 579 |
696 src = CreateFileW(source.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 580 src = CreateFileW(source.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); |
697 if (src == INVALID_HANDLE_VALUE) 698 return; 699 | 581 if (src == INVALID_HANDLE_VALUE) 582 return; 583 |
700 h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 584 h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); |
701 | 585 |
702 if (h == INVALID_HANDLE_VALUE) { 703 CloseHandle(src); | 586 if (h == INVALID_HANDLE_VALUE) |
704 return; | 587 return; |
705 } | |
706 707 bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR)); 708 bcs = (btrfs_create_snapshot*)malloc(bcslen); 709 | 588 589 bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR)); 590 bcs = (btrfs_create_snapshot*)malloc(bcslen); 591 |
710 bcs->readonly = FALSE; 711 bcs->posix = FALSE; 712 bcs->namelen = file.length() * sizeof(WCHAR); | 592 bcs->readonly = false; 593 bcs->posix = false; 594 bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR)); |
713 memcpy(bcs->name, file.c_str(), bcs->namelen); 714 bcs->subvol = src; 715 | 595 memcpy(bcs->name, file.c_str(), bcs->namelen); 596 bcs->subvol = src; 597 |
716 NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, NULL, 0); | 598 NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0); 599} |
717 | 600 |
718 CloseHandle(h); 719 CloseHandle(src); | 601extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { 602 vector<wstring> args; 603 604 command_line_to_args(lpszCmdLine, args); 605 606 if (args.size() >= 2) 607 create_snapshot2(args[0], args[1]); |
720} 721 | 608} 609 |
722void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { 723 LPWSTR* args; | 610void command_line_to_args(LPWSTR cmdline, vector<wstring> args) { 611 LPWSTR* l; |
724 int num_args; 725 | 612 int num_args; 613 |
726 args = CommandLineToArgvW(lpszCmdLine, &num_args); | 614 args.clear(); |
727 | 615 |
728 if (!args) | 616 l = CommandLineToArgvW(cmdline, &num_args); 617 618 if (!l) |
729 return; 730 | 619 return; 620 |
731 if (num_args >= 2) 732 create_snapshot2(args[0], args[1]); | 621 try { 622 args.reserve(num_args); |
733 | 623 |
734 LocalFree(args); | 624 for (unsigned int i = 0; i < (unsigned int)num_args; i++) { 625 args.push_back(l[i]); 626 } 627 } catch (...) { 628 LocalFree(l); 629 throw; 630 } 631 632 LocalFree(l); |
735} 736 | 633} 634 |
737#ifdef __cplusplus | 635#ifdef _MSC_VER 636#pragma warning(push) 637#pragma warning(disable: 4996) 638#endif 639 640string_error::string_error(int resno, ...) { 641 wstring fmt, s; 642 int len; 643 va_list args; 644 645 if (!load_string(module, resno, fmt)) 646 throw runtime_error("LoadString failed."); // FIXME 647 648 va_start(args, resno); 649 len = _vsnwprintf(nullptr, 0, fmt.c_str(), args); 650 651 if (len == 0) 652 s = L""; 653 else { 654 s.resize(len); 655 _vsnwprintf((wchar_t*)s.c_str(), len, fmt.c_str(), args); 656 } 657 658 va_end(args); 659 660 utf16_to_utf8(s, msg); |
738} | 661} |
662 663#ifdef _MSC_VER 664#pragma warning(pop) |
|
739#endif | 665#endif |
666 667void utf8_to_utf16(const string& utf8, wstring& utf16) { 668 NTSTATUS Status; 669 ULONG utf16len; 670 WCHAR* buf; 671 672 Status = RtlUTF8ToUnicodeN(nullptr, 0, &utf16len, utf8.c_str(), utf8.length()); 673 if (!NT_SUCCESS(Status)) 674 throw string_error(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str()); 675 676 buf = (WCHAR*)malloc(utf16len + sizeof(WCHAR)); 677 678 if (!buf) 679 throw string_error(IDS_OUT_OF_MEMORY); 680 681 Status = RtlUTF8ToUnicodeN(buf, utf16len, &utf16len, utf8.c_str(), utf8.length()); 682 if (!NT_SUCCESS(Status)) { 683 free(buf); 684 throw string_error(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str()); 685 } 686 687 buf[utf16len / sizeof(WCHAR)] = 0; 688 689 utf16 = buf; 690 691 free(buf); 692} 693 694void utf16_to_utf8(const wstring& utf16, string& utf8) { 695 NTSTATUS Status; 696 ULONG utf8len; 697 char* buf; 698 699 Status = RtlUnicodeToUTF8N(nullptr, 0, &utf8len, utf16.c_str(), utf16.length() * sizeof(WCHAR)); 700 if (!NT_SUCCESS(Status)) 701 throw string_error(IDS_RECV_RTLUNICODETOUTF8N_FAILED, Status, format_ntstatus(Status).c_str()); 702 703 buf = (char*)malloc(utf8len + sizeof(char)); 704 705 if (!buf) 706 throw string_error(IDS_OUT_OF_MEMORY); 707 708 Status = RtlUnicodeToUTF8N(buf, utf8len, &utf8len, utf16.c_str(), utf16.length() * sizeof(WCHAR)); 709 if (!NT_SUCCESS(Status)) { 710 free(buf); 711 throw string_error(IDS_RECV_RTLUNICODETOUTF8N_FAILED, Status, format_ntstatus(Status).c_str()); 712 } 713 714 buf[utf8len] = 0; 715 716 utf8 = buf; 717 718 free(buf); 719} 720 721last_error::last_error(DWORD errnum) { 722 WCHAR* buf; 723 724 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, 725 errnum, 0, (WCHAR*)&buf, 0, nullptr) == 0) 726 throw runtime_error("FormatMessage failed"); 727 728 try { 729 utf16_to_utf8(buf, msg); 730 } catch (...) { 731 LocalFree(buf); 732 throw; 733 } 734 735 LocalFree(buf); 736} 737 738void error_message(HWND hwnd, const char* msg) { 739 wstring title, wmsg; 740 741 load_string(module, IDS_ERROR, title); 742 743 utf8_to_utf16(msg, wmsg); 744 745 MessageBoxW(hwnd, wmsg.c_str(), title.c_str(), MB_ICONERROR); 746} 747 748ntstatus_error::ntstatus_error(NTSTATUS Status) { 749 _RtlNtStatusToDosError RtlNtStatusToDosError; 750 HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); 751 WCHAR* buf; 752 753 if (!ntdll) 754 throw runtime_error("Error loading ntdll.dll."); 755 756 try { 757 RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); 758 759 if (!RtlNtStatusToDosError) 760 throw runtime_error("Error loading RtlNtStatusToDosError in ntdll.dll."); 761 762 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, 763 RtlNtStatusToDosError(Status), 0, (WCHAR*)&buf, 0, nullptr) == 0) 764 throw runtime_error("FormatMessage failed"); 765 766 try { 767 utf16_to_utf8(buf, msg); 768 } catch (...) { 769 LocalFree(buf); 770 throw; 771 } 772 773 LocalFree(buf); 774 } catch (...) { 775 FreeLibrary(ntdll); 776 throw; 777 } 778 779 FreeLibrary(ntdll); 780} 781 782#ifdef __REACTOS__ 783NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max, 784 ULONG *utf8_bytes_written, 785 const WCHAR *uni_src, ULONG uni_bytes) 786{ 787 NTSTATUS status; 788 ULONG i; 789 ULONG written; 790 ULONG ch; 791 BYTE utf8_ch[4]; 792 ULONG utf8_ch_len; 793 794 if (!uni_src) 795 return STATUS_INVALID_PARAMETER_4; 796 if (!utf8_bytes_written) 797 return STATUS_INVALID_PARAMETER; 798 if (utf8_dest && uni_bytes % sizeof(WCHAR)) 799 return STATUS_INVALID_PARAMETER_5; 800 801 written = 0; 802 status = STATUS_SUCCESS; 803 804 for (i = 0; i < uni_bytes / sizeof(WCHAR); i++) 805 { 806 /* decode UTF-16 into ch */ 807 ch = uni_src[i]; 808 if (ch >= 0xdc00 && ch <= 0xdfff) 809 { 810 ch = 0xfffd; 811 status = STATUS_SOME_NOT_MAPPED; 812 } 813 else if (ch >= 0xd800 && ch <= 0xdbff) 814 { 815 if (i + 1 < uni_bytes / sizeof(WCHAR)) 816 { 817 ch -= 0xd800; 818 ch <<= 10; 819 if (uni_src[i + 1] >= 0xdc00 && uni_src[i + 1] <= 0xdfff) 820 { 821 ch |= uni_src[i + 1] - 0xdc00; 822 ch += 0x010000; 823 i++; 824 } 825 else 826 { 827 ch = 0xfffd; 828 status = STATUS_SOME_NOT_MAPPED; 829 } 830 } 831 else 832 { 833 ch = 0xfffd; 834 status = STATUS_SOME_NOT_MAPPED; 835 } 836 } 837 838 /* encode ch as UTF-8 */ 839 ASSERT(ch <= 0x10ffff); 840 if (ch < 0x80) 841 { 842 utf8_ch[0] = ch & 0x7f; 843 utf8_ch_len = 1; 844 } 845 else if (ch < 0x800) 846 { 847 utf8_ch[0] = 0xc0 | (ch >> 6 & 0x1f); 848 utf8_ch[1] = 0x80 | (ch >> 0 & 0x3f); 849 utf8_ch_len = 2; 850 } 851 else if (ch < 0x10000) 852 { 853 utf8_ch[0] = 0xe0 | (ch >> 12 & 0x0f); 854 utf8_ch[1] = 0x80 | (ch >> 6 & 0x3f); 855 utf8_ch[2] = 0x80 | (ch >> 0 & 0x3f); 856 utf8_ch_len = 3; 857 } 858 else if (ch < 0x200000) 859 { 860 utf8_ch[0] = 0xf0 | (ch >> 18 & 0x07); 861 utf8_ch[1] = 0x80 | (ch >> 12 & 0x3f); 862 utf8_ch[2] = 0x80 | (ch >> 6 & 0x3f); 863 utf8_ch[3] = 0x80 | (ch >> 0 & 0x3f); 864 utf8_ch_len = 4; 865 } 866 867 if (!utf8_dest) 868 { 869 written += utf8_ch_len; 870 continue; 871 } 872 873 if (utf8_bytes_max >= utf8_ch_len) 874 { 875 memcpy(utf8_dest, utf8_ch, utf8_ch_len); 876 utf8_dest += utf8_ch_len; 877 utf8_bytes_max -= utf8_ch_len; 878 written += utf8_ch_len; 879 } 880 else 881 { 882 utf8_bytes_max = 0; 883 status = STATUS_BUFFER_TOO_SMALL; 884 } 885 } 886 887 *utf8_bytes_written = written; 888 return status; 889} 890#endif |
|