1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/win/get_function.h"
16
17 #include <windows.h>
18 #include <winternl.h>
19
20 #include "gtest/gtest.h"
21
22 namespace crashpad {
23 namespace test {
24 namespace {
25
TEST(GetFunction,GetFunction)26 TEST(GetFunction, GetFunction) {
27 // Check equivalence of GET_FUNCTION_REQUIRED() with functions that are
28 // available in the SDK normally.
29 EXPECT_EQ(GET_FUNCTION_REQUIRED(L"kernel32.dll", GetProcAddress),
30 &GetProcAddress);
31 EXPECT_EQ(GET_FUNCTION_REQUIRED(L"kernel32.dll", LoadLibraryW),
32 &LoadLibraryW);
33
34 // Make sure that a function pointer retrieved by GET_FUNCTION_REQUIRED() can
35 // be called and that it works correctly.
36 const auto get_current_process_id =
37 GET_FUNCTION_REQUIRED(L"kernel32.dll", GetCurrentProcessId);
38 EXPECT_EQ(get_current_process_id, &GetCurrentProcessId);
39 ASSERT_TRUE(get_current_process_id);
40 EXPECT_EQ(get_current_process_id(), GetCurrentProcessId());
41
42 // GET_FUNCTION_REQUIRED() and GET_FUNCTION() should behave identically when
43 // the function is present.
44 EXPECT_EQ(GET_FUNCTION(L"kernel32.dll", GetCurrentProcessId),
45 get_current_process_id);
46
47 // Using a leading :: should also work.
48 EXPECT_EQ(GET_FUNCTION(L"kernel32.dll", ::GetCurrentProcessId),
49 get_current_process_id);
50 EXPECT_EQ(GET_FUNCTION_REQUIRED(L"kernel32.dll", ::GetCurrentProcessId),
51 get_current_process_id);
52
53 // Try a function that’s declared in the SDK’s headers but that has no import
54 // library.
55 EXPECT_TRUE(GET_FUNCTION_REQUIRED(L"ntdll.dll", RtlNtStatusToDosError));
56
57 // GetNamedPipeClientProcessId() is only available on Vista and later.
58 const auto get_named_pipe_client_process_id =
59 GET_FUNCTION(L"kernel32.dll", GetNamedPipeClientProcessId);
60 const DWORD version = GetVersion();
61 const DWORD major_version = LOBYTE(LOWORD(version));
62 EXPECT_EQ(get_named_pipe_client_process_id != nullptr, major_version >= 6);
63
64 // Test that GET_FUNCTION() can fail by trying a nonexistent library and a
65 // symbol that doesn’t exist in the specified library.
66 EXPECT_FALSE(GET_FUNCTION(L"not_a_real_library.dll", TerminateProcess));
67 EXPECT_FALSE(GET_FUNCTION(L"ntdll.dll", TerminateProcess));
68 EXPECT_FALSE(GET_FUNCTION(L"not_a_real_library.dll", ::TerminateProcess));
69 EXPECT_FALSE(GET_FUNCTION(L"ntdll.dll", ::TerminateProcess));
70
71 // Here it is!
72 EXPECT_TRUE(GET_FUNCTION(L"kernel32.dll", TerminateProcess));
73 EXPECT_TRUE(GET_FUNCTION(L"kernel32.dll", ::TerminateProcess));
74 }
75
76 } // namespace
77 } // namespace test
78 } // namespace crashpad
79