ReactOS  0.4.13-dev-455-g28ed234
main.cpp
Go to the documentation of this file.
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.
9  *
10  * WinBtrfs is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public Licence for more details.
14  *
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>
24 #include "factory.h"
25 #include "resource.h"
26 
27 static const GUID CLSID_ShellBtrfsIconHandler = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf0 } };
28 static const GUID CLSID_ShellBtrfsContextMenu = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf1 } };
29 static const GUID CLSID_ShellBtrfsPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf2 } };
30 static const GUID CLSID_ShellBtrfsVolPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf3 } };
31 
32 #define COM_DESCRIPTION_ICON_HANDLER L"WinBtrfs shell extension (icon handler)"
33 #define COM_DESCRIPTION_CONTEXT_MENU L"WinBtrfs shell extension (context menu)"
34 #define COM_DESCRIPTION_PROP_SHEET L"WinBtrfs shell extension (property sheet)"
35 #define COM_DESCRIPTION_VOL_PROP_SHEET L"WinBtrfs shell extension (volume property sheet)"
36 #define ICON_OVERLAY_NAME L"WinBtrfs"
37 
38 typedef enum _PROCESS_DPI_AWARENESS {
43 
46 
49 
50 void 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 
65 void format_size(uint64_t size, wstring& s, bool show_bytes) {
66  wstring t, bytes, kb, nb;
67  WCHAR nb2[255];
68  ULONG sr;
69  float f;
71  WCHAR dec[2], thou[4], grouping[64], *c;
72 #ifdef __REACTOS__
73  WCHAR buffer[64];
74 #endif
75 
76 #ifndef __REACTOS__
77  nb = to_wstring(size);
78 #else
79  swprintf(buffer, L"%I64d", size);
80  nb = wstring(buffer);
81 #endif
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 
87  fmt.NumDigits = 0;
88  fmt.LeadingZero = 1;
89  fmt.lpDecimalSep = dec;
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 
98  c = grouping;
99  while (*c) {
100  if (*c >= '0' && *c < '9') {
101  fmt.Grouping *= 10;
102  fmt.Grouping += *c - '0';
103  }
104 
105  c++;
106  }
107 
108  if (fmt.Grouping % 10 == 0)
109  fmt.Grouping /= 10;
110  else
111  fmt.Grouping *= 10;
112 
113  GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb.c_str(), &fmt, nb2, sizeof(nb2) / sizeof(WCHAR));
114 
115  if (size < 1024) {
117  throw last_error(GetLastError());
118 
119  wstring_sprintf(s, t, nb2);
120  return;
121  }
122 
123  if (show_bytes) {
125  throw last_error(GetLastError());
126 
127  wstring_sprintf(bytes, t, nb2);
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;
136  } else if (size >= 1099511627776) {
137  sr = IDS_SIZE_TB;
138  f = (float)size / 1099511627776.0f;
139  } else if (size >= 1073741824) {
140  sr = IDS_SIZE_GB;
141  f = (float)size / 1073741824.0f;
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 
150  if (!load_string(module, sr, t))
151  throw last_error(GetLastError());
152 
153  if (show_bytes) {
154  wstring_sprintf(kb, t, f);
155 
157  throw last_error(GetLastError());
158 
159  wstring_sprintf(s, t, kb.c_str(), bytes.c_str());
160  } else
161  wstring_sprintf(s, t, f);
162 }
163 
165  WCHAR* buf;
166  wstring s;
167 
169  last_error, 0, (WCHAR*)&buf, 0, nullptr) == 0) {
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 
186  wstring s;
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 
200 
201  FreeLibrary(ntdll);
202 
203  return s;
204 }
205 
206 bool 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)
223 #endif
224 
225 void 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 
246 extern "C" STDAPI DllCanUnloadNow(void) {
247  return objs_loaded == 0 ? S_OK : S_FALSE;
248 }
249 
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);
259  }
260  } else if (rclsid == CLSID_ShellBtrfsContextMenu) {
261  Factory* fact = new Factory;
262  if (!fact)
263  return E_OUTOFMEMORY;
264  else {
265  fact->type = FactoryContextMenu;
266 
267  return fact->QueryInterface(riid, ppv);
268  }
269  } else if (rclsid == CLSID_ShellBtrfsPropSheet) {
270  Factory* fact = new Factory;
271  if (!fact)
272  return E_OUTOFMEMORY;
273  else {
274  fact->type = FactoryPropSheet;
275 
276  return fact->QueryInterface(riid, ppv);
277  }
278  } else if (rclsid == CLSID_ShellBtrfsVolPropSheet) {
279  Factory* fact = new Factory;
280  if (!fact)
281  return E_OUTOFMEMORY;
282  else {
283  fact->type = FactoryVolPropSheet;
284 
285  return fact->QueryInterface(riid, ppv);
286  }
287  }
288 
290 }
291 
292 static void write_reg_key(HKEY root, const wstring& keyname, const WCHAR* val, const wstring& data) {
293  LONG l;
294  HKEY hk;
295  DWORD dispos;
296 
297  l = RegCreateKeyExW(root, keyname.c_str(), 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hk, &dispos);
298  if (l != ERROR_SUCCESS)
300 
301  l = RegSetValueExW(hk, val, 0, REG_SZ, (const BYTE*)data.c_str(), (data.length() + 1) * sizeof(WCHAR));
302  if (l != ERROR_SUCCESS)
304 
305  l = RegCloseKey(hk);
306  if (l != ERROR_SUCCESS)
308 }
309 
310 static void register_clsid(const GUID clsid, const WCHAR* description) {
311  WCHAR* clsidstring;
312  wstring inproc, progid, clsidkeyname;
314 
315  StringFromCLSID(clsid, &clsidstring);
316 
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
327 
328  write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, nullptr, description);
329 
331 
332  write_reg_key(HKEY_CLASSES_ROOT, inproc, nullptr, dllpath);
333 
334  write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", L"Apartment");
335  } catch (...) {
336  CoTaskMemFree(clsidstring);
337  throw;
338  }
339 
340  CoTaskMemFree(clsidstring);
341 }
342 
343 static void unregister_clsid(const GUID clsid) {
344  WCHAR* clsidstring;
345 
346  StringFromCLSID(clsid, &clsidstring);
347 
348  try {
349  WCHAR clsidkeyname[MAX_PATH];
350 
351  wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring);
352 
353  LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname);
354 
355  if (l != ERROR_SUCCESS)
357  } catch (...) {
358  CoTaskMemFree(clsidstring);
359  throw;
360  }
361 
362  CoTaskMemFree(clsidstring);
363 }
364 
365 static void reg_icon_overlay(const GUID clsid, const wstring& name) {
366  WCHAR* clsidstring;
367 
368  StringFromCLSID(clsid, &clsidstring);
369 
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
376 
377  write_reg_key(HKEY_LOCAL_MACHINE, path, nullptr, clsidstring);
378  } catch (...) {
379  CoTaskMemFree(clsidstring);
380  throw;
381  }
382 
383  CoTaskMemFree(clsidstring);
384 }
385 
386 static 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
392 
394 
395  if (l != ERROR_SUCCESS)
397 }
398 
399 static void reg_context_menu_handler(const GUID clsid, const wstring& filetype, const wstring& name) {
400  WCHAR* clsidstring;
401 
402  StringFromCLSID(clsid, &clsidstring);
403 
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
410 
411  write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring);
412  } catch (...) {
413  CoTaskMemFree(clsidstring);
414  throw;
415  }
416 }
417 
418 static 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
424 
426 
427  if (l != ERROR_SUCCESS)
429 }
430 
431 static void reg_prop_sheet_handler(const GUID clsid, const wstring& filetype, const wstring& name) {
432  WCHAR* clsidstring;
433 
434  StringFromCLSID(clsid, &clsidstring);
435 
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
442 
443  write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring);
444  } catch (...) {
445  CoTaskMemFree(clsidstring);
446  throw;
447  }
448 }
449 
450 static 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
456 
458 
459  if (l != ERROR_SUCCESS)
461 }
462 
463 extern "C" STDAPI DllRegisterServer(void) {
464  try {
469 
471 
474 
478  } catch (const exception& e) {
479  error_message(nullptr, e.what());
480  return E_FAIL;
481  }
482 
483  return S_OK;
484 }
485 
486 extern "C" STDAPI DllUnregisterServer(void) {
487  try {
492  unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME);
494 
499  } catch (const exception& e) {
500  error_message(nullptr, e.what());
501  return E_FAIL;
502  }
503 
504  return S_OK;
505 }
506 
507 extern "C" STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) {
508  if (bInstall)
509  return DllRegisterServer();
510  else
511  return DllUnregisterServer();
512 }
513 
514 extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) {
517 
518  return true;
519 }
520 
521 static void create_subvol(const wstring& fn) {
522  size_t found = fn.rfind(L"\\");
523  wstring path, file;
524  win_handle h;
525  ULONG bcslen;
526  btrfs_create_subvol* bcs;
528 
529  if (found == wstring::npos) {
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 
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 
546  bcs->readonly = false;
547  bcs->posix = false;
548  bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR));
549  memcpy(bcs->name, file.c_str(), bcs->namelen);
550 
551  NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
552 }
553 
554 extern "C" void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
556 
557  command_line_to_args(lpszCmdLine, args);
558 
559  if (args.size() >= 1)
560  create_subvol(args[0]);
561 }
562 
563 static void create_snapshot2(const wstring& source, const wstring& fn) {
564  size_t found = fn.rfind(L"\\");
565  wstring path, file;
566  win_handle h, src;
567  ULONG bcslen;
570 
571  if (found == wstring::npos) {
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 
581  if (src == INVALID_HANDLE_VALUE)
582  return;
583 
585 
586  if (h == INVALID_HANDLE_VALUE)
587  return;
588 
589  bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR));
590  bcs = (btrfs_create_snapshot*)malloc(bcslen);
591 
592  bcs->readonly = false;
593  bcs->posix = false;
594  bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR));
595  memcpy(bcs->name, file.c_str(), bcs->namelen);
596  bcs->subvol = src;
597 
598  NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
599 }
600 
601 extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
603 
604  command_line_to_args(lpszCmdLine, args);
605 
606  if (args.size() >= 2)
607  create_snapshot2(args[0], args[1]);
608 }
609 
611  LPWSTR* l;
612  int num_args;
613 
614  args.clear();
615 
616  l = CommandLineToArgvW(cmdline, &num_args);
617 
618  if (!l)
619  return;
620 
621  try {
622  args.reserve(num_args);
623 
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);
633 }
634 
635 #ifdef _MSC_VER
636 #pragma warning(push)
637 #pragma warning(disable: 4996)
638 #endif
639 
640 string_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);
661 }
662 
663 #ifdef _MSC_VER
664 #pragma warning(pop)
665 #endif
666 
667 void utf8_to_utf16(const string& utf8, wstring& utf16) {
669  ULONG utf16len;
670  WCHAR* buf;
671 
672  Status = RtlUTF8ToUnicodeN(nullptr, 0, &utf16len, utf8.c_str(), utf8.length());
673  if (!NT_SUCCESS(Status))
675 
676  buf = (WCHAR*)malloc(utf16len + sizeof(WCHAR));
677 
678  if (!buf)
680 
681  Status = RtlUTF8ToUnicodeN(buf, utf16len, &utf16len, utf8.c_str(), utf8.length());
682  if (!NT_SUCCESS(Status)) {
683  free(buf);
685  }
686 
687  buf[utf16len / sizeof(WCHAR)] = 0;
688 
689  utf16 = buf;
690 
691  free(buf);
692 }
693 
694 void utf16_to_utf8(const wstring& utf16, string& utf8) {
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))
702 
703  buf = (char*)malloc(utf8len + sizeof(char));
704 
705  if (!buf)
707 
708  Status = RtlUnicodeToUTF8N(buf, utf8len, &utf8len, utf16.c_str(), utf16.length() * sizeof(WCHAR));
709  if (!NT_SUCCESS(Status)) {
710  free(buf);
712  }
713 
714  buf[utf8len] = 0;
715 
716  utf8 = buf;
717 
718  free(buf);
719 }
720 
722  WCHAR* buf;
723 
725  errnum, 0, (WCHAR*)&buf, 0, nullptr) == 0)
726  throw runtime_error("FormatMessage failed");
727 
728  try {
730  } catch (...) {
731  LocalFree(buf);
732  throw;
733  }
734 
735  LocalFree(buf);
736 }
737 
738 void error_message(HWND hwnd, const char* msg) {
739  wstring title, wmsg;
740 
742 
743  utf8_to_utf16(msg, wmsg);
744 
745  MessageBoxW(hwnd, wmsg.c_str(), title.c_str(), MB_ICONERROR);
746 }
747 
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 
760  throw runtime_error("Error loading RtlNtStatusToDosError in ntdll.dll.");
761 
763  RtlNtStatusToDosError(Status), 0, (WCHAR*)&buf, 0, nullptr) == 0)
764  throw runtime_error("FormatMessage failed");
765 
766  try {
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__
783 NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
784  ULONG *utf8_bytes_written,
785  const WCHAR *uni_src, ULONG uni_bytes)
786 {
788  ULONG i;
789  ULONG written;
790  ULONG ch;
791  BYTE utf8_ch[4];
792  ULONG utf8_ch_len;
793 
794  if (!uni_src)
796  if (!utf8_bytes_written)
798  if (utf8_dest && uni_bytes % sizeof(WCHAR))
800 
801  written = 0;
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;
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;
829  }
830  }
831  else
832  {
833  ch = 0xfffd;
835  }
836  }
837 
838  /* encode ch as UTF-8 */
839  if (ch < 0x80)
840  {
841  utf8_ch[0] = ch & 0x7f;
842  utf8_ch_len = 1;
843  }
844  else if (ch < 0x800)
845  {
846  utf8_ch[0] = 0xc0 | (ch >> 6 & 0x1f);
847  utf8_ch[1] = 0x80 | (ch >> 0 & 0x3f);
848  utf8_ch_len = 2;
849  }
850  else if (ch < 0x10000)
851  {
852  utf8_ch[0] = 0xe0 | (ch >> 12 & 0x0f);
853  utf8_ch[1] = 0x80 | (ch >> 6 & 0x3f);
854  utf8_ch[2] = 0x80 | (ch >> 0 & 0x3f);
855  utf8_ch_len = 3;
856  }
857  else if (ch < 0x200000)
858  {
859  utf8_ch[0] = 0xf0 | (ch >> 18 & 0x07);
860  utf8_ch[1] = 0x80 | (ch >> 12 & 0x3f);
861  utf8_ch[2] = 0x80 | (ch >> 6 & 0x3f);
862  utf8_ch[3] = 0x80 | (ch >> 0 & 0x3f);
863  utf8_ch_len = 4;
864  }
865 
866  if (!utf8_dest)
867  {
868  written += utf8_ch_len;
869  continue;
870  }
871 
872  if (utf8_bytes_max >= utf8_ch_len)
873  {
874  memcpy(utf8_dest, utf8_ch, utf8_ch_len);
875  utf8_dest += utf8_ch_len;
876  utf8_bytes_max -= utf8_ch_len;
877  written += utf8_ch_len;
878  }
879  else
880  {
881  utf8_bytes_max = 0;
883  }
884  }
885 
886  *utf8_bytes_written = written;
887  return status;
888 }
889 #endif
#define IDS_SIZE_KB
Definition: resource.h:32
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define LOCALE_SGROUPING
Definition: winnls.h:44
#define STDAPI
Definition: basetyps.h:41
STDAPI DllRegisterServer(void)
Definition: main.cpp:463
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
void utf16_to_utf8(const wstring &utf16, string &utf8)
Definition: main.cpp:694
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define HRESULT
Definition: msvc.h:9
#define IDS_SIZE_BYTES
Definition: resource.h:31
HRESULT(WINAPI * _SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value)
Definition: main.cpp:45
#define REFIID
Definition: guiddef.h:113
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj)
Definition: factory.cpp:26
HMODULE module
Definition: main.cpp:47
static void write_reg_key(HKEY root, const wstring &keyname, const WCHAR *val, const wstring &data)
Definition: main.cpp:292
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
wstring format_ntstatus(NTSTATUS Status)
Definition: main.cpp:184
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ICON_OVERLAY_NAME
Definition: main.cpp:36
string msg
Definition: shellext.h:337
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
ntstatus_error(NTSTATUS Status)
Definition: main.cpp:748
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
Definition: main.cpp:250
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
static void create_subvol(const wstring &fn)
Definition: main.cpp:521
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
GLsizei const GLchar ** path
Definition: glext.h:7234
REFIID riid
Definition: precomp.h:44
#define REFCLSID
Definition: guiddef.h:112
#define LOCALE_USER_DEFAULT
char CHAR
Definition: xmlstorage.h:175
#define free
Definition: debug_ros.c:5
#define IDS_SIZE_PB
Definition: resource.h:36
LONG NTSTATUS
Definition: precomp.h:26
#define CALLBACK
Definition: compat.h:27
const char * fmt
Definition: wsprintf.c:30
REFIID LPVOID * ppv
Definition: atlbase.h:39
static const size_t npos
Definition: _string_npos.h:26
GLdouble GLdouble t
Definition: gl.h:2047
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR uni_dest, ULONG uni_bytes_max, PULONG uni_bytes_written, PCCH utf8_src, ULONG utf8_bytes)
Definition: reactos.cpp:21
GLuint buffer
Definition: glext.h:5915
#define IDS_OUT_OF_MEMORY
Definition: resource.h:63
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
ios_base &_STLP_CALL dec(ios_base &__s)
Definition: _ios_base.h:321
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
STDAPI DllCanUnloadNow(void)
Definition: main.cpp:246
enum _PROCESS_DPI_AWARENESS PROCESS_DPI_AWARENESS
TCHAR * cmdline
Definition: stretchblt.cpp:32
const char * description
Definition: directx.c:2502
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define uint16_t
Definition: nsiface.idl:60
#define IDS_REGSETVALUEEX_FAILED
Definition: resource.h:202
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
#define E_FAIL
Definition: ddrawi.h:102
Definition: match.c:390
#define CLASS_E_CLASSNOTAVAILABLE
Definition: winerror.h:2663
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define IDS_RECV_RTLUTF8TOUNICODEN_FAILED
Definition: resource.h:136
#define COM_DESCRIPTION_PROP_SHEET
Definition: main.cpp:34
#define FILE_SHARE_READ
Definition: compat.h:125
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1091
static const GUID CLSID_ShellBtrfsPropSheet
Definition: main.cpp:29
#define COM_DESCRIPTION_ICON_HANDLER
Definition: main.cpp:32
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1098
string_error(int resno,...)
Definition: main.cpp:640
DWORD dwReason
Definition: misc.cpp:154
#define FILE_TRAVERSE
Definition: nt_native.h:643
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define LOCALE_STHOUSAND
Definition: winnls.h:43
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
void error_message(HWND hwnd, const char *msg)
Definition: main.cpp:738
ULONG(WINAPI * _RtlNtStatusToDosError)(NTSTATUS Status)
Definition: main.cpp:44
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define va_end(ap)
Definition: acmsvcex.h:90
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:10
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static void reg_prop_sheet_handler(const GUID clsid, const wstring &filetype, const wstring &name)
Definition: main.cpp:431
#define e
Definition: ke_i.h:82
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
#define S_FALSE
Definition: winerror.h:2357
LPWSTR *WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int *numargs)
Definition: shell32_main.c:76
#define LoadLibraryW(x)
Definition: compat.h:404
#define offsetof(TYPE, MEMBER)
char * va_list
Definition: acmsvcex.h:78
static const GUID CLSID_ShellBtrfsContextMenu
Definition: main.cpp:28
#define IDS_RECV_RTLUNICODETOUTF8N_FAILED
Definition: resource.h:200
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
#define OPEN_EXISTING
Definition: compat.h:426
GLuint GLfloat * val
Definition: glext.h:7180
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:9
r l[0]
Definition: byte_order.h:167
#define STATUS_INVALID_PARAMETER_5
Definition: ntstatus.h:465
void wstring_sprintf(wstring &s, wstring fmt,...)
Definition: main.cpp:225
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4895
static void register_clsid(const GUID clsid, const WCHAR *description)
Definition: main.cpp:310
GLfloat f
Definition: glext.h:7540
#define FreeLibrary(x)
Definition: compat.h:405
GLsizeiptr size
Definition: glext.h:5919
WCHAR dllpath[MAX_PATH]
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void unreg_prop_sheet_handler(const wstring &filetype, const wstring &name)
Definition: main.cpp:450
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define WINAPI
Definition: msvc.h:8
const char file[]
Definition: icontest.c:11
const GLubyte * c
Definition: glext.h:8905
string msg
Definition: shellext.h:350
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IDS_SIZE_TB
Definition: resource.h:35
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
REFCLSID clsid
Definition: msctf.c:84
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
#define IDS_SIZE_BYTE
Definition: resource.h:30
#define MB_ICONERROR
Definition: winuser.h:781
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
GLdouble s
Definition: gl.h:2039
STDAPI DllUnregisterServer(void)
Definition: main.cpp:486
LONG objs_loaded
Definition: main.cpp:48
GLenum src
Definition: glext.h:6340
bool load_string(HMODULE module, UINT id, wstring &s)
Definition: main.cpp:206
#define IDS_REGDELETETREE_FAILED
Definition: resource.h:204
GLsizei const GLfloat * value
Definition: glext.h:6069
Status
Definition: gdiplustypes.h:24
LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
Definition: reg.c:1746
static void unregister_clsid(const GUID clsid)
Definition: main.cpp:343
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
Definition: main.cpp:601
HANDLE HMODULE
Definition: typedefs.h:75
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:401
last_error(DWORD errnum)
Definition: main.cpp:721
#define STATUS_SOME_NOT_MAPPED
Definition: ntstatus.h:86
#define IDS_SIZE_EB
Definition: resource.h:37
string msg
Definition: shellext.h:362
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
Definition: main.cpp:507
#define S_OK
Definition: intsafe.h:59
UINT64 uint64_t
Definition: types.h:77
_CRTIMP int __cdecl _vsnwprintf(wchar_t *_Dest, size_t _Count, const wchar_t *_Format, va_list _Args)
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define IDS_SIZE_LARGE
Definition: resource.h:42
#define f
Definition: ke_i.h:83
static void create_snapshot2(const wstring &source, const wstring &fn)
Definition: main.cpp:563
Definition: services.c:325
wstring format_message(ULONG last_error)
Definition: main.cpp:164
#define va_start(ap, A)
Definition: acmsvcex.h:91
unsigned int UINT
Definition: ndis.h:50
#define CreateFileW
Definition: compat.h:400
#define IDS_REGCLOSEKEY_FAILED
Definition: resource.h:203
#define msg(x)
Definition: auth_time.c:54
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:130
static void reg_context_menu_handler(const GUID clsid, const wstring &filetype, const wstring &name)
Definition: main.cpp:399
#define IDS_ERROR
Definition: resource.h:18
Definition: name.c:36
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
static void unreg_context_menu_handler(const wstring &filetype, const wstring &name)
Definition: main.cpp:418
#define c
Definition: ke_i.h:80
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void *lpReserved)
Definition: main.cpp:514
unsigned int ULONG
Definition: retypes.h:1
#define COM_DESCRIPTION_CONTEXT_MENU
Definition: main.cpp:33
#define progid(str)
Definition: exdisp.idl:31
static HINSTANCE hinst
Definition: edit.c:551
LOCAL char * filetype(int t)
Definition: tree.c:114
void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
Definition: main.cpp:554
#define GetProcAddress(x, y)
Definition: compat.h:410
#define malloc
Definition: debug_ros.c:4
_PROCESS_DPI_AWARENESS
Definition: main.cpp:38
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define COM_DESCRIPTION_VOL_PROP_SHEET
Definition: main.cpp:35
#define IDS_REGCREATEKEY_FAILED
Definition: resource.h:201
INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchOut)
Definition: lcformat.c:1198
factory_type type
Definition: factory.h:64
#define IDS_SIZE_GB
Definition: resource.h:34
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:464
static void unreg_icon_overlay(const wstring &name)
Definition: main.cpp:386
return STATUS_SUCCESS
Definition: btrfs.c:2777
static SERVICE_STATUS status
Definition: service.c:31
#define args
Definition: format.c:66
void set_dpi_aware()
Definition: main.cpp:50
static char title[]
Definition: ps.c:92
Definition: dsound.c:943
static const GUID CLSID_ShellBtrfsVolPropSheet
Definition: main.cpp:30
#define APIENTRY
Definition: api.h:79
HMODULE hModule
Definition: animate.c:44
void utf8_to_utf16(const string &utf8, wstring &utf16)
Definition: main.cpp:667
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
void command_line_to_args(LPWSTR cmdline, vector< wstring > args)
Definition: main.cpp:610
Definition: fci.c:126
HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR *idstr)
Definition: compobj.c:2321
static const GUID CLSID_ShellBtrfsIconHandler
Definition: main.cpp:27
#define REG_SZ
Definition: layer.c:22
void format_size(uint64_t size, wstring &s, bool show_bytes)
Definition: main.cpp:65
static void reg_icon_overlay(const GUID clsid, const wstring &name)
Definition: main.cpp:365
Definition: ps.c:97
GLuint const GLchar * name
Definition: glext.h:6031
#define IDS_SIZE_MB
Definition: resource.h:33
NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF8StringMaxByteCount, PULONG UTF8StringActualByteCount, PCWCH UnicodeStringSource, ULONG UnicodeStringByteCount)