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