1577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch// Copyright (c) 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CommCtrl.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <commdlg.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windowsx.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlbase.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlsecurity.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/main_ui_window.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/resource.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/acl.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/win_utils.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWND MainUIWindow::list_view_ = NULL; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t MainUIWindow::kDefaultDll_[] = L"\\POCDLL.dll"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t MainUIWindow::kDefaultEntryPoint_[] = L"Run"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t MainUIWindow::kDefaultLogFile_[] = L""; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MainUIWindow::MainUIWindow() 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : instance_handle_(NULL), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_(L""), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_(L""), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry_point_(L""), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) broker_(NULL) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MainUIWindow::~MainUIWindow() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int MainUIWindow::CreateMainWindowAndLoop( 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HINSTANCE instance, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* command_line, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int show_command, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::BrokerServices* broker) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(instance); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(command_line); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(broker); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_handle_ = instance; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_ = command_line; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) broker_ = broker; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll use spawn_target_ later for creating a child process, but 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CreateProcess doesn't like double quotes, so we remove them along with 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tabs and spaces from the start and end of the string 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t *trim_removal = L" \r\t\""; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_.erase(0, spawn_target_.find_first_not_of(trim_removal)); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_.erase(spawn_target_.find_last_not_of(trim_removal) + 1); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WNDCLASSEX window_class = {0}; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.cbSize = sizeof(WNDCLASSEX); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.style = CS_HREDRAW | CS_VREDRAW; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.lpfnWndProc = MainUIWindow::WndProc; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.cbClsExtra = 0; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.cbWndExtra = 0; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.hInstance = instance; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.hIcon = 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::LoadIcon(instance, MAKEINTRESOURCE(IDI_SANDBOX)); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.hCursor = ::LoadCursor(NULL, IDC_ARROW); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.hbrBackground = GetStockBrush(WHITE_BRUSH); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_MAIN_UI); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.lpszClassName = L"sandbox_ui_1"; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_class.hIconSm = NULL; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INITCOMMONCONTROLSEX controls = { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(INITCOMMONCONTROLSEX), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ICC_STANDARD_CLASSES | ICC_LISTVIEW_CLASSES 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::InitCommonControlsEx(&controls); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::RegisterClassEx(&window_class)) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::GetLastError(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a main window of size 600x400 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND window = ::CreateWindowW(window_class.lpszClassName, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"", // window name 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WS_OVERLAPPEDWINDOW, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CW_USEDEFAULT, // x 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CW_USEDEFAULT, // y 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 600, // width 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 400, // height 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // parent 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // NULL = use class menu 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); // lpParam 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == window) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::GetLastError(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowLongPtr(window, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GWLP_USERDATA, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LONG_PTR>(this)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(window, L"Sandbox Proof of Concept"); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ShowWindow(window, show_command); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MSG message; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now lets start the message pump retrieving messages for any window that 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // belongs to the current thread 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (::GetMessage(&message, NULL, 0, 0)) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::TranslateMessage(&message); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::DispatchMessage(&message); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT CALLBACK MainUIWindow::WndProc(HWND window, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT message_id, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM wparam, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPARAM lparam) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MainUIWindow* host = FromWindow(window); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define HANDLE_MSG(hwnd, message, fn) \ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn)) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (message_id) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_CREATE: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'host' is not yet available when we get the WM_CREATE message 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HANDLE_WM_CREATE(window, wparam, lparam, OnCreate); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_DESTROY: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HANDLE_WM_DESTROY(window, wparam, lparam, host->OnDestroy); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_SIZE: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HANDLE_WM_SIZE(window, wparam, lparam, host->OnSize); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_COMMAND: { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look at which menu item was clicked on (or which accelerator) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id = LOWORD(wparam); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (id) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ID_FILE_EXIT: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->OnFileExit(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ID_COMMANDS_SPAWNTARGET: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->OnCommandsLaunch(window); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some other menu item or accelerator 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some other WM_message, let it pass to DefWndProc 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefWindowProc(window, message_id, wparam, lparam); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INT_PTR CALLBACK MainUIWindow::SpawnTargetWndProc(HWND dialog, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT message_id, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM wparam, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPARAM lparam) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNREFERENCED_PARAMETER(lparam); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grab a reference to the main UI window (from the window handle) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MainUIWindow* host = FromWindow(GetParent(dialog)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (message_id) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_INITDIALOG: { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the window text for DLL name edit box 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_dll_name = ::GetDlgItem(dialog, IDC_DLL_NAME); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t current_dir[MAX_PATH]; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetCurrentDirectory(MAX_PATH, current_dir)) { 177d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::string16 dll_path = base::string16(current_dir) + 178d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::string16(kDefaultDll_); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(edit_box_dll_name, dll_path.c_str()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the window text for Entry Point edit box 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_entry_point = ::GetDlgItem(dialog, IDC_ENTRY_POINT); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(edit_box_entry_point, kDefaultEntryPoint_); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the window text for Log File edit box 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(edit_box_log_file, kDefaultLogFile_); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(TRUE); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_COMMAND: 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user presses the OK button (Launch) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LOWORD(wparam) == IDOK) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host->OnLaunchDll(dialog)) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host->SpawnTarget()) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::EndDialog(dialog, LOWORD(wparam)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(TRUE); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (LOWORD(wparam) == IDCANCEL) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user presses the Cancel button 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::EndDialog(dialog, LOWORD(wparam)); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(TRUE); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (LOWORD(wparam) == IDC_BROWSE_DLL) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user presses the Browse button to look for a DLL 207d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::string16 dll_path = host->OnShowBrowseForDllDlg(dialog); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dll_path.length() > 0) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the window text for Log File edit box 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_dll_path = ::GetDlgItem(dialog, IDC_DLL_NAME); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(edit_box_dll_path, dll_path.c_str()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(TRUE); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (LOWORD(wparam) == IDC_BROWSE_LOG) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user presses the Browse button to look for a log file 216d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::string16 log_path = host->OnShowBrowseForLogFileDlg(dialog); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (log_path.length() > 0) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the window text for Log File edit box 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowText(edit_box_log_file, log_path.c_str()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(TRUE); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<INT_PTR>(FALSE); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MainUIWindow* MainUIWindow::FromWindow(HWND main_window) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We store a 'this' pointer using SetWindowLong in CreateMainWindowAndLoop 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so that we can retrieve it with this function later. This prevents us 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from having to define all the message handling functions (that we refer to 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the window proc) as static 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetWindowLongPtr(main_window, GWLP_USERDATA); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<MainUIWindow*>( 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetWindowLongPtr(main_window, GWLP_USERDATA)); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL MainUIWindow::OnCreate(HWND parent_window, LPCREATESTRUCT) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the listview that will the main app UI 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_view_ = ::CreateWindow(WC_LISTVIEW, // Class name 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"", // Window name 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WS_CHILD | WS_VISIBLE | LVS_REPORT | 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LVS_NOCOLUMNHEADER | WS_BORDER, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // x 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // y 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // width 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // height 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_window, // parent 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // menu 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetModuleHandle(NULL), 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); // lpParam 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(list_view_); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!list_view_) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LVCOLUMN list_view_column = {0}; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_view_column.mask = LVCF_FMT | LVCF_WIDTH ; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_view_column.fmt = LVCFMT_LEFT; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_view_column.cx = 10000; // Maximum size of an entry in the list view. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListView_InsertColumn(list_view_, 0, &list_view_column); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set list view to show green font on black background 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListView_SetBkColor(list_view_, CLR_NONE); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListView_SetTextColor(list_view_, RGB(0x0, 0x0, 0x0)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListView_SetTextBkColor(list_view_, CLR_NONE); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::OnDestroy(HWND window) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNREFERENCED_PARAMETER(window); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Post a quit message because our application is over when the 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user closes this window. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::PostQuitMessage(0); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::OnSize(HWND window, UINT state, int cx, int cy) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNREFERENCED_PARAMETER(window); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNREFERENCED_PARAMETER(state); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a valid inner child, resize it to cover the entire 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client area of the main UI window. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list_view_) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MoveWindow(list_view_, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // x 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // y 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cx, // width 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cy, // height 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRUE); // repaint 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::OnPaint(HWND window) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAINTSTRUCT paintstruct; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::BeginPaint(window, &paintstruct); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add painting code here if required 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::EndPaint(window, &paintstruct); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::OnFileExit() { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::PostQuitMessage(0); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::OnCommandsLaunch(HWND window) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // User wants to see the Select DLL dialog box 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::DialogBox(instance_handle_, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAKEINTRESOURCE(IDD_LAUNCH_DLL), 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpawnTargetWndProc); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MainUIWindow::OnLaunchDll(HWND dialog) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_dll_name = ::GetDlgItem(dialog, IDC_DLL_NAME); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_box_entry_point = ::GetDlgItem(dialog, IDC_ENTRY_POINT); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND edit_log_file = ::GetDlgItem(dialog, IDC_LOG_FILE); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t dll_path[MAX_PATH]; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t entry_point[MAX_PATH]; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t log_file[MAX_PATH]; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dll_name_len = ::GetWindowText(edit_box_dll_name, dll_path, MAX_PATH); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int entry_point_len = ::GetWindowText(edit_box_entry_point, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry_point, MAX_PATH); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Log file is optional (can be blank) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetWindowText(edit_log_file, log_file, MAX_PATH); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 >= dll_name_len) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(dialog, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Please specify a DLL for the target to load", 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"No DLL specified", 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MB_ICONERROR); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetFileAttributes(dll_path) == INVALID_FILE_ATTRIBUTES) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(dialog, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"DLL specified was not found", 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"DLL not found", 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MB_ICONERROR); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 >= entry_point_len) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(dialog, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Please specify an entry point for the DLL", 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"No entry point specified", 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MB_ICONERROR); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // store these values in the member variables for use in SpawnTarget 357d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) log_file_ = base::string16(L"\"") + log_file + base::string16(L"\""); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_ = dll_path; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry_point_ = entry_point; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD WINAPI MainUIWindow::ListenPipeThunk(void *param) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<MainUIWindow*>(param)->ListenPipe(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD WINAPI MainUIWindow::WaitForTargetThunk(void *param) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<MainUIWindow*>(param)->WaitForTarget(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Thread waiting for the target application to die. It displays 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a message in the list view when it happens. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD MainUIWindow::WaitForTarget() { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForSingleObject(target_.hProcess, INFINITE); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD exit_code = 0; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetExitCodeProcess(target_.hProcess, &exit_code)) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit_code = 0xFFFF; // Default exit code 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(target_.hProcess); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(target_.hThread); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"Targed exited with return code %d", exit_code); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Thread waiting for messages on the log pipe. It displays the messages 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the listview. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD MainUIWindow::ListenPipe() { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE logfile_handle = NULL; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATL::CString file_to_open = log_file_.c_str(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_to_open.Remove(L'\"'); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_to_open.GetLength()) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logfile_handle = ::CreateFile(file_to_open.GetBuffer(), 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GENERIC_WRITE, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // Default security attributes 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CREATE_ALWAYS, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_ATTRIBUTE_NORMAL, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); // No template 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (INVALID_HANDLE_VALUE == logfile_handle) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"Failed to open \"%ls\" for logging. Error %d", 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_to_open.GetBuffer(), ::GetLastError()); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logfile_handle = NULL; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSizeBuffer = 1024; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE read_buffer[kSizeBuffer] = {0}; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATL::CStringA read_buffer_global; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATL::CStringA string_to_print; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD last_error = 0; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while(last_error == ERROR_SUCCESS || last_error == ERROR_PIPE_LISTENING || 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_error == ERROR_NO_DATA) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD read_data_length; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::ReadFile(pipe_handle_, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSizeBuffer - 1, // Max read size 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &read_data_length, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL)) { // Not overlapped 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (logfile_handle) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD write_data_length; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::WriteFile(logfile_handle, 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer, 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_data_length, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &write_data_length, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE); // Not overlapped 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append the new buffer to the current buffer 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer[read_data_length] = NULL; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_global += reinterpret_cast<char *>(read_buffer); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_global.Remove(10); // Remove the CRs 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we completed a new line, output it 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int endline = read_buffer_global.Find(13); // search for LF 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (-1 != endline) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_to_print = read_buffer_global; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string_to_print.Delete(endline, string_to_print.GetLength()); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_global.Delete(0, endline); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // print the line (with the ending LF) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputDebugStringA(string_to_print.GetBuffer()); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the ending LF 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_global.Delete(0, 1); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the line to the log 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"%S", string_to_print.GetBuffer()); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) endline = read_buffer_global.Find(13); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_error = ERROR_SUCCESS; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_error = GetLastError(); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(100); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buffer_global.GetLength()) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"%S", read_buffer_global.GetBuffer()); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pipe_handle_); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (logfile_handle) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(logfile_handle); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MainUIWindow::SpawnTarget() { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate the pipe name 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GUID random_id; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoCreateGuid(&random_id); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t log_pipe[MAX_PATH] = {0}; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wnsprintf(log_pipe, MAX_PATH - 1, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"\\\\.\\pipe\\sbox_pipe_log_%lu_%lu_%lu_%lu", 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) random_id.Data1, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) random_id.Data2, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) random_id.Data3, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) random_id.Data4); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We concatenate the four strings, add three spaces and a zero termination 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use the resulting string as a param to CreateProcess (in SpawnTarget) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Documented maximum for command line in CreateProcess is 32K (msdn) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_call = spawn_target_.length() + entry_point_.length() + 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_.length() + wcslen(log_pipe) + 6; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (32 * 1024 < (size_call * sizeof(wchar_t))) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"The length of the arguments exceeded 32K. " 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Aborting operation."); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t * arguments = new wchar_t[size_call]; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wnsprintf(arguments, static_cast<int>(size_call), L"%ls %ls \"%ls\" %ls", 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_.c_str(), entry_point_.c_str(), 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_.c_str(), log_pipe); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arguments[size_call - 1] = L'\0'; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::TargetPolicy* policy = broker_->CreatePolicy(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::USER_LOCKDOWN); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->SetAlternateDesktop(true); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the rule to allow the POC dll to be loaded by the target. Note that 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the rule allows 'all access' to the DLL, which could mean that the target 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could modify the DLL on disk. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::TargetPolicy::FILES_ALLOW_ANY, dll_path_.c_str()); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox::ResultCode result = broker_->SpawnTarget(spawn_target_.c_str(), 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arguments, policy, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &target_); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy->Release(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy = NULL; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool return_value = false; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sandbox::SBOX_ALL_OK != result) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage( 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Failed to spawn target %ls w/args (%ls), sandbox error code: %d", 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawn_target_.c_str(), arguments, result); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_value = false; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD thread_id; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CreateThread(NULL, // Default security attributes 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // Default stack size 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &MainUIWindow::WaitForTargetThunk, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // No flags 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &thread_id); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_handle_ = ::CreateNamedPipe(log_pipe, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PIPE_ACCESS_INBOUND | WRITE_DAC, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PIPE_TYPE_MESSAGE | PIPE_NOWAIT, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, // Number of instances. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512, // Out buffer size. 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512, // In buffer size. 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NMPWAIT_USE_DEFAULT_WAIT, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); // Default security descriptor 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (INVALID_HANDLE_VALUE == pipe_handle_) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"Failed to create pipe. Error %d", ::GetLastError()); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 556577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch if (!sandbox::AddKnownSidToObject(pipe_handle_, SE_KERNEL_OBJECT, 557577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch WinWorldSid, GRANT_ACCESS, 558577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch FILE_ALL_ACCESS)) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"Failed to set security on pipe. Error %d", 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetLastError()); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CreateThread(NULL, // Default security attributes 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // Default stack size 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &MainUIWindow::ListenPipeThunk, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // No flags 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &thread_id); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ResumeThread(target_.hThread); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDebugMessage(L"Successfully spawned target w/args (%ls)", arguments); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_value = true; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] arguments; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return return_value; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 579d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)base::string16 MainUIWindow::OnShowBrowseForDllDlg(HWND owner) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t filename[MAX_PATH]; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcscpy_s(filename, MAX_PATH, L""); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPENFILENAMEW file_info = {0}; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lStructSize = sizeof(file_info); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.hwndOwner = owner; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lpstrFile = filename; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.nMaxFile = MAX_PATH; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lpstrFilter = L"DLL files (*.dll)\0*.dll\0All files\0*.*\0\0\0"; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetOpenFileName(&file_info)) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file_info.lpstrFile; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return L""; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 599d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)base::string16 MainUIWindow::OnShowBrowseForLogFileDlg(HWND owner) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t filename[MAX_PATH]; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcscpy_s(filename, MAX_PATH, L""); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPENFILENAMEW file_info = {0}; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lStructSize = sizeof(file_info); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.hwndOwner = owner; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lpstrFile = filename; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.nMaxFile = MAX_PATH; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.lpstrFilter = L"Log file (*.txt)\0*.txt\0All files\0*.*\0\0\0"; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_info.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetSaveFileName(&file_info)) { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file_info.lpstrFile; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return L""; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::AddDebugMessage(const wchar_t* format, ...) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(format); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!format) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxDebugBuffSize = 1024; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list arg_list; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _crt_va_start(arg_list, format); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t text[kMaxDebugBuffSize + 1]; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vswprintf_s(text, kMaxDebugBuffSize, format, arg_list); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text[kMaxDebugBuffSize] = L'\0'; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InsertLineInListView(text); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainUIWindow::InsertLineInListView(wchar_t* debug_message) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(debug_message); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!debug_message) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepend the time to the message 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSizeTime = 100; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_message_with_time = wcslen(debug_message) + kSizeTime; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t * message_time = new wchar_t[size_message_with_time]; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_t time_temp; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_temp = time(NULL); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct tm time = {0}; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) localtime_s(&time, &time_temp); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t return_code; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_code = wcsftime(message_time, kSizeTime, L"[%H:%M:%S] ", &time); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcscat_s(message_time, size_message_with_time, debug_message); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We add the debug message to the top of the listview 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LVITEM item; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.iItem = ListView_GetItemCount(list_view_); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.iSubItem = 0; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.mask = LVIF_TEXT | LVIF_PARAM; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.pszText = message_time; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.lParam = 0; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListView_InsertItem(list_view_, &item); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] message_time; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 670