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

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

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

Powered by Google App Engine
This is Rietveld 408576698