main.cpp (6798B)
1 // This Source Code Form is subject to the terms of the Mozilla Public 2 // License, v. 2.0.If a copy of the MPL was not distributed with this 3 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 #include <windows.h> 6 #include "resource.h" 7 #include "WebBrowser.h" 8 #include "exdll.h" 9 10 // These variables are global because they're needed by more than one of 11 // our plugin methods. The expectation is that these are safe because the 12 // NSIS framework doesn't really support more than one dialog or thread 13 // at a time, and that means we don't have to either. 14 15 // Instance handle for this DLL 16 HINSTANCE gHInst = nullptr; 17 // Parent window proc which we'll need to override and then restore 18 WNDPROC gWndProcOld = nullptr; 19 // Handle to the dialog we'll create 20 HWND gHwnd = nullptr; 21 // Set to true when our dialog should be destroyed 22 bool gDone = false; 23 // Web browser OLE site 24 WebBrowser* gBrowser = nullptr; 25 26 // Set web browser control feature flags that are configured on a per-process 27 // basis, not for individual instances of the control. This mainly means 28 // disabling things that could turn into security holes. 29 static void ConfigurePerProcessBrowserFeatures() { 30 // For most of the features we're configuring, setting them to TRUE means 31 // we're disabling something, but for a few setting them to FALSE disables the 32 // thing. We don't necessarily care about *every* feature that's in the 33 // INTERNETFEATURELIST enum, but it seems safer to set them all anyway, to 34 // make sure we don't miss anything we *do* care about. 35 struct Feature { 36 INTERNETFEATURELIST id; 37 BOOL value; 38 } features[] = {{FEATURE_OBJECT_CACHING, TRUE}, 39 {FEATURE_ZONE_ELEVATION, TRUE}, 40 {FEATURE_MIME_HANDLING, TRUE}, 41 {FEATURE_MIME_SNIFFING, FALSE}, 42 {FEATURE_WINDOW_RESTRICTIONS, TRUE}, 43 {FEATURE_WEBOC_POPUPMANAGEMENT, TRUE}, 44 {FEATURE_BEHAVIORS, TRUE}, 45 {FEATURE_DISABLE_MK_PROTOCOL, TRUE}, 46 // It isn't possible to set FEATURE_LOCALMACHINE_LOCKDOWN 47 // using the SET_FEATURE_ON_PROCESS mode; see the MSDN page 48 // on CoInternetSetFeatureEnabled for the explanation. 49 //{FEATURE_LOCALMACHINE_LOCKDOWN, TRUE}, 50 {FEATURE_SECURITYBAND, FALSE}, 51 {FEATURE_RESTRICT_ACTIVEXINSTALL, TRUE}, 52 {FEATURE_VALIDATE_NAVIGATE_URL, TRUE}, 53 {FEATURE_RESTRICT_FILEDOWNLOAD, TRUE}, 54 {FEATURE_ADDON_MANAGEMENT, TRUE}, 55 {FEATURE_PROTOCOL_LOCKDOWN, TRUE}, 56 {FEATURE_HTTP_USERNAME_PASSWORD_DISABLE, TRUE}, 57 {FEATURE_SAFE_BINDTOOBJECT, TRUE}, 58 {FEATURE_UNC_SAVEDFILECHECK, TRUE}, 59 {FEATURE_GET_URL_DOM_FILEPATH_UNENCODED, FALSE}, 60 {FEATURE_TABBED_BROWSING, FALSE}, 61 {FEATURE_SSLUX, FALSE}, 62 {FEATURE_DISABLE_NAVIGATION_SOUNDS, TRUE}, 63 {FEATURE_DISABLE_LEGACY_COMPRESSION, TRUE}, 64 {FEATURE_FORCE_ADDR_AND_STATUS, FALSE}, 65 {FEATURE_XMLHTTP, FALSE}, 66 {FEATURE_DISABLE_TELNET_PROTOCOL, TRUE}, 67 {FEATURE_FEEDS, FALSE}, 68 {FEATURE_BLOCK_INPUT_PROMPTS, TRUE}}; 69 70 for (Feature feature : features) { 71 CoInternetSetFeatureEnabled(feature.id, SET_FEATURE_ON_PROCESS, 72 feature.value); 73 } 74 } 75 76 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID) { 77 if (reason == DLL_PROCESS_ATTACH) { 78 gHInst = instance; 79 (void)OleInitialize(nullptr); 80 ConfigurePerProcessBrowserFeatures(); 81 } 82 return TRUE; 83 } 84 85 UINT_PTR __cdecl NSISPluginCallback(NSPIM msg) { 86 if (msg == NSPIM_UNLOAD) { 87 OleUninitialize(); 88 } 89 return 0; 90 } 91 92 BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, 93 LPARAM lParam) { 94 BOOL bRes = 95 CallWindowProc((WNDPROC)gWndProcOld, hwnd, message, wParam, lParam); 96 if (!bRes && message == WM_NOTIFY_OUTER_NEXT) { 97 gDone = true; 98 PostMessage(gHwnd, WM_CLOSE, 0, 0); 99 } 100 return bRes; 101 } 102 103 BOOL CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 104 return FALSE; 105 } 106 107 void Init(HWND hWndParent, int string_size, TCHAR* variables, 108 stack_t** stacktop, extra_parameters* extra) { 109 EXDLL_INIT(); 110 extra->RegisterPluginCallback(gHInst, NSISPluginCallback); 111 112 HWND hwndChild = GetDlgItem(hWndParent, 1018); 113 if (!hwndChild) { 114 return; 115 } 116 117 HWND hwnd = 118 CreateDialog(gHInst, MAKEINTRESOURCE(IDD_DIALOG1), hWndParent, DlgProc); 119 if (!hwnd) { 120 gDone = true; 121 } else { 122 gDone = false; 123 gWndProcOld = 124 (WNDPROC)SetWindowLong(hWndParent, DWL_DLGPROC, (LONG)ParentWndProc); 125 126 // Tell NSIS to replace its inner dialog with ours. 127 SendMessage(hWndParent, WM_NOTIFY_CUSTOM_READY, (WPARAM)hwnd, 0); 128 129 // Initialize the browser control. 130 if (gBrowser) { 131 gBrowser->Shutdown(); 132 gBrowser->Release(); 133 } 134 gBrowser = new WebBrowser(hwnd); 135 136 if (!gBrowser || !gBrowser->IsInitialized()) { 137 return; 138 } 139 140 gHwnd = hwnd; 141 142 // Move our dialog to match the size of the parent. 143 RECT r; 144 GetClientRect(hwndChild, &r); 145 MoveWindow(hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE); 146 gBrowser->SetRect(r); 147 } 148 } 149 150 PLUGINFUNCTION(ShowPage) { 151 if (!gBrowser) { 152 Init(hWndParent, string_size, variables, stacktop, extra); 153 } 154 155 if (!gBrowser->IsInitialized()) { 156 return; 157 } 158 159 TCHAR* sUrl = 160 (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR)); 161 popstring(sUrl); 162 163 if (gBrowser) { 164 gBrowser->Navigate(sUrl); 165 166 ShowWindow(gHwnd, SW_SHOWNA); 167 UpdateWindow(gHwnd); 168 169 while (!gDone) { 170 // This explicit wait call is needed rather than just a blocking 171 // GetMessage because we need this thread to be alertable so that our 172 // timers can wake it up and run their callbacks. 173 MsgWaitForMultipleObjectsEx(0, nullptr, 100, QS_ALLINPUT, 174 MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); 175 MSG msg; 176 if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { 177 bool tab = msg.message == WM_KEYDOWN && msg.wParam == VK_TAB; 178 179 if (gBrowser->ActiveObjectTranslateAccelerator(tab, &msg) != S_OK && 180 !IsDialogMessage(gHwnd, &msg) && 181 !IsDialogMessage(g_hwndParent, &msg)) { 182 TranslateMessage(&msg); 183 DispatchMessage(&msg); 184 } 185 } 186 } 187 188 SetWindowLong(g_hwndParent, DWL_DLGPROC, (LONG)gWndProcOld); 189 if (gHwnd) { 190 DestroyWindow(gHwnd); 191 } 192 193 gBrowser->Shutdown(); 194 gBrowser->Release(); 195 gBrowser = nullptr; 196 } 197 198 HeapFree(GetProcessHeap(), 0, (char*)sUrl); 199 }