1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <windows.h>
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(_WIN32_WINNT_WIN8) && _MSC_VER < 1700
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h, and in
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// delayimp.h previous to VS2012.
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#undef FACILITY_VISUALCPP
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <DelayIMP.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/compiler_specific.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/scoped_native_library.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/app/delay_load_hook_win.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ChromeDelayLoadHookTest : public testing::Test {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ChromeDelayLoadHookTest() : proc_ptr_(NULL) {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetupInfo("kernel32.dll");
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void SetupInfo(const char* dll_name) {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.cb = sizeof(info_);
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.pidd =  NULL;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.ppfn = &proc_ptr_;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.szDll = dll_name;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.dlp.fImportByName = TRUE;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.dlp.szProcName = "CreateFileA";
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.hmodCur = NULL;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.pfnCur = NULL;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    info_.dwLastError = 0;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FARPROC proc_ptr_;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DelayLoadInfo info_;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(ChromeDelayLoadHookTest, HooksAreSetAtLinkTime) {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test verifies that referencing the ChromeDelayLoadHook at link
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // time results in overriding the delay loader's hook instances in the CRT
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ropriately.
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(__pfnDliNotifyHook2 == ChromeDelayLoadHook);
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(__pfnDliFailureHook2 == ChromeDelayLoadHook);
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(ChromeDelayLoadHookTest, NonSuffixedDllsAreNotHandled) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The hook should ignore non-suffixed DLLs.
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetupInfo("kernel32.dll");
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HMODULE none = reinterpret_cast<HMODULE>(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ChromeDelayLoadHook(dliNotePreLoadLibrary, &info_));
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   // Make sure the library is released on exit.
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   base::ScopedNativeLibrary lib_holder(none);
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   ASSERT_TRUE(none == NULL);
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(ChromeDelayLoadHookTest, SuffixedDllsAreRedirected) {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that a DLL name of the form "foo-delay.dll" gets redirected to
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the "foo.dll".
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetupInfo("kernel32-delay.dll");
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HMODULE kernel32 = reinterpret_cast<HMODULE>(
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ChromeDelayLoadHook(dliNotePreLoadLibrary, &info_));
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   // Make sure the library is released on exit.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   base::ScopedNativeLibrary lib_holder(kernel32);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   ASSERT_TRUE(kernel32 == ::GetModuleHandle(L"kernel32.dll"));
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(ChromeDelayLoadHookTest, IgnoresUnhandledNotifications) {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetupInfo("kernel32-delay.dll");
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The hook should ignore all notifications but the preload notifications.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(ChromeDelayLoadHook(dliNoteStartProcessing, &info_) == NULL);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(ChromeDelayLoadHook(dliNotePreGetProcAddress, &info_) == NULL);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(ChromeDelayLoadHook(dliNoteEndProcessing, &info_) == NULL);
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(ChromeDelayLoadHook(dliFailLoadLib, &info_) == NULL);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(ChromeDelayLoadHook(dliFailGetProc, &info_) == NULL);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
91