OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/environment.h" | 5 #include "base/environment.h" |
6 #include "base/files/file_path.h" | 6 #include "base/files/file_path.h" |
7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
8 #include "base/i18n/case_conversion.h" | 8 #include "base/i18n/case_conversion.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
10 #include "base/scoped_native_library.h" | 10 #include "base/scoped_native_library.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}"; | 27 const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}"; |
28 | 28 |
29 extern const wchar_t* kEnvVars[]; | 29 extern const wchar_t* kEnvVars[]; |
30 | 30 |
31 extern "C" { | 31 extern "C" { |
32 // When modifying the blacklist in the test process, use the exported test dll | 32 // When modifying the blacklist in the test process, use the exported test dll |
33 // functions on the test blacklist dll, not the ones linked into the test | 33 // functions on the test blacklist dll, not the ones linked into the test |
34 // executable itself. | 34 // executable itself. |
35 __declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist(); | 35 __declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist(); |
36 __declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name); | 36 __declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name); |
| 37 __declspec(dllimport) int TestDll_BlacklistSize(); |
| 38 __declspec(dllimport) void TestDll_BlockedDll(size_t blocked_index); |
| 39 __declspec(dllimport) int TestDll_GetBlacklistIndex(const wchar_t* dll_name); |
37 __declspec(dllimport) bool TestDll_IsBlacklistInitialized(); | 40 __declspec(dllimport) bool TestDll_IsBlacklistInitialized(); |
38 __declspec(dllimport) bool TestDll_RemoveDllFromBlacklist( | 41 __declspec(dllimport) bool TestDll_RemoveDllFromBlacklist( |
39 const wchar_t* dll_name); | 42 const wchar_t* dll_name); |
40 __declspec(dllimport) bool TestDll_SuccessfullyBlocked( | 43 __declspec(dllimport) bool TestDll_SuccessfullyBlocked( |
41 const wchar_t** blocked_dlls, | 44 const wchar_t** blocked_dlls, |
42 int* size); | 45 int* size); |
43 } | 46 } |
44 | 47 |
45 namespace { | 48 namespace { |
46 | 49 |
| 50 struct TestData { |
| 51 const wchar_t* dll_name; |
| 52 const wchar_t* dll_beacon; |
| 53 } test_data[] = { |
| 54 {kTestDllName2, kDll2Beacon}, |
| 55 {kTestDllName3, kDll3Beacon} |
| 56 }; |
| 57 |
47 class BlacklistTest : public testing::Test { | 58 class BlacklistTest : public testing::Test { |
48 protected: | 59 protected: |
49 BlacklistTest() : override_manager_() { | 60 BlacklistTest() : override_manager_(), num_initially_blocked_(0) { |
50 override_manager_.OverrideRegistry(HKEY_CURRENT_USER); | 61 override_manager_.OverrideRegistry(HKEY_CURRENT_USER); |
51 } | 62 } |
52 | 63 |
| 64 void CheckBlacklistedDllsNotLoaded() { |
| 65 base::FilePath current_dir; |
| 66 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); |
| 67 |
| 68 for (int i = 0; i < arraysize(test_data); ++i) { |
| 69 // Ensure that the dll has not been loaded both by inspecting the handle |
| 70 // returned by LoadLibrary and by looking for an environment variable that |
| 71 // is set when the DLL's entry point is called. |
| 72 base::ScopedNativeLibrary dll_blacklisted( |
| 73 current_dir.Append(test_data[i].dll_name)); |
| 74 EXPECT_FALSE(dll_blacklisted.is_valid()); |
| 75 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); |
| 76 dll_blacklisted.Reset(NULL); |
| 77 |
| 78 // Ensure that the dll is recorded as blocked. |
| 79 int array_size = 1 + num_initially_blocked_; |
| 80 std::vector<const wchar_t*> blocked_dlls(array_size); |
| 81 TestDll_SuccessfullyBlocked(&blocked_dlls[0], &array_size); |
| 82 EXPECT_EQ(1 + num_initially_blocked_, array_size); |
| 83 EXPECT_STREQ(test_data[i].dll_name, blocked_dlls[num_initially_blocked_]); |
| 84 |
| 85 // Remove the DLL from the blacklist. Ensure that it loads and that its |
| 86 // entry point was called. |
| 87 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name)); |
| 88 base::ScopedNativeLibrary dll(current_dir.Append(test_data[i].dll_name)); |
| 89 EXPECT_TRUE(dll.is_valid()); |
| 90 EXPECT_NE(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); |
| 91 dll.Reset(NULL); |
| 92 |
| 93 ::SetEnvironmentVariable(test_data[i].dll_beacon, NULL); |
| 94 |
| 95 // Ensure that the dll won't load even if the name has different |
| 96 // capitalization. |
| 97 base::string16 uppercase_name = |
| 98 base::i18n::ToUpper(test_data[i].dll_name); |
| 99 EXPECT_TRUE(TestDll_AddDllToBlacklist(uppercase_name.c_str())); |
| 100 base::ScopedNativeLibrary dll_blacklisted_different_case( |
| 101 current_dir.Append(test_data[i].dll_name)); |
| 102 EXPECT_FALSE(dll_blacklisted_different_case.is_valid()); |
| 103 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); |
| 104 dll_blacklisted_different_case.Reset(NULL); |
| 105 |
| 106 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str())); |
| 107 |
| 108 // The blocked dll was removed, so the number of blocked dlls should |
| 109 // return to what it originally was. |
| 110 int num_blocked_dlls = 0; |
| 111 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); |
| 112 EXPECT_EQ(num_initially_blocked_, num_blocked_dlls); |
| 113 } |
| 114 } |
| 115 |
53 scoped_ptr<base::win::RegKey> blacklist_registry_key_; | 116 scoped_ptr<base::win::RegKey> blacklist_registry_key_; |
54 registry_util::RegistryOverrideManager override_manager_; | 117 registry_util::RegistryOverrideManager override_manager_; |
55 | 118 |
| 119 // The number of dlls initially blocked by the blacklist. |
| 120 int num_initially_blocked_; |
| 121 |
56 private: | 122 private: |
57 virtual void SetUp() { | 123 virtual void SetUp() { |
58 // Force an import from blacklist_test_main_dll. | 124 // Force an import from blacklist_test_main_dll. |
59 InitBlacklistTestDll(); | 125 InitBlacklistTestDll(); |
60 blacklist_registry_key_.reset( | 126 blacklist_registry_key_.reset( |
61 new base::win::RegKey(HKEY_CURRENT_USER, | 127 new base::win::RegKey(HKEY_CURRENT_USER, |
62 blacklist::kRegistryBeaconPath, | 128 blacklist::kRegistryBeaconPath, |
63 KEY_QUERY_VALUE | KEY_SET_VALUE)); | 129 KEY_QUERY_VALUE | KEY_SET_VALUE)); |
| 130 |
| 131 // Find out how many dlls were blocked before the test starts. |
| 132 TestDll_SuccessfullyBlocked(NULL, &num_initially_blocked_); |
64 } | 133 } |
65 | 134 |
66 virtual void TearDown() { | 135 virtual void TearDown() { |
67 TestDll_RemoveDllFromBlacklist(kTestDllName1); | 136 TestDll_RemoveDllFromBlacklist(kTestDllName1); |
68 TestDll_RemoveDllFromBlacklist(kTestDllName2); | 137 TestDll_RemoveDllFromBlacklist(kTestDllName2); |
69 TestDll_RemoveDllFromBlacklist(kTestDllName3); | 138 TestDll_RemoveDllFromBlacklist(kTestDllName3); |
70 } | 139 } |
71 }; | 140 }; |
72 | 141 |
73 struct TestData { | |
74 const wchar_t* dll_name; | |
75 const wchar_t* dll_beacon; | |
76 } test_data[] = { | |
77 {kTestDllName2, kDll2Beacon}, | |
78 #if !defined(_WIN64) | |
79 // The third test dll is special in that it does not contain an export | |
80 // table. This prevents SafeGetImageInfo from extracting the name from there | |
81 // AND for some reason NtQueryVirtualMemory with MemorySectionName returns | |
82 // STATUS_ACCESS_VIOLATION in 64 bit builds for reasons still unknown. | |
83 // http://crbug.com/397137 | |
84 {kTestDllName3, kDll3Beacon} | |
85 #endif | |
86 }; | |
87 | |
88 TEST_F(BlacklistTest, Beacon) { | 142 TEST_F(BlacklistTest, Beacon) { |
89 // Ensure that the beacon state starts off 'running' for this version. | 143 // Ensure that the beacon state starts off 'running' for this version. |
90 LONG result = blacklist_registry_key_->WriteValue( | 144 LONG result = blacklist_registry_key_->WriteValue( |
91 blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING); | 145 blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING); |
92 EXPECT_EQ(ERROR_SUCCESS, result); | 146 EXPECT_EQ(ERROR_SUCCESS, result); |
93 | 147 |
94 result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, | 148 result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, |
95 TEXT(CHROME_VERSION_STRING)); | 149 TEXT(CHROME_VERSION_STRING)); |
96 EXPECT_EQ(ERROR_SUCCESS, result); | 150 EXPECT_EQ(ERROR_SUCCESS, result); |
97 | 151 |
98 // First call should find the beacon and reset it. | 152 // First call should find the beacon and reset it. |
99 EXPECT_TRUE(blacklist::ResetBeacon()); | 153 EXPECT_TRUE(blacklist::ResetBeacon()); |
100 | 154 |
101 // First call should succeed as the beacon is enabled. | 155 // First call should succeed as the beacon is enabled. |
102 EXPECT_TRUE(blacklist::LeaveSetupBeacon()); | 156 EXPECT_TRUE(blacklist::LeaveSetupBeacon()); |
103 } | 157 } |
104 | 158 |
105 TEST_F(BlacklistTest, AddAndRemoveModules) { | 159 TEST_F(BlacklistTest, AddAndRemoveModules) { |
106 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll")); | 160 EXPECT_TRUE(TestDll_AddDllToBlacklist(L"foo.dll")); |
107 // Adding the same item twice should be idempotent. | 161 // Adding the same item twice should be idempotent. |
108 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll")); | 162 EXPECT_TRUE(TestDll_AddDllToBlacklist(L"foo.dll")); |
109 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(L"foo.dll")); | 163 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(L"foo.dll")); |
110 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(L"foo.dll")); | 164 EXPECT_FALSE(TestDll_RemoveDllFromBlacklist(L"foo.dll")); |
111 | 165 |
112 // Increase the blacklist size by 1 to include the NULL pointer | 166 // Increase the blacklist size by 1 to include the NULL pointer |
113 // that marks the end. | 167 // that marks the end. |
114 int empty_spaces = blacklist::kTroublesomeDllsMaxCount - ( | 168 int empty_spaces = |
115 blacklist::BlacklistSize() + 1); | 169 blacklist::kTroublesomeDllsMaxCount - (TestDll_BlacklistSize() + 1); |
116 std::vector<base::string16> added_dlls; | 170 std::vector<base::string16> added_dlls; |
117 added_dlls.reserve(empty_spaces); | 171 added_dlls.reserve(empty_spaces); |
118 for (int i = 0; i < empty_spaces; ++i) { | 172 for (int i = 0; i < empty_spaces; ++i) { |
119 added_dlls.push_back(base::IntToString16(i) + L".dll"); | 173 added_dlls.push_back(base::IntToString16(i) + L".dll"); |
120 EXPECT_TRUE(blacklist::AddDllToBlacklist(added_dlls[i].c_str())) << i; | 174 EXPECT_TRUE(TestDll_AddDllToBlacklist(added_dlls[i].c_str())) << i; |
121 } | 175 } |
122 EXPECT_FALSE(blacklist::AddDllToBlacklist(L"overflow.dll")); | 176 EXPECT_FALSE(TestDll_AddDllToBlacklist(L"overflow.dll")); |
123 for (int i = 0; i < empty_spaces; ++i) { | 177 for (int i = 0; i < empty_spaces; ++i) { |
124 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(added_dlls[i].c_str())) << i; | 178 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(added_dlls[i].c_str())) << i; |
125 } | 179 } |
126 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(added_dlls[0].c_str())); | 180 EXPECT_FALSE(TestDll_RemoveDllFromBlacklist(added_dlls[0].c_str())); |
127 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist( | 181 EXPECT_FALSE( |
128 added_dlls[empty_spaces - 1].c_str())); | 182 TestDll_RemoveDllFromBlacklist(added_dlls[empty_spaces - 1].c_str())); |
129 } | 183 } |
130 | 184 |
131 TEST_F(BlacklistTest, SuccessfullyBlocked) { | 185 TEST_F(BlacklistTest, SuccessfullyBlocked) { |
132 // Ensure that we have at least 5 dlls to blacklist. | 186 // Add 5 news dlls to blacklist. |
133 int blacklist_size = blacklist::BlacklistSize(); | 187 const int kDesiredBlacklistSize = 1; |
134 const int kDesiredBlacklistSize = 5; | 188 std::vector<base::string16> dlls_to_block; |
135 for (int i = blacklist_size; i < kDesiredBlacklistSize; ++i) { | 189 for (int i = 0; i < kDesiredBlacklistSize; ++i) { |
136 base::string16 new_dll_name(base::IntToString16(i) + L".dll"); | 190 dlls_to_block.push_back(base::IntToString16(i) + L".dll"); |
137 EXPECT_TRUE(blacklist::AddDllToBlacklist(new_dll_name.c_str())); | 191 ASSERT_TRUE(TestDll_AddDllToBlacklist(dlls_to_block[i].c_str())); |
138 } | 192 } |
139 | 193 |
140 // Block 5 dlls, one at a time, starting from the end of the list, and | 194 // Block the dlls, one at a time, and ensure SuccesfullyBlocked correctly |
141 // ensuring SuccesfullyBlocked correctly passes the list of blocked dlls. | 195 // passes the list of blocked dlls. |
142 for (int i = 0; i < kDesiredBlacklistSize; ++i) { | 196 for (int i = 0; i < kDesiredBlacklistSize; ++i) { |
143 blacklist::BlockedDll(i); | 197 TestDll_BlockedDll(TestDll_GetBlacklistIndex(dlls_to_block[i].c_str())); |
144 | 198 |
145 int size = 0; | 199 int size = 0; |
146 blacklist::SuccessfullyBlocked(NULL, &size); | 200 TestDll_SuccessfullyBlocked(NULL, &size); |
147 EXPECT_EQ(i + 1, size); | 201 ASSERT_EQ(num_initially_blocked_ + i + 1, size); |
148 | 202 |
149 std::vector<const wchar_t*> blocked_dlls(size); | 203 std::vector<const wchar_t*> blocked_dlls(size); |
150 blacklist::SuccessfullyBlocked(&(blocked_dlls[0]), &size); | 204 TestDll_SuccessfullyBlocked(&(blocked_dlls[0]), &size); |
151 EXPECT_EQ(i + 1, size); | 205 ASSERT_EQ(num_initially_blocked_ + i + 1, size); |
152 | 206 |
153 for (size_t j = 0; j < blocked_dlls.size(); ++j) { | 207 for (int j = 0; j <= i; ++j) { |
154 EXPECT_EQ(blocked_dlls[j], blacklist::g_troublesome_dlls[j]); | 208 EXPECT_STREQ(blocked_dlls[num_initially_blocked_ + j], |
| 209 dlls_to_block[j].c_str()); |
155 } | 210 } |
156 } | 211 } |
| 212 |
| 213 // Remove the dlls from the blacklist now that we are done. |
| 214 for (const auto& dll : dlls_to_block) { |
| 215 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(dll.c_str())); |
| 216 } |
157 } | 217 } |
158 | 218 |
159 void CheckBlacklistedDllsNotLoaded() { | |
160 base::FilePath current_dir; | |
161 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); | |
162 | |
163 for (int i = 0; i < arraysize(test_data); ++i) { | |
164 // Ensure that the dll has not been loaded both by inspecting the handle | |
165 // returned by LoadLibrary and by looking for an environment variable that | |
166 // is set when the DLL's entry point is called. | |
167 base::ScopedNativeLibrary dll_blacklisted( | |
168 current_dir.Append(test_data[i].dll_name)); | |
169 EXPECT_FALSE(dll_blacklisted.is_valid()); | |
170 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); | |
171 dll_blacklisted.Reset(NULL); | |
172 | |
173 // Ensure that the dll is recorded as blocked. | |
174 int array_size = 1; | |
175 const wchar_t* blocked_dll = NULL; | |
176 TestDll_SuccessfullyBlocked(&blocked_dll, &array_size); | |
177 EXPECT_EQ(1, array_size); | |
178 EXPECT_EQ(test_data[i].dll_name, base::string16(blocked_dll)); | |
179 | |
180 // Remove the DLL from the blacklist. Ensure that it loads and that its | |
181 // entry point was called. | |
182 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name)); | |
183 base::ScopedNativeLibrary dll(current_dir.Append(test_data[i].dll_name)); | |
184 EXPECT_TRUE(dll.is_valid()); | |
185 EXPECT_NE(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); | |
186 dll.Reset(NULL); | |
187 | |
188 ::SetEnvironmentVariable(test_data[i].dll_beacon, NULL); | |
189 | |
190 // Ensure that the dll won't load even if the name has different | |
191 // capitalization. | |
192 base::string16 uppercase_name = base::i18n::ToUpper(test_data[i].dll_name); | |
193 EXPECT_TRUE(TestDll_AddDllToBlacklist(uppercase_name.c_str())); | |
194 base::ScopedNativeLibrary dll_blacklisted_different_case( | |
195 current_dir.Append(test_data[i].dll_name)); | |
196 EXPECT_FALSE(dll_blacklisted_different_case.is_valid()); | |
197 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); | |
198 dll_blacklisted_different_case.Reset(NULL); | |
199 | |
200 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str())); | |
201 | |
202 // The blocked dll was removed, so we shouldn't get anything returned | |
203 // here. | |
204 int num_blocked_dlls = 0; | |
205 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); | |
206 EXPECT_EQ(0, num_blocked_dlls); | |
207 } | |
208 } | |
209 | |
210 TEST_F(BlacklistTest, LoadBlacklistedLibrary) { | 219 TEST_F(BlacklistTest, LoadBlacklistedLibrary) { |
211 base::FilePath current_dir; | 220 base::FilePath current_dir; |
212 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); | 221 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); |
213 | 222 |
214 // Ensure that the blacklist is loaded. | 223 // Ensure that the blacklist is loaded. |
215 ASSERT_TRUE(TestDll_IsBlacklistInitialized()); | 224 ASSERT_TRUE(TestDll_IsBlacklistInitialized()); |
216 | 225 |
217 // Test that an un-blacklisted DLL can load correctly. | 226 // Test that an un-blacklisted DLL can load correctly. |
218 base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1)); | 227 base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1)); |
219 EXPECT_TRUE(dll1.is_valid()); | 228 EXPECT_TRUE(dll1.is_valid()); |
220 dll1.Reset(NULL); | 229 dll1.Reset(NULL); |
221 | 230 |
222 int num_blocked_dlls = 0; | 231 int num_blocked_dlls = 0; |
223 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); | 232 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); |
224 EXPECT_EQ(0, num_blocked_dlls); | 233 EXPECT_EQ(num_initially_blocked_, num_blocked_dlls); |
225 | 234 |
226 // Add all DLLs to the blacklist then check they are blocked. | 235 // Add all DLLs to the blacklist then check they are blocked. |
227 for (int i = 0; i < arraysize(test_data); ++i) { | 236 for (int i = 0; i < arraysize(test_data); ++i) { |
228 EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name)); | 237 EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name)); |
229 } | 238 } |
230 CheckBlacklistedDllsNotLoaded(); | 239 CheckBlacklistedDllsNotLoaded(); |
231 } | 240 } |
232 | 241 |
233 TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) { | 242 TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) { |
234 // Ensure that the blacklist is loaded. | 243 // Ensure that the blacklist is loaded. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 &blacklist_state); | 336 &blacklist_state); |
328 EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_RUNNING); | 337 EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_RUNNING); |
329 | 338 |
330 DWORD attempt_count = blacklist::kBeaconMaxAttempts; | 339 DWORD attempt_count = blacklist::kBeaconMaxAttempts; |
331 blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount, | 340 blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount, |
332 &attempt_count); | 341 &attempt_count); |
333 EXPECT_EQ(static_cast<DWORD>(0), attempt_count); | 342 EXPECT_EQ(static_cast<DWORD>(0), attempt_count); |
334 } | 343 } |
335 | 344 |
336 } // namespace | 345 } // namespace |
OLD | NEW |