1
0

obs-windows.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "util/windows/win-registry.h"
  15. #include "util/windows/win-version.h"
  16. #include "util/platform.h"
  17. #include "util/dstr.h"
  18. #include "obs.h"
  19. #include "obs-internal.h"
  20. #include <windows.h>
  21. #include <wscapi.h>
  22. #include <iwscapi.h>
  23. static uint32_t win_ver = 0;
  24. static uint32_t win_build = 0;
  25. const char *get_module_extension(void)
  26. {
  27. return ".dll";
  28. }
  29. static const char *module_bin[] = {"../../obs-plugins/64bit"};
  30. static const char *module_data[] = {"../../data/obs-plugins/%module%"};
  31. static const int module_patterns_size = sizeof(module_bin) / sizeof(module_bin[0]);
  32. void add_default_module_paths(void)
  33. {
  34. for (int i = 0; i < module_patterns_size; i++)
  35. obs_add_module_path(module_bin[i], module_data[i]);
  36. }
  37. /* on windows, points to [base directory]/data/libobs */
  38. char *find_libobs_data_file(const char *file)
  39. {
  40. struct dstr path;
  41. dstr_init(&path);
  42. if (check_path(file, "../../data/libobs/", &path))
  43. return path.array;
  44. dstr_free(&path);
  45. return NULL;
  46. }
  47. static void log_processor_info(void)
  48. {
  49. HKEY key;
  50. wchar_t data[1024];
  51. char *str = NULL;
  52. DWORD size, speed;
  53. LSTATUS status;
  54. memset(data, 0, sizeof(data));
  55. status = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
  56. if (status != ERROR_SUCCESS)
  57. return;
  58. size = sizeof(data);
  59. status = RegQueryValueExW(key, L"ProcessorNameString", NULL, NULL, (LPBYTE)data, &size);
  60. if (status == ERROR_SUCCESS) {
  61. os_wcs_to_utf8_ptr(data, 0, &str);
  62. blog(LOG_INFO, "CPU Name: %s", str);
  63. bfree(str);
  64. }
  65. size = sizeof(speed);
  66. status = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE)&speed, &size);
  67. if (status == ERROR_SUCCESS)
  68. blog(LOG_INFO, "CPU Speed: %ldMHz", speed);
  69. RegCloseKey(key);
  70. }
  71. static void log_processor_cores(void)
  72. {
  73. blog(LOG_INFO, "Physical Cores: %d, Logical Cores: %d", os_get_physical_cores(), os_get_logical_cores());
  74. }
  75. static void log_emulation_status(void)
  76. {
  77. if (os_get_emulation_status()) {
  78. blog(LOG_WARNING, "Windows ARM64: Running with x64 emulation");
  79. }
  80. }
  81. static void log_available_memory(void)
  82. {
  83. MEMORYSTATUSEX ms;
  84. ms.dwLength = sizeof(ms);
  85. GlobalMemoryStatusEx(&ms);
  86. #ifdef _WIN64
  87. const char *note = "";
  88. #else
  89. const char *note = " (NOTE: 32bit programs cannot use more than 3gb)";
  90. #endif
  91. blog(LOG_INFO, "Physical Memory: %luMB Total, %luMB Free%s", (DWORD)(ms.ullTotalPhys / 1048576),
  92. (DWORD)(ms.ullAvailPhys / 1048576), note);
  93. }
  94. static void log_lenovo_vantage(void)
  95. {
  96. SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  97. if (!manager)
  98. return;
  99. SC_HANDLE service = OpenService(manager, L"FBNetFilter", SERVICE_QUERY_STATUS);
  100. if (service) {
  101. blog(LOG_WARNING, "Lenovo Vantage / Legion Edge is installed. The \"Network Boost\" "
  102. "feature must be disabled when streaming with OBS.");
  103. CloseServiceHandle(service);
  104. }
  105. CloseServiceHandle(manager);
  106. }
  107. static void log_conflicting_software(void)
  108. {
  109. log_lenovo_vantage();
  110. }
  111. extern const char *get_win_release_id();
  112. static void log_windows_version(void)
  113. {
  114. struct win_version_info ver;
  115. get_win_ver(&ver);
  116. const char *release_id = get_win_release_id();
  117. bool b64 = is_64_bit_windows();
  118. const char *windows_bitness = b64 ? "64" : "32";
  119. bool arm64 = is_arm64_windows();
  120. const char *arm64_windows = arm64 ? "ARM " : "";
  121. blog(LOG_INFO, "Windows Version: %d.%d Build %d (release: %s; revision: %d; %s%s-bit)", ver.major, ver.minor,
  122. ver.build, release_id, ver.revis, arm64_windows, windows_bitness);
  123. }
  124. static void log_admin_status(void)
  125. {
  126. SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
  127. PSID admin_group;
  128. BOOL success;
  129. success = AllocateAndInitializeSid(&auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0,
  130. 0, 0, &admin_group);
  131. if (success) {
  132. if (!CheckTokenMembership(NULL, admin_group, &success))
  133. success = false;
  134. FreeSid(admin_group);
  135. }
  136. blog(LOG_INFO, "Running as administrator: %s", success ? "true" : "false");
  137. }
  138. #define WIN10_GAME_BAR_REG_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR"
  139. #define WIN10_GAME_DVR_POLICY_REG_KEY L"SOFTWARE\\Policies\\Microsoft\\Windows\\GameDVR"
  140. #define WIN10_GAME_DVR_REG_KEY L"System\\GameConfigStore"
  141. #define WIN10_GAME_MODE_REG_KEY L"Software\\Microsoft\\GameBar"
  142. static void log_gaming_features(void)
  143. {
  144. if (win_ver < 0xA00)
  145. return;
  146. struct reg_dword game_bar_enabled;
  147. struct reg_dword game_dvr_allowed;
  148. struct reg_dword game_dvr_enabled;
  149. struct reg_dword game_dvr_bg_recording;
  150. struct reg_dword game_mode_enabled;
  151. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_BAR_REG_KEY, L"AppCaptureEnabled", &game_bar_enabled);
  152. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_DVR_POLICY_REG_KEY, L"AllowGameDVR", &game_dvr_allowed);
  153. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_DVR_REG_KEY, L"GameDVR_Enabled", &game_dvr_enabled);
  154. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_BAR_REG_KEY, L"HistoricalCaptureEnabled", &game_dvr_bg_recording);
  155. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_MODE_REG_KEY, L"AutoGameModeEnabled", &game_mode_enabled);
  156. if (game_mode_enabled.status != ERROR_SUCCESS) {
  157. get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_MODE_REG_KEY, L"AllowAutoGameMode", &game_mode_enabled);
  158. }
  159. blog(LOG_INFO, "Windows 10/11 Gaming Features:");
  160. if (game_bar_enabled.status == ERROR_SUCCESS) {
  161. blog(LOG_INFO, "\tGame Bar: %s", (bool)game_bar_enabled.return_value ? "On" : "Off");
  162. }
  163. if (game_dvr_allowed.status == ERROR_SUCCESS) {
  164. blog(LOG_INFO, "\tGame DVR Allowed: %s", (bool)game_dvr_allowed.return_value ? "Yes" : "No");
  165. }
  166. if (game_dvr_enabled.status == ERROR_SUCCESS) {
  167. blog(LOG_INFO, "\tGame DVR: %s", (bool)game_dvr_enabled.return_value ? "On" : "Off");
  168. }
  169. if (game_dvr_bg_recording.status == ERROR_SUCCESS) {
  170. blog(LOG_INFO, "\tGame DVR Background Recording: %s",
  171. (bool)game_dvr_bg_recording.return_value ? "On" : "Off");
  172. }
  173. if (game_mode_enabled.status == ERROR_SUCCESS) {
  174. blog(LOG_INFO, "\tGame Mode: %s", (bool)game_mode_enabled.return_value ? "On" : "Off");
  175. } else if (win_build >= 19042) {
  176. // On by default in newer Windows 10 builds (no registry key set)
  177. blog(LOG_INFO, "\tGame Mode: Probably On (no reg key set)");
  178. }
  179. }
  180. static const char *get_str_for_state(int state)
  181. {
  182. switch (state) {
  183. case WSC_SECURITY_PRODUCT_STATE_ON:
  184. return "enabled";
  185. case WSC_SECURITY_PRODUCT_STATE_OFF:
  186. return "disabled";
  187. case WSC_SECURITY_PRODUCT_STATE_SNOOZED:
  188. return "temporarily disabled";
  189. case WSC_SECURITY_PRODUCT_STATE_EXPIRED:
  190. return "expired";
  191. default:
  192. return "unknown";
  193. }
  194. }
  195. static const char *get_str_for_type(int type)
  196. {
  197. switch (type) {
  198. case WSC_SECURITY_PROVIDER_ANTIVIRUS:
  199. return "AV";
  200. case WSC_SECURITY_PROVIDER_FIREWALL:
  201. return "FW";
  202. case WSC_SECURITY_PROVIDER_ANTISPYWARE:
  203. return "ASW";
  204. default:
  205. return "unknown";
  206. }
  207. }
  208. static void log_security_products_by_type(IWSCProductList *prod_list, int type)
  209. {
  210. HRESULT hr;
  211. LONG count = 0;
  212. IWscProduct *prod;
  213. BSTR name;
  214. WSC_SECURITY_PRODUCT_STATE prod_state;
  215. hr = prod_list->lpVtbl->Initialize(prod_list, type);
  216. if (FAILED(hr))
  217. return;
  218. hr = prod_list->lpVtbl->get_Count(prod_list, &count);
  219. if (FAILED(hr)) {
  220. prod_list->lpVtbl->Release(prod_list);
  221. return;
  222. }
  223. for (int i = 0; i < count; i++) {
  224. hr = prod_list->lpVtbl->get_Item(prod_list, i, &prod);
  225. if (FAILED(hr))
  226. continue;
  227. hr = prod->lpVtbl->get_ProductName(prod, &name);
  228. if (FAILED(hr))
  229. continue;
  230. hr = prod->lpVtbl->get_ProductState(prod, &prod_state);
  231. if (FAILED(hr)) {
  232. SysFreeString(name);
  233. continue;
  234. }
  235. char *product_name;
  236. os_wcs_to_utf8_ptr(name, 0, &product_name);
  237. blog(LOG_INFO, "\t%s: %s (%s)", product_name, get_str_for_state(prod_state), get_str_for_type(type));
  238. bfree(product_name);
  239. SysFreeString(name);
  240. prod->lpVtbl->Release(prod);
  241. }
  242. prod_list->lpVtbl->Release(prod_list);
  243. }
  244. static void log_security_products(void)
  245. {
  246. IWSCProductList *prod_list = NULL;
  247. HMODULE h_wsc;
  248. HRESULT hr;
  249. /* We load the DLL rather than import wcsapi.lib because the clsid /
  250. * iid only exists on Windows 8 or higher. */
  251. h_wsc = LoadLibraryW(L"wscapi.dll");
  252. if (!h_wsc)
  253. return;
  254. const CLSID *prod_list_clsid = (const CLSID *)GetProcAddress(h_wsc, "CLSID_WSCProductList");
  255. const IID *prod_list_iid = (const IID *)GetProcAddress(h_wsc, "IID_IWSCProductList");
  256. if (prod_list_clsid && prod_list_iid) {
  257. blog(LOG_INFO, "Sec. Software Status:");
  258. hr = CoCreateInstance(prod_list_clsid, NULL, CLSCTX_INPROC_SERVER, prod_list_iid, &prod_list);
  259. if (!FAILED(hr)) {
  260. log_security_products_by_type(prod_list, WSC_SECURITY_PROVIDER_ANTIVIRUS);
  261. }
  262. hr = CoCreateInstance(prod_list_clsid, NULL, CLSCTX_INPROC_SERVER, prod_list_iid, &prod_list);
  263. if (!FAILED(hr)) {
  264. log_security_products_by_type(prod_list, WSC_SECURITY_PROVIDER_FIREWALL);
  265. }
  266. hr = CoCreateInstance(prod_list_clsid, NULL, CLSCTX_INPROC_SERVER, prod_list_iid, &prod_list);
  267. if (!FAILED(hr)) {
  268. log_security_products_by_type(prod_list, WSC_SECURITY_PROVIDER_ANTISPYWARE);
  269. }
  270. }
  271. FreeLibrary(h_wsc);
  272. }
  273. void log_system_info(void)
  274. {
  275. struct win_version_info ver;
  276. get_win_ver(&ver);
  277. win_ver = (ver.major << 8) | ver.minor;
  278. win_build = ver.build;
  279. log_processor_info();
  280. log_processor_cores();
  281. log_available_memory();
  282. log_windows_version();
  283. log_emulation_status();
  284. log_admin_status();
  285. log_gaming_features();
  286. log_security_products();
  287. log_conflicting_software();
  288. }
  289. struct obs_hotkeys_platform {
  290. int vk_codes[OBS_KEY_LAST_VALUE];
  291. };
  292. static int get_virtual_key(obs_key_t key)
  293. {
  294. switch (key) {
  295. case OBS_KEY_RETURN:
  296. return VK_RETURN;
  297. case OBS_KEY_ESCAPE:
  298. return VK_ESCAPE;
  299. case OBS_KEY_TAB:
  300. return VK_TAB;
  301. case OBS_KEY_BACKTAB:
  302. return VK_OEM_BACKTAB;
  303. case OBS_KEY_BACKSPACE:
  304. return VK_BACK;
  305. case OBS_KEY_INSERT:
  306. return VK_INSERT;
  307. case OBS_KEY_DELETE:
  308. return VK_DELETE;
  309. case OBS_KEY_PAUSE:
  310. return VK_PAUSE;
  311. case OBS_KEY_PRINT:
  312. return VK_SNAPSHOT;
  313. case OBS_KEY_CLEAR:
  314. return VK_CLEAR;
  315. case OBS_KEY_HOME:
  316. return VK_HOME;
  317. case OBS_KEY_END:
  318. return VK_END;
  319. case OBS_KEY_LEFT:
  320. return VK_LEFT;
  321. case OBS_KEY_UP:
  322. return VK_UP;
  323. case OBS_KEY_RIGHT:
  324. return VK_RIGHT;
  325. case OBS_KEY_DOWN:
  326. return VK_DOWN;
  327. case OBS_KEY_PAGEUP:
  328. return VK_PRIOR;
  329. case OBS_KEY_PAGEDOWN:
  330. return VK_NEXT;
  331. case OBS_KEY_SHIFT:
  332. return VK_SHIFT;
  333. case OBS_KEY_CONTROL:
  334. return VK_CONTROL;
  335. case OBS_KEY_ALT:
  336. return VK_MENU;
  337. case OBS_KEY_CAPSLOCK:
  338. return VK_CAPITAL;
  339. case OBS_KEY_NUMLOCK:
  340. return VK_NUMLOCK;
  341. case OBS_KEY_SCROLLLOCK:
  342. return VK_SCROLL;
  343. case OBS_KEY_F1:
  344. return VK_F1;
  345. case OBS_KEY_F2:
  346. return VK_F2;
  347. case OBS_KEY_F3:
  348. return VK_F3;
  349. case OBS_KEY_F4:
  350. return VK_F4;
  351. case OBS_KEY_F5:
  352. return VK_F5;
  353. case OBS_KEY_F6:
  354. return VK_F6;
  355. case OBS_KEY_F7:
  356. return VK_F7;
  357. case OBS_KEY_F8:
  358. return VK_F8;
  359. case OBS_KEY_F9:
  360. return VK_F9;
  361. case OBS_KEY_F10:
  362. return VK_F10;
  363. case OBS_KEY_F11:
  364. return VK_F11;
  365. case OBS_KEY_F12:
  366. return VK_F12;
  367. case OBS_KEY_F13:
  368. return VK_F13;
  369. case OBS_KEY_F14:
  370. return VK_F14;
  371. case OBS_KEY_F15:
  372. return VK_F15;
  373. case OBS_KEY_F16:
  374. return VK_F16;
  375. case OBS_KEY_F17:
  376. return VK_F17;
  377. case OBS_KEY_F18:
  378. return VK_F18;
  379. case OBS_KEY_F19:
  380. return VK_F19;
  381. case OBS_KEY_F20:
  382. return VK_F20;
  383. case OBS_KEY_F21:
  384. return VK_F21;
  385. case OBS_KEY_F22:
  386. return VK_F22;
  387. case OBS_KEY_F23:
  388. return VK_F23;
  389. case OBS_KEY_F24:
  390. return VK_F24;
  391. case OBS_KEY_SPACE:
  392. return VK_SPACE;
  393. case OBS_KEY_APOSTROPHE:
  394. return VK_OEM_7;
  395. case OBS_KEY_PLUS:
  396. return VK_OEM_PLUS;
  397. case OBS_KEY_COMMA:
  398. return VK_OEM_COMMA;
  399. case OBS_KEY_MINUS:
  400. return VK_OEM_MINUS;
  401. case OBS_KEY_PERIOD:
  402. return VK_OEM_PERIOD;
  403. case OBS_KEY_SLASH:
  404. return VK_OEM_2;
  405. case OBS_KEY_0:
  406. return '0';
  407. case OBS_KEY_1:
  408. return '1';
  409. case OBS_KEY_2:
  410. return '2';
  411. case OBS_KEY_3:
  412. return '3';
  413. case OBS_KEY_4:
  414. return '4';
  415. case OBS_KEY_5:
  416. return '5';
  417. case OBS_KEY_6:
  418. return '6';
  419. case OBS_KEY_7:
  420. return '7';
  421. case OBS_KEY_8:
  422. return '8';
  423. case OBS_KEY_9:
  424. return '9';
  425. case OBS_KEY_NUMASTERISK:
  426. return VK_MULTIPLY;
  427. case OBS_KEY_NUMPLUS:
  428. return VK_ADD;
  429. case OBS_KEY_NUMMINUS:
  430. return VK_SUBTRACT;
  431. case OBS_KEY_NUMPERIOD:
  432. return VK_DECIMAL;
  433. case OBS_KEY_NUMSLASH:
  434. return VK_DIVIDE;
  435. case OBS_KEY_NUM0:
  436. return VK_NUMPAD0;
  437. case OBS_KEY_NUM1:
  438. return VK_NUMPAD1;
  439. case OBS_KEY_NUM2:
  440. return VK_NUMPAD2;
  441. case OBS_KEY_NUM3:
  442. return VK_NUMPAD3;
  443. case OBS_KEY_NUM4:
  444. return VK_NUMPAD4;
  445. case OBS_KEY_NUM5:
  446. return VK_NUMPAD5;
  447. case OBS_KEY_NUM6:
  448. return VK_NUMPAD6;
  449. case OBS_KEY_NUM7:
  450. return VK_NUMPAD7;
  451. case OBS_KEY_NUM8:
  452. return VK_NUMPAD8;
  453. case OBS_KEY_NUM9:
  454. return VK_NUMPAD9;
  455. case OBS_KEY_SEMICOLON:
  456. return VK_OEM_1;
  457. case OBS_KEY_A:
  458. return 'A';
  459. case OBS_KEY_B:
  460. return 'B';
  461. case OBS_KEY_C:
  462. return 'C';
  463. case OBS_KEY_D:
  464. return 'D';
  465. case OBS_KEY_E:
  466. return 'E';
  467. case OBS_KEY_F:
  468. return 'F';
  469. case OBS_KEY_G:
  470. return 'G';
  471. case OBS_KEY_H:
  472. return 'H';
  473. case OBS_KEY_I:
  474. return 'I';
  475. case OBS_KEY_J:
  476. return 'J';
  477. case OBS_KEY_K:
  478. return 'K';
  479. case OBS_KEY_L:
  480. return 'L';
  481. case OBS_KEY_M:
  482. return 'M';
  483. case OBS_KEY_N:
  484. return 'N';
  485. case OBS_KEY_O:
  486. return 'O';
  487. case OBS_KEY_P:
  488. return 'P';
  489. case OBS_KEY_Q:
  490. return 'Q';
  491. case OBS_KEY_R:
  492. return 'R';
  493. case OBS_KEY_S:
  494. return 'S';
  495. case OBS_KEY_T:
  496. return 'T';
  497. case OBS_KEY_U:
  498. return 'U';
  499. case OBS_KEY_V:
  500. return 'V';
  501. case OBS_KEY_W:
  502. return 'W';
  503. case OBS_KEY_X:
  504. return 'X';
  505. case OBS_KEY_Y:
  506. return 'Y';
  507. case OBS_KEY_Z:
  508. return 'Z';
  509. case OBS_KEY_BRACKETLEFT:
  510. return VK_OEM_4;
  511. case OBS_KEY_BACKSLASH:
  512. return VK_OEM_5;
  513. case OBS_KEY_BRACKETRIGHT:
  514. return VK_OEM_6;
  515. case OBS_KEY_ASCIITILDE:
  516. return VK_OEM_3;
  517. case OBS_KEY_HENKAN:
  518. return VK_CONVERT;
  519. case OBS_KEY_MUHENKAN:
  520. return VK_NONCONVERT;
  521. case OBS_KEY_KANJI:
  522. return VK_KANJI;
  523. case OBS_KEY_TOUROKU:
  524. return VK_OEM_FJ_TOUROKU;
  525. case OBS_KEY_MASSYO:
  526. return VK_OEM_FJ_MASSHOU;
  527. case OBS_KEY_HANGUL:
  528. return VK_HANGUL;
  529. case OBS_KEY_BACKSLASH_RT102:
  530. return VK_OEM_102;
  531. case OBS_KEY_MOUSE1:
  532. return VK_LBUTTON;
  533. case OBS_KEY_MOUSE2:
  534. return VK_RBUTTON;
  535. case OBS_KEY_MOUSE3:
  536. return VK_MBUTTON;
  537. case OBS_KEY_MOUSE4:
  538. return VK_XBUTTON1;
  539. case OBS_KEY_MOUSE5:
  540. return VK_XBUTTON2;
  541. case OBS_KEY_VK_CANCEL:
  542. return VK_CANCEL;
  543. case OBS_KEY_0x07:
  544. return 0x07;
  545. case OBS_KEY_0x0A:
  546. return 0x0A;
  547. case OBS_KEY_0x0B:
  548. return 0x0B;
  549. case OBS_KEY_0x0E:
  550. return 0x0E;
  551. case OBS_KEY_0x0F:
  552. return 0x0F;
  553. case OBS_KEY_0x16:
  554. return 0x16;
  555. case OBS_KEY_VK_JUNJA:
  556. return VK_JUNJA;
  557. case OBS_KEY_VK_FINAL:
  558. return VK_FINAL;
  559. case OBS_KEY_0x1A:
  560. return 0x1A;
  561. case OBS_KEY_VK_ACCEPT:
  562. return VK_ACCEPT;
  563. case OBS_KEY_VK_MODECHANGE:
  564. return VK_MODECHANGE;
  565. case OBS_KEY_VK_SELECT:
  566. return VK_SELECT;
  567. case OBS_KEY_VK_PRINT:
  568. return VK_PRINT;
  569. case OBS_KEY_VK_EXECUTE:
  570. return VK_EXECUTE;
  571. case OBS_KEY_VK_HELP:
  572. return VK_HELP;
  573. case OBS_KEY_0x30:
  574. return 0x30;
  575. case OBS_KEY_0x31:
  576. return 0x31;
  577. case OBS_KEY_0x32:
  578. return 0x32;
  579. case OBS_KEY_0x33:
  580. return 0x33;
  581. case OBS_KEY_0x34:
  582. return 0x34;
  583. case OBS_KEY_0x35:
  584. return 0x35;
  585. case OBS_KEY_0x36:
  586. return 0x36;
  587. case OBS_KEY_0x37:
  588. return 0x37;
  589. case OBS_KEY_0x38:
  590. return 0x38;
  591. case OBS_KEY_0x39:
  592. return 0x39;
  593. case OBS_KEY_0x3A:
  594. return 0x3A;
  595. case OBS_KEY_0x3B:
  596. return 0x3B;
  597. case OBS_KEY_0x3C:
  598. return 0x3C;
  599. case OBS_KEY_0x3D:
  600. return 0x3D;
  601. case OBS_KEY_0x3E:
  602. return 0x3E;
  603. case OBS_KEY_0x3F:
  604. return 0x3F;
  605. case OBS_KEY_0x40:
  606. return 0x40;
  607. case OBS_KEY_0x41:
  608. return 0x41;
  609. case OBS_KEY_0x42:
  610. return 0x42;
  611. case OBS_KEY_0x43:
  612. return 0x43;
  613. case OBS_KEY_0x44:
  614. return 0x44;
  615. case OBS_KEY_0x45:
  616. return 0x45;
  617. case OBS_KEY_0x46:
  618. return 0x46;
  619. case OBS_KEY_0x47:
  620. return 0x47;
  621. case OBS_KEY_0x48:
  622. return 0x48;
  623. case OBS_KEY_0x49:
  624. return 0x49;
  625. case OBS_KEY_0x4A:
  626. return 0x4A;
  627. case OBS_KEY_0x4B:
  628. return 0x4B;
  629. case OBS_KEY_0x4C:
  630. return 0x4C;
  631. case OBS_KEY_0x4D:
  632. return 0x4D;
  633. case OBS_KEY_0x4E:
  634. return 0x4E;
  635. case OBS_KEY_0x4F:
  636. return 0x4F;
  637. case OBS_KEY_0x50:
  638. return 0x50;
  639. case OBS_KEY_0x51:
  640. return 0x51;
  641. case OBS_KEY_0x52:
  642. return 0x52;
  643. case OBS_KEY_0x53:
  644. return 0x53;
  645. case OBS_KEY_0x54:
  646. return 0x54;
  647. case OBS_KEY_0x55:
  648. return 0x55;
  649. case OBS_KEY_0x56:
  650. return 0x56;
  651. case OBS_KEY_0x57:
  652. return 0x57;
  653. case OBS_KEY_0x58:
  654. return 0x58;
  655. case OBS_KEY_0x59:
  656. return 0x59;
  657. case OBS_KEY_0x5A:
  658. return 0x5A;
  659. case OBS_KEY_VK_LWIN:
  660. return VK_LWIN;
  661. case OBS_KEY_VK_RWIN:
  662. return VK_RWIN;
  663. case OBS_KEY_VK_APPS:
  664. return VK_APPS;
  665. case OBS_KEY_0x5E:
  666. return 0x5E;
  667. case OBS_KEY_VK_SLEEP:
  668. return VK_SLEEP;
  669. case OBS_KEY_VK_SEPARATOR:
  670. return VK_SEPARATOR;
  671. case OBS_KEY_0x88:
  672. return 0x88;
  673. case OBS_KEY_0x89:
  674. return 0x89;
  675. case OBS_KEY_0x8A:
  676. return 0x8A;
  677. case OBS_KEY_0x8B:
  678. return 0x8B;
  679. case OBS_KEY_0x8C:
  680. return 0x8C;
  681. case OBS_KEY_0x8D:
  682. return 0x8D;
  683. case OBS_KEY_0x8E:
  684. return 0x8E;
  685. case OBS_KEY_0x8F:
  686. return 0x8F;
  687. case OBS_KEY_VK_OEM_FJ_JISHO:
  688. return VK_OEM_FJ_JISHO;
  689. case OBS_KEY_VK_OEM_FJ_LOYA:
  690. return VK_OEM_FJ_LOYA;
  691. case OBS_KEY_VK_OEM_FJ_ROYA:
  692. return VK_OEM_FJ_ROYA;
  693. case OBS_KEY_0x97:
  694. return 0x97;
  695. case OBS_KEY_0x98:
  696. return 0x98;
  697. case OBS_KEY_0x99:
  698. return 0x99;
  699. case OBS_KEY_0x9A:
  700. return 0x9A;
  701. case OBS_KEY_0x9B:
  702. return 0x9B;
  703. case OBS_KEY_0x9C:
  704. return 0x9C;
  705. case OBS_KEY_0x9D:
  706. return 0x9D;
  707. case OBS_KEY_0x9E:
  708. return 0x9E;
  709. case OBS_KEY_0x9F:
  710. return 0x9F;
  711. case OBS_KEY_VK_LSHIFT:
  712. return VK_LSHIFT;
  713. case OBS_KEY_VK_RSHIFT:
  714. return VK_RSHIFT;
  715. case OBS_KEY_VK_LCONTROL:
  716. return VK_LCONTROL;
  717. case OBS_KEY_VK_RCONTROL:
  718. return VK_RCONTROL;
  719. case OBS_KEY_VK_LMENU:
  720. return VK_LMENU;
  721. case OBS_KEY_VK_RMENU:
  722. return VK_RMENU;
  723. case OBS_KEY_VK_BROWSER_BACK:
  724. return VK_BROWSER_BACK;
  725. case OBS_KEY_VK_BROWSER_FORWARD:
  726. return VK_BROWSER_FORWARD;
  727. case OBS_KEY_VK_BROWSER_REFRESH:
  728. return VK_BROWSER_REFRESH;
  729. case OBS_KEY_VK_BROWSER_STOP:
  730. return VK_BROWSER_STOP;
  731. case OBS_KEY_VK_BROWSER_SEARCH:
  732. return VK_BROWSER_SEARCH;
  733. case OBS_KEY_VK_BROWSER_FAVORITES:
  734. return VK_BROWSER_FAVORITES;
  735. case OBS_KEY_VK_BROWSER_HOME:
  736. return VK_BROWSER_HOME;
  737. case OBS_KEY_VK_VOLUME_MUTE:
  738. return VK_VOLUME_MUTE;
  739. case OBS_KEY_VK_VOLUME_DOWN:
  740. return VK_VOLUME_DOWN;
  741. case OBS_KEY_VK_VOLUME_UP:
  742. return VK_VOLUME_UP;
  743. case OBS_KEY_VK_MEDIA_NEXT_TRACK:
  744. return VK_MEDIA_NEXT_TRACK;
  745. case OBS_KEY_VK_MEDIA_PREV_TRACK:
  746. return VK_MEDIA_PREV_TRACK;
  747. case OBS_KEY_VK_MEDIA_STOP:
  748. return VK_MEDIA_STOP;
  749. case OBS_KEY_VK_MEDIA_PLAY_PAUSE:
  750. return VK_MEDIA_PLAY_PAUSE;
  751. case OBS_KEY_VK_LAUNCH_MAIL:
  752. return VK_LAUNCH_MAIL;
  753. case OBS_KEY_VK_LAUNCH_MEDIA_SELECT:
  754. return VK_LAUNCH_MEDIA_SELECT;
  755. case OBS_KEY_VK_LAUNCH_APP1:
  756. return VK_LAUNCH_APP1;
  757. case OBS_KEY_VK_LAUNCH_APP2:
  758. return VK_LAUNCH_APP2;
  759. case OBS_KEY_0xB8:
  760. return 0xB8;
  761. case OBS_KEY_0xB9:
  762. return 0xB9;
  763. case OBS_KEY_0xC1:
  764. return 0xC1;
  765. case OBS_KEY_0xC2:
  766. return 0xC2;
  767. case OBS_KEY_0xC3:
  768. return 0xC3;
  769. case OBS_KEY_0xC4:
  770. return 0xC4;
  771. case OBS_KEY_0xC5:
  772. return 0xC5;
  773. case OBS_KEY_0xC6:
  774. return 0xC6;
  775. case OBS_KEY_0xC7:
  776. return 0xC7;
  777. case OBS_KEY_0xC8:
  778. return 0xC8;
  779. case OBS_KEY_0xC9:
  780. return 0xC9;
  781. case OBS_KEY_0xCA:
  782. return 0xCA;
  783. case OBS_KEY_0xCB:
  784. return 0xCB;
  785. case OBS_KEY_0xCC:
  786. return 0xCC;
  787. case OBS_KEY_0xCD:
  788. return 0xCD;
  789. case OBS_KEY_0xCE:
  790. return 0xCE;
  791. case OBS_KEY_0xCF:
  792. return 0xCF;
  793. case OBS_KEY_0xD0:
  794. return 0xD0;
  795. case OBS_KEY_0xD1:
  796. return 0xD1;
  797. case OBS_KEY_0xD2:
  798. return 0xD2;
  799. case OBS_KEY_0xD3:
  800. return 0xD3;
  801. case OBS_KEY_0xD4:
  802. return 0xD4;
  803. case OBS_KEY_0xD5:
  804. return 0xD5;
  805. case OBS_KEY_0xD6:
  806. return 0xD6;
  807. case OBS_KEY_0xD7:
  808. return 0xD7;
  809. case OBS_KEY_0xD8:
  810. return 0xD8;
  811. case OBS_KEY_0xD9:
  812. return 0xD9;
  813. case OBS_KEY_0xDA:
  814. return 0xDA;
  815. case OBS_KEY_VK_OEM_8:
  816. return VK_OEM_8;
  817. case OBS_KEY_0xE0:
  818. return 0xE0;
  819. case OBS_KEY_VK_OEM_AX:
  820. return VK_OEM_AX;
  821. case OBS_KEY_VK_ICO_HELP:
  822. return VK_ICO_HELP;
  823. case OBS_KEY_VK_ICO_00:
  824. return VK_ICO_00;
  825. case OBS_KEY_VK_PROCESSKEY:
  826. return VK_PROCESSKEY;
  827. case OBS_KEY_VK_ICO_CLEAR:
  828. return VK_ICO_CLEAR;
  829. case OBS_KEY_VK_PACKET:
  830. return VK_PACKET;
  831. case OBS_KEY_0xE8:
  832. return 0xE8;
  833. case OBS_KEY_VK_OEM_RESET:
  834. return VK_OEM_RESET;
  835. case OBS_KEY_VK_OEM_JUMP:
  836. return VK_OEM_JUMP;
  837. case OBS_KEY_VK_OEM_PA1:
  838. return VK_OEM_PA1;
  839. case OBS_KEY_VK_OEM_PA2:
  840. return VK_OEM_PA2;
  841. case OBS_KEY_VK_OEM_PA3:
  842. return VK_OEM_PA3;
  843. case OBS_KEY_VK_OEM_WSCTRL:
  844. return VK_OEM_WSCTRL;
  845. case OBS_KEY_VK_OEM_CUSEL:
  846. return VK_OEM_CUSEL;
  847. case OBS_KEY_VK_OEM_ATTN:
  848. return VK_OEM_ATTN;
  849. case OBS_KEY_VK_OEM_FINISH:
  850. return VK_OEM_FINISH;
  851. case OBS_KEY_VK_OEM_COPY:
  852. return VK_OEM_COPY;
  853. case OBS_KEY_VK_OEM_AUTO:
  854. return VK_OEM_AUTO;
  855. case OBS_KEY_VK_OEM_ENLW:
  856. return VK_OEM_ENLW;
  857. case OBS_KEY_VK_ATTN:
  858. return VK_ATTN;
  859. case OBS_KEY_VK_CRSEL:
  860. return VK_CRSEL;
  861. case OBS_KEY_VK_EXSEL:
  862. return VK_EXSEL;
  863. case OBS_KEY_VK_EREOF:
  864. return VK_EREOF;
  865. case OBS_KEY_VK_PLAY:
  866. return VK_PLAY;
  867. case OBS_KEY_VK_ZOOM:
  868. return VK_ZOOM;
  869. case OBS_KEY_VK_NONAME:
  870. return VK_NONAME;
  871. case OBS_KEY_VK_PA1:
  872. return VK_PA1;
  873. case OBS_KEY_VK_OEM_CLEAR:
  874. return VK_OEM_CLEAR;
  875. /* TODO: Implement keys for non-US keyboards */
  876. default:;
  877. }
  878. return 0;
  879. }
  880. bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
  881. {
  882. hotkeys->platform_context = bzalloc(sizeof(obs_hotkeys_platform_t));
  883. for (size_t i = 0; i < OBS_KEY_LAST_VALUE; i++)
  884. hotkeys->platform_context->vk_codes[i] = get_virtual_key(i);
  885. return true;
  886. }
  887. void obs_hotkeys_platform_free(struct obs_core_hotkeys *hotkeys)
  888. {
  889. bfree(hotkeys->platform_context);
  890. hotkeys->platform_context = NULL;
  891. }
  892. static bool vk_down(DWORD vk)
  893. {
  894. short state = GetAsyncKeyState(vk);
  895. bool down = (state & 0x8000) != 0;
  896. return down;
  897. }
  898. bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *context, obs_key_t key)
  899. {
  900. if (key == OBS_KEY_META) {
  901. return vk_down(VK_LWIN) || vk_down(VK_RWIN);
  902. }
  903. UNUSED_PARAMETER(context);
  904. return vk_down(obs_key_to_virtual_key(key));
  905. }
  906. void obs_key_to_str(obs_key_t key, struct dstr *str)
  907. {
  908. wchar_t name[128] = L"";
  909. UINT scan_code;
  910. int vk;
  911. if (key == OBS_KEY_NONE) {
  912. return;
  913. } else if (key >= OBS_KEY_F13 && key <= OBS_KEY_F24) {
  914. dstr_printf(str, "F%d", (int)(key - OBS_KEY_F13 + 13));
  915. return;
  916. } else if (key >= OBS_KEY_MOUSE1 && key <= OBS_KEY_MOUSE29) {
  917. if (obs->hotkeys.translations[key]) {
  918. dstr_copy(str, obs->hotkeys.translations[key]);
  919. } else {
  920. dstr_printf(str, "Mouse %d", (int)(key - OBS_KEY_MOUSE1 + 1));
  921. }
  922. return;
  923. }
  924. if (key == OBS_KEY_PAUSE) {
  925. dstr_copy(str, obs_get_hotkey_translation(key, "Pause"));
  926. return;
  927. } else if (key == OBS_KEY_META) {
  928. dstr_copy(str, obs_get_hotkey_translation(key, "Windows"));
  929. return;
  930. }
  931. vk = obs_key_to_virtual_key(key);
  932. scan_code = MapVirtualKey(vk, 0) << 16;
  933. switch (vk) {
  934. case VK_HOME:
  935. case VK_END:
  936. case VK_LEFT:
  937. case VK_UP:
  938. case VK_RIGHT:
  939. case VK_DOWN:
  940. case VK_PRIOR:
  941. case VK_NEXT:
  942. case VK_INSERT:
  943. case VK_DELETE:
  944. case VK_NUMLOCK:
  945. scan_code |= 0x01000000;
  946. }
  947. if ((key < OBS_KEY_VK_CANCEL || key > OBS_KEY_VK_OEM_CLEAR) && scan_code != 0 &&
  948. GetKeyNameTextW(scan_code, name, 128) != 0) {
  949. dstr_from_wcs(str, name);
  950. } else if (key != OBS_KEY_NONE) {
  951. dstr_copy(str, obs_key_to_name(key));
  952. }
  953. }
  954. obs_key_t obs_key_from_virtual_key(int code)
  955. {
  956. obs_hotkeys_platform_t *platform = obs->hotkeys.platform_context;
  957. for (size_t i = 0; i < OBS_KEY_LAST_VALUE; i++) {
  958. if (platform->vk_codes[i] == code) {
  959. return (obs_key_t)i;
  960. }
  961. }
  962. return OBS_KEY_NONE;
  963. }
  964. int obs_key_to_virtual_key(obs_key_t key)
  965. {
  966. if (key == OBS_KEY_META)
  967. return VK_LWIN;
  968. return obs->hotkeys.platform_context->vk_codes[(int)key];
  969. }
  970. static inline void add_combo_key(obs_key_t key, struct dstr *str)
  971. {
  972. struct dstr key_str = {0};
  973. obs_key_to_str(key, &key_str);
  974. if (!dstr_is_empty(&key_str)) {
  975. if (!dstr_is_empty(str)) {
  976. dstr_cat(str, " + ");
  977. }
  978. dstr_cat_dstr(str, &key_str);
  979. }
  980. dstr_free(&key_str);
  981. }
  982. void obs_key_combination_to_str(obs_key_combination_t combination, struct dstr *str)
  983. {
  984. if ((combination.modifiers & INTERACT_CONTROL_KEY) != 0) {
  985. add_combo_key(OBS_KEY_CONTROL, str);
  986. }
  987. if ((combination.modifiers & INTERACT_COMMAND_KEY) != 0) {
  988. add_combo_key(OBS_KEY_META, str);
  989. }
  990. if ((combination.modifiers & INTERACT_ALT_KEY) != 0) {
  991. add_combo_key(OBS_KEY_ALT, str);
  992. }
  993. if ((combination.modifiers & INTERACT_SHIFT_KEY) != 0) {
  994. add_combo_key(OBS_KEY_SHIFT, str);
  995. }
  996. if (combination.key != OBS_KEY_NONE) {
  997. add_combo_key(combination.key, str);
  998. }
  999. }
  1000. bool sym_initialize_called = false;
  1001. void reset_win32_symbol_paths(void)
  1002. {
  1003. static BOOL(WINAPI * sym_initialize_w)(HANDLE, const wchar_t *, BOOL);
  1004. static BOOL(WINAPI * sym_set_search_path_w)(HANDLE, const wchar_t *);
  1005. static bool funcs_initialized = false;
  1006. static bool initialize_success = false;
  1007. struct obs_module *module = obs->first_module;
  1008. struct dstr path_str = {0};
  1009. DARRAY(char *) paths;
  1010. wchar_t *path_str_w = NULL;
  1011. char *abspath;
  1012. da_init(paths);
  1013. if (!funcs_initialized) {
  1014. HMODULE mod;
  1015. funcs_initialized = true;
  1016. mod = LoadLibraryW(L"DbgHelp");
  1017. if (!mod)
  1018. return;
  1019. sym_initialize_w = (void *)GetProcAddress(mod, "SymInitializeW");
  1020. sym_set_search_path_w = (void *)GetProcAddress(mod, "SymSetSearchPathW");
  1021. if (!sym_initialize_w || !sym_set_search_path_w) {
  1022. FreeLibrary(mod);
  1023. return;
  1024. }
  1025. initialize_success = true;
  1026. // Leaks 'mod' once.
  1027. }
  1028. if (!initialize_success)
  1029. return;
  1030. abspath = os_get_abs_path_ptr(".");
  1031. if (abspath)
  1032. da_push_back(paths, &abspath);
  1033. while (module) {
  1034. bool found = false;
  1035. struct dstr path = {0};
  1036. char *path_end;
  1037. dstr_copy(&path, module->bin_path);
  1038. dstr_replace(&path, "/", "\\");
  1039. path_end = strrchr(path.array, '\\');
  1040. if (!path_end) {
  1041. module = module->next;
  1042. dstr_free(&path);
  1043. continue;
  1044. }
  1045. *path_end = 0;
  1046. abspath = os_get_abs_path_ptr(path.array);
  1047. if (abspath) {
  1048. for (size_t i = 0; i < paths.num; i++) {
  1049. const char *existing_path = paths.array[i];
  1050. if (astrcmpi(abspath, existing_path) == 0) {
  1051. found = true;
  1052. break;
  1053. }
  1054. }
  1055. if (!found) {
  1056. da_push_back(paths, &abspath);
  1057. } else {
  1058. bfree(abspath);
  1059. }
  1060. }
  1061. dstr_free(&path);
  1062. module = module->next;
  1063. }
  1064. for (size_t i = 0; i < paths.num; i++) {
  1065. const char *path = paths.array[i];
  1066. if (path && *path) {
  1067. if (i != 0)
  1068. dstr_cat(&path_str, ";");
  1069. dstr_cat(&path_str, paths.array[i]);
  1070. }
  1071. }
  1072. if (path_str.array) {
  1073. os_utf8_to_wcs_ptr(path_str.array, path_str.len, &path_str_w);
  1074. if (path_str_w) {
  1075. if (!sym_initialize_called) {
  1076. sym_initialize_w(GetCurrentProcess(), path_str_w, false);
  1077. sym_initialize_called = true;
  1078. } else {
  1079. sym_set_search_path_w(GetCurrentProcess(), path_str_w);
  1080. }
  1081. bfree(path_str_w);
  1082. }
  1083. }
  1084. for (size_t i = 0; i < paths.num; i++)
  1085. bfree(paths.array[i]);
  1086. dstr_free(&path_str);
  1087. da_free(paths);
  1088. }
  1089. extern void initialize_crash_handler(void);
  1090. void obs_init_win32_crash_handler(void)
  1091. {
  1092. initialize_crash_handler();
  1093. }
  1094. bool initialize_com(void)
  1095. {
  1096. const HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
  1097. const bool success = SUCCEEDED(hr);
  1098. if (!success)
  1099. blog(LOG_ERROR, "CoInitializeEx failed: 0x%08X", hr);
  1100. return success;
  1101. }
  1102. void uninitialize_com(void)
  1103. {
  1104. CoUninitialize();
  1105. }