Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // EDGECLOSER v1.0
- // ---------------
- // The Windows 10 start menu wants to open Edge always, ignoring my choice of default browser.
- // This utility scans for opened web pages in Edge, closes it and reopens the page in your default browser.
- // EdgeCloser runs with a hidden window, so to stop it you need to kill it from Task Manager.
- // I am too lazy to add a taskbar icon.
- // No copyright, use this for whatever you want.
- // Phoenix
- #include <windows.h>
- #include <UIAutomation.h>
- #include <time.h>
- #include <string>
- #include <algorithm>
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
- #define CHECK_PTR(p) { if(SUCCEEDED(hr) && ((p) == NULL)) hr = E_FAIL; }
- wchar_t *szWindowClass = L"EdgeCloserWndClass";
- #define STRBUF_LEN 4095
- const int TIMER_ID = 1;
- const int ACTION_INTERVAL = 3500; // Courtesy delay in the polling after each browser triggering
- const int TIMER_INTERVAL = 80; // Poll windows every x ms
- const long long MAX_DEFAULT_BROWSER_CHECK_INTERVAL = 4;
- IUIAutomation *uiAutomation;
- HINSTANCE hInst;
- int nextTrigger = 0;
- VARIANT s_searchClassStr;
- void LowerCase(std::wstring &str)
- {
- std::transform(str.begin(), str.end(), str.begin(), ::tolower);
- }
- bool GetRegistryString (HKEY rootKey,
- const std::wstring &keyName,
- const std::wstring &valueName,
- std::wstring &target)
- {
- bool rc = false;
- target.clear();
- HKEY hKey = 0;
- if (ERROR_SUCCESS == RegOpenKeyExW(rootKey, keyName.c_str(), 0, KEY_READ, &hKey))
- {
- WCHAR buffer[STRBUF_LEN];
- DWORD bufferSize = sizeof(buffer);
- if (ERROR_SUCCESS == RegQueryValueEx(hKey, valueName.c_str(), 0, NULL, (LPBYTE)buffer, &bufferSize))
- {
- target = buffer;
- rc = true;
- }
- RegCloseKey(hKey);
- }
- return rc;
- }
- bool ExpandEnvironmentStrings(std::wstring const &str, std::wstring &target)
- {
- bool rc = false;
- target.clear();
- wchar_t buffer[STRBUF_LEN + 1];
- if (ExpandEnvironmentStrings(str.c_str(), buffer, STRBUF_LEN) != 0)
- {
- target = buffer;
- rc = true;
- }
- return rc;
- }
- bool LoadDllString(const std::wstring &dllPath, UINT stringId, std::wstring &target)
- {
- bool rc = false;
- target.clear();
- HMODULE hDll = LoadLibrary(dllPath.c_str());
- if (hDll != NULL)
- {
- wchar_t *strReadOnlyPointer = NULL;
- if (LoadString(hDll, stringId, (LPWSTR)&strReadOnlyPointer, 0) > 0)
- {
- if (strReadOnlyPointer != NULL)
- {
- target = strReadOnlyPointer;
- rc = true;
- }
- }
- FreeLibrary(hDll);
- }
- return rc;
- }
- void HandleRegistryDllString(std::wstring &str)
- {
- // Handle resource strings
- // Format: "@<PE-path>,-<stringID>[;<optionalComment>]"
- // Example: @C:\Windows\System32\ieframe.dll,-55175
- if (str.find(L"@") != 0) // First character must be '@'
- return;
- const int MIN_DLL_PATH_LEN = 5;
- size_t commaPos = str.find(L",-");
- if ((commaPos != std::wstring::npos) && (commaPos >= MIN_DLL_PATH_LEN))
- {
- std::wstring dllPath = str.substr(1, commaPos - 1);
- std::wstring stringId = str.substr(commaPos + 2);
- // Remove any optional comments
- size_t semiColPos = stringId.find(L";");
- if ((semiColPos != std::wstring::npos) && (semiColPos >= 1)) // Require at least one digit
- stringId = stringId.substr(0, semiColPos);
- long long strId = _wcstoi64(stringId.c_str(), NULL, 10);
- if (strId > 0)
- {
- std::wstring dllPathEnvExpanded;
- if (ExpandEnvironmentStrings(dllPath, dllPathEnvExpanded))
- {
- std::wstring appNameFromDll;
- if (LoadDllString(dllPathEnvExpanded, (UINT)strId, appNameFromDll))
- str = appNameFromDll;
- }
- }
- }
- }
- // Cache the result of inspecting the progId as this operation can be slow and resource consuming
- std::wstring browserCheckLastProgId;
- bool browserCheckLastResult = false;
- __time64_t lastBrowserCheck = 0;
- bool IsDefaultBrowserEdge()
- {
- bool isEdge = false;
- // Don't do this check too frequently
- __time64_t now = _time64(NULL);
- if(abs(now - lastBrowserCheck) < MAX_DEFAULT_BROWSER_CHECK_INTERVAL)
- return browserCheckLastResult;
- lastBrowserCheck = now;
- std::wstring progId;
- if (GetRegistryString(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice", L"ProgId", progId))
- {
- const int MIN_PROGID_LENGTH = 3;
- if (progId.length() >= MIN_PROGID_LENGTH)
- {
- if (progId == browserCheckLastProgId)
- {
- // We recognize this progId, so use the cached result
- isEdge = browserCheckLastResult;
- }
- else
- {
- std::wstring appNameKey = progId;
- appNameKey += L"\\Application";
- std::wstring appName;
- if (GetRegistryString(HKEY_CLASSES_ROOT, appNameKey, L"ApplicationName", appName))
- {
- HandleRegistryDllString(appName);
- const size_t MINIMUM_APPNAME_LEN_SANITY_CHECK = 4;
- size_t equalsPos = appName.find(L"=");
- if ((equalsPos != std::wstring::npos) && (equalsPos >= MINIMUM_APPNAME_LEN_SANITY_CHECK))
- appName = appName.substr(0, equalsPos);
- LowerCase(appName);
- isEdge = (appName.find(L"edge") != std::wstring::npos);
- }
- browserCheckLastProgId = progId;
- browserCheckLastResult = isEdge;
- }
- }
- }
- return isEdge;
- }
- BSTR UIAutomationSearcher(HWND hWnd)
- {
- BSTR foundUri = NULL;
- HRESULT hr = S_OK;
- IUIAutomationElement *edgeRoot = NULL;
- IUIAutomationCacheRequest *cacheRequest = NULL;
- IUIAutomationCondition *conditionUri = NULL;
- IUIAutomationElement *uriElement = NULL;
- if (SUCCEEDED(hr))
- hr = uiAutomation->ElementFromHandle(hWnd, &edgeRoot);
- CHECK_PTR(edgeRoot);
- if (SUCCEEDED(hr))
- hr = uiAutomation->CreateCacheRequest(&cacheRequest);
- CHECK_PTR(cacheRequest);
- if (SUCCEEDED(hr))
- hr = cacheRequest->AddProperty(UIA_NamePropertyId);
- if (SUCCEEDED(hr))
- hr = uiAutomation->CreatePropertyCondition(UIA_ClassNamePropertyId, s_searchClassStr, &conditionUri);
- CHECK_PTR(conditionUri);
- if (SUCCEEDED(hr))
- hr = edgeRoot->FindFirstBuildCache(TreeScope_Descendants, conditionUri, cacheRequest, &uriElement);
- CHECK_PTR(uriElement);
- if (SUCCEEDED(hr))
- {
- if (FAILED(uriElement->get_CachedName(&foundUri)))
- foundUri = NULL; // Probably NULL already but make sure
- }
- SAFE_RELEASE(uriElement);
- SAFE_RELEASE(conditionUri);
- SAFE_RELEASE(cacheRequest);
- SAFE_RELEASE(edgeRoot);
- return foundUri;
- }
- BOOL CALLBACK EdgeChildFinder(HWND hWnd, LPARAM lParam)
- {
- BSTR *foundUri = (BSTR *)lParam;
- wchar_t buf[STRBUF_LEN + 1];
- if ((nextTrigger >= 0) && hWnd && ::IsWindowVisible(hWnd))
- {
- if (::GetClassName(hWnd, buf, STRBUF_LEN))
- {
- if (::wcscmp(buf, L"Windows.UI.Core.CoreWindow") == 0)
- {
- if (::GetWindowText(hWnd, buf, STRBUF_LEN))
- {
- if (::wcscmp(buf, L"Microsoft Edge") == 0)
- {
- BSTR uri = UIAutomationSearcher(hWnd);
- if (uri != NULL)
- {
- // Allow manual start of Edge and an initial search
- if ((::wcsstr(uri, L"msn.com/spartan") != NULL) ||
- (::wcsstr(uri, L"bing.com/AS/API") != NULL) ||
- (::wcsstr(uri, L"about:blank") != NULL) ||
- (::wcsstr(uri, L"bing.com/search?") != NULL))
- {
- }
- else
- {
- if ((*foundUri) == NULL)
- *foundUri = ::SysAllocString(uri);
- }
- ::SysFreeString(uri);
- }
- }
- }
- }
- }
- }
- return TRUE;
- }
- bool StartDefaultBrowser(BSTR uriBSTR, HWND edgeWindow)
- {
- std::wstring uri(uriBSTR, SysStringLen(uriBSTR));
- // Try to make sure we are not launching some hacker-crafted special uri string
- if (uri.find('\"') == std::wstring::npos)
- {
- std::wstring uriTL(uri);
- LowerCase(uriTL);
- if ((0 == uriTL.find(L"http:")) ||
- (0 == uriTL.find(L"https:")))
- {
- // Close the Edge window
- // FIX!! - Dialog pops up if there are multiple tabs...
- ::SendMessage(edgeWindow, WM_CLOSE, 0, 0);
- // Start the default browser
- ShellExecute(NULL, L"open", uri.c_str(), NULL, NULL, SW_SHOWNORMAL);
- return true;
- }
- }
- return false;
- }
- BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
- {
- wchar_t buf[STRBUF_LEN + 1];
- if ((nextTrigger >= 0) && hWnd && ::IsWindowVisible(hWnd))
- {
- if (GetWindowText(hWnd, buf, STRBUF_LEN))
- {
- if (::wcsstr(buf, L"Microsoft Edge") != NULL)
- {
- BSTR foundUri = NULL;
- EnumChildWindows(hWnd, EdgeChildFinder, (LPARAM)&foundUri);
- if (foundUri != NULL)
- {
- if (!IsDefaultBrowserEdge())
- {
- if (StartDefaultBrowser(foundUri, hWnd))
- nextTrigger = -(ACTION_INTERVAL / TIMER_INTERVAL);
- }
- ::SysFreeString(foundUri);
- }
- }
- }
- }
- return TRUE;
- }
- BOOL InitializeUIAutomation()
- {
- CoInitialize(NULL);
- HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER,
- __uuidof(IUIAutomation), (void**)&uiAutomation);
- return (SUCCEEDED(hr));
- }
- static bool inTimer = false;
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_CREATE:
- {
- SetTimer(hWnd, TIMER_ID, TIMER_INTERVAL, NULL);
- break;
- }
- case WM_TIMER:
- {
- if ((wParam == TIMER_ID) && (!inTimer))
- {
- inTimer = true;
- if (nextTrigger < 0)
- nextTrigger++;
- if (nextTrigger >= 0)
- ::EnumWindows(EnumWindowsProc, 0);
- inTimer = false;
- }
- break;
- }
- case WM_DESTROY:
- {
- PostQuitMessage(0);
- break;
- }
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }
- ATOM MyRegisterClass(HINSTANCE hInstance)
- {
- WNDCLASSEXW wcex;
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = NULL;
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = NULL;
- wcex.lpszClassName = szWindowClass;
- wcex.hIconSm = NULL;
- return RegisterClassExW(&wcex);
- }
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
- hInst = hInstance;
- HWND hWnd = CreateWindowW(szWindowClass, L"EdgeCloser Hidden Window", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
- if (!hWnd)
- return FALSE;
- nCmdShow = SW_HIDE; // Remove this line when testing/debugging
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- return TRUE;
- }
- int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
- _In_opt_ HINSTANCE hPrevInstance,
- _In_ LPWSTR lpCmdLine,
- _In_ int nCmdShow)
- {
- UNREFERENCED_PARAMETER(hPrevInstance);
- UNREFERENCED_PARAMETER(lpCmdLine);
- InitializeUIAutomation();
- s_searchClassStr.vt = VT_BSTR;
- s_searchClassStr.bstrVal = ::SysAllocString(L"Internet Explorer_Server");
- MyRegisterClass(hInstance);
- if (!InitInstance(hInstance, nCmdShow))
- return FALSE;
- MSG msg;
- while (GetMessage(&msg, nullptr, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return (int)msg.wParam;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement