普通文本  |  71行  |  2.35 KB

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "metro_driver_win.h"

#include <string.h>

#include "chrome/app/client_util.h"
#include "chrome/common/chrome_constants.h"

namespace {
// This environment variable controls the loading of the metro driver DLL.
const char* kMetroModeEnvVar = "CHROME_METRO_DLL";

typedef int (*InitMetro)(LPTHREAD_START_ROUTINE thread_proc, void* context);

struct Context {
  MetroDriver::MainFn fn;
  HINSTANCE instance;
};

DWORD WINAPI MainThread(void* param) {
  Context* context = reinterpret_cast<Context*>(param);
  int rv = context->fn(context->instance);
  delete context;
  return rv;
}

}  // namespace

MetroDriver::MetroDriver() : init_metro_fn_(NULL) {
  if (0 != ::GetEnvironmentVariableA(kMetroModeEnvVar, NULL, 0))
    return;
  // The metro activation always has the |ServerName| parameter. If we dont
  // see it, we are being launched in desktop mode.
  if (!wcsstr(::GetCommandLineW(), L" -ServerName:DefaultBrowserServer")) {
    ::SetEnvironmentVariableA(kMetroModeEnvVar, "0");
    return;
  }
  // We haven't tried to load the metro driver, this probably means we are the
  // browser. Find it or not we set the environment variable because we don't
  // want to keep trying in the child processes.
  HMODULE metro_dll = ::LoadLibraryW(chrome::kMetroDriverDll);
  if (!metro_dll) {
    // It is not next to the build output, so this must be an actual deployment
    // and in that case we need the mainloader to find the current version
    // directory.
    string16 version(GetCurrentModuleVersion());
    if (!version.empty()) {
      std::wstring exe_path(GetExecutablePath());
      exe_path.append(version).append(L"\\").append(chrome::kMetroDriverDll);
      metro_dll = ::LoadLibraryW(exe_path.c_str());
    }
  }
  // We set the environment variable always, so we don't keep trying in
  // the child processes.
  ::SetEnvironmentVariableA(kMetroModeEnvVar, metro_dll ? "1" : "0");
  if (!metro_dll)
    return;
  init_metro_fn_ = ::GetProcAddress(metro_dll, "InitMetro");
}

int MetroDriver::RunInMetro(HINSTANCE instance, MainFn main_fn) {
  Context* context = new Context;
  context->fn = main_fn;
  context->instance = instance;

  return reinterpret_cast<InitMetro>(init_metro_fn_)(&MainThread, context);
}