FileTypeRegistrar.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. #include "FileTypeRegistrar.h"
  2. #include <windows.h>
  3. #include <shlwapi.h>
  4. #include <shellapi.h>
  5. #include <shobjidl.h>
  6. #define _STD_USING
  7. //#include "../nu/cast64.h"
  8. #include <strsafe.h>
  9. #ifdef ELEVATOR_SCOPE
  10. void Lock();
  11. void UnLock();
  12. #endif
  13. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  14. #include <VersionHelpers.h>
  15. #endif
  16. FileTypeRegistrar::FileTypeRegistrar()
  17. {
  18. refCount = 0;
  19. }
  20. HRESULT FileTypeRegistrar::QueryInterface(REFIID riid, LPVOID FAR *ppvObj)
  21. {
  22. if (!ppvObj)
  23. return E_POINTER;
  24. else if (IsEqualIID(riid, IID_IUnknown))
  25. *ppvObj = static_cast<IUnknown *>(this);
  26. else if (IsEqualIID(riid, __uuidof(IFileTypeRegistrar)))
  27. *ppvObj = static_cast<IFileTypeRegistrar *>(this);
  28. else
  29. {
  30. *ppvObj = NULL;
  31. return E_NOINTERFACE;
  32. }
  33. AddRef();
  34. return S_OK;
  35. }
  36. ULONG FileTypeRegistrar::AddRef(void)
  37. {
  38. #ifdef ELEVATOR_SCOPE
  39. Lock();
  40. #endif
  41. return ++refCount;
  42. }
  43. ULONG FileTypeRegistrar::Release(void)
  44. {
  45. ULONG retCount=--refCount;
  46. #ifdef ELEVATOR_SCOPE
  47. UnLock();
  48. #endif
  49. return retCount;
  50. }
  51. static LONG SetValue(HKEY hkey, const wchar_t *data)
  52. {
  53. return RegSetValueExW(hkey, NULL,0,REG_SZ,(const BYTE *)data, (DWORD)(sizeof(wchar_t)*(wcslen(data)+1)));
  54. }
  55. static LONG SetValue(HKEY hkey, const wchar_t *value, const wchar_t *data)
  56. {
  57. return RegSetValueExW(hkey, value,0,REG_SZ,(const BYTE *)data, (DWORD)(sizeof(wchar_t)*(wcslen(data)+1)));
  58. }
  59. HRESULT FileTypeRegistrar::RegisterMIMEType(const wchar_t *mimeType, const wchar_t *programName, const wchar_t *extension, int netscapeOnly)
  60. {
  61. HKEY mp3Key = NULL;
  62. if (!netscapeOnly)
  63. {
  64. wchar_t s[MAX_PATH] = {0};
  65. if (RegCreateKeyW(HKEY_CLASSES_ROOT, extension, &mp3Key) == ERROR_SUCCESS)
  66. {
  67. SetValue(mp3Key, L"Content Type", mimeType);
  68. RegCloseKey(mp3Key);
  69. }
  70. StringCchPrintfW(s, MAX_PATH, L"MIME\\Database\\Content Type\\%s", mimeType);
  71. if (RegCreateKeyW(HKEY_CLASSES_ROOT, s, &mp3Key) == ERROR_SUCCESS)
  72. {
  73. RegDeleteValueW(mp3Key, L"CLSID");
  74. SetValue(mp3Key, L"Extension", extension);
  75. RegCloseKey(mp3Key);
  76. }
  77. }
  78. if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Netscape\\Netscape Navigator\\Viewers", &mp3Key) == ERROR_SUCCESS)
  79. {
  80. SetValue(mp3Key, mimeType, programName);
  81. for (int x = 0; x < 999; x ++)
  82. {
  83. wchar_t st[100] = {0};
  84. DWORD vt;
  85. DWORD s = 128;
  86. wchar_t b[128] = {0};
  87. StringCchPrintfW(st, 100, L"TYPE%d", x);
  88. if (RegQueryValueExW(mp3Key, st, 0, &vt, (LPBYTE)b, &s) == ERROR_SUCCESS)
  89. {
  90. if (!wcscmp(b, mimeType)) break;
  91. }
  92. else
  93. {
  94. SetValue(mp3Key, st, mimeType);
  95. break;
  96. }
  97. }
  98. RegCloseKey(mp3Key);
  99. }
  100. return S_OK;
  101. }
  102. HRESULT FileTypeRegistrar::RegisterCDPlayer(const wchar_t *programName)
  103. {
  104. wchar_t buf2[MAX_PATH] = {0};
  105. HKEY mp3Key = NULL;
  106. StringCchPrintfW(buf2, MAX_PATH, L"\"%s\" %%1", programName);
  107. if (RegOpenKeyW(HKEY_CLASSES_ROOT, L"AudioCD\\shell\\play\\command", &mp3Key) == ERROR_SUCCESS)
  108. {
  109. wchar_t b[MAX_PATH] = {0};
  110. DWORD s = sizeof(b)/sizeof(*b);
  111. if (RegQueryValueEx(mp3Key, NULL, 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  112. {
  113. if (_wcsicmp(b, buf2))
  114. {
  115. wchar_t buf3[MAX_PATH] = {0};
  116. DWORD st = sizeof(buf3)/sizeof(*buf3);
  117. if (RegQueryValueExW(mp3Key, L"Winamp_Back", 0, NULL, (LPBYTE)buf3, &st) != ERROR_SUCCESS ||
  118. _wcsicmp(buf3, b))
  119. {
  120. SetValue(mp3Key, L"Winamp_Back", b);
  121. }
  122. SetValue(mp3Key, buf2);
  123. }
  124. }
  125. else SetValue(mp3Key, buf2);
  126. RegCloseKey(mp3Key);
  127. }
  128. return S_OK;
  129. }
  130. HRESULT FileTypeRegistrar::UnregisterCDPlayer(const wchar_t *programName)
  131. {
  132. wchar_t buf2[MAX_PATH] = {0};
  133. HKEY mp3Key = NULL;
  134. StringCchPrintfW(buf2, MAX_PATH, L"\"%s\" %%1", programName);
  135. if (RegOpenKeyW(HKEY_CLASSES_ROOT, L"AudioCD\\shell\\play\\command", &mp3Key) == ERROR_SUCCESS)
  136. {
  137. wchar_t b[MAX_PATH] = {0};
  138. DWORD s = sizeof(b)/sizeof(*b);
  139. if (RegQueryValueEx(mp3Key, NULL, 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  140. {
  141. if (!wcscmp(b, buf2))
  142. {
  143. s = sizeof(b);
  144. if (RegQueryValueExW(mp3Key, L"Winamp_Back", 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  145. {
  146. if (!_wcsicmp(b, buf2)) b[0] = 0;
  147. if (SetValue(mp3Key, b) == ERROR_SUCCESS)
  148. RegDeleteValueW(mp3Key, L"Winamp_Back");
  149. }
  150. else
  151. {
  152. buf2[0] = 0;
  153. SetValue(mp3Key, buf2);
  154. }
  155. }
  156. }
  157. RegCloseKey(mp3Key);
  158. }
  159. return S_OK;
  160. }
  161. static LONG myRegDeleteKeyEx(HKEY thiskey, LPCWSTR lpSubKey)
  162. {
  163. HKEY key = NULL;
  164. int retval = RegOpenKeyW(thiskey, lpSubKey, &key);
  165. if (retval == ERROR_SUCCESS)
  166. {
  167. wchar_t buffer[1024] = {0};
  168. while (RegEnumKeyW(key, 0, buffer, 1024) == ERROR_SUCCESS)
  169. if ((retval = myRegDeleteKeyEx(key, buffer)) != ERROR_SUCCESS) break;
  170. RegCloseKey(key);
  171. retval = RegDeleteKeyW(thiskey, lpSubKey);
  172. }
  173. return retval;
  174. }
  175. HRESULT FileTypeRegistrar::RegisterType(const wchar_t *extension, const wchar_t *which_str, const wchar_t *prog_name)
  176. {
  177. HKEY mp3Key = NULL;
  178. LONG regResult = RegCreateKeyW(HKEY_CLASSES_ROOT, extension, &mp3Key);
  179. if (regResult == ERROR_SUCCESS)
  180. {
  181. wchar_t b[128] = {0};
  182. DWORD s = sizeof(b)/sizeof(*b);
  183. if (RegQueryValueEx(mp3Key, NULL, 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  184. {
  185. if (wcsncmp(b, which_str, wcslen(b)))
  186. {
  187. SetValue(mp3Key, L"Winamp_Back", b);
  188. SetValue(mp3Key, which_str);
  189. }
  190. }
  191. else SetValue(mp3Key, which_str);
  192. if (mp3Key) RegCloseKey(mp3Key);
  193. }
  194. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  195. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  196. #else
  197. OSVERSIONINFO version = {0};
  198. version.dwOSVersionInfoSize = sizeof(version);
  199. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  200. if (version.dwMajorVersion >= 6) // Vista
  201. #endif
  202. {
  203. TCHAR szKey[256] = {0};
  204. StringCbPrintfW(szKey, sizeof(szKey), L"Software\\Clients\\Media\\%s\\Capabilities\\FileAssociations", prog_name);
  205. if (ERROR_SUCCESS == RegCreateKeyW(HKEY_LOCAL_MACHINE, szKey, &mp3Key))
  206. {
  207. SetValue(mp3Key, extension, which_str);
  208. // TODO: cache IApplicationAssociationRegistration
  209. IApplicationAssociationRegistration* pAAR = NULL;
  210. HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
  211. NULL, CLSCTX_INPROC,
  212. __uuidof(IApplicationAssociationRegistration),
  213. (void**)&pAAR);
  214. if (SUCCEEDED(hr) && pAAR)
  215. {
  216. pAAR->SetAppAsDefault(prog_name, extension, AT_FILEEXTENSION);
  217. pAAR->Release();
  218. }
  219. RegCloseKey(mp3Key);
  220. }
  221. }
  222. return S_OK;
  223. }
  224. HRESULT FileTypeRegistrar::UnregisterType(const wchar_t *extension, const wchar_t *which_str, const wchar_t *prog_name, int is_playlist)
  225. {
  226. HKEY mp3Key = NULL;
  227. LONG regResult = RegOpenKeyW(HKEY_CLASSES_ROOT, extension, &mp3Key);
  228. if (regResult == ERROR_SUCCESS)
  229. {
  230. wchar_t b[128] = {0};
  231. DWORD s = sizeof(b)/sizeof(*b);
  232. if (RegQueryValueEx(mp3Key, NULL, 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  233. {
  234. size_t len = min(wcslen(b), wcslen(which_str));
  235. if (!wcsncmp(b, which_str, len))
  236. {
  237. s = sizeof(b)/sizeof(*b);
  238. if (RegQueryValueExW(mp3Key, L"Winamp_Back", 0, NULL, (LPBYTE)b, &s) == ERROR_SUCCESS)
  239. {
  240. if (SetValue(mp3Key, b) == ERROR_SUCCESS)
  241. RegDeleteValueW(mp3Key, L"Winamp_Back");
  242. }
  243. else
  244. {
  245. RegDeleteValue(mp3Key, NULL);
  246. RegCloseKey(mp3Key);
  247. mp3Key = NULL;
  248. myRegDeleteKeyEx(HKEY_CLASSES_ROOT, extension);
  249. }
  250. }
  251. }
  252. if (mp3Key) RegCloseKey(mp3Key);
  253. if(!is_playlist)
  254. {
  255. myRegDeleteKeyEx(HKEY_CLASSES_ROOT, which_str);
  256. }
  257. }
  258. // TODO: benski> it'd be nice to have a function to remove any capabilities for which we no longer have a plugin for ...
  259. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  260. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  261. #else
  262. OSVERSIONINFO version = { 0 };
  263. version.dwOSVersionInfoSize = sizeof(version);
  264. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  265. if (version.dwMajorVersion >= 6) // Vista
  266. #endif
  267. {
  268. TCHAR szKey[256] = {0};
  269. StringCbPrintfW(szKey, sizeof(szKey), L"Software\\Clients\\Media\\%s\\Capabilities\\FileAssociations", prog_name);
  270. if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &mp3Key))
  271. {
  272. RegDeleteValue(mp3Key, extension);
  273. RegCloseKey(mp3Key);
  274. }
  275. }
  276. return S_OK;
  277. }
  278. HRESULT FileTypeRegistrar::AddDirectoryContext(const wchar_t *commandLine, const wchar_t *which_str, const wchar_t *description)
  279. {
  280. HKEY mp3Key = NULL;
  281. wchar_t regStr[256] = {0};
  282. StringCbPrintfW(regStr, sizeof(regStr), L"SOFTWARE\\Classes\\Directory\\shell\\%s", which_str);
  283. if (RegCreateKeyW(HKEY_LOCAL_MACHINE, regStr,&mp3Key) == ERROR_SUCCESS)
  284. {
  285. SetValue(mp3Key, description);
  286. RegCloseKey(mp3Key);
  287. }
  288. StringCbPrintfW(regStr, sizeof(regStr), L"SOFTWARE\\Classes\\Directory\\shell\\%s\\command", which_str);
  289. if (RegCreateKeyW(HKEY_LOCAL_MACHINE,regStr,&mp3Key) == ERROR_SUCCESS)
  290. {
  291. SetValue(mp3Key, commandLine);
  292. RegCloseKey(mp3Key);
  293. }
  294. return S_OK;
  295. }
  296. HRESULT FileTypeRegistrar::RemoveDirectoryContext(const wchar_t *which_str)
  297. {
  298. wchar_t regStr[256] = {0};
  299. StringCbPrintfW(regStr, sizeof(regStr), L"SOFTWARE\\Classes\\Directory\\shell\\%s", which_str);
  300. myRegDeleteKeyEx(HKEY_LOCAL_MACHINE, regStr);
  301. return S_OK;
  302. }
  303. HRESULT FileTypeRegistrar::AddAgent(const wchar_t *agentFilename)
  304. {
  305. HKEY key = NULL;
  306. STARTUPINFOW si = {sizeof(si), };
  307. PROCESS_INFORMATION pi = {0, };
  308. if (RegCreateKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &key) == ERROR_SUCCESS)
  309. {
  310. SetValue(key, L"WinampAgent", agentFilename);
  311. RegCloseKey(key);
  312. }
  313. CreateProcessW(NULL, (LPWSTR)agentFilename, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
  314. CloseHandle(pi.hProcess);
  315. CloseHandle(pi.hThread);
  316. return S_OK;
  317. }
  318. HRESULT FileTypeRegistrar::RemoveAgent()
  319. {
  320. HKEY key = NULL;
  321. // caller will have done this also, but we'll do it again at elevated level just in case that's where winamp agent is running
  322. HWND hwnd = FindWindow(L"WinampAgentMain", NULL);
  323. if (hwnd)
  324. {
  325. SendMessageW(hwnd, WM_CLOSE, 0, 0);
  326. }
  327. if (RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &key) == ERROR_SUCCESS)
  328. {
  329. RegDeleteValue(key, L"WinampAgent");
  330. RegCloseKey(key);
  331. }
  332. return S_OK;
  333. }
  334. static LONG RegMedia_CreateKey(LPCWSTR lpSubKey, HKEY *phkResult, LPCWSTR prog_name)
  335. {
  336. WCHAR szKey[256] = {0};
  337. HRESULT hr = (lpSubKey && *lpSubKey) ?
  338. StringCbPrintfW(szKey, sizeof(szKey), L"Software\\Clients\\Media\\%s\\%s", prog_name, lpSubKey) :
  339. StringCbPrintfW(szKey, sizeof(szKey), L"Software\\Clients\\Media\\%s", prog_name);
  340. if (S_OK != hr) return ERROR_NOT_ENOUGH_MEMORY;
  341. return RegCreateKeyW(HKEY_LOCAL_MACHINE, szKey, phkResult);
  342. }
  343. HRESULT FileTypeRegistrar::RegisterMediaPlayer(DWORD accessEnabled, const wchar_t *programName, const wchar_t *prog_name, int iconNumber)
  344. {
  345. HKEY mp3Key = NULL;
  346. wchar_t str[MAX_PATH+128] = {0};
  347. if (RegMedia_CreateKey(NULL, &mp3Key, prog_name) == ERROR_SUCCESS)
  348. {
  349. SetValue(mp3Key, prog_name);
  350. RegCloseKey(mp3Key);
  351. }
  352. if (RegMedia_CreateKey(L"DefaultIcon",&mp3Key, prog_name) == ERROR_SUCCESS)
  353. {
  354. StringCchPrintfW(str,MAX_PATH+128,L"%s,%d",programName,iconNumber);
  355. SetValue(mp3Key, str);
  356. RegCloseKey(mp3Key);
  357. }
  358. if (RegMedia_CreateKey(L"InstallInfo",&mp3Key, prog_name) == ERROR_SUCCESS)
  359. {
  360. RegSetValueExW(mp3Key, L"IconsVisible", 0, REG_DWORD, (BYTE *)&accessEnabled, sizeof(accessEnabled));
  361. StringCchPrintfW(str,MAX_PATH+128, L"\"%s\" /REG=AVCDL", programName);
  362. SetValue(mp3Key,L"ReinstallCommand", str);
  363. SetValue(mp3Key,L"ShowIconsCommand", str);
  364. StringCchPrintfW(str,MAX_PATH+128,L"\"%s\" /UNREG",programName);
  365. SetValue(mp3Key,L"HideIconsCommand", str);
  366. RegCloseKey(mp3Key);
  367. }
  368. if (RegMedia_CreateKey(L"shell",&mp3Key, prog_name) == ERROR_SUCCESS)
  369. RegCloseKey(mp3Key);
  370. if (RegMedia_CreateKey(L"shell\\open",&mp3Key, prog_name) == ERROR_SUCCESS)
  371. RegCloseKey(mp3Key);
  372. if (RegMedia_CreateKey(L"shell\\open\\command",&mp3Key, prog_name) == ERROR_SUCCESS)
  373. {
  374. SetValue(mp3Key, programName);
  375. RegCloseKey(mp3Key);
  376. }
  377. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  378. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  379. #else
  380. OSVERSIONINFO version = { 0 };
  381. version.dwOSVersionInfoSize = sizeof(version);
  382. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  383. if (version.dwMajorVersion >= 6) // Vista
  384. #endif
  385. {
  386. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities",&mp3Key, prog_name))
  387. {
  388. SetValue(mp3Key,L"ApplicationDescription", L"Winamp. The Ultimate Media Player.");
  389. SetValue(mp3Key,L"ApplicationName", prog_name);
  390. RegCloseKey(mp3Key);
  391. }
  392. if (ERROR_SUCCESS == RegCreateKeyW(HKEY_LOCAL_MACHINE, L"Software\\RegisteredApplications", &mp3Key))
  393. {
  394. TCHAR szValue[256] = {0};
  395. StringCbPrintfW(szValue, sizeof(szValue), L"Software\\Clients\\Media\\%s\\Capabilities", prog_name);
  396. SetValue(mp3Key, prog_name, szValue);
  397. RegCloseKey(mp3Key);
  398. }
  399. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities\\FileAssociations",&mp3Key, prog_name))
  400. {
  401. RegCloseKey(mp3Key);
  402. }
  403. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities\\MimeAssociations",&mp3Key, prog_name))
  404. {
  405. RegCloseKey(mp3Key);
  406. }
  407. }
  408. return S_OK;
  409. }
  410. HRESULT FileTypeRegistrar::RegisterMediaPlayerProtocol(LPCWSTR protocol, LPCWSTR prog_name)
  411. {
  412. HKEY mp3Key = NULL;
  413. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  414. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  415. #else
  416. OSVERSIONINFO version = { 0 };
  417. version.dwOSVersionInfoSize = sizeof(version);
  418. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  419. if (version.dwMajorVersion >= 6) // Vista
  420. #endif
  421. {
  422. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities\\URLAssociations",&mp3Key, prog_name))
  423. {
  424. wchar_t szBuffer[64] = {0};
  425. StringCbCopyW(szBuffer, sizeof(szBuffer), protocol);
  426. CharUpperW(szBuffer);
  427. SetValue(mp3Key, protocol, szBuffer);
  428. RegCloseKey(mp3Key);
  429. }
  430. }
  431. return S_OK;
  432. }
  433. HRESULT FileTypeRegistrar::UnregisterMediaPlayerProtocol(LPCWSTR protocol, LPCWSTR prog_name)
  434. {
  435. HKEY mp3Key = NULL;
  436. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  437. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  438. #else
  439. OSVERSIONINFO version = { 0 };
  440. version.dwOSVersionInfoSize = sizeof(version);
  441. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  442. if (version.dwMajorVersion >= 6) // Vista
  443. #endif
  444. {
  445. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities\\URLAssociations",&mp3Key, prog_name))
  446. {
  447. RegDeleteValue(mp3Key, protocol);
  448. RegCloseKey(mp3Key);
  449. }
  450. }
  451. return S_OK;
  452. }
  453. static LONG RegCreateKey4(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpSubKey2, PHKEY phkResult)
  454. {
  455. wchar_t temp[1024] = {0};
  456. StringCchPrintfW(temp, 1024, L"%s%s", lpSubKey, lpSubKey2);
  457. return RegCreateKeyW(hKey,temp,phkResult);
  458. }
  459. static LONG RegCreateKey5(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpSubKey2, LPCWSTR lpSubKey3, PHKEY phkResult)
  460. {
  461. wchar_t temp[1024] = {0};
  462. StringCchPrintfW(temp, 1024, L"%s%s%s", lpSubKey, lpSubKey2, lpSubKey3);
  463. return RegCreateKeyW(hKey,temp,phkResult);
  464. }
  465. static LONG RegCreateKey6(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpSubKey2, LPCWSTR lpSubKey3, LPCWSTR lpSubKey4, PHKEY phkResult)
  466. {
  467. wchar_t temp[1024] = {0};
  468. StringCchPrintfW(temp, 1024, L"%s%s%s%s", lpSubKey, lpSubKey2, lpSubKey3,lpSubKey4);
  469. return RegCreateKeyW(hKey,temp,phkResult);
  470. }
  471. HRESULT FileTypeRegistrar::SetupShell(const wchar_t *commandLine, const wchar_t *winamp_file, const wchar_t *description, const wchar_t *commandName, const wchar_t *dragAndDropGUID)
  472. {
  473. HKEY mp3Key = NULL;
  474. if (RegCreateKey5(HKEY_CLASSES_ROOT,winamp_file, L"\\shell\\", commandName,&mp3Key) == ERROR_SUCCESS)
  475. {
  476. SetValue(mp3Key, description);
  477. RegCloseKey(mp3Key);
  478. }
  479. if (RegCreateKey6(HKEY_CLASSES_ROOT,winamp_file, L"\\shell\\", commandName, L"\\command",&mp3Key) == ERROR_SUCCESS)
  480. {
  481. SetValue(mp3Key, commandLine);
  482. RegCloseKey(mp3Key);
  483. }
  484. /* Drag and Drop stuff */
  485. if (dragAndDropGUID && *dragAndDropGUID)
  486. {
  487. if (RegCreateKey6(HKEY_CLASSES_ROOT,winamp_file, L"\\shell\\", commandName, L"\\DropTarget",&mp3Key) == ERROR_SUCCESS)
  488. {
  489. SetValue(mp3Key, L"Clsid", dragAndDropGUID);
  490. RegCloseKey(mp3Key);
  491. }
  492. }
  493. return S_OK;
  494. }
  495. HRESULT FileTypeRegistrar::RemoveShell(const wchar_t *winamp_file, const wchar_t *commandName)
  496. {
  497. wchar_t temp[1024] = {0};
  498. StringCchPrintfW(temp, 1024, L"%s\\shell\\%s", winamp_file, commandName);
  499. myRegDeleteKeyEx(HKEY_CLASSES_ROOT, temp);
  500. return S_OK;
  501. }
  502. HRESULT FileTypeRegistrar::SetupFileType(const wchar_t *programName, const wchar_t *winamp_file, const wchar_t *name, int iconNumber, const wchar_t *defaultShellCommand, const wchar_t *iconPath)
  503. {
  504. HKEY mp3Key = NULL;
  505. wchar_t str[MAX_PATH+32] = {0};
  506. if (RegCreateKeyW(HKEY_CLASSES_ROOT,winamp_file,&mp3Key) == ERROR_SUCCESS)
  507. {
  508. StringCchCopyW(str,MAX_PATH+32,name);
  509. SetValue(mp3Key, str);
  510. RegCloseKey(mp3Key);
  511. }
  512. if (RegCreateKey4(HKEY_CLASSES_ROOT,winamp_file, L"\\DefaultIcon",&mp3Key) == ERROR_SUCCESS)
  513. {
  514. StringCchPrintfW(str,MAX_PATH+32,(iconPath[0]?L"%s":L"%s,%d"),(iconPath[0]?iconPath:programName),iconNumber);
  515. SetValue(mp3Key, str);
  516. RegCloseKey(mp3Key);
  517. }
  518. if (RegCreateKey4(HKEY_CLASSES_ROOT,winamp_file, L"\\shell",&mp3Key) == ERROR_SUCCESS)
  519. {
  520. SetValue(mp3Key, defaultShellCommand);
  521. RegCloseKey(mp3Key);
  522. }
  523. return S_OK;
  524. }
  525. HRESULT FileTypeRegistrar::SetupDefaultFileType(const wchar_t *winamp_file, const wchar_t *defaultShellCommand){
  526. HKEY mp3Key = NULL;
  527. if (RegCreateKey4(HKEY_CLASSES_ROOT,winamp_file, L"\\shell",&mp3Key) == ERROR_SUCCESS)
  528. {
  529. SetValue(mp3Key, defaultShellCommand);
  530. RegCloseKey(mp3Key);
  531. }
  532. return S_OK;
  533. }
  534. HRESULT FileTypeRegistrar::RegisterTypeShell(const wchar_t *programName, const wchar_t *which_file, const wchar_t *description, int iconNumber, const wchar_t *commandName)
  535. {
  536. HKEY mp3Key = NULL;
  537. if (RegCreateKeyW(HKEY_CLASSES_ROOT,which_file,&mp3Key) == ERROR_SUCCESS)
  538. {
  539. SetValue(mp3Key, description);
  540. char str[4];
  541. str[0]=0;
  542. str[1]=0;
  543. str[2]=1;
  544. str[3]=0;
  545. RegSetValueExW(mp3Key, L"EditFlags",0,REG_BINARY,(BYTE *)str,4);
  546. RegCloseKey(mp3Key);
  547. }
  548. if (RegCreateKey4(HKEY_CLASSES_ROOT, which_file, L"\\DefaultIcon",&mp3Key) == ERROR_SUCCESS)
  549. {
  550. wchar_t str[MAX_PATH+32] = {0};
  551. StringCchPrintfW(str,MAX_PATH+32,L"%s,%d",programName,iconNumber);
  552. SetValue(mp3Key, str);
  553. RegCloseKey(mp3Key);
  554. }
  555. if (RegCreateKey4(HKEY_CLASSES_ROOT,which_file, L"\\shell",&mp3Key) == ERROR_SUCCESS)
  556. {
  557. SetValue(mp3Key, commandName);
  558. RegCloseKey(mp3Key);
  559. }
  560. return S_OK;
  561. }
  562. HRESULT FileTypeRegistrar::RegisterGUID(const wchar_t *programName, const wchar_t *guidString)
  563. {
  564. HKEY mp3Key = NULL;
  565. if (RegCreateKey4(HKEY_CLASSES_ROOT,L"CLSID\\", guidString, &mp3Key) == ERROR_SUCCESS)
  566. {
  567. RegCloseKey(mp3Key);
  568. }
  569. if (RegCreateKey5(HKEY_CLASSES_ROOT,L"CLSID\\", guidString, L"\\LocalServer32",&mp3Key) == ERROR_SUCCESS)
  570. {
  571. wchar_t str[MAX_PATH+32] = {0};
  572. StringCchPrintfW(str,MAX_PATH+32, L"\"%s\"",programName);
  573. SetValue(mp3Key, str);
  574. RegCloseKey(mp3Key);
  575. }
  576. return S_OK;
  577. }
  578. HRESULT FileTypeRegistrar::RegisterDVDPlayer(const wchar_t *programName, int iconNumber,
  579. const wchar_t *which_file /*Winamp.DVD*/, const wchar_t *commandName /* Winamp */,
  580. const wchar_t *provider /* Nullsoft Winamp */, const wchar_t *description /* Play in Winamp */)
  581. {
  582. // TODO: stop hardcoding stuff as soon as we start using this
  583. wchar_t winampPath[MAX_PATH+128] = {0};
  584. wchar_t winampIcon[MAX_PATH] = {0};
  585. HKEY mp3Key = NULL;
  586. // create icon path and exe-with-param path
  587. StringCbPrintfW(winampIcon,sizeof(winampIcon), L"\"%s\", %d", programName, iconNumber);
  588. StringCbPrintfW(winampPath,sizeof(winampPath), L"\"%s\" %1", programName);
  589. // uncomment if we ever want to overwrite the default icon... not set because we don't have a good dvd icon in winamp.exe
  590. /*
  591. if (RegOpenKey(HKEY_CLASSES_ROOT,"DVD\\DefaultIcon",&mp3Key) == ERROR_SUCCESS)
  592. {
  593. RegSetValueExW(mp3Key,NULL,0,REG_SZ,winampIcon,iconSize);
  594. }
  595. */
  596. if (RegCreateKeyW(HKEY_CLASSES_ROOT,L"DVD\\shell",&mp3Key) == ERROR_SUCCESS)
  597. {
  598. // set winamp to be the default player
  599. SetValue(mp3Key, commandName);
  600. RegCloseKey(mp3Key);
  601. }
  602. if (RegCreateKey4(HKEY_CLASSES_ROOT,L"DVD\\shell\\", commandName, &mp3Key) == ERROR_SUCCESS)
  603. {
  604. // text to appear in right-click shell menu in explorer
  605. SetValue(mp3Key, description);
  606. RegCloseKey(mp3Key);
  607. }
  608. if (RegCreateKey5(HKEY_CLASSES_ROOT,L"DVD\\shell\\", commandName, L"\\command",&mp3Key) == ERROR_SUCCESS)
  609. {
  610. // set the executable path
  611. SetValue(mp3Key, winampPath);
  612. RegCloseKey(mp3Key);
  613. }
  614. if (RegCreateKeyW(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\EventHandlers\\PlayDVDMovieOnArrival",&mp3Key) == ERROR_SUCCESS)
  615. {
  616. // register winamp for dvd autoplay
  617. RegSetValueExW(mp3Key,which_file,0,REG_SZ,0,0);
  618. RegCloseKey(mp3Key);
  619. }
  620. if (RegCreateKey4(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\Handlers\\", which_file, &mp3Key) == ERROR_SUCCESS)
  621. {
  622. // autoplay details
  623. SetValue(mp3Key,L"Action", description);
  624. SetValue(mp3Key,L"DefaultIcon", winampIcon);
  625. SetValue(mp3Key,L"InvokeProgID", L"DVD");
  626. SetValue(mp3Key,L"InvokeVerb", commandName);
  627. SetValue(mp3Key,L"Provider", provider);
  628. RegCloseKey(mp3Key);
  629. }
  630. return S_OK;
  631. }
  632. HRESULT FileTypeRegistrar::InstallItem(LPCWSTR sourceFile, LPCWSTR destinationFolder, LPCWSTR destinationFilename)
  633. {
  634. SHFILEOPSTRUCT op = {0};
  635. op.hwnd = 0;
  636. op.wFunc = FO_COPY;
  637. wchar_t srcFile[MAX_PATH+1] = {0};
  638. wchar_t *end;
  639. StringCchCopyExW(srcFile, MAX_PATH, sourceFile, &end, 0, 0);
  640. if (end)
  641. end[1]=0; // double null terminate
  642. op.pFrom = srcFile;
  643. wchar_t destFile[MAX_PATH+1] = {0};
  644. PathCombineW(destFile, destinationFolder, destinationFilename);
  645. destFile[wcslen(destFile)+1]=0; // double null terminate
  646. op.pTo = destFile;
  647. op.fFlags=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SIMPLEPROGRESS|FOF_NOERRORUI|FOF_SILENT;
  648. op.lpszProgressTitle = L"";
  649. int val = SHFileOperation(&op);
  650. // send back the error message so we can show on the UI
  651. if (val != 0 && val != 0x71/*DE_SAMEFILE*/)
  652. {
  653. StringCchPrintfW((LPWSTR)destinationFilename,MAX_PATH,L"0x%x",val);
  654. }
  655. return ((val == 0 || val == 0x71/*DE_SAMEFILE*/) ? S_OK : E_FAIL);
  656. }
  657. HRESULT FileTypeRegistrar::DeleteItem(LPCWSTR file)
  658. {
  659. SHFILEOPSTRUCT op = {0};
  660. op.wFunc = FO_DELETE;
  661. wchar_t srcFile[MAX_PATH+1] = {0};
  662. wchar_t *end;
  663. StringCchCopyExW(srcFile, MAX_PATH, file, &end, 0, 0);
  664. if (end) end[1]=0; // double null terminate
  665. op.pFrom = srcFile;
  666. op.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SIMPLEPROGRESS|FOF_NORECURSION|FOF_NOERRORUI|FOF_SILENT|FOF_ALLOWUNDO;
  667. op.lpszProgressTitle = L"";
  668. int val = SHFileOperation(&op);
  669. return val == 0?S_OK:E_FAIL;
  670. }
  671. HRESULT FileTypeRegistrar::RenameItem(LPCWSTR oldFile, LPCWSTR newFile, BOOL force)
  672. {
  673. SHFILEOPSTRUCT op = {0};
  674. op.wFunc = force?FO_MOVE:FO_RENAME;
  675. wchar_t srcFile[MAX_PATH+1] = {0};
  676. wchar_t *end;
  677. StringCchCopyExW(srcFile, MAX_PATH, oldFile, &end, 0, 0);
  678. if (end) end[1]=0; // double null terminate
  679. op.pFrom = srcFile;
  680. wchar_t destFile[MAX_PATH+1] = {0};
  681. end=0;
  682. StringCchCopyExW(destFile, MAX_PATH, newFile, &end, 0, 0);
  683. if (end) end[1]=0; // double null terminate
  684. op.pTo = destFile;
  685. op.fFlags=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SIMPLEPROGRESS|FOF_NOERRORUI|FOF_SILENT;
  686. op.lpszProgressTitle = L"";
  687. int val = SHFileOperation(&op);
  688. return val == 0?S_OK:E_FAIL;
  689. /*
  690. if (!MoveFile(oldFile, newFile))
  691. {
  692. // if move failed
  693. if (!force) // if they don't want to force the move
  694. return E_FAIL;
  695. if (CopyFile(oldFile, newFile, FALSE) && DeleteFile(oldFile)) // copy then delete
  696. return E_FAIL;
  697. }
  698. return S_OK;
  699. */
  700. }
  701. HRESULT FileTypeRegistrar::CleanupDirectory(LPCWSTR directory)
  702. {
  703. wchar_t dirmask[MAX_PATH] = {0};
  704. WIN32_FIND_DATAW d = {0};
  705. PathCombineW(dirmask, directory, L"*.*");
  706. HANDLE h = FindFirstFileW(dirmask, &d);
  707. if (h != INVALID_HANDLE_VALUE)
  708. {
  709. do
  710. {
  711. wchar_t v[MAX_PATH] = {0};
  712. PathCombineW(v, directory, d.cFileName);
  713. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  714. {
  715. if (wcscmp(d.cFileName,L".") && wcscmp(d.cFileName,L".."))
  716. CleanupDirectory(v);
  717. }
  718. else
  719. {
  720. if(!DeleteFileW(v))
  721. {
  722. // this handles some rogue cases where files in the wlz's aren't unloadable
  723. MoveFileExW(v, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  724. MoveFileExW(directory, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  725. }
  726. }
  727. }
  728. while (FindNextFileW(h, &d));
  729. FindClose(h);
  730. }
  731. RemoveDirectoryW(directory);
  732. return S_OK;
  733. }
  734. HRESULT FileTypeRegistrar::MoveDirectoryContents(LPCWSTR oldDirectory, LPCWSTR newDirectory)
  735. {
  736. wchar_t fromDirectory[MAX_PATH+1] = {0}; // need to zero it all so it will be double-null terminated
  737. SHFILEOPSTRUCT sf = {0};
  738. StringCchPrintfW(fromDirectory,MAX_PATH,L"%s\\*",oldDirectory);
  739. sf.wFunc = FO_MOVE;
  740. sf.pFrom = fromDirectory;
  741. sf.pTo = newDirectory;
  742. sf.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_NOERRORUI|FOF_NORECURSION;
  743. if(SHFileOperation(&sf)){
  744. return E_FAIL;
  745. }
  746. return S_OK;
  747. }
  748. HRESULT FileTypeRegistrar::WriteProKey(LPCWSTR name, LPCWSTR key)
  749. {
  750. HKEY hkey = NULL;
  751. if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Nullsoft\\Winamp", 0, 0, 0, KEY_READ | KEY_WRITE, NULL, &hkey, NULL) == ERROR_SUCCESS)
  752. {
  753. if (*name)
  754. SetValue(hkey, L"regname", name);
  755. else
  756. RegDeleteValueW(hkey, L"regname");
  757. if (*key)
  758. {
  759. wchar_t buf[33] = {0};
  760. StringCchCopyW(buf + 1, 32, key);
  761. buf[0] = '~';
  762. for (int x = 1;buf[x]; x ++)
  763. {
  764. wchar_t c = towupper(buf[x]);
  765. //char c = buf[x]; // benski> goes with above commented line that i'd like to uncomment
  766. if (c >= 'A' && c <= 'Z')
  767. {
  768. int w = c - 'A';
  769. w += x;
  770. w %= 26;
  771. buf[x] = 'A' + w;
  772. }
  773. else if (c >= '0' && c <= '9')
  774. {
  775. int w = c - '0';
  776. w += x * 27;
  777. w %= 10;
  778. buf[x] = 'a' + w;
  779. }
  780. else if (c == '-') buf[x] = '/';
  781. }
  782. SetValue(hkey, L"regkey", buf);
  783. }
  784. else
  785. {
  786. RegDeleteValueW(hkey, L"regkey");
  787. }
  788. RegCloseKey(hkey);
  789. return S_OK;
  790. }
  791. return E_FAIL;
  792. }
  793. HRESULT FileTypeRegistrar::WriteClientUIDKey(LPCWSTR path, LPCWSTR uid_str)
  794. {
  795. HKEY hkey = NULL;
  796. if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Nullsoft\\Winamp", 0, 0, 0, KEY_READ | KEY_WRITE, NULL, &hkey, NULL) == ERROR_SUCCESS)
  797. {
  798. SetValue(hkey, path, uid_str);
  799. RegCloseKey(hkey);
  800. return S_OK;
  801. }
  802. return E_FAIL;
  803. }
  804. HRESULT FileTypeRegistrar::RegisterProtocol(LPCWSTR protocol, LPCWSTR command, LPCWSTR icon)
  805. {
  806. return S_OK;
  807. HKEY mp3Key = NULL;
  808. if (RegCreateKeyW(HKEY_CLASSES_ROOT, protocol, &mp3Key) == ERROR_SUCCESS)
  809. {
  810. wchar_t regStr[256] = {0};
  811. SetValue(mp3Key, L"URL:Winamp Command Handler");
  812. SetValue(mp3Key, L"URL Protocol", L"");
  813. RegCloseKey(mp3Key);
  814. StringCbPrintfW(regStr, sizeof(regStr), L"%s\\DefaultIcon", protocol);
  815. if (RegCreateKeyW(HKEY_CLASSES_ROOT,regStr,&mp3Key) == ERROR_SUCCESS)
  816. {
  817. SetValue(mp3Key, icon);
  818. RegCloseKey(mp3Key);
  819. }
  820. StringCbPrintfW(regStr, sizeof(regStr), L"%s\\shell\\open\\command", protocol);
  821. if (RegCreateKeyW(HKEY_CLASSES_ROOT,regStr,&mp3Key) == ERROR_SUCCESS)
  822. {
  823. SetValue(mp3Key, command);
  824. RegCloseKey(mp3Key);
  825. }
  826. }
  827. return S_OK;
  828. }
  829. HRESULT FileTypeRegistrar::RegisterCapability(const wchar_t *programName, const wchar_t *winamp_file, const wchar_t *extension)
  830. {
  831. #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
  832. if (IsWindowsVersionOrGreater(6, 0, 0)) // Vista
  833. #else
  834. OSVERSIONINFO version = { 0 };
  835. version.dwOSVersionInfoSize = sizeof(version);
  836. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  837. if (version.dwMajorVersion >= 6) // Vista
  838. #endif
  839. {
  840. HKEY hkey_file_associations = NULL;
  841. if (ERROR_SUCCESS == RegMedia_CreateKey(L"Capabilities\\FileAssociations", &hkey_file_associations, programName))
  842. {
  843. RegDeleteValueW(hkey_file_associations, extension); // to make sure that they are all in case that we need
  844. SetValue(hkey_file_associations, extension, winamp_file);
  845. RegCloseKey(hkey_file_associations);
  846. }
  847. }
  848. return S_OK;
  849. }