1 // Copyright 2018 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/chrome_cleaner/os/disk_util.h"
6 
7 #include <windows.h>
8 
9 #include <shlobj.h>
10 
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/files/file.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/logging.h"
19 #include "base/path_service.h"
20 #include "base/process/launch.h"
21 #include "base/stl_util.h"
22 #include "base/strings/strcat.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/test/scoped_path_override.h"
27 #include "base/test/test_shortcut_win.h"
28 #include "base/test/test_timeouts.h"
29 #include "base/unguessable_token.h"
30 #include "base/win/windows_version.h"
31 #include "chrome/chrome_cleaner/os/file_path_sanitization.h"
32 #include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
33 #include "chrome/chrome_cleaner/os/system_util_cleaner.h"
34 #include "chrome/chrome_cleaner/strings/string_util.h"
35 #include "chrome/chrome_cleaner/test/test_executables.h"
36 #include "chrome/chrome_cleaner/test/test_file_util.h"
37 #include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
38 #include "chrome/chrome_cleaner/test/test_strings.h"
39 #include "chrome/chrome_cleaner/test/test_util.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42 
43 namespace chrome_cleaner {
44 
45 namespace {
46 
47 // A path name under program files.
48 const wchar_t kProgramFilesBaseName[] = L"Foo";
49 
50 // Keep these digests in sorted order.
51 const char* const kFileContentDigests[] = {
52     "02544E052F29BBA79C81243EC63B43B6CD85B185461928E65BFF501346C62A75",
53     "04614470DDF4939091F5EC4A13C92A9EAAACF07CA5C3F713E792E2D21CD24075",
54     // Hash for content: |kFileContent2|.
55     "82E0B92772BC0DA59AAB0B9231AA006FB37B4F99EC3E853C5A62786A1C7215BD",
56     "94F7BDF53CDFDE7AA5E5C90BCDA6793B7377CE39E2591ABC758EBAE8072A275C",
57     // Hash for content: |kFileContent1|.
58     "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371"};
59 
60 const wchar_t kFileName1[] = L"Filename one";
61 const wchar_t kFileName2[] = L"Filename two";
62 const wchar_t kFileName3[] = L"Third filename";
63 const wchar_t kLongFileName1[] = L"Long File Name.bla";
64 const wchar_t kLongFileName2[] = L"Other Long File Name.bla";
65 const char kFileContent1[] = "This is the file content.";
66 const char kFileContent2[] = "Hi!";
67 const char kFileContent3[] = "Hello World!";
68 
69 const internal::FileInformation kFileInformation1(L"some/path/something.tmp",
70                                                   "3/1/2016",
71                                                   "3/3/2016",
72                                                   "somedigest1234",
73                                                   9876,
74                                                   L"Company Name",
75                                                   L"CNShort",
76                                                   L"Product Name",
77                                                   L"PNShort",
78                                                   L"Internal Name",
79                                                   L"Something_Original.tmp",
80                                                   L"Very descriptive",
81                                                   L"42.1.2");
82 
83 const wchar_t kFileInformation1ExpectedString[] =
84     L"path = 'some/path/something.tmp', file_creation_date = "
85     L"'3/1/2016', file_last_modified_date = '3/3/2016', digest = "
86     L"'somedigest1234', size = '9876', company_name = 'Company Name', "
87     L"company_short_name = 'CNShort', product_name = 'Product Name', "
88     L"product_short_name = 'PNShort', internal_name = 'Internal Name', "
89     L"original_filename = 'Something_Original.tmp', file_description = 'Very "
90     L"descriptive', file_version = '42.1.2', active_file = '0'";
91 
92 // All potential format of content that get from registry. %ls will be replaced
93 // by the executable path.
94 // clang-format off
95 const wchar_t* kMockRegistryContents[] = {
96     // Straight path as is.
97     L"%ls",
98     L"\"%ls\"",
99     // With command line arguments.
100     L"%ls -s",
101     L"\"%ls\" -s",
102     L"\"%ls -s\"",
103     // Using rundll.
104     L"C:\\Windows\\SysWow64\\rundll32 %ls",
105     L"C:\\Windows\\SysWow64\\rundll32 \"%ls\"",
106     // Using rundll with args.
107     L"C:\\Windows\\SysWow64\\rundll32.exe %ls,OpenAs_RunDLL %%1",
108     L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\",OpenAs_RunDLL %%1",
109     L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls,OpenAs_RunDLL\" %%1",
110     L"C:\\Windows\\SysWow64\\rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
111     L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\" a1,OpenAs_RunDLL %%1",
112     L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls a1,OpenAs_RunDLL\" %%1",
113     L"C:\\Windows\\System32\\rundll32 %ls",
114     // Rundll without a path.
115     L"rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
116     L"rundll32.exe \"%ls\" -s %%1",
117     L"rundll32.exe \"%ls -s\" %%1",
118     // Rundll without extension.
119     L"C:\\Windows\\SysWow64\\rundll32 %ls a1 a2,OpenAs_RunDLL %%1",
120     L"C:\\Windows\\SysWow64\\rundll32 \"%ls\" -s %%1",
121     L"C:\\Windows\\SysWow64\\rundll32 \"%ls -s\" %%1"};
122 // clang-format on
123 
LaunchTestProcess(const wchar_t * executable,const char * action,bool wait)124 bool LaunchTestProcess(const wchar_t* executable,
125                        const char* action,
126                        bool wait) {
127   base::FilePath executable_path(executable);
128   base::CommandLine command_line(executable_path);
129   command_line.AppendSwitch(action);
130   base::LaunchOptions options = base::LaunchOptions();
131   options.wait = wait;
132   return base::LaunchProcess(command_line, options).IsValid();
133 }
134 
DoesVolumeSupportNamedStreams(const base::FilePath & path)135 bool DoesVolumeSupportNamedStreams(const base::FilePath& path) {
136   std::vector<std::wstring> components;
137   path.GetComponents(&components);
138   DCHECK(!components.empty());
139   std::wstring& drive = components[0];
140   drive += L'\\';
141   DWORD system_flags = 0;
142   if (::GetVolumeInformation(drive.c_str(), nullptr, 0, nullptr, nullptr,
143                              &system_flags, nullptr, 0) != TRUE) {
144     PLOG(ERROR) << "Cannot retrieve drive information: '" << path.value()
145                 << "'.";
146     return false;
147   }
148 
149   return (system_flags & FILE_NAMED_STREAMS) != 0;
150 }
151 
CreateProgramPathsAndFiles(const base::FilePath & temp_dir_path,base::FilePath * program_path,base::FilePath * spaced_program_path)152 void CreateProgramPathsAndFiles(const base::FilePath& temp_dir_path,
153                                 base::FilePath* program_path,
154                                 base::FilePath* spaced_program_path) {
155   DCHECK(program_path);
156   DCHECK(spaced_program_path);
157   base::FilePath folder;
158   base::FilePath file_path;
159   base::FilePath spaced_folder;
160   base::FilePath spaced_file_path;
161 
162   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"folder", &folder));
163   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"  spaced folder",
164                                             &spaced_folder));
165 
166   ASSERT_TRUE(CreateTemporaryFileInDir(folder, &file_path));
167   ASSERT_TRUE(CreateTemporaryFileInDir(spaced_folder, &spaced_file_path));
168 
169   *program_path = file_path;
170   *spaced_program_path = spaced_file_path;
171 }
172 
173 // Substitutes |registry_path| into each entry in the mock registry in turn
174 // and passes the result to ExtractExecutablePathFromRegistryContent to get a
175 // file path. Returns success if every file path matches |expected_path|.
ExtractExecutablePathFromMockRegistryAndExpect(const std::wstring & registry_path,const base::FilePath & expected_path)176 ::testing::AssertionResult ExtractExecutablePathFromMockRegistryAndExpect(
177     const std::wstring& registry_path,
178     const base::FilePath& expected_path) {
179   for (const std::wstring& registry_content : kMockRegistryContents) {
180     std::wstring full_registry_content =
181         base::StringPrintf(registry_content.c_str(), registry_path.c_str());
182     base::FilePath extracted_path =
183         ExtractExecutablePathFromRegistryContent(full_registry_content);
184     if (!PathEqual(expected_path, extracted_path)) {
185       return ::testing::AssertionFailure()
186              << expected_path.value() << " != " << extracted_path.value()
187              << ", full_registry_content = " << full_registry_content;
188     }
189   }
190   return ::testing::AssertionSuccess();
191 }
192 
193 // Return that the sample DLL is whitelisted and all other files are not.
WhitelistSampleDLL(const base::FilePath & path)194 bool WhitelistSampleDLL(const base::FilePath& path) {
195   return PathEqual(path, GetSampleDLLPath());
196 }
197 
198 }  // namespace
199 
TEST(DiskUtilTests,GetX64ProgramFilePath)200 TEST(DiskUtilTests, GetX64ProgramFilePath) {
201   base::FilePath x64_program_files =
202       GetX64ProgramFilesPath(base::FilePath(kProgramFilesBaseName));
203   if (base::win::OSInfo::GetArchitecture() ==
204       base::win::OSInfo::X86_ARCHITECTURE) {
205     EXPECT_TRUE(x64_program_files.empty());
206     return;
207   }
208 
209   EXPECT_FALSE(x64_program_files.empty());
210   EXPECT_NE(x64_program_files,
211             ExpandSpecialFolderPath(CSIDL_PROGRAM_FILES,
212                                     base::FilePath(kProgramFilesBaseName)));
213 }
214 
TEST(DiskUtilTests,PathContainsWildcards)215 TEST(DiskUtilTests, PathContainsWildcards) {
216   EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\foo.txt")));
217   EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\bar\\foo.txt")));
218   EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t?t")));
219   EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t*t")));
220   EXPECT_TRUE(
221       PathContainsWildcards(base::FilePath(L"c:\\"
222                                            LR"(???)"
223                                            L"*\\foo.txt")));
224   EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"*:\\")));
225   EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"foo.txt")));
226   EXPECT_TRUE(PathContainsWildcards(base::FilePath(LR"(foo.???)")));
227 }
228 
TEST(DiskUtilTests,CollectMatchingPathsMultipleWildcards)229 TEST(DiskUtilTests, CollectMatchingPathsMultipleWildcards) {
230   base::ScopedTempDir temp_dir;
231   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
232 
233   // Create files and folders under |temp_dir| and add them to |expected_files|.
234   std::set<base::FilePath> expected_files;
235 
236   base::ScopedTempDir sub_dir1;
237   ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
238 
239   base::ScopedTempDir sub_dir2;
240   ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
241 
242   base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
243   base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
244   ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
245 
246   base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
247   base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
248   ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
249 
250   base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
251   base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
252   ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
253 
254   base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
255   base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
256   ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
257 
258   base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
259   base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
260   ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
261 
262   expected_files.insert(sub_dir1_file_path1);
263   expected_files.insert(sub_dir1_file_path2);
264   expected_files.insert(sub_dir2_file_path1);
265   expected_files.insert(sub_dir2_file_path2);
266 
267   base::FilePath wildcard_path1(
268       temp_dir.GetPath().Append(L"*").Append(L"Filename*"));
269   std::vector<base::FilePath> matches;
270   CollectMatchingPaths(wildcard_path1, &matches);
271   EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
272 }
273 
TEST(DiskUtilTests,CollectMatchingPathsDriveWildcard)274 TEST(DiskUtilTests, CollectMatchingPathsDriveWildcard) {
275   std::vector<base::FilePath> matches;
276 
277   // The drive could not be enumerated, thus no file will exists..
278   base::FilePath wildcard_path1(L"*:\\test");
279   CollectMatchingPaths(wildcard_path1, &matches);
280   EXPECT_TRUE(matches.empty());
281 
282   base::FilePath wildcard_path2(L"*:\\");
283   CollectMatchingPaths(wildcard_path2, &matches);
284   EXPECT_TRUE(matches.empty());
285 }
286 
TEST(DiskUtilTests,CollectMatchingPathsDirectoryWildcard)287 TEST(DiskUtilTests, CollectMatchingPathsDirectoryWildcard) {
288   base::ScopedTempDir temp_dir;
289   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
290 
291   // Create files and folders under |temp_dir| and add them to |expected_files|.
292   std::set<base::FilePath> expected_files;
293 
294   base::ScopedTempDir sub_dir1;
295   ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
296 
297   base::ScopedTempDir sub_dir2;
298   ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
299 
300   base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
301   base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
302   ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
303 
304   base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
305   base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
306   ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
307 
308   base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
309   base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
310   ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
311 
312   base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
313   base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
314   ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
315 
316   base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
317   base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
318   ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
319 
320   expected_files.insert(sub_dir1_file_path1);
321   expected_files.insert(sub_dir2_file_path1);
322   base::FilePath wildcard_path3(
323       temp_dir.GetPath().Append(L"*").Append(kFileName1));
324   std::vector<base::FilePath> matches;
325   CollectMatchingPaths(wildcard_path3, &matches);
326   EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
327 }
328 
TEST(DiskUtilTests,CollectMatchingPathsMultipleFileWildcards)329 TEST(DiskUtilTests, CollectMatchingPathsMultipleFileWildcards) {
330   base::ScopedTempDir temp_dir;
331   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
332 
333   base::ScopedTempDir sub_dir1;
334   ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
335 
336   base::ScopedTempDir sub_dir2;
337   ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
338 
339   base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
340   base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
341   ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
342 
343   base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
344   base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
345   ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
346 
347   base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
348   base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
349   ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
350 
351   base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
352   base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
353   ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
354 
355   base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
356   base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
357   ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
358 
359   // Create files and folders under |temp_dir| and add them to |expected_files|.
360   std::set<base::FilePath> expected_files;
361   expected_files.insert(sub_dir1_file_path3);
362   base::FilePath wildcard_path4(
363       temp_dir.GetPath().Append(L"*").Append(L"*Third*"));
364   std::vector<base::FilePath> matches;
365   CollectMatchingPaths(wildcard_path4, &matches);
366   EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
367 }
368 
TEST(DiskUtilTests,CollectMatchingPathsNoWildcards)369 TEST(DiskUtilTests, CollectMatchingPathsNoWildcards) {
370   base::ScopedTempDir temp_dir;
371   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
372 
373   base::ScopedTempDir sub_dir;
374   ASSERT_TRUE(sub_dir.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
375 
376   base::FilePath sub_dir_file_path1(sub_dir.GetPath().Append(kFileName1));
377   base::File sub_dir_file1(sub_dir_file_path1, base::File::FLAG_CREATE);
378   ASSERT_TRUE(base::PathExists(sub_dir_file_path1));
379 
380   base::FilePath sub_dir_file_path2(sub_dir.GetPath().Append(kFileName2));
381   base::File sub_dir_file2(sub_dir_file_path2, base::File::FLAG_CREATE);
382   ASSERT_TRUE(base::PathExists(sub_dir_file_path2));
383 
384   base::FilePath sub_dir_file_path3(sub_dir.GetPath().Append(kFileName3));
385   base::File sub_dir_file3(sub_dir_file_path3, base::File::FLAG_CREATE);
386   ASSERT_TRUE(base::PathExists(sub_dir_file_path3));
387 
388   // Create files and folders under |temp_dir| and add them to |expected_files|.
389   std::vector<base::FilePath> matches;
390 
391   base::FilePath no_wildcard_path(sub_dir.GetPath());
392   CollectMatchingPaths(no_wildcard_path, &matches);
393   EXPECT_EQ(1UL, matches.size());
394   EXPECT_TRUE(base::Contains(matches, sub_dir.GetPath()));
395 }
396 
TEST(DiskUtilTests,CollectExecutableMatchingPaths)397 TEST(DiskUtilTests, CollectExecutableMatchingPaths) {
398   base::ScopedTempDir temp_dir;
399   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
400 
401   base::FilePath subfolder1_path;
402   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
403                                             &subfolder1_path));
404 
405   base::FilePath subfolder2_path;
406   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
407                                             &subfolder2_path));
408 
409   base::FilePath subfolder3_path(subfolder2_path.Append(L"folder.exe"));
410   ASSERT_TRUE(base::CreateDirectory(subfolder3_path));
411 
412   base::FilePath file_path1(subfolder1_path.Append(L"dummy1.exe"));
413   base::FilePath file_path2(subfolder1_path.Append(L"dummy2.exe"));
414   base::FilePath file_path3(subfolder2_path.Append(L"dummy3.exe"));
415   base::FilePath file_path4(subfolder2_path.Append(L"dummy4.exe"));
416   base::FilePath file_path5(subfolder2_path.Append(L"info.exe.txt"));
417   base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
418 
419   CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
420   CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
421   CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
422   CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
423   CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
424   CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
425 
426   base::FilePath wildcard_path(temp_dir.GetPath().Append(L"*\\*.exe"));
427   std::vector<base::FilePath> executable_matches;
428   CollectMatchingPaths(wildcard_path, &executable_matches);
429 
430   EXPECT_THAT(executable_matches,
431               testing::ElementsAre(file_path1, file_path2, file_path3,
432                                    file_path4, subfolder3_path));
433 }
434 
TEST(DiskUtilTests,CollectMultipleDotWildcardsMatchingPaths)435 TEST(DiskUtilTests, CollectMultipleDotWildcardsMatchingPaths) {
436   base::ScopedTempDir temp_dir;
437   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
438 
439   base::FilePath subfolder1_path;
440   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
441                                             &subfolder1_path));
442 
443   base::FilePath subfolder2_path;
444   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
445                                             &subfolder2_path));
446 
447   base::FilePath subfolder3_path;
448   ASSERT_TRUE(base::CreateTemporaryDirInDir(subfolder2_path, L"folder.exe",
449                                             &subfolder3_path));
450 
451   base::FilePath file_path1(subfolder1_path.Append(L"dummy1.tar.gz"));
452   base::FilePath file_path2(subfolder1_path.Append(L"dummy2.12.exe"));
453   base::FilePath file_path3(subfolder2_path.Append(L"dummy3.tar.gz"));
454   base::FilePath file_path4(subfolder2_path.Append(L"dummy4.12.exe"));
455   base::FilePath file_path5(subfolder2_path.Append(L"info.tar.gz.txt"));
456   base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
457 
458   CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
459   CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
460   CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
461   CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
462   CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
463   CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
464 
465   base::FilePath wildcard_path_tar_gz(
466       temp_dir.GetPath().Append(L"*\\*.tar.gz"));
467   std::vector<base::FilePath> executable_matches_tar_gz;
468   CollectMatchingPaths(wildcard_path_tar_gz, &executable_matches_tar_gz);
469 
470   EXPECT_THAT(executable_matches_tar_gz,
471               testing::ElementsAre(file_path1, file_path3));
472 
473   base::FilePath wildcard_path_all(temp_dir.GetPath().Append(L"*\\*.*.*"));
474   std::vector<base::FilePath> executable_matches_all;
475   CollectMatchingPaths(wildcard_path_all, &executable_matches_all);
476 
477   EXPECT_THAT(executable_matches_all,
478               testing::ElementsAre(file_path1, file_path2, file_path3,
479                                    file_path4, file_path5));
480 }
481 
TEST(DiskUtilTests,CollectEmptyDirMatchingPaths)482 TEST(DiskUtilTests, CollectEmptyDirMatchingPaths) {
483   base::ScopedTempDir temp_dir;
484   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
485 
486   base::FilePath subfolder1_path;
487   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
488                                             &subfolder1_path));
489 
490   base::FilePath subfolder2_path;
491   ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
492                                             &subfolder2_path));
493 
494   base::FilePath wildcard_path1(temp_dir.GetPath().Append(L"*\\dummy.exe"));
495   std::vector<base::FilePath> executable_matches;
496   CollectMatchingPaths(wildcard_path1, &executable_matches);
497   EXPECT_TRUE(executable_matches.empty());
498 }
499 
TEST(DiskUtilTests,CollectCumulativeMatchingPaths)500 TEST(DiskUtilTests, CollectCumulativeMatchingPaths) {
501   base::ScopedTempDir temp_dir;
502   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
503 
504   base::ScopedTempDir sub_dir1;
505   ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
506 
507   // Create files and folders under |sub_dirX| and add them to |expected_files|.
508   std::set<base::FilePath> expected_files;
509   base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
510   base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
511   ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
512   expected_files.insert(sub_dir1_file_path1);
513 
514   base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
515   base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
516   ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
517   expected_files.insert(sub_dir1_file_path2);
518 
519   base::ScopedTempDir sub_dir2;
520   ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
521 
522   base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
523   base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
524   ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
525   expected_files.insert(sub_dir2_file_path1);
526 
527   base::FilePath wildcard_path1(sub_dir1.GetPath().Append(L"*"));
528   std::vector<base::FilePath> matches;
529   CollectMatchingPaths(wildcard_path1, &matches);
530   base::FilePath wildcard_path2(sub_dir2.GetPath().Append(L"*"));
531   CollectMatchingPaths(wildcard_path2, &matches);
532   EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
533 }
534 
TEST(DiskUtilTests,PathHasActiveExtension)535 TEST(DiskUtilTests, PathHasActiveExtension) {
536   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe")));
537   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe  ")));
538   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg.exe")));
539   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.lnk")));
540   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file")));
541   EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\file.lnk::$DATA")));
542 
543   EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.wvm")));
544   EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg")));
545   EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg ")));
546   EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\file.txt::$DATA")));
547 }
548 
TEST(DiskUtilTests,ExpandEnvPath)549 TEST(DiskUtilTests, ExpandEnvPath) {
550   ASSERT_TRUE(
551       ::SetEnvironmentVariable(L"CLEANER_TEST_VAR", L"CLEANER_TEST_VALUE"));
552   ASSERT_TRUE(::SetEnvironmentVariable(L"ROOT_TEST_VAR", L"c:\\root"));
553   base::FilePath test_path1(L"C:\\%CLEANER_TEST_VAR%\\test\\foo");
554   base::FilePath test_path2(L"%ROOT_TEST_VAR%\\test\\foo");
555   base::FilePath test_path3(
556       L"C:\\aa%CLEANER_TEST_VAR%bb\\test\\%%CLEANER_TEST_VAR%%");
557 
558   base::FilePath expanded_path;
559   ExpandEnvPath(test_path1, &expanded_path);
560   EXPECT_EQ(L"C:\\CLEANER_TEST_VALUE\\test\\foo", expanded_path.value());
561 
562   ExpandEnvPath(test_path2, &expanded_path);
563   EXPECT_EQ(L"c:\\root\\test\\foo", expanded_path.value());
564 
565   ExpandEnvPath(test_path3, &expanded_path);
566   EXPECT_EQ(L"C:\\aaCLEANER_TEST_VALUEbb\\test\\%CLEANER_TEST_VALUE%",
567             expanded_path.value());
568 }
569 
TEST(DiskUtilTests,ExpandWow64Path)570 TEST(DiskUtilTests, ExpandWow64Path) {
571   base::ScopedPathOverride windows_override(
572       CsidlToPathServiceKey(CSIDL_WINDOWS));
573   base::FilePath windows_folder;
574   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_WINDOWS),
575                                      &windows_folder));
576 
577   base::FilePath system_folder(windows_folder.Append(L"system32"));
578   base::ScopedPathOverride system_override(CsidlToPathServiceKey(CSIDL_SYSTEM),
579                                            system_folder, true, true);
580 
581   base::FilePath native_folder(windows_folder.Append(L"sysnative"));
582   ASSERT_TRUE(base::CreateDirectory(native_folder));
583 
584   base::FilePath file_path1(system_folder.Append(kFileName1));
585   base::FilePath file_path2(native_folder.Append(kFileName2));
586   base::FilePath file_path3_system(system_folder.Append(kFileName3));
587   base::FilePath file_path3_native(native_folder.Append(kFileName3));
588   CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
589   CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
590   CreateFileWithContent(file_path3_system, kFileContent3,
591                         sizeof(kFileContent3));
592   CreateFileWithContent(file_path3_native, kFileContent3,
593                         sizeof(kFileContent3));
594 
595   base::FilePath expanded_file1;
596   ExpandWow64Path(file_path1, &expanded_file1);
597   ASSERT_TRUE(PathEqual(expanded_file1, file_path1));
598 
599   base::FilePath expanded_file2;
600   ExpandWow64Path(file_path2, &expanded_file2);
601   ASSERT_TRUE(PathEqual(expanded_file2, file_path2));
602 
603   base::FilePath expanded_file3;
604   ExpandWow64Path(file_path3_system, &expanded_file3);
605   ASSERT_TRUE(PathEqual(expanded_file3, file_path3_native));
606 }
607 
TEST(DiskUtilTests,ComputeSHA256DigestOfPath)608 TEST(DiskUtilTests, ComputeSHA256DigestOfPath) {
609   base::ScopedTempDir temp_dir;
610   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
611 
612   // Check the digest of an non-existing file.
613   base::FilePath file_path1(temp_dir.GetPath().Append(kFileName1));
614   std::string digest1;
615   EXPECT_FALSE(ComputeSHA256DigestOfPath(file_path1, &digest1));
616   EXPECT_TRUE(digest1.empty());
617 
618   // Create an empty file and validate the digest.
619   base::FilePath file_path2(temp_dir.GetPath().Append(kFileName2));
620   base::File empty_file(file_path2, base::File::FLAG_CREATE);
621   empty_file.Close();
622 
623   std::string digest2;
624   EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path2, &digest2));
625   EXPECT_STREQ(
626       "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
627       digest2.c_str());
628 
629   // Create a file with some content and validate the digest.
630   base::FilePath file_path3(temp_dir.GetPath().Append(kFileName3));
631   base::File valid_file(
632       file_path3, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
633   ASSERT_EQ(sizeof(kFileContent),
634             static_cast<size_t>(valid_file.WriteAtCurrentPos(
635                 kFileContent, sizeof(kFileContent))));
636   valid_file.Close();
637 
638   std::string digest3;
639   EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path3, &digest3));
640   EXPECT_STREQ(
641       "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371",
642       digest3.c_str());
643 }
644 
TEST(DiskUtilTests,ComputeSHA256DigestOfPathOnBigFile)645 TEST(DiskUtilTests, ComputeSHA256DigestOfPathOnBigFile) {
646   base::ScopedTempDir temp_dir;
647   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
648 
649   struct DigestInfo {
650     size_t size;
651     const char* digest;
652   } digests[] = {
653       {1, "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"},
654       {2, "FB8E20FC2E4C3F248C60C39BD652F3C1347298BB977B8B4D5903B85055620603"},
655       {3, "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"},
656       {100, "2AC123DCD759EEBABFA1B17C0332B88B3815EF3F95FBFCCEB5FAC07E233235BD"},
657       {128, "6C05BE2C4268843AE47E68E611277CE62C02153F2F4D2E1E2A1A4B44F766CF74"},
658       {1000,
659        "915E53A44C18B19BB06BA5B3F5FCAF1DC4651E8404C63425CFC6174E74659D87"},
660       {1023,
661        "6A6EE128AAC6B98D2697EED0A912AE264603D046B3CBFD5E7EA1D01C865474D9"},
662       {1024,
663        "DBA4A6315B76548B7A4DD079EF6AA29A7B34FA8B92C11668473441715C5F0AF5"},
664       {1025,
665        "2B4B65474580781B4DC0AB66B9A0F39B869DE5A44CF26DBA22AC0496760D4230"},
666       {4095,
667        "7413609B553226A9A8A3203A82062111DC1F98C24163E303774F27E4F615BFB2"},
668       {4096,
669        "BC45051AC426475F459EC0B0C88A6646D037B8DFB1B9FA3CA3EF9203CE33E283"},
670       {4097,
671        "A9145EB3812CA8F11A014029FEE1854FABB76D2FFEA680D0875F78FA786F58B8"},
672       {10000,
673        "5B92F844F0ED521B75688F4B6FF58E127711709613589EB6EC88FDFBBDC7DC63"}};
674 
675   for (size_t offset = 0; offset < base::size(digests); ++offset) {
676     DigestInfo* info = &digests[offset];
677     DCHECK(info);
678 
679     // Create a file and write some content into it.
680     base::FilePath file_path(temp_dir.GetPath().Append(kFileName1));
681     base::File valid_file(
682         file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
683     for (size_t position = 0; position < info->size; ++position) {
684       char c = 'a' + (position % 26);
685       ASSERT_EQ(1, valid_file.WriteAtCurrentPos(&c, 1));
686     }
687     valid_file.Close();
688 
689     std::string digest;
690     EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path, &digest));
691     EXPECT_STREQ(info->digest, digest.c_str());
692   }
693 }
694 
TEST(DiskUtilTests,ComputeSHA256DigestOfString)695 TEST(DiskUtilTests, ComputeSHA256DigestOfString) {
696   std::string digest_result;
697   std::string content(kFileContent2, sizeof(kFileContent2));
698   EXPECT_TRUE(ComputeSHA256DigestOfString(content, &digest_result));
699   EXPECT_STREQ(kFileContentDigests[2], digest_result.c_str());
700 }
701 
TEST(DiskUtilTests,GetLayeredServiceProviders)702 TEST(DiskUtilTests, GetLayeredServiceProviders) {
703   // Make sure that running the OS implementation doesn't crash/dcheck.
704   LSPPathToGUIDs providers;
705   GetLayeredServiceProviders(LayeredServiceProviderWrapper(), &providers);
706   providers.clear();
707 
708   // Make sure an empty test provider returns nothing
709   TestLayeredServiceProvider lsp;
710   GetLayeredServiceProviders(lsp, &providers);
711   EXPECT_TRUE(providers.empty());
712 
713   // Now try with a couple of providers
714   base::FilePath file_path1 = base::FilePath(kFileName1);
715   base::FilePath file_path2 = base::FilePath(kFileName2);
716   lsp.AddProvider(kGUID1, file_path1);
717   lsp.AddProvider(kGUID2, file_path2);
718   lsp.AddProvider(kGUID3, file_path2);
719 
720   GetLayeredServiceProviders(lsp, &providers);
721 
722   EXPECT_EQ(2UL, providers.size());
723   EXPECT_NE(providers.end(), providers.find(file_path1));
724   EXPECT_NE(providers.end(), providers.find(file_path2));
725   EXPECT_EQ(1UL, providers.find(file_path1)->second.size());
726   EXPECT_NE(providers.find(file_path1)->second.end(),
727             providers.find(file_path1)->second.find(kGUID1));
728   EXPECT_EQ(2UL, providers.find(file_path2)->second.size());
729   EXPECT_NE(providers.find(file_path2)->second.end(),
730             providers.find(file_path2)->second.find(kGUID2));
731   EXPECT_NE(providers.find(file_path2)->second.end(),
732             providers.find(file_path2)->second.find(kGUID3));
733 }
734 
TEST(DiskUtilTests,DeleteFileFromTempProcess)735 TEST(DiskUtilTests, DeleteFileFromTempProcess) {
736   base::FilePath test_file;
737   base::ScopedTempDir test_dir;
738   ASSERT_TRUE(test_dir.CreateUniqueTempDir());
739   base::CreateTemporaryFileInDir(test_dir.GetPath(), &test_file);
740   ASSERT_TRUE(base::PathExists(test_file));
741   base::WriteFile(test_file, "foo", 3);
742   base::win::ScopedHandle process_handle;
743   EXPECT_TRUE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
744   ASSERT_NE(static_cast<HANDLE>(nullptr), process_handle.Get());
745   DWORD wait_result = ::WaitForSingleObject(
746       process_handle.Get(),
747       TestTimeouts::action_max_timeout().InMilliseconds());
748   process_handle.Close();
749   EXPECT_EQ(WAIT_OBJECT_0, wait_result);
750   EXPECT_FALSE(base::PathExists(test_file));
751   EXPECT_FALSE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
752   EXPECT_FALSE(process_handle.IsValid());
753 }
754 
TEST(DiskUtilTests,PathEqual)755 TEST(DiskUtilTests, PathEqual) {
756   base::ScopedTempDir temp_dir;
757   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
758   base::FilePath long_path1(temp_dir.GetPath().Append(kLongFileName1));
759   base::FilePath long_path2(temp_dir.GetPath().Append(kLongFileName2));
760   base::FilePath long_path1_upper(base::ToUpperASCII(long_path1.value()));
761 
762   base::FilePath short_path1;
763   CreateFileAndGetShortName(long_path1, &short_path1);
764 
765   // Same paths are equal.
766   EXPECT_TRUE(PathEqual(long_path1, long_path1));
767   EXPECT_TRUE(PathEqual(long_path2, long_path2));
768   // Same paths with different case are equal.
769   EXPECT_TRUE(PathEqual(long_path1, long_path1_upper));
770   // Different path are not equal.
771   EXPECT_FALSE(PathEqual(long_path1, long_path2));
772 
773   // Short and long path to the same file are equal.
774   EXPECT_TRUE(PathEqual(short_path1, long_path1));
775   // Short and long path to different files are not equal.
776   EXPECT_FALSE(PathEqual(short_path1, long_path2));
777 }
778 
TEST(DiskUtilTests,GetAppDataProductDirectory)779 TEST(DiskUtilTests, GetAppDataProductDirectory) {
780   base::ScopedPathOverride appdata_override(
781       CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
782   base::FilePath appdata_dir;
783   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
784                                      &appdata_dir));
785 
786   base::FilePath product_folder;
787   EXPECT_TRUE(GetAppDataProductDirectory(&product_folder));
788   EXPECT_TRUE(base::DirectoryExists(product_folder));
789   EXPECT_TRUE(PathEqual(appdata_dir, product_folder.DirName().DirName()));
790 }
791 
TEST(DiskUtilTests,ZoneIdentifier)792 TEST(DiskUtilTests, ZoneIdentifier) {
793   base::ScopedTempDir temp_dir;
794   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
795   base::FilePath path(temp_dir.GetPath().Append(kTestProcessExecutableName));
796 
797   if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
798     LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
799     return;
800   }
801 
802   // Copy the test_process executable in a temporary folder.
803   base::FilePath executable_path;
804   ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
805   base::FilePath source_path =
806       executable_path.Append(kTestProcessExecutableName);
807   ASSERT_TRUE(base::CopyFile(source_path, path));
808 
809   // Overwrite the ZoneIdentifier.
810   EXPECT_FALSE(HasZoneIdentifier(path));
811   EXPECT_TRUE(OverwriteZoneIdentifier(path));
812   EXPECT_TRUE(HasZoneIdentifier(path));
813 
814   // Validate the content of the Zone.Identifier stream.
815   base::FilePath stream_path(path.value() + L":Zone.Identifier");
816   std::string content;
817   ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
818   EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
819 }
820 
TEST(DiskUtilTests,ZoneIdentifierWhenProcessIsRunning)821 TEST(DiskUtilTests, ZoneIdentifierWhenProcessIsRunning) {
822   base::FilePath executable_path;
823   ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
824 
825   if (!DoesVolumeSupportNamedStreams(executable_path)) {
826     LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
827     return;
828   }
829 
830   // Copy the test_process executable to a temporary name. We don't use a
831   // ScopedTempDir here because in a component build, the executable depends on
832   // DLL's that would have to be copied into the folder too.
833   base::FilePath source_exe_path(
834       executable_path.Append(kTestProcessExecutableName));
835   std::wstring target_exe_name = base::StrCat(
836       {base::UTF8ToWide(base::UnguessableToken::Create().ToString()), L".exe"});
837   base::FilePath target_exe_path(executable_path.Append(target_exe_name));
838 
839   ASSERT_TRUE(base::CopyFile(source_exe_path, target_exe_path));
840   base::ScopedClosureRunner delete_temp_file(
841       base::BindOnce(base::GetDeleteFileCallback(), target_exe_path));
842 
843   // Launch the test_process and wait it's completion. The process must set its
844   // zone identifier.
845   EXPECT_FALSE(HasZoneIdentifier(target_exe_path));
846   ASSERT_FALSE(IsProcessRunning(target_exe_name.c_str()));
847   ASSERT_TRUE(LaunchTestProcess(target_exe_path.value().c_str(),
848                                 kTestForceOverwriteZoneIdentifier, false));
849   EXPECT_TRUE(WaitForProcessesStopped(target_exe_name.c_str()));
850   EXPECT_TRUE(HasZoneIdentifier(target_exe_path));
851 
852   // Validate the content of the Zone.Identifier stream.
853   base::FilePath stream_path(target_exe_path.value() + L":Zone.Identifier");
854   std::string content;
855   ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
856   EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
857 }
858 
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContentWithSysnativeReplacement)859 TEST(DiskUtilTests,
860      ExtractExecutablePathFromRegistryContentWithSysnativeReplacement) {
861   base::FilePath system_folder;
862   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_SYSTEM),
863                                      &system_folder));
864 
865   base::FilePath native_folder(system_folder.DirName().Append(L"sysnative"));
866   // Only run this test on 64-bits Windows with 32-bits process.
867   if (base::PathExists(native_folder)) {
868     base::ScopedTempDir temp_dir;
869     ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(native_folder));
870 
871     base::FilePath program_path, spaced_program_path;
872     CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
873                                &spaced_program_path);
874     const base::FilePath program_paths[] = {program_path, spaced_program_path};
875     for (const auto& program_path : program_paths) {
876       // convert C:\\Windows\sysnative\scoped_folder\folder1234\file1 into
877       // C:\\Windows\system32\scoped_folder\folder1234\file1
878       base::FilePath program_path_system =
879           system_folder.Append(program_path.DirName().DirName().BaseName())
880               .Append(program_path.DirName().BaseName())
881               .Append(program_path.BaseName());
882       EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
883           program_path_system.value(), program_path));
884     }
885   }
886 }
887 
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContentWithEnvVariable)888 TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContentWithEnvVariable) {
889   // This test expects files to be placed in %TEMP% and not anywhere else
890   // ScopedTempDir might decide to put them.
891   std::wstring temp_str;
892   ASSERT_NE(0U, ::GetEnvironmentVariableW(
893                     L"TEMP", ::base::WriteInto(&temp_str, MAX_PATH), MAX_PATH))
894       << logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
895   base::FilePath temp_path(temp_str);
896   ASSERT_TRUE(base::PathExists(temp_path));
897 
898   base::ScopedTempDir temp_dir;
899   ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(temp_path));
900 
901   base::FilePath program_path, spaced_program_path;
902   CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
903                              &spaced_program_path);
904   const base::FilePath program_paths[] = {program_path, spaced_program_path};
905 
906   for (const auto& program_path : program_paths) {
907     // Convert
908     // "C:\Users\$USER\AppData\Local\Temp\scoped_dir1234\folder6788\A111.tmp"
909     // into "scoped_dir1234\folder6789\A111.tmp"
910     base::FilePath relative_program_path =
911         program_path.DirName()
912             .DirName()
913             .BaseName()
914             .Append(program_path.DirName().BaseName())
915             .Append(program_path.BaseName());
916     const auto program_path_with_var =
917         base::StrCat({L"%TEMP%\\", relative_program_path.value()});
918 
919     EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
920         program_path_with_var, program_path));
921   }
922 }
923 
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContent)924 TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContent) {
925   // Create the executable to be recognized.
926   base::ScopedTempDir temp_dir;
927 
928   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
929   base::FilePath program_path, spaced_program_path;
930   CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
931                              &spaced_program_path);
932   const base::FilePath program_paths[] = {program_path, spaced_program_path};
933 
934   for (const auto& program_path : program_paths) {
935     EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
936         program_path.value(), program_path));
937   }
938 }
939 
TEST(DiskUtilTests,FilePathLess)940 TEST(DiskUtilTests, FilePathLess) {
941   base::FilePath path_a(L"c:\\a");
942   base::FilePath path_upper_a(L"c:\\A");
943   base::FilePath path_b(L"c:\\b");
944   FilePathLess file_path_less;
945   EXPECT_TRUE(file_path_less(path_a, path_b));
946   EXPECT_TRUE(file_path_less(path_upper_a, path_b));
947   EXPECT_FALSE(file_path_less(path_b, path_a));
948   EXPECT_FALSE(file_path_less(path_a, path_upper_a));
949   EXPECT_FALSE(file_path_less(path_upper_a, path_a));
950 
951   std::map<base::FilePath, int, FilePathLess> collection;
952   collection[path_a] = 0;
953   EXPECT_NE(collection.find(path_a), collection.end());
954   EXPECT_NE(collection.find(path_upper_a), collection.end());
955   EXPECT_EQ(collection.find(path_b), collection.end());
956 }
957 
TEST(DiskUtilTests,RetrieveDetailedFileInformation)958 TEST(DiskUtilTests, RetrieveDetailedFileInformation) {
959   base::ScopedPathOverride appdata_override(
960       CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
961   base::FilePath appdata_folder;
962 
963   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
964                                      &appdata_folder));
965 
966   base::FilePath temp_file(appdata_folder.Append(L"DUMMY.inactive"));
967   CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
968 
969   bool whitelisted = false;
970   internal::FileInformation file_information;
971   RetrieveDetailedFileInformation(temp_file, &file_information, &whitelisted);
972 
973   EXPECT_FALSE(whitelisted);
974 
975   std::wstring sanitized_path = SanitizePath(temp_file);
976 
977   EXPECT_EQ(sanitized_path, file_information.path);
978   EXPECT_FALSE(file_information.creation_date.empty());
979   EXPECT_FALSE(file_information.last_modified_date.empty());
980   EXPECT_FALSE(file_information.active_file);
981   EXPECT_EQ(kFileContentDigests[4], file_information.sha256);
982   EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
983   // The next fields are parsed from PE headers so they won't exist.
984   EXPECT_TRUE(file_information.company_name.empty());
985   EXPECT_TRUE(file_information.company_short_name.empty());
986   EXPECT_TRUE(file_information.product_name.empty());
987   EXPECT_TRUE(file_information.product_short_name.empty());
988   EXPECT_TRUE(file_information.internal_name.empty());
989   EXPECT_TRUE(file_information.original_filename.empty());
990   EXPECT_TRUE(file_information.file_description.empty());
991   EXPECT_TRUE(file_information.file_version.empty());
992 }
993 
TEST(DiskUtilTests,RetrieveDetailedFileInformationNoFile)994 TEST(DiskUtilTests, RetrieveDetailedFileInformationNoFile) {
995   base::FilePath appdata_folder;
996 
997   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
998                                      &appdata_folder));
999 
1000   base::FilePath non_existent_file(
1001       appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
1002 
1003   bool whitelisted = false;
1004   internal::FileInformation file_information;
1005   RetrieveDetailedFileInformation(non_existent_file, &file_information,
1006                                   &whitelisted);
1007 
1008   EXPECT_FALSE(whitelisted);
1009   EXPECT_TRUE(file_information.path.empty());
1010   EXPECT_TRUE(file_information.creation_date.empty());
1011   EXPECT_TRUE(file_information.last_modified_date.empty());
1012   EXPECT_FALSE(file_information.active_file);
1013   EXPECT_TRUE(file_information.sha256.empty());
1014   EXPECT_EQ(0, file_information.size);
1015   EXPECT_TRUE(file_information.company_name.empty());
1016   EXPECT_TRUE(file_information.company_short_name.empty());
1017   EXPECT_TRUE(file_information.product_name.empty());
1018   EXPECT_TRUE(file_information.product_short_name.empty());
1019   EXPECT_TRUE(file_information.internal_name.empty());
1020   EXPECT_TRUE(file_information.original_filename.empty());
1021   EXPECT_TRUE(file_information.file_description.empty());
1022   EXPECT_TRUE(file_information.file_version.empty());
1023 }
1024 
TEST(DiskUtilTests,RetrieveDetailedFileInformationWhitelisted)1025 TEST(DiskUtilTests, RetrieveDetailedFileInformationWhitelisted) {
1026   bool whitelisted = false;
1027   internal::FileInformation file_information;
1028 
1029   RetrieveDetailedFileInformation(GetSampleDLLPath(), &file_information,
1030                                   &whitelisted,
1031                                   base::BindOnce(&WhitelistSampleDLL));
1032 
1033   EXPECT_TRUE(whitelisted);
1034   EXPECT_TRUE(file_information.path.empty());
1035   EXPECT_TRUE(file_information.creation_date.empty());
1036   EXPECT_TRUE(file_information.last_modified_date.empty());
1037   EXPECT_FALSE(file_information.active_file);
1038   EXPECT_TRUE(file_information.sha256.empty());
1039   EXPECT_EQ(0, file_information.size);
1040   EXPECT_TRUE(file_information.company_name.empty());
1041   EXPECT_TRUE(file_information.company_short_name.empty());
1042   EXPECT_TRUE(file_information.product_name.empty());
1043   EXPECT_TRUE(file_information.product_short_name.empty());
1044   EXPECT_TRUE(file_information.internal_name.empty());
1045   EXPECT_TRUE(file_information.original_filename.empty());
1046   EXPECT_TRUE(file_information.file_description.empty());
1047   EXPECT_TRUE(file_information.file_version.empty());
1048 }
1049 
TEST(DiskUtilTests,RetrieveBasicFileInformation)1050 TEST(DiskUtilTests, RetrieveBasicFileInformation) {
1051   base::ScopedPathOverride appdata_override(
1052       CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
1053   base::FilePath appdata_folder;
1054 
1055   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1056                                      &appdata_folder));
1057 
1058   base::FilePath temp_file(appdata_folder.Append(L"DUMMY.exe"));
1059   CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
1060 
1061   internal::FileInformation file_information;
1062   RetrieveBasicFileInformation(temp_file, &file_information);
1063 
1064   // The expected file path value should be sanitized.
1065   EXPECT_EQ(SanitizePath(temp_file), file_information.path);
1066   EXPECT_FALSE(file_information.creation_date.empty());
1067   EXPECT_FALSE(file_information.last_modified_date.empty());
1068   EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
1069   EXPECT_TRUE(file_information.active_file);
1070   // The next fields are not included in basic file information.
1071   EXPECT_TRUE(file_information.sha256.empty());
1072   EXPECT_TRUE(file_information.company_name.empty());
1073   EXPECT_TRUE(file_information.company_short_name.empty());
1074   EXPECT_TRUE(file_information.product_name.empty());
1075   EXPECT_TRUE(file_information.product_short_name.empty());
1076   EXPECT_TRUE(file_information.internal_name.empty());
1077   EXPECT_TRUE(file_information.original_filename.empty());
1078   EXPECT_TRUE(file_information.file_description.empty());
1079   EXPECT_TRUE(file_information.file_version.empty());
1080 }
1081 
TEST(DiskUtilTests,RetrieveBasicFileInformationNoFile)1082 TEST(DiskUtilTests, RetrieveBasicFileInformationNoFile) {
1083   base::FilePath appdata_folder;
1084   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1085                                      &appdata_folder));
1086 
1087   base::FilePath non_existent_file(
1088       appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
1089 
1090   internal::FileInformation file_information;
1091   RetrieveBasicFileInformation(non_existent_file, &file_information);
1092 
1093   EXPECT_TRUE(file_information.path.empty());
1094   EXPECT_TRUE(file_information.creation_date.empty());
1095   EXPECT_TRUE(file_information.last_modified_date.empty());
1096   EXPECT_FALSE(file_information.active_file);
1097   EXPECT_TRUE(file_information.sha256.empty());
1098   EXPECT_EQ(0, file_information.size);
1099   EXPECT_TRUE(file_information.company_name.empty());
1100   EXPECT_TRUE(file_information.company_short_name.empty());
1101   EXPECT_TRUE(file_information.product_name.empty());
1102   EXPECT_TRUE(file_information.product_short_name.empty());
1103   EXPECT_TRUE(file_information.internal_name.empty());
1104   EXPECT_TRUE(file_information.original_filename.empty());
1105   EXPECT_TRUE(file_information.file_description.empty());
1106   EXPECT_TRUE(file_information.file_version.empty());
1107 }
1108 
TEST(DiskUtilTests,FileInformationToString)1109 TEST(DiskUtilTests, FileInformationToString) {
1110   std::wstring display_str = FileInformationToString(kFileInformation1);
1111   EXPECT_EQ(kFileInformation1ExpectedString, display_str);
1112 }
1113 
TEST(DiskUtilTests,FileInformationToStringEmpty)1114 TEST(DiskUtilTests, FileInformationToStringEmpty) {
1115   internal::FileInformation file_information;
1116   EXPECT_TRUE(FileInformationToString(file_information).empty());
1117 }
1118 
TEST(DiskUtilTests,TryToExpandPath_NonSystemNativePath)1119 TEST(DiskUtilTests, TryToExpandPath_NonSystemNativePath) {
1120   base::ScopedPathOverride appdata_override(
1121       CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
1122   base::FilePath appdata_folder;
1123   ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1124                                      &appdata_folder));
1125 
1126   base::FilePath non_existing_file(
1127       appdata_folder.DirName().Append(L"non-existing-file.tmp"));
1128   base::FilePath unused_expanded_path;
1129   ASSERT_FALSE(TryToExpandPath(non_existing_file, &unused_expanded_path));
1130 
1131   base::FilePath existing_file(appdata_folder.Append(L"existing-file.tmp"));
1132   CreateFileWithContent(existing_file, kFileContent1, sizeof(kFileContent1));
1133   base::FilePath expanded_path;
1134   ASSERT_TRUE(TryToExpandPath(existing_file, &expanded_path));
1135   ASSERT_EQ(existing_file.value(), expanded_path.value());
1136 
1137   // TODO: Figure out how to test paths in C:\Windows\System32.
1138 }
1139 
TEST(DiskUtilTests,TruncateLogFileToTail_FindsNewline)1140 TEST(DiskUtilTests, TruncateLogFileToTail_FindsNewline) {
1141   const char kFileContents[] = "File with utf8 \n\xe2\x82\xac \ntail";
1142   const int kFileSize = strlen(kFileContents);
1143   const char kTailContents[] = "\ntail";
1144   const int kTailSize = strlen(kTailContents);
1145 
1146   base::ScopedTempDir temp_dir;
1147   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1148   base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1149   ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
1150 
1151   // The tail threshold lands in the middle of a multi-byte character.
1152   TruncateLogFileToTail(file_path, kTailSize + 3);
1153 
1154   int64_t file_size;
1155   ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
1156   EXPECT_EQ(kTailSize, file_size);
1157   std::string tail;
1158   ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
1159   EXPECT_EQ(kTailContents, tail);
1160 }
1161 
TEST(DiskUtilTests,TruncateLogFileToTail_FileSmallerThanLimit)1162 TEST(DiskUtilTests, TruncateLogFileToTail_FileSmallerThanLimit) {
1163   const char kFileContents[] = "I am file";
1164   const int kFileSize = strlen(kFileContents);
1165 
1166   base::ScopedTempDir temp_dir;
1167   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1168   base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1169   ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
1170 
1171   TruncateLogFileToTail(file_path, kFileSize * 2);
1172 
1173   int64_t file_size;
1174   ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
1175   EXPECT_EQ(kFileSize, file_size);
1176   std::string tail;
1177   ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
1178   EXPECT_EQ(kFileContents, tail);
1179 }
1180 
TEST(DiskUtilTests,TruncateLogFileToTail_NotExisting)1181 TEST(DiskUtilTests, TruncateLogFileToTail_NotExisting) {
1182   base::ScopedTempDir temp_dir;
1183   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1184   base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1185 
1186   TruncateLogFileToTail(file_path, 42);
1187 
1188   EXPECT_FALSE(base::PathExists(file_path));
1189 }
1190 
TEST(DiskUtilTests,IgnoredReportingList)1191 TEST(DiskUtilTests, IgnoredReportingList) {
1192   EXPECT_TRUE(IsCompanyOnIgnoredReportingList(L"Google LLC"));
1193   EXPECT_FALSE(IsCompanyOnIgnoredReportingList(L"google llc"));
1194   EXPECT_FALSE(IsCompanyOnIgnoredReportingList(L"Unrecognized Inc"));
1195 }
1196 
1197 }  // namespace chrome_cleaner
1198