// Copyright 2012 Software Freedom Conservancy
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "stdafx.h"
#include "resource.h"
#include "IEServer.h"
#include "CommandLineArguments.h"
#include <algorithm>
#include <map>
#include <string>
#include <vector>

// TODO(JimEvans): Change the prototypes of these functions in the
// IEDriver project to match the prototype specified here.
typedef void* (__cdecl *STARTSERVEREXPROC)(int, const std::string&, const std::string&, const std::string&, const std::string&);
typedef void (__cdecl *STOPSERVERPROC)(void);

#define ERR_DLL_EXTRACT_FAIL 1
#define ERR_DLL_LOAD_FAIL 2
#define ERR_FUNCTION_NOT_FOUND 3
#define ERR_SERVER_START 4

#define RESOURCE_TYPE L"BINARY"
#define TEMP_FILE_PREFIX L"IEDriver"
#define START_SERVER_EX_API_NAME "StartServerEx"
#define STOP_SERVER_API_NAME "StopServer"

#define PORT_COMMAND_LINE_ARG "port"
#define HOST_COMMAND_LINE_ARG "host"
#define LOGLEVEL_COMMAND_LINE_ARG "log-level"
#define LOGFILE_COMMAND_LINE_ARG "log-file"
#define SILENT_COMMAND_LINE_ARG "silent"
#define EXTRACTPATH_COMMAND_LINE_ARG "extract-path"
#define BOOLEAN_COMMAND_LINE_ARG_MISSING_VALUE "value-not-specified"

bool ExtractResource(unsigned short resource_id,
                     const std::wstring& output_file_name) {
  bool success = false; 
  try {
    // First find and load the required resource
    HRSRC resource_handle = ::FindResource(NULL, 
                                           MAKEINTRESOURCE(resource_id),
                                           RESOURCE_TYPE);
    HGLOBAL global_resouce_handle = ::LoadResource(NULL, resource_handle);

    // Now open and map this to a disk file
    LPVOID file_pointer = ::LockResource(global_resouce_handle);
    DWORD resource_size = ::SizeofResource(NULL, resource_handle);
 
    // Open the file and filemap
    HANDLE file_handle = ::CreateFile(output_file_name.c_str(),
                                      GENERIC_READ | GENERIC_WRITE,
                                      0,
                                      NULL,
                                      CREATE_ALWAYS, 
                                      FILE_ATTRIBUTE_NORMAL, 
                                      NULL);
    HANDLE file_mapping_handle = ::CreateFileMapping(file_handle,
                                                     NULL,
                                                     PAGE_READWRITE, 
                                                     0,
                                                     resource_size, 
                                                     NULL);
    LPVOID base_address_pointer = ::MapViewOfFile(file_mapping_handle,
                                                  FILE_MAP_WRITE,
                                                  0,
                                                  0,
                                                  0);

    // Write the file
    ::CopyMemory(base_address_pointer, file_pointer, resource_size);

    // Unmap the file and close the handles
    ::UnmapViewOfFile(base_address_pointer);
    ::CloseHandle(file_mapping_handle);
    ::CloseHandle(file_handle);
    success = true;
  } catch(...) {
    // Ignore all type of errors
  } 
  return success;
}

std::string GetProcessArchitectureDescription() {
  std::string arch_description = "32-bit";
  SYSTEM_INFO system_info;
  ::GetNativeSystemInfo(&system_info);
  if (system_info.wProcessorArchitecture != 0) {
    BOOL is_emulated;
    HANDLE process_handle = ::GetCurrentProcess();
    ::IsWow64Process(process_handle, &is_emulated);
    if (!is_emulated) {
      arch_description = "64-bit";
    }
    ::CloseHandle(process_handle);
  }

  return arch_description;
}

std::string GetExecutableVersion() {
  struct LANGANDCODEPAGE {
    WORD language;
    WORD code_page;
  } *lang_info;

  // get the filename of the executable containing the version resource
  std::vector<char> file_name_buffer(MAX_PATH + 1);
  ::GetModuleFileNameA(NULL, &file_name_buffer[0], MAX_PATH);

  DWORD dummy;
  DWORD length = ::GetFileVersionInfoSizeA(&file_name_buffer[0],
                                           &dummy);
  std::vector<BYTE> version_buffer(length);
  ::GetFileVersionInfoA(&file_name_buffer[0],
                       dummy,
                       length,
                       &version_buffer[0]);

  UINT page_count;
  BOOL query_result = ::VerQueryValueA(&version_buffer[0],
                                      "\\VarFileInfo\\Translation",
                                      reinterpret_cast<void**>(&lang_info),
                                      &page_count);
    
  char sub_block[MAX_PATH];
  _snprintf_s(sub_block,
               MAX_PATH,
               MAX_PATH,
               "\\StringFileInfo\\%04x%04x\\FileVersion",
               lang_info->language,
               lang_info->code_page);
  LPVOID value = NULL;
  UINT size;
  query_result = ::VerQueryValueA(&version_buffer[0],
                                 sub_block,
                                 &value,
                                 &size);
  return static_cast<char*>(value);
}

void ShowUsage(void) {
  std::wcout << L"Launches the WebDriver server for the Internet Explorer driver" << std::endl
             << std::endl
             << L"IEDriverServer [/port=<port>] [/host=<host>] [/log-level=<level>]" << std::endl
             << L"               [/log-file=<file>] [/extract-path=<path>] [/silent]" << std::endl
             << std::endl
             << L"  /port=<port>  Specifies the port on which the server will listen for" << std::endl
             << L"                commands. Defaults to 5555 if not specified." << std::endl
             << L"  /host=<host>  Specifies the address of the host adapter on which the server" << std::endl
             << L"                will listen for commands." << std::endl
             << L"  /log-level=<level>" << std::endl
             << L"                Specifies the log level used by the server. Valid values are:" << std::endl
             << L"                TRACE, DEBUG, INFO, WARN, ERROR, and FATAL. Defaults to FATAL" << std::endl
             << L"                if not specified." << std::endl
             << L"  /log-file=<file>" << std::endl
             << L"                Specifies the full path and file name of the log file used by" << std::endl
             << L"                the server. Defaults logging to stdout if not specified. " << std::endl
             << L"  /extract-path=<path>" << std::endl
             << L"                Specifies the full path to the directory used to extract" << std::endl
             << L"                supporting files used by the server. Defaults to the TEMP" << std::endl
             << L"                directory if not specified." << std::endl
             << L"  /silent       Suppresses diagnostic output when the server is started." << std::endl;
}

int _tmain(int argc, _TCHAR* argv[]) {
  CommandLineArguments args(argc, argv);
  if (args.is_help_requested()) {
    ShowUsage();
    return 0;
  }
  vector<TCHAR> temp_file_name_buffer(MAX_PATH);
  vector<TCHAR> temp_path_buffer(MAX_PATH);

  //  Gets the temp path env string (no guarantee it's a valid path).
  unsigned long temp_path_length = ::GetTempPath(MAX_PATH,
                                                 &temp_path_buffer[0]);

  std::wstring extraction_path(&temp_path_buffer[0]);

  std::string extraction_path_arg = args.GetValue(EXTRACTPATH_COMMAND_LINE_ARG, "");
  if (extraction_path_arg.size() != 0) {
    extraction_path = CA2W(extraction_path_arg.c_str(), CP_UTF8);
  }
  
  unsigned int error_code = ::GetTempFileName(extraction_path.c_str(),
                                              TEMP_FILE_PREFIX,
                                              0,
                                              &temp_file_name_buffer[0]);

  std::wstring temp_file_name(&temp_file_name_buffer[0]);
  if (!ExtractResource(IDR_DRIVER_LIBRARY, temp_file_name)) {
    std::wcout << L"Failed to extract the library to temp directory: "
               << temp_file_name;
    return ERR_DLL_EXTRACT_FAIL;
  }

  HMODULE module_handle = ::LoadLibrary(temp_file_name.c_str());
  if (module_handle == NULL) {
    std::wcout << L"Failed to load the library from temp directory: "
               << temp_file_name;
    return ERR_DLL_LOAD_FAIL;
  }

  STARTSERVEREXPROC start_server_ex_proc = reinterpret_cast<STARTSERVEREXPROC>(
      ::GetProcAddress(module_handle, START_SERVER_EX_API_NAME));
  STOPSERVERPROC stop_server_proc = reinterpret_cast<STOPSERVERPROC>(
      ::GetProcAddress(module_handle, STOP_SERVER_API_NAME));
  if (start_server_ex_proc == NULL || stop_server_proc == NULL) {
    std::wcout << L"Could not find entry point in extracted library: "
               << temp_file_name;
    return ERR_FUNCTION_NOT_FOUND;
  }

  int port = atoi(args.GetValue(PORT_COMMAND_LINE_ARG, "5555").c_str());
  std::string host_address = args.GetValue(HOST_COMMAND_LINE_ARG, "");
  std::string log_level = args.GetValue(LOGLEVEL_COMMAND_LINE_ARG, "");
  std::string log_file = args.GetValue(LOGFILE_COMMAND_LINE_ARG, "");
  bool silent = args.GetValue(SILENT_COMMAND_LINE_ARG,
      BOOLEAN_COMMAND_LINE_ARG_MISSING_VALUE).size() == 0;
  std::string executable_version = GetExecutableVersion();
  void* server_value = start_server_ex_proc(port,
                                            host_address,
                                            log_level,
                                            log_file,
                                            executable_version);
  if (server_value == NULL) {
    std::cout << L"Failed to start the server with: "
              << L"port = '" << port << "', "
              << L"host = '" << host_address << "', "
              << L"log level = '" << log_level << "', "
              << L"log file = '" << log_file << "'";
    return ERR_SERVER_START;
  }
  if (!silent) {
    std::cout << "Started InternetExplorerDriver server"
              << " (" << GetProcessArchitectureDescription() << ")"
              << std::endl;
    std::cout << executable_version
              << std::endl;
    std::cout << "Listening on port " << port << std::endl;
    if (host_address.size() > 0) {
      std::cout << "Bound to network adapter with IP address " 
                << host_address
                << std::endl;
    }
    if (log_level.size() > 0) {
      std::cout << "Log level is set to "
                << log_level
                << std::endl;
    }
    if (log_file.size() > 0) {
      std::cout << "Log file is set to "
                << log_file
                << std::endl;
    }
    if (extraction_path_arg.size() > 0) {
      std::cout << "Library extracted to "
                << extraction_path_arg
                << std::endl;
    }
  }

  // Create the shutdown event and wait for it to be signaled.
  DWORD process_id = ::GetCurrentProcessId();
  vector<wchar_t> process_id_buffer(10);
  _ltow_s(process_id, &process_id_buffer[0], process_id_buffer.size(), 10);
  std::wstring process_id_string(&process_id_buffer[0]);
  std::wstring event_name = IESERVER_SHUTDOWN_EVENT_NAME + process_id_string;
  HANDLE event_handle = ::CreateEvent(NULL,
                                      TRUE, 
                                      FALSE,
                                      event_name.c_str());
  ::WaitForSingleObject(event_handle, INFINITE);
  ::CloseHandle(event_handle);
  stop_server_proc();

  ::FreeLibrary(module_handle);
  ::DeleteFile(temp_file_name.c_str());
  return 0;
}
