Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: trunk/src/chrome_elf/create_file/chrome_create_file.cc

Issue 140783009: Revert 245464 "Use an alternate mechanism for CreateFile calls i..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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_elf/create_file/chrome_create_file.h"
6
7 #include <string>
8
9 #include "base/strings/string16.h"
10 #include "chrome_elf/chrome_elf_constants.h"
11 #include "chrome_elf/ntdll_cache.h"
12 #include "sandbox/win/src/nt_internals.h"
13
14 namespace {
15
16 // From ShlObj.h in the Windows SDK.
17 #define CSIDL_LOCAL_APPDATA 0x001c
18
19 typedef BOOL (WINAPI *PathIsUNCFunction)(
20 IN LPCWSTR path);
21
22 typedef BOOL (WINAPI *PathAppendFunction)(
23 IN LPWSTR path,
24 IN LPCWSTR more);
25
26 typedef BOOL (WINAPI *PathIsPrefixFunction)(
27 IN LPCWSTR prefix,
28 IN LPCWSTR path);
29
30 typedef HRESULT (WINAPI *SHGetFolderPathFunction)(
31 IN HWND hwnd_owner,
32 IN int folder,
33 IN HANDLE token,
34 IN DWORD flags,
35 OUT LPWSTR path);
36
37 PathIsUNCFunction g_path_is_unc_func;
38 PathAppendFunction g_path_append_func;
39 PathIsPrefixFunction g_path_is_prefix_func;
40 SHGetFolderPathFunction g_get_folder_func;
41
42 // Populates the g_*_func pointers to functions which will be used in
43 // ShouldBypass(). Chrome_elf cannot have a load-time dependency on shell32 or
44 // shlwapi as this would induce a load-time dependency on user32.dll. Instead,
45 // the addresses of the functions we need are retrieved the first time this
46 // method is called, and cached to avoid subsequent calls to GetProcAddress().
47 // It is assumed that the host process will never unload these functions.
48 // Returns true if all the functions needed are present.
49 bool PopulateShellFunctions() {
50 // Early exit if functions have already been populated.
51 if (g_path_is_unc_func && g_path_append_func &&
52 g_path_is_prefix_func && g_get_folder_func) {
53 return true;
54 }
55
56 // Get the addresses of the functions we need and store them for future use.
57 // These handles are intentionally leaked to ensure that these modules do not
58 // get unloaded.
59 HMODULE shell32 = ::LoadLibrary(L"shell32.dll");
60 HMODULE shlwapi = ::LoadLibrary(L"shlwapi.dll");
61
62 if (!shlwapi || !shell32)
63 return false;
64
65 g_path_is_unc_func = reinterpret_cast<PathIsUNCFunction>(
66 ::GetProcAddress(shlwapi, "PathIsUNCW"));
67 g_path_append_func = reinterpret_cast<PathAppendFunction>(
68 ::GetProcAddress(shlwapi, "PathAppendW"));
69 g_path_is_prefix_func = reinterpret_cast<PathIsPrefixFunction>(
70 ::GetProcAddress(shlwapi, "PathIsPrefixW"));
71 g_get_folder_func = reinterpret_cast<SHGetFolderPathFunction>(
72 ::GetProcAddress(shell32, "SHGetFolderPathW"));
73
74 return g_path_is_unc_func && g_path_append_func &&
75 g_path_is_prefix_func && g_get_folder_func;
76 }
77
78 } // namespace
79
80 HANDLE WINAPI CreateFileWRedirect(
81 LPCWSTR file_name,
82 DWORD desired_access,
83 DWORD share_mode,
84 LPSECURITY_ATTRIBUTES security_attributes,
85 DWORD creation_disposition,
86 DWORD flags_and_attributes,
87 HANDLE template_file) {
88 if (ShouldBypass(file_name)) {
89 return CreateFileNTDLL(file_name,
90 desired_access,
91 share_mode,
92 security_attributes,
93 creation_disposition,
94 flags_and_attributes,
95 template_file);
96 }
97 return CreateFile(file_name,
98 desired_access,
99 share_mode,
100 security_attributes,
101 creation_disposition,
102 flags_and_attributes,
103 template_file);
104
105 }
106
107 HANDLE CreateFileNTDLL(
108 LPCWSTR file_name,
109 DWORD desired_access,
110 DWORD share_mode,
111 LPSECURITY_ATTRIBUTES security_attributes,
112 DWORD creation_disposition,
113 DWORD flags_and_attributes,
114 HANDLE template_file) {
115 HANDLE file_handle = INVALID_HANDLE_VALUE;
116 NTSTATUS result = STATUS_UNSUCCESSFUL;
117 IO_STATUS_BLOCK io_status_block = {};
118
119 // Convert from Win32 domain to to NT creation disposition values.
120 switch (creation_disposition) {
121 case CREATE_NEW:
122 creation_disposition = FILE_CREATE;
123 break;
124 case CREATE_ALWAYS:
125 creation_disposition = FILE_OVERWRITE_IF;
126 break;
127 case OPEN_EXISTING:
128 creation_disposition = FILE_OPEN;
129 break;
130 case OPEN_ALWAYS:
131 creation_disposition = FILE_OPEN_IF;
132 break;
133 case TRUNCATE_EXISTING:
134 creation_disposition = FILE_OVERWRITE;
135 break;
136 default:
137 SetLastError(ERROR_INVALID_PARAMETER);
138 return INVALID_HANDLE_VALUE;
139 }
140
141 if (!g_ntdll_lookup["NtCreateFile"] ||
142 !g_ntdll_lookup["RtlInitUnicodeString"]) {
143 return INVALID_HANDLE_VALUE;
144 }
145
146 NtCreateFileFunction create_file =
147 reinterpret_cast<NtCreateFileFunction>(g_ntdll_lookup["NtCreateFile"]);
148
149 RtlInitUnicodeStringFunction init_unicode_string =
150 reinterpret_cast<RtlInitUnicodeStringFunction>(
151 g_ntdll_lookup["RtlInitUnicodeString"]);
152
153 UNICODE_STRING path_unicode_string;
154
155 // Format the path into an NT path. Arguably this should be done with
156 // RtlDosPathNameToNtPathName_U, but afaict this is equivalent for
157 // local paths. Using this with a UNC path name will almost certainly
158 // break in interesting ways.
159 base::string16 filename_string(L"\\??\\");
160 filename_string += file_name;
161
162 init_unicode_string(&path_unicode_string, filename_string.c_str());
163
164 OBJECT_ATTRIBUTES path_attributes = {};
165 InitializeObjectAttributes(&path_attributes,
166 &path_unicode_string,
167 OBJ_CASE_INSENSITIVE,
168 NULL, // No Root Directory
169 NULL); // No Security Descriptor
170
171 // Set create_options, desired_access, and flags_and_attributes to match those
172 // set by kernel32!CreateFile.
173 ULONG create_options = FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_ARCHIVE;
174 desired_access |= 0x100080;
175 flags_and_attributes &= 0x2FFA7;
176
177 result = create_file(&file_handle,
178 desired_access,
179 &path_attributes,
180 &io_status_block,
181 0, // Allocation size
182 flags_and_attributes,
183 share_mode,
184 creation_disposition,
185 create_options,
186 NULL,
187 0);
188
189 if (result != STATUS_SUCCESS) {
190 if (result == STATUS_OBJECT_NAME_COLLISION &&
191 creation_disposition == FILE_CREATE) {
192 SetLastError(ERROR_FILE_EXISTS);
193 }
194 return INVALID_HANDLE_VALUE;
195 }
196
197 if (creation_disposition == FILE_OPEN_IF) {
198 SetLastError(io_status_block.Information == FILE_OPENED ?
199 ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
200 } else if (creation_disposition == FILE_OVERWRITE_IF) {
201 SetLastError(io_status_block.Information == FILE_OVERWRITTEN ?
202 ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
203 } else {
204 SetLastError(ERROR_SUCCESS);
205 }
206
207 return file_handle;
208 }
209
210 bool ShouldBypass(LPCWSTR file_name) {
211 // If the shell functions are not present, forward the call to kernel32.
212 if (!PopulateShellFunctions())
213 return false;
214
215 // Forward all UNC filepaths to kernel32.
216 if (g_path_is_unc_func(file_name))
217 return false;
218
219 wchar_t local_appdata_path[MAX_PATH];
220
221 // Get the %LOCALAPPDATA% Path and append the location of our UserData
222 // directory to it.
223 HRESULT appdata_result = g_get_folder_func(
224 NULL, CSIDL_LOCAL_APPDATA, NULL, 0, local_appdata_path);
225
226 // If getting the %LOCALAPPDATA% path or appending to it failed, then forward
227 // the call to kernel32.
228 if (!SUCCEEDED(appdata_result) ||
229 !g_path_append_func(local_appdata_path, kAppDataDirName) ||
230 !g_path_append_func(local_appdata_path, kUserDataDirName)) {
231 return false;
232 }
233
234 // Check if we are trying to access something in the UserData dir. If so,
235 // then redirect the call to bypass kernel32.
236 return !!g_path_is_prefix_func(local_appdata_path, file_name);
237 }
OLDNEW
« no previous file with comments | « trunk/src/chrome_elf/create_file/chrome_create_file.h ('k') | trunk/src/chrome_elf/create_file/chrome_create_file_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698