Home | History | Annotate | Download | only in app
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/app/close_handle_hook_win.h"
      6 
      7 #include <Windows.h>
      8 
      9 #include <vector>
     10 
     11 #include "base/files/file_path.h"
     12 #include "base/lazy_instance.h"
     13 #include "base/strings/string16.h"
     14 #include "base/win/iat_patch_function.h"
     15 #include "base/win/scoped_handle.h"
     16 #include "chrome/common/chrome_version_info.h"
     17 
     18 namespace {
     19 
     20 typedef BOOL (WINAPI* CloseHandleType) (HANDLE handle);
     21 CloseHandleType g_close_function = NULL;
     22 
     23 // The entry point for CloseHandle interception. This function notifies the
     24 // verifier about the handle that is being closed, and calls the original
     25 // function.
     26 BOOL WINAPI CloseHandleHook(HANDLE handle) {
     27   base::win::OnHandleBeingClosed(handle);
     28   return g_close_function(handle);
     29 }
     30 
     31 // Keeps track of all the hooks needed to intercept CloseHandle.
     32 class CloseHandleHooks {
     33  public:
     34   CloseHandleHooks() {}
     35   ~CloseHandleHooks() {}
     36 
     37   void AddIATPatch(const base::string16& module);
     38   void Unpatch();
     39 
     40  private:
     41   std::vector<base::win::IATPatchFunction*> hooks_;
     42   DISALLOW_COPY_AND_ASSIGN(CloseHandleHooks);
     43 };
     44 base::LazyInstance<CloseHandleHooks> g_hooks = LAZY_INSTANCE_INITIALIZER;
     45 
     46 void CloseHandleHooks::AddIATPatch(const base::string16& module) {
     47   if (module.empty())
     48     return;
     49 
     50   base::win::IATPatchFunction* patch = new base::win::IATPatchFunction;
     51   patch->Patch(module.c_str(), "kernel32.dll", "CloseHandle", CloseHandleHook);
     52   hooks_.push_back(patch);
     53   if (!g_close_function) {
     54     // Things are probably messed up if each intercepted function points to
     55     // a different place, but we need only one function to call.
     56     g_close_function =
     57       reinterpret_cast<CloseHandleType>(patch->original_function());
     58   }
     59 }
     60 
     61 void CloseHandleHooks::Unpatch() {
     62   for (std::vector<base::win::IATPatchFunction*>::iterator it = hooks_.begin();
     63        it != hooks_.end(); ++it) {
     64     (*it)->Unpatch();
     65   }
     66 }
     67 
     68 bool UseHooks() {
     69   return false;
     70 }
     71 
     72 base::string16 GetModuleName(HMODULE module) {
     73   base::string16 name;
     74   if (!module)
     75     return name;
     76   wchar_t buffer[MAX_PATH];
     77   int rv = GetModuleFileName(module, buffer, MAX_PATH);
     78   if (rv == MAX_PATH)
     79     return name;
     80 
     81   buffer[MAX_PATH - 1] = L'\0';
     82   name.assign(buffer);
     83   base::FilePath path(name);
     84   return path.BaseName().AsUTF16Unsafe();
     85 }
     86 
     87 HMODULE GetChromeDLLModule() {
     88   HMODULE module;
     89   if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
     90                              GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
     91                          reinterpret_cast<wchar_t*>(&GetChromeDLLModule),
     92                          &module)) {
     93     return NULL;
     94   }
     95   return module;
     96 }
     97 
     98 }  // namespace
     99 
    100 void InstallCloseHandleHooks() {
    101   if (UseHooks()) {
    102     CloseHandleHooks* hooks = g_hooks.Pointer();
    103     hooks->AddIATPatch(L"chrome.exe");
    104     hooks->AddIATPatch(GetModuleName(GetChromeDLLModule()));
    105   } else {
    106     base::win::DisableHandleVerifier();
    107   }
    108 }
    109 
    110 void RemoveCloseHandleHooks() {
    111   g_hooks.Get().Unpatch();
    112 }
    113