// Elevator.cpp : Implementation of WinMain #include "stdafx.h" #include "resource1.h" #include "FileTypeRegistrar.h" #include "ElevatorFactory.h" #include #include HRESULT RegisterServer(HINSTANCE hInstance); HRESULT UnregisterServer(HINSTANCE hInstance); DWORD g_allLocks = 0; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (lpCmdLine == NULL || !*lpCmdLine) { MSGBOXPARAMSW msgbx = {sizeof(MSGBOXPARAMS),0}; msgbx.lpszText = L"Winamp Elevator\nCopyright © 2008-2014 Winamp SA"; msgbx.lpszCaption = L"About..."; msgbx.lpszIcon = MAKEINTRESOURCEW(IDI_ICON1); msgbx.hInstance = GetModuleHandle(0); msgbx.dwStyle = MB_USERICON; MessageBoxIndirectW(&msgbx); return 0; } if ( lpCmdLine != NULL && ( _strcmpi( lpCmdLine, "/RegServer" ) == 0 || _strcmpi( lpCmdLine, "-RegServer" ) == 0 )) { RegisterServer(hInstance); return 0; } if ( lpCmdLine != NULL && ( _strcmpi( lpCmdLine, "/UnregServer" ) == 0 || _strcmpi( lpCmdLine, "-UnregServer" ) == 0 )) { UnregisterServer(hInstance); return 0; } CoInitialize(NULL); if(lpCmdLine && (strstr(lpCmdLine, "/Embedding") || strstr(lpCmdLine, "-Embedding"))) { ElevatorFactory cf; DWORD regID = 0; CoRegisterClassObject(CLSID_WFileTypeRegistrar,(IClassFactory*)&cf, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®ID); MSG ms; while(GetMessage(&ms, 0, 0, 0)) { TranslateMessage(&ms); DispatchMessage(&ms); } CoRevokeClassObject(regID); } CoUninitialize(); return 0; } extern FileTypeRegistrar registrar; void Lock() { ++g_allLocks; } void UnLock() { --g_allLocks; if(g_allLocks == 0 )//&& registrar.refCount == 0/* benski> a hack, for now */) { PostQuitMessage(0); } } static BOOL GetAccessPermissionsForLUAServer(SECURITY_DESCRIPTOR **ppSD) { // Local call permissions to IU, SY LPWSTR lpszSDDL = L"O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)"; SECURITY_DESCRIPTOR *pSD; *ppSD = NULL; if (ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1, (PSECURITY_DESCRIPTOR *)&pSD, NULL)) { *ppSD = pSD; return TRUE; } return FALSE; } // hKey is the HKCR\AppID\{GUID} key static BOOL SetAccessPermissions(HKEY hkey, PSECURITY_DESCRIPTOR pSD) { BOOL bResult = FALSE; DWORD dwLen = GetSecurityDescriptorLength(pSD); LONG lResult; lResult = RegSetValueExA(hkey, "AccessPermission", 0, REG_BINARY, (BYTE*)pSD, dwLen); if (lResult != ERROR_SUCCESS) goto done; bResult = TRUE; done: return bResult; } static BOOL GetLaunchActPermissionsWithIL (SECURITY_DESCRIPTOR **ppSD) { // Allow World Local Launch/Activation permissions. Label the SD for LOW IL Execute UP LPWSTR lpszSDDL = L"O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)"; SECURITY_DESCRIPTOR *pSD; if (ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1, (PSECURITY_DESCRIPTOR *)&pSD, NULL)) { *ppSD = pSD; return TRUE; } return FALSE; } static BOOL SetLaunchActPermissions(HKEY hkey, PSECURITY_DESCRIPTOR pSD) { BOOL bResult = FALSE; DWORD dwLen = GetSecurityDescriptorLength(pSD); LONG lResult; lResult = RegSetValueExA(hkey, "LaunchPermission", 0, REG_BINARY, (BYTE*)pSD, dwLen); if (lResult != ERROR_SUCCESS) goto done; bResult = TRUE; done: return bResult; }; static HRESULT UnregisterComponent(const CLSID &clsid, LPCWSTR pszVersionIndProgId, LPCWSTR pszProgId); static HRESULT RegisterComponent(HMODULE hModule, const CLSID &clsid, LPCWSTR pszFriendlyName, LPCWSTR pszVersionIndProgId, LPCWSTR pszProgId); static const WCHAR szComponentFriendlyName[] = L"Winamp Elevator"; static const WCHAR szVersionIndependentProgId[] = L"Elevator.WFileTypeRegistrar2"; static const WCHAR szProgId[] = L"Elevator.WFileTypeRegistrar2.1"; HRESULT RegisterServer(HINSTANCE hInstance) { HRESULT hr(S_OK); hr = RegisterComponent(hInstance, CLSID_WFileTypeRegistrar, szComponentFriendlyName, szVersionIndependentProgId, szProgId); return hr; } HRESULT UnregisterServer(HINSTANCE hInstance) { HRESULT hr(S_OK); hr = UnregisterComponent(CLSID_WFileTypeRegistrar, szVersionIndependentProgId, szProgId); return hr; } static BOOL WriteRegKey(HKEY hKeyParent, LPCWSTR pszKey, LPCWSTR pszValue, HKEY *phKey = NULL) { HKEY hKey; LONG result; result = RegCreateKeyExW(hKeyParent, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); if (ERROR_SUCCESS != result || !hKey) return FALSE; if (pszValue) { result = RegSetValueExW(hKey, NULL, 0, REG_SZ, (BYTE*)pszValue, (DWORD)(sizeof(wchar_t)*(1 + lstrlenW(pszValue)))); } if (!phKey) RegCloseKey(hKey); else *phKey = hKey; return (ERROR_SUCCESS == result); } static BOOL WriteRegValue(HKEY hKeyParent, LPCWSTR pszKey, LPCWSTR pszEntry, LPCWSTR pszValue) { HKEY hKey; LONG result; result = RegOpenKeyExW(hKeyParent, pszKey, 0, KEY_SET_VALUE, &hKey); if (ERROR_SUCCESS != result || !hKey) return FALSE; if (pszValue) { result = RegSetValueEx(hKey, pszEntry, 0, REG_SZ, (BYTE*)pszValue, (DWORD)(sizeof(wchar_t)*(1 + lstrlenW(pszValue)))); } RegCloseKey(hKey); return (ERROR_SUCCESS == result); } static BOOL WriteRegValue(HKEY hKeyParent, LPCWSTR pszKey, LPCWSTR pszEntry, DWORD pszValue) { HKEY hKey; LONG result; result = RegOpenKeyExW(hKeyParent, pszKey, 0, KEY_SET_VALUE, &hKey); if (ERROR_SUCCESS != result || !hKey) return FALSE; if (pszValue) { result = RegSetValueEx(hKey, pszEntry, 0, REG_DWORD, (BYTE*)&pszValue, sizeof(DWORD)); } RegCloseKey(hKey); return (ERROR_SUCCESS == result); } static LONG DeleteRegKey(HKEY hKeyParent, LPCWSTR pszKey) { HKEY hKey; LONG result; FILETIME time = {0}; WCHAR szBuffer[512] = {0}; DWORD dwSize = sizeof(szBuffer)/sizeof(WCHAR); result = RegOpenKeyExW(hKeyParent, pszKey, 0, KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS , &hKey); if (ERROR_SUCCESS != result) return result; while (ERROR_SUCCESS == RegEnumKeyExW(hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time)) { if (ERROR_SUCCESS != (result = DeleteRegKey(hKey, szBuffer))) { RegCloseKey(hKey); return result; } dwSize = sizeof(szBuffer)/sizeof(WCHAR); } RegCloseKey(hKey); return RegDeleteKeyW(hKeyParent, pszKey); } HRESULT RegisterComponent(HMODULE hModule, const CLSID &clsid, LPCWSTR pszFriendlyName, LPCWSTR pszVersionIndProgId, LPCWSTR pszProgId) { SECURITY_DESCRIPTOR *sd; HKEY hKey, hKey2, hKey3; BOOL br; WCHAR szBuffer[MAX_PATH] = {0}, szCLSID[64] = {0}; if (!StringFromGUID2(clsid, szCLSID, sizeof(szCLSID)/sizeof(WCHAR))) return E_OUTOFMEMORY; StringCchPrintfW(szBuffer, sizeof(szBuffer)/sizeof(WCHAR), L"SOFTWARE\\Classes\\CLSID\\%s", szCLSID); if (!WriteRegKey(HKEY_LOCAL_MACHINE, szBuffer, pszFriendlyName, &hKey)) return S_FALSE; if (!GetModuleFileNameW(hModule, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) return S_FALSE; RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Classes\\AppID\\{3B29AB5C-52CB-4a36-9314-E3FEE0BA7468}", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey3, NULL); if (GetAccessPermissionsForLUAServer(&sd)) SetAccessPermissions(hKey3, sd); if (GetLaunchActPermissionsWithIL(&sd)) SetLaunchActPermissions(hKey3, sd); WriteRegValue(hKey3, NULL, NULL, szBuffer); RegCloseKey(hKey3); RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Classes\\AppID\\elevator.exe", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey3, NULL); WriteRegValue(hKey3, NULL, L"AppID", L"{3B29AB5C-52CB-4a36-9314-E3FEE0BA7468}"); RegCloseKey(hKey3); wchar_t localizedString[MAX_PATH+15] = {0}; StringCbPrintf(localizedString, sizeof(localizedString), L"@%s,-%u", szBuffer, IDS_WINAMP); br = (WriteRegKey(hKey, L"LocalServer32" , szBuffer, &hKey2) && WriteRegValue(hKey2, NULL, L"ThreadingModel", L"Both") && WriteRegKey(hKey, L"ProgID", pszProgId) && WriteRegKey(hKey, L"VersionIndependentProgID", pszVersionIndProgId) && WriteRegValue(hKey, NULL, L"LocalizedString", localizedString) && WriteRegValue(hKey, NULL, L"AppId", L"{3B29AB5C-52CB-4a36-9314-E3FEE0BA7468}") && WriteRegKey(hKey, L"Elevation", 0) //&& WriteRegValue(hKey, L"Elevation", L"IconReference", && WriteRegValue(hKey, L"Elevation", L"Enabled", 1) ); RegCloseKey(hKey); if (hKey2) RegCloseKey(hKey2); if (!br) return S_FALSE; if (!WriteRegKey(HKEY_CLASSES_ROOT, pszVersionIndProgId, pszFriendlyName, &hKey)) return S_FALSE; br = (WriteRegKey(hKey, L"CLSID", szCLSID) && WriteRegKey(hKey, L"CurVer", pszProgId)); RegCloseKey(hKey); if (!br) return S_FALSE; if (!WriteRegKey(HKEY_CLASSES_ROOT, pszProgId, pszFriendlyName, &hKey)) return S_FALSE; br = WriteRegKey(hKey, L"CLSID", szCLSID); RegCloseKey(hKey); if (!br) return S_FALSE; return S_OK; } static HRESULT UnregisterComponent(const CLSID &clsid, LPCWSTR pszVersionIndProgId, LPCWSTR pszProgId) { LONG result; WCHAR szBuffer[MAX_PATH] = {0}, szCLSID[64] = {0}; if (!StringFromGUID2(clsid, szCLSID, sizeof(szCLSID)/sizeof(WCHAR))) return E_OUTOFMEMORY; StringCchPrintfW(szBuffer, sizeof(szBuffer)/sizeof(WCHAR), L"CLSID\\%s", szCLSID); result = DeleteRegKey(HKEY_CLASSES_ROOT, szBuffer); if (ERROR_SUCCESS != result && ERROR_FILE_NOT_FOUND != result) return S_FALSE; result = DeleteRegKey(HKEY_CLASSES_ROOT, pszVersionIndProgId); if (ERROR_SUCCESS != result && ERROR_FILE_NOT_FOUND != result) return S_FALSE; result = DeleteRegKey(HKEY_CLASSES_ROOT, pszProgId); if (ERROR_SUCCESS != result && ERROR_FILE_NOT_FOUND != result) return S_FALSE; return S_OK; }