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

Side by Side Diff: runtime/bin/directory_win.cc

Issue 12252006: dart:io: Use PathBuffer class for Directory.list on Windows platform. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 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
« no previous file with comments | « no previous file | utils/tests/pub/pub.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/directory.h" 5 #include "bin/directory.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include "bin/log.h" 10 #include "bin/log.h"
11 11
12 // Forward declaration. 12 class PathBuffer {
13 public:
14 PathBuffer() : length(0) { }
15
16 wchar_t data[MAX_PATH + 1];
17 int length;
18
19 bool Add(const wchar_t* name) {
20 size_t written = _snwprintf(data + length,
21 MAX_PATH - length,
22 L"%s",
23 name);
24 data[MAX_PATH] = L'\0';
25 if (written == wcsnlen(name, MAX_PATH + 1)) {
26 length += written;
27 return true;
28 } else {
29 SetLastError(ERROR_BUFFER_OVERFLOW);
30 return false;
31 }
32 }
33
34 void Reset(int new_length) {
35 length = new_length;
36 data[length] = L'\0';
37 }
38 };
39
40
41 // Forward declarations.
13 static bool ListRecursively(const wchar_t* dir_name, 42 static bool ListRecursively(const wchar_t* dir_name,
14 bool recursive, 43 bool recursive,
15 DirectoryListing* listing); 44 DirectoryListing* listing);
16 static bool DeleteRecursively(const wchar_t* dir_name); 45 static bool DeleteRecursively(const wchar_t* dir_name);
17 46
18 47
48 static void PostError(DirectoryListing* listing,
49 const wchar_t* dir_name) {
50 const char* utf8_path = StringUtils::WideToUtf8(dir_name);
51 listing->HandleError(utf8_path);
52 free(const_cast<char*>(utf8_path));
53 }
54
55
19 static bool HandleDir(wchar_t* dir_name, 56 static bool HandleDir(wchar_t* dir_name,
20 wchar_t* path, 57 PathBuffer* path,
21 int path_length,
22 bool recursive, 58 bool recursive,
23 DirectoryListing* listing) { 59 DirectoryListing* listing) {
24 if (wcscmp(dir_name, L".") != 0 && 60 if (wcscmp(dir_name, L".") == 0) return true;
25 wcscmp(dir_name, L"..") != 0) { 61 if (wcscmp(dir_name, L"..") == 0) return true;
26 size_t written = _snwprintf(path + path_length, 62 if (!path->Add(dir_name)) {
27 MAX_PATH - path_length, 63 PostError(listing, path->data);
28 L"%s", 64 return false;
29 dir_name);
30 if (written != wcslen(dir_name)) {
31 return false;
32 }
33 char* utf8_path = StringUtils::WideToUtf8(path);
34 bool ok = listing->HandleDirectory(utf8_path);
35 free(utf8_path);
36 if (!ok) return ok;
37 if (recursive) {
38 return ListRecursively(path, recursive, listing);
39 }
40 } 65 }
41 return true; 66 char* utf8_path = StringUtils::WideToUtf8(path->data);
67 bool ok = listing->HandleDirectory(utf8_path);
68 free(utf8_path);
69 return ok && (!recursive || ListRecursively(path->data, recursive, listing));
Bill Hesse 2013/02/13 14:41:40 Line 69 is the only change from the previously com
42 } 70 }
43 71
44 72
45 static bool HandleFile(wchar_t* file_name, 73 static bool HandleFile(wchar_t* file_name,
46 wchar_t* path, 74 PathBuffer* path,
47 int path_length,
48 DirectoryListing* listing) { 75 DirectoryListing* listing) {
49 size_t written = _snwprintf(path + path_length, 76 if (!path->Add(file_name)) {
50 MAX_PATH - path_length, 77 PostError(listing, path->data);
51 L"%s",
52 file_name);
53 if (written != wcslen(file_name)) {
54 return false; 78 return false;
55 }; 79 }
56 char* utf8_path = StringUtils::WideToUtf8(path); 80 char* utf8_path = StringUtils::WideToUtf8(path->data);
57 bool ok = listing->HandleFile(utf8_path); 81 bool ok = listing->HandleFile(utf8_path);
58 free(utf8_path); 82 free(utf8_path);
59 return ok; 83 return ok;
60 } 84 }
61 85
62 86
63 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data, 87 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
64 wchar_t* path, 88 PathBuffer* path,
65 int path_length,
66 bool recursive, 89 bool recursive,
67 DirectoryListing* listing) { 90 DirectoryListing* listing) {
68 DWORD attributes = find_file_data->dwFileAttributes; 91 DWORD attributes = find_file_data->dwFileAttributes;
69 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 92 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
70 return HandleDir(find_file_data->cFileName, 93 return HandleDir(find_file_data->cFileName,
71 path, 94 path,
72 path_length,
73 recursive, 95 recursive,
74 listing); 96 listing);
75 } else { 97 } else {
76 return HandleFile(find_file_data->cFileName, path, path_length, listing); 98 return HandleFile(find_file_data->cFileName, path, listing);
77 } 99 }
78 } 100 }
79 101
80 102
81 // ComputeFullSearchPath must be called with a path array of size at 103 static PathBuffer* ComputeFullSearchPath(const wchar_t* dir_name) {
82 // least MAX_PATH.
83 static bool ComputeFullSearchPath(const wchar_t* dir_name,
84 wchar_t* path,
85 int* path_length) {
86 // GetFullPathName only works in a multi-threaded environment if 104 // GetFullPathName only works in a multi-threaded environment if
87 // SetCurrentDirectory is not used. We currently have no plan for 105 // SetCurrentDirectory is not used. We currently have no plan for
88 // exposing SetCurrentDirectory. 106 // exposing SetCurrentDirectory.
89 size_t written = GetFullPathNameW(dir_name, MAX_PATH, path, NULL); 107 PathBuffer* path = new PathBuffer();
108
109 size_t written = GetFullPathNameW(dir_name, MAX_PATH + 1, path->data, NULL);
90 // GetFullPathName only accepts input strings of size less than 110 // GetFullPathName only accepts input strings of size less than
91 // MAX_PATH and returns 0 to indicate failure for paths longer than 111 // MAX_PATH and returns 0 to indicate failure for paths longer than
92 // that. Therefore the path buffer is always big enough. 112 // that. Therefore the path buffer is always big enough.
93 if (written == 0 || written > MAX_PATH) { 113 if (written == 0 || written > MAX_PATH) {
94 return false; 114 delete path;
115 return NULL;
95 } 116 }
96 *path_length = written; 117 path->length = written;
97 written = _snwprintf(path + *path_length, 118 if (path->Add(L"\\*")) {
98 MAX_PATH - *path_length, 119 return path;
99 L"%s", 120 } else {
100 L"\\*"); 121 delete path;
101 if (written != 2) { 122 return NULL;
102 return false;
103 } 123 }
104 *path_length += written;
105 return true;
106 }
107
108 static void PostError(DirectoryListing* listing,
109 const wchar_t* dir_name) {
110 const char* utf8_path = StringUtils::WideToUtf8(dir_name);
111 listing->HandleError(utf8_path);
112 free(const_cast<char*>(utf8_path));
113 } 124 }
114 125
115 126
116 static bool ListRecursively(const wchar_t* dir_name, 127 static bool ListRecursively(const wchar_t* dir_name,
117 bool recursive, 128 bool recursive,
118 DirectoryListing* listing) { 129 DirectoryListing* listing) {
119 // Compute full path for the directory currently being listed. The 130 // Compute full path for the directory currently being listed. The
120 // path buffer will be used to construct the current path in the 131 // path buffer will be used to construct the current path in the
121 // recursive traversal. path_length does not always equal 132 // recursive traversal. path_length does not always equal
122 // strlen(path) but indicates the current prefix of path that is the 133 // strlen(path) but indicates the current prefix of path that is the
123 // path of the current directory in the traversal. 134 // path of the current directory in the traversal.
124 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); 135 PathBuffer* path = ComputeFullSearchPath(dir_name);
125 int path_length = 0; 136 if (path == NULL) {
126 bool valid = ComputeFullSearchPath(dir_name, path, &path_length);
127 if (!valid) {
128 PostError(listing, dir_name); 137 PostError(listing, dir_name);
129 free(path); 138 delete path;
130 return false; 139 return false;
131 } 140 }
132 141
133 WIN32_FIND_DATAW find_file_data; 142 WIN32_FIND_DATAW find_file_data;
134 HANDLE find_handle = FindFirstFileW(path, &find_file_data); 143 HANDLE find_handle = FindFirstFileW(path->data, &find_file_data);
135 144
136 // Adjust the path by removing the '*' used for the search. 145 // Adjust the path by removing the '*' used for the search.
137 path_length -= 1; 146 path->Reset(path->length - 1);
138 path[path_length] = '\0';
139 147
140 if (find_handle == INVALID_HANDLE_VALUE) { 148 if (find_handle == INVALID_HANDLE_VALUE) {
141 PostError(listing, path); 149 PostError(listing, path->data);
142 free(path); 150 delete path;
143 return false; 151 return false;
144 } 152 }
145 153
154 int path_length = path->length;
146 bool success = HandleEntry(&find_file_data, 155 bool success = HandleEntry(&find_file_data,
147 path, 156 path,
148 path_length,
149 recursive, 157 recursive,
150 listing); 158 listing);
151 159
152 while ((FindNextFileW(find_handle, &find_file_data) != 0)) { 160 while ((FindNextFileW(find_handle, &find_file_data) != 0)) {
161 path->Reset(path_length); // HandleEntry adds the entry name to path.
153 success = HandleEntry(&find_file_data, 162 success = HandleEntry(&find_file_data,
154 path, 163 path,
155 path_length,
156 recursive, 164 recursive,
157 listing) && success; 165 listing) && success;
158 } 166 }
159 167
160 if (GetLastError() != ERROR_NO_MORE_FILES) { 168 if (GetLastError() != ERROR_NO_MORE_FILES) {
161 success = false; 169 success = false;
162 PostError(listing, dir_name); 170 PostError(listing, dir_name);
163 } 171 }
164 172
165 if (FindClose(find_handle) == 0) { 173 if (FindClose(find_handle) == 0) {
166 success = false; 174 success = false;
167 PostError(listing, dir_name); 175 PostError(listing, dir_name);
168 } 176 }
169 free(path); 177 delete path;
170 178
171 return success; 179 return success;
172 } 180 }
173 181
174 182
175 static bool DeleteFile(wchar_t* file_name, 183 static bool DeleteFile(wchar_t* file_name, PathBuffer* path) {
176 wchar_t* path, 184 if (!path->Add(file_name)) return false;
177 int path_length) {
178 size_t written = _snwprintf(path + path_length,
179 MAX_PATH - path_length,
180 L"%s",
181 file_name);
182 if (written != wcslen(file_name)) {
183 return false;
184 }
185 185
186 if (DeleteFileW(path) != 0) { 186 if (DeleteFileW(path->data) != 0) {
187 return true; 187 return true;
188 } 188 }
189 189
190 // If we failed because the file is read-only, make it writeable and try 190 // If we failed because the file is read-only, make it writeable and try
191 // again. This mirrors Linux/Mac where a directory containing read-only files 191 // again. This mirrors Linux/Mac where a directory containing read-only files
192 // can still be recursively deleted. 192 // can still be recursively deleted.
193 if (GetLastError() == ERROR_ACCESS_DENIED) { 193 if (GetLastError() == ERROR_ACCESS_DENIED) {
194 DWORD attributes = GetFileAttributesW(path); 194 DWORD attributes = GetFileAttributesW(path->data);
195 if (attributes == INVALID_FILE_ATTRIBUTES) { 195 if (attributes == INVALID_FILE_ATTRIBUTES) {
196 return false; 196 return false;
197 } 197 }
198 198
199 if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { 199 if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
200 attributes &= ~FILE_ATTRIBUTE_READONLY; 200 attributes &= ~FILE_ATTRIBUTE_READONLY;
201 201
202 if (SetFileAttributesW(path, attributes) == 0) { 202 if (SetFileAttributesW(path->data, attributes) == 0) {
203 return false; 203 return false;
204 } 204 }
205 205
206 return DeleteFileW(path) != 0; 206 return DeleteFileW(path->data) != 0;
207 } 207 }
208 } 208 }
209 209
210 return false; 210 return false;
211 } 211 }
212 212
213 213
214 static bool DeleteDir(wchar_t* dir_name, 214 static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) {
215 wchar_t* path, 215 if (wcscmp(dir_name, L".") == 0) return true;
216 int path_length) { 216 if (wcscmp(dir_name, L"..") == 0) return true;
217 if (wcscmp(dir_name, L".") != 0 && 217 return path->Add(dir_name) && DeleteRecursively(path->data);
218 wcscmp(dir_name, L"..") != 0) {
219 size_t written = _snwprintf(path + path_length,
220 MAX_PATH - path_length,
221 L"%s",
222 dir_name);
223 if (written != wcslen(dir_name)) {
224 return false;
225 }
226 return DeleteRecursively(path);
227 }
228 return true;
229 } 218 }
230 219
231 220
232 static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, 221 static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, PathBuffer* path) {
233 wchar_t* path,
234 int path_length) {
235 DWORD attributes = find_file_data->dwFileAttributes; 222 DWORD attributes = find_file_data->dwFileAttributes;
236 223
237 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 224 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
238 return DeleteDir(find_file_data->cFileName, path, path_length); 225 return DeleteDir(find_file_data->cFileName, path);
239 } else { 226 } else {
240 return DeleteFile(find_file_data->cFileName, path, path_length); 227 return DeleteFile(find_file_data->cFileName, path);
241 } 228 }
242 } 229 }
243 230
244 231
245 static bool DeleteRecursively(const wchar_t* dir_name) { 232 static bool DeleteRecursively(const wchar_t* dir_name) {
246 // If the directory is a junction, it's pointing to some other place in the 233 // If the directory is a junction, it's pointing to some other place in the
247 // filesystem that we do not want to recurse into. 234 // filesystem that we do not want to recurse into.
248 DWORD attributes = GetFileAttributesW(dir_name); 235 DWORD attributes = GetFileAttributesW(dir_name);
249 if ((attributes != INVALID_FILE_ATTRIBUTES) && 236 if ((attributes != INVALID_FILE_ATTRIBUTES) &&
250 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { 237 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
251 // Just delete the junction itself. 238 // Just delete the junction itself.
252 return RemoveDirectoryW(dir_name) != 0; 239 return RemoveDirectoryW(dir_name) != 0;
253 } 240 }
254 241
255 // Compute full path for the directory currently being deleted. The 242 // Compute full path for the directory currently being deleted. The
256 // path buffer will be used to construct the current path in the 243 // path buffer will be used to construct the current path in the
257 // recursive traversal. path_length does not always equal 244 // recursive traversal. path_length does not always equal
258 // strlen(path) but indicates the current prefix of path that is the 245 // strlen(path) but indicates the current prefix of path that is the
259 // path of the current directory in the traversal. 246 // path of the current directory in the traversal.
260 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); 247 PathBuffer* path = ComputeFullSearchPath(dir_name);
261 int path_length = 0; 248 if (path == NULL) return false;
262 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); 249
263 if (!valid) { 250 WIN32_FIND_DATAW find_file_data;
264 free(path); 251 HANDLE find_handle = FindFirstFileW(path->data, &find_file_data);
252
253 // Adjust the path by removing the '*' used for the search.
254 int path_length = path->length - 1;
255 path->Reset(path_length);
256
257 if (find_handle == INVALID_HANDLE_VALUE) {
258 delete path;
265 return false; 259 return false;
266 } 260 }
267 261
268 WIN32_FIND_DATAW find_file_data; 262 bool success = DeleteEntry(&find_file_data, path);
269 HANDLE find_handle = FindFirstFileW(path, &find_file_data);
270 263
271 // Adjust the path by removing the '*' used for the search. 264 while ((FindNextFileW(find_handle, &find_file_data) != 0) && success) {
272 path_length -= 1; 265 path->Reset(path_length); // DeleteEntry adds to the path.
273 path[path_length] = '\0'; 266 success = success && DeleteEntry(&find_file_data, path);
274
275 if (find_handle == INVALID_HANDLE_VALUE) {
276 free(path);
277 return false;
278 } 267 }
279 268
280 bool success = DeleteEntry(&find_file_data, path, path_length); 269 delete path;
281
282 while ((FindNextFileW(find_handle, &find_file_data) != 0) && success) {
283 success = success && DeleteEntry(&find_file_data, path, path_length);
284 }
285
286 free(path);
287 270
288 if ((GetLastError() != ERROR_NO_MORE_FILES) || 271 if ((GetLastError() != ERROR_NO_MORE_FILES) ||
289 (FindClose(find_handle) == 0) || 272 (FindClose(find_handle) == 0) ||
290 (RemoveDirectoryW(dir_name) == 0)) { 273 (RemoveDirectoryW(dir_name) == 0)) {
291 return false; 274 return false;
292 } 275 }
293 276
294 return success; 277 return success;
295 } 278 }
296 279
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 free(const_cast<wchar_t*>(system_name)); 338 free(const_cast<wchar_t*>(system_name));
356 return (create_status != 0); 339 return (create_status != 0);
357 } 340 }
358 341
359 342
360 char* Directory::CreateTemp(const char* const_template) { 343 char* Directory::CreateTemp(const char* const_template) {
361 // Returns a new, unused directory name, modifying the contents of 344 // Returns a new, unused directory name, modifying the contents of
362 // dir_template. Creates this directory, with a default security 345 // dir_template. Creates this directory, with a default security
363 // descriptor inherited from its parent directory. 346 // descriptor inherited from its parent directory.
364 // The return value must be freed by the caller. 347 // The return value must be freed by the caller.
365 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); 348 PathBuffer* path = new PathBuffer();
366 int path_length;
367 if (0 == strncmp(const_template, "", 1)) { 349 if (0 == strncmp(const_template, "", 1)) {
368 path_length = GetTempPathW(MAX_PATH, path); 350 path->length = GetTempPathW(MAX_PATH, path->data);
369 if (path_length == 0) { 351 if (path->length == 0) {
370 free(path); 352 delete path;
371 return NULL; 353 return NULL;
372 } 354 }
373 } else { 355 } else {
374 const wchar_t* system_template = StringUtils::Utf8ToWide(const_template); 356 const wchar_t* system_template = StringUtils::Utf8ToWide(const_template);
375 _snwprintf(path, MAX_PATH, L"%s", system_template); 357 path->Add(system_template);
376 free(const_cast<wchar_t*>(system_template)); 358 free(const_cast<wchar_t*>(system_template));
377 path_length = wcslen(path);
378 } 359 }
379 // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44. 360 // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44.
380 if (path_length > MAX_PATH - 44) { 361 if (path->length > MAX_PATH - 44) {
381 free(path); 362 delete path;
382 return NULL; 363 return NULL;
383 } 364 }
384 if ((path)[path_length - 1] == L'\\') { 365 if ((path->data)[path->length - 1] == L'\\') {
385 // No base name for the directory - use "tempdir". 366 // No base name for the directory - use "tempdir".
386 _snwprintf(path + path_length, MAX_PATH - path_length, L"tempdir"); 367 path->Add(L"tempdir");
387 path_length = wcslen(path);
388 } 368 }
389 369
390 UUID uuid; 370 UUID uuid;
391 RPC_STATUS status = UuidCreateSequential(&uuid); 371 RPC_STATUS status = UuidCreateSequential(&uuid);
392 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { 372 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
393 free(path); 373 delete path;
394 return NULL; 374 return NULL;
395 } 375 }
396 RPC_WSTR uuid_string; 376 RPC_WSTR uuid_string;
397 status = UuidToStringW(&uuid, &uuid_string); 377 status = UuidToStringW(&uuid, &uuid_string);
398 if (status != RPC_S_OK) { 378 if (status != RPC_S_OK) {
399 free(path); 379 delete path;
400 return NULL; 380 return NULL;
401 } 381 }
402 382
403 _snwprintf(path + path_length, MAX_PATH - path_length, L"-%s", uuid_string); 383 path->Add(L"-");
384 // RPC_WSTR is an unsigned short*, so we cast to wchar_t*.
385 path->Add(reinterpret_cast<wchar_t*>(uuid_string));
404 RpcStringFreeW(&uuid_string); 386 RpcStringFreeW(&uuid_string);
405 if (!CreateDirectoryW(path, NULL)) { 387 if (!CreateDirectoryW(path->data, NULL)) {
406 free(path); 388 delete path;
407 return NULL; 389 return NULL;
408 } 390 }
409 char* result = StringUtils::WideToUtf8(path); 391 char* result = StringUtils::WideToUtf8(path->data);
410 free(path); 392 delete path;
411 return result; 393 return result;
412 } 394 }
413 395
414 396
415 bool Directory::Delete(const char* dir_name, bool recursive) { 397 bool Directory::Delete(const char* dir_name, bool recursive) {
416 bool result = false; 398 bool result = false;
417 const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name); 399 const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
418 if (!recursive) { 400 if (!recursive) {
419 result = (RemoveDirectoryW(system_dir_name) != 0); 401 result = (RemoveDirectoryW(system_dir_name) != 0);
420 } else { 402 } else {
(...skipping 17 matching lines...) Expand all
438 bool success = DeleteRecursively(system_new_path); 420 bool success = DeleteRecursively(system_new_path);
439 if (!success) return false; 421 if (!success) return false;
440 } 422 }
441 DWORD flags = MOVEFILE_WRITE_THROUGH; 423 DWORD flags = MOVEFILE_WRITE_THROUGH;
442 int move_status = 424 int move_status =
443 MoveFileExW(system_path, system_new_path, flags); 425 MoveFileExW(system_path, system_new_path, flags);
444 free(const_cast<wchar_t*>(system_path)); 426 free(const_cast<wchar_t*>(system_path));
445 free(const_cast<wchar_t*>(system_new_path)); 427 free(const_cast<wchar_t*>(system_new_path));
446 return (move_status != 0); 428 return (move_status != 0);
447 } 429 }
OLDNEW
« no previous file with comments | « no previous file | utils/tests/pub/pub.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698