1// Copyright (c) 2006-2008 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 "sandbox/win/src/restricted_token.h"
6#include "sandbox/win/src/restricted_token_utils.h"
7#include "sandbox/win/tools/finder/finder.h"
8
9DWORD Finder::ParseFileSystem(ATL::CString directory) {
10  WIN32_FIND_DATA find_data;
11  HANDLE find;
12
13  //Search for items in the directory.
14  ATL::CString name_to_search = directory + L"\\*";
15  find = ::FindFirstFile(name_to_search, &find_data);
16  if (INVALID_HANDLE_VALUE == find) {
17    DWORD error = ::GetLastError();
18    Output(FS_ERR, error, directory);
19    filesystem_stats_[BROKEN]++;
20    return error;
21  }
22
23  // parse all files or folders.
24  do {
25    if (_tcscmp(find_data.cFileName, L".") == 0 ||
26        _tcscmp(find_data.cFileName, L"..") == 0)
27      continue;
28
29    ATL::CString complete_name = directory + L"\\" + find_data.cFileName;
30    TestFileAccess(complete_name);
31
32    // Call recursively the function if the path found is a directory.
33    if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
34      ParseFileSystem(complete_name);
35    }
36  } while (::FindNextFile(find, &find_data) != 0);
37
38  DWORD err_code = ::GetLastError();
39  ::FindClose(find);
40
41  if (ERROR_NO_MORE_FILES != err_code) {
42    Output(FS_ERR, err_code, directory);
43    filesystem_stats_[BROKEN]++;
44    return err_code;
45  }
46
47  return ERROR_SUCCESS;
48}
49
50DWORD Finder::TestFileAccess(ATL::CString name) {
51  Impersonater impersonate(token_handle_);
52
53  filesystem_stats_[PARSE]++;
54
55  HANDLE file;
56  if (access_type_ & kTestForAll) {
57    file = ::CreateFile(name.GetBuffer(),
58                        GENERIC_ALL,
59                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
60                        NULL,
61                        OPEN_EXISTING,
62                        FILE_ATTRIBUTE_NORMAL,
63                        NULL);
64
65    if (file != INVALID_HANDLE_VALUE) {
66      filesystem_stats_[ALL]++;
67      Output(FS, L"R/W", name.GetBuffer());
68      ::CloseHandle(file);
69      return GENERIC_ALL;
70    } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
71      Output(FS_ERR, GetLastError(), name);
72      filesystem_stats_[BROKEN]++;
73    }
74  }
75
76  if (access_type_ & kTestForWrite) {
77    file = ::CreateFile(name.GetBuffer(),
78                        GENERIC_WRITE,
79                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
80                        NULL,
81                        OPEN_EXISTING,
82                        FILE_ATTRIBUTE_NORMAL,
83                        NULL);
84
85    if (file != INVALID_HANDLE_VALUE) {
86      filesystem_stats_[WRITE]++;
87      Output(FS, L"W", name);
88      ::CloseHandle(file);
89      return GENERIC_WRITE;
90    } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
91      Output(FS_ERR, ::GetLastError(), name);
92      filesystem_stats_[BROKEN]++;
93    }
94  }
95
96  if (access_type_ & kTestForRead) {
97    file = ::CreateFile(name.GetBuffer(),
98                        GENERIC_READ,
99                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
100                        NULL,
101                        OPEN_EXISTING,
102                        FILE_ATTRIBUTE_NORMAL,
103                        NULL);
104
105    if (file != INVALID_HANDLE_VALUE) {
106      filesystem_stats_[READ]++;
107      Output(FS, L"R", name);
108      ::CloseHandle(file);
109      return GENERIC_READ;
110    } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
111      Output(FS_ERR, GetLastError(), name);
112      filesystem_stats_[BROKEN]++;
113    }
114  }
115
116  return 0;
117}
118