| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/src/sandbox_nt_util.h" | |
| 6 | |
| 7 #include "base/win/pe_image.h" | |
| 8 #include "sandbox/src/sandbox_factory.h" | |
| 9 #include "sandbox/src/target_services.h" | |
| 10 | |
| 11 namespace sandbox { | |
| 12 | |
| 13 // This is the list of all imported symbols from ntdll.dll. | |
| 14 SANDBOX_INTERCEPT NtExports g_nt = { NULL }; | |
| 15 | |
| 16 } | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 #if defined(_WIN64) | |
| 21 void* AllocateNearTo(void* source, size_t size) { | |
| 22 using sandbox::g_nt; | |
| 23 | |
| 24 // Start with 1 GB above the source. | |
| 25 const unsigned int kOneGB = 0x40000000; | |
| 26 void* base = reinterpret_cast<char*>(source) + kOneGB; | |
| 27 SIZE_T actual_size = size; | |
| 28 ULONG_PTR zero_bits = 0; // Not the correct type if used. | |
| 29 ULONG type = MEM_RESERVE; | |
| 30 | |
| 31 if (reinterpret_cast<SIZE_T>(source) > 0x7ff80000000) { | |
| 32 // We are at the top of the address space. Let's try the highest available | |
| 33 // address. | |
| 34 base = NULL; | |
| 35 type |= MEM_TOP_DOWN; | |
| 36 } | |
| 37 | |
| 38 NTSTATUS ret; | |
| 39 int attempts = 0; | |
| 40 for (; attempts < 20; attempts++) { | |
| 41 ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits, | |
| 42 &actual_size, type, PAGE_READWRITE); | |
| 43 if (NT_SUCCESS(ret)) { | |
| 44 if (base < source) { | |
| 45 // We won't be able to patch this dll. | |
| 46 VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size, | |
| 47 MEM_RELEASE)); | |
| 48 return NULL; | |
| 49 } | |
| 50 break; | |
| 51 } | |
| 52 | |
| 53 // Try 100 MB higher. | |
| 54 base = reinterpret_cast<char*>(base) + 100 * 0x100000; | |
| 55 }; | |
| 56 | |
| 57 if (attempts == 20) | |
| 58 return NULL; | |
| 59 | |
| 60 ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits, | |
| 61 &actual_size, MEM_COMMIT, PAGE_READWRITE); | |
| 62 | |
| 63 if (!NT_SUCCESS(ret)) { | |
| 64 VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size, | |
| 65 MEM_RELEASE)); | |
| 66 base = NULL; | |
| 67 } | |
| 68 | |
| 69 return base; | |
| 70 } | |
| 71 #else // defined(_WIN64). | |
| 72 void* AllocateNearTo(void* source, size_t size) { | |
| 73 using sandbox::g_nt; | |
| 74 UNREFERENCED_PARAMETER(source); | |
| 75 | |
| 76 // In 32-bit processes allocations below 512k are predictable, so mark | |
| 77 // anything in that range as reserved and retry until we get a good address. | |
| 78 const void* const kMinAddress = reinterpret_cast<void*>(512 * 1024); | |
| 79 NTSTATUS ret; | |
| 80 SIZE_T actual_size; | |
| 81 void* base; | |
| 82 do { | |
| 83 base = NULL; | |
| 84 actual_size = 64 * 1024; | |
| 85 ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size, | |
| 86 MEM_RESERVE, PAGE_NOACCESS); | |
| 87 if (!NT_SUCCESS(ret)) | |
| 88 return NULL; | |
| 89 } while (base < kMinAddress); | |
| 90 | |
| 91 actual_size = size; | |
| 92 ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size, | |
| 93 MEM_COMMIT, PAGE_READWRITE); | |
| 94 if (!NT_SUCCESS(ret)) | |
| 95 return NULL; | |
| 96 return base; | |
| 97 } | |
| 98 #endif // defined(_WIN64). | |
| 99 | |
| 100 } // namespace. | |
| 101 | |
| 102 namespace sandbox { | |
| 103 | |
| 104 // Handle for our private heap. | |
| 105 void* g_heap = NULL; | |
| 106 | |
| 107 SANDBOX_INTERCEPT HANDLE g_shared_section; | |
| 108 SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0; | |
| 109 SANDBOX_INTERCEPT size_t g_shared_policy_size = 0; | |
| 110 | |
| 111 void* volatile g_shared_policy_memory = NULL; | |
| 112 void* volatile g_shared_IPC_memory = NULL; | |
| 113 | |
| 114 // Both the IPC and the policy share a single region of memory in which the IPC | |
| 115 // memory is first and the policy memory is last. | |
| 116 bool MapGlobalMemory() { | |
| 117 if (NULL == g_shared_IPC_memory) { | |
| 118 void* memory = NULL; | |
| 119 SIZE_T size = 0; | |
| 120 // Map the entire shared section from the start. | |
| 121 NTSTATUS ret = g_nt.MapViewOfSection(g_shared_section, NtCurrentProcess, | |
| 122 &memory, 0, 0, NULL, &size, ViewUnmap, | |
| 123 0, PAGE_READWRITE); | |
| 124 | |
| 125 if (!NT_SUCCESS(ret) || NULL == memory) { | |
| 126 NOTREACHED_NT(); | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 if (NULL != _InterlockedCompareExchangePointer(&g_shared_IPC_memory, | |
| 131 memory, NULL)) { | |
| 132 // Somebody beat us to the memory setup. | |
| 133 ret = g_nt.UnmapViewOfSection(NtCurrentProcess, memory); | |
| 134 VERIFY_SUCCESS(ret); | |
| 135 } | |
| 136 DCHECK_NT(g_shared_IPC_size > 0); | |
| 137 g_shared_policy_memory = reinterpret_cast<char*>(g_shared_IPC_memory) | |
| 138 + g_shared_IPC_size; | |
| 139 } | |
| 140 DCHECK_NT(g_shared_policy_memory); | |
| 141 DCHECK_NT(g_shared_policy_size > 0); | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 void* GetGlobalIPCMemory() { | |
| 146 if (!MapGlobalMemory()) | |
| 147 return NULL; | |
| 148 return g_shared_IPC_memory; | |
| 149 } | |
| 150 | |
| 151 void* GetGlobalPolicyMemory() { | |
| 152 if (!MapGlobalMemory()) | |
| 153 return NULL; | |
| 154 return g_shared_policy_memory; | |
| 155 } | |
| 156 | |
| 157 bool InitHeap() { | |
| 158 if (!g_heap) { | |
| 159 // Create a new heap using default values for everything. | |
| 160 void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); | |
| 161 if (!heap) | |
| 162 return false; | |
| 163 | |
| 164 if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) { | |
| 165 // Somebody beat us to the memory setup. | |
| 166 g_nt.RtlDestroyHeap(heap); | |
| 167 } | |
| 168 } | |
| 169 return (g_heap) ? true : false; | |
| 170 } | |
| 171 | |
| 172 // Physically reads or writes from memory to verify that (at this time), it is | |
| 173 // valid. Returns a dummy value. | |
| 174 int TouchMemory(void* buffer, size_t size_bytes, RequiredAccess intent) { | |
| 175 const int kPageSize = 4096; | |
| 176 int dummy = 0; | |
| 177 char* start = reinterpret_cast<char*>(buffer); | |
| 178 char* end = start + size_bytes - 1; | |
| 179 | |
| 180 if (WRITE == intent) { | |
| 181 for (; start < end; start += kPageSize) { | |
| 182 *start = 0; | |
| 183 } | |
| 184 *end = 0; | |
| 185 } else { | |
| 186 for (; start < end; start += kPageSize) { | |
| 187 dummy += *start; | |
| 188 } | |
| 189 dummy += *end; | |
| 190 } | |
| 191 | |
| 192 return dummy; | |
| 193 } | |
| 194 | |
| 195 bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { | |
| 196 DCHECK_NT(size); | |
| 197 __try { | |
| 198 TouchMemory(buffer, size, intent); | |
| 199 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 200 return false; | |
| 201 } | |
| 202 return true; | |
| 203 } | |
| 204 | |
| 205 NTSTATUS CopyData(void* destination, const void* source, size_t bytes) { | |
| 206 NTSTATUS ret = STATUS_SUCCESS; | |
| 207 __try { | |
| 208 if (SandboxFactory::GetTargetServices()->GetState()->InitCalled()) { | |
| 209 memcpy(destination, source, bytes); | |
| 210 } else { | |
| 211 const char* from = reinterpret_cast<const char*>(source); | |
| 212 char* to = reinterpret_cast<char*>(destination); | |
| 213 for (size_t i = 0; i < bytes; i++) { | |
| 214 to[i] = from[i]; | |
| 215 } | |
| 216 } | |
| 217 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 218 ret = GetExceptionCode(); | |
| 219 } | |
| 220 return ret; | |
| 221 } | |
| 222 | |
| 223 // Hacky code... replace with AllocAndCopyObjectAttributes. | |
| 224 NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object, | |
| 225 wchar_t** out_name, uint32* attributes, | |
| 226 HANDLE* root) { | |
| 227 if (!InitHeap()) | |
| 228 return STATUS_NO_MEMORY; | |
| 229 | |
| 230 DCHECK_NT(out_name); | |
| 231 *out_name = NULL; | |
| 232 NTSTATUS ret = STATUS_UNSUCCESSFUL; | |
| 233 __try { | |
| 234 do { | |
| 235 if (in_object->RootDirectory != static_cast<HANDLE>(0) && !root) | |
| 236 break; | |
| 237 if (NULL == in_object->ObjectName) | |
| 238 break; | |
| 239 if (NULL == in_object->ObjectName->Buffer) | |
| 240 break; | |
| 241 | |
| 242 size_t size = in_object->ObjectName->Length + sizeof(wchar_t); | |
| 243 *out_name = new(NT_ALLOC) wchar_t[size/sizeof(wchar_t)]; | |
| 244 if (NULL == *out_name) | |
| 245 break; | |
| 246 | |
| 247 ret = CopyData(*out_name, in_object->ObjectName->Buffer, | |
| 248 size - sizeof(wchar_t)); | |
| 249 if (!NT_SUCCESS(ret)) | |
| 250 break; | |
| 251 | |
| 252 (*out_name)[size / sizeof(wchar_t) - 1] = L'\0'; | |
| 253 | |
| 254 if (attributes) | |
| 255 *attributes = in_object->Attributes; | |
| 256 | |
| 257 if (root) | |
| 258 *root = in_object->RootDirectory; | |
| 259 ret = STATUS_SUCCESS; | |
| 260 } while (false); | |
| 261 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 262 ret = GetExceptionCode(); | |
| 263 } | |
| 264 | |
| 265 if (!NT_SUCCESS(ret) && *out_name) { | |
| 266 operator delete(*out_name, NT_ALLOC); | |
| 267 *out_name = NULL; | |
| 268 } | |
| 269 | |
| 270 return ret; | |
| 271 } | |
| 272 | |
| 273 NTSTATUS GetProcessId(HANDLE process, ULONG *process_id) { | |
| 274 PROCESS_BASIC_INFORMATION proc_info; | |
| 275 ULONG bytes_returned; | |
| 276 | |
| 277 NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation, | |
| 278 &proc_info, sizeof(proc_info), | |
| 279 &bytes_returned); | |
| 280 if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) | |
| 281 return ret; | |
| 282 | |
| 283 *process_id = proc_info.UniqueProcessId; | |
| 284 return STATUS_SUCCESS; | |
| 285 } | |
| 286 | |
| 287 bool IsSameProcess(HANDLE process) { | |
| 288 if (NtCurrentProcess == process) | |
| 289 return true; | |
| 290 | |
| 291 static ULONG s_process_id = 0; | |
| 292 | |
| 293 if (!s_process_id) { | |
| 294 NTSTATUS ret = GetProcessId(NtCurrentProcess, &s_process_id); | |
| 295 if (!NT_SUCCESS(ret)) | |
| 296 return false; | |
| 297 } | |
| 298 | |
| 299 ULONG process_id; | |
| 300 NTSTATUS ret = GetProcessId(process, &process_id); | |
| 301 if (!NT_SUCCESS(ret)) | |
| 302 return false; | |
| 303 | |
| 304 return (process_id == s_process_id); | |
| 305 } | |
| 306 | |
| 307 bool IsValidImageSection(HANDLE section, PVOID *base, PLARGE_INTEGER offset, | |
| 308 PSIZE_T view_size) { | |
| 309 if (!section || !base || !view_size || offset) | |
| 310 return false; | |
| 311 | |
| 312 HANDLE query_section; | |
| 313 | |
| 314 NTSTATUS ret = g_nt.DuplicateObject(NtCurrentProcess, section, | |
| 315 NtCurrentProcess, &query_section, | |
| 316 SECTION_QUERY, 0, 0); | |
| 317 if (!NT_SUCCESS(ret)) | |
| 318 return false; | |
| 319 | |
| 320 SECTION_BASIC_INFORMATION basic_info; | |
| 321 SIZE_T bytes_returned; | |
| 322 ret = g_nt.QuerySection(query_section, SectionBasicInformation, &basic_info, | |
| 323 sizeof(basic_info), &bytes_returned); | |
| 324 | |
| 325 VERIFY_SUCCESS(g_nt.Close(query_section)); | |
| 326 | |
| 327 if (!NT_SUCCESS(ret) || sizeof(basic_info) != bytes_returned) | |
| 328 return false; | |
| 329 | |
| 330 if (!(basic_info.Attributes & SEC_IMAGE)) | |
| 331 return false; | |
| 332 | |
| 333 return true; | |
| 334 } | |
| 335 | |
| 336 UNICODE_STRING* AnsiToUnicode(const char* string) { | |
| 337 ANSI_STRING ansi_string; | |
| 338 ansi_string.Length = static_cast<USHORT>(g_nt.strlen(string)); | |
| 339 ansi_string.MaximumLength = ansi_string.Length + 1; | |
| 340 ansi_string.Buffer = const_cast<char*>(string); | |
| 341 | |
| 342 if (ansi_string.Length > ansi_string.MaximumLength) | |
| 343 return NULL; | |
| 344 | |
| 345 size_t name_bytes = ansi_string.MaximumLength * sizeof(wchar_t) + | |
| 346 sizeof(UNICODE_STRING); | |
| 347 | |
| 348 UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>( | |
| 349 new(NT_ALLOC) char[name_bytes]); | |
| 350 if (!out_string) | |
| 351 return NULL; | |
| 352 | |
| 353 out_string->MaximumLength = ansi_string.MaximumLength * sizeof(wchar_t); | |
| 354 out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]); | |
| 355 | |
| 356 BOOLEAN alloc_destination = FALSE; | |
| 357 NTSTATUS ret = g_nt.RtlAnsiStringToUnicodeString(out_string, &ansi_string, | |
| 358 alloc_destination); | |
| 359 DCHECK_NT(STATUS_BUFFER_OVERFLOW != ret); | |
| 360 if (!NT_SUCCESS(ret)) { | |
| 361 operator delete(out_string, NT_ALLOC); | |
| 362 return NULL; | |
| 363 } | |
| 364 | |
| 365 return out_string; | |
| 366 } | |
| 367 | |
| 368 UNICODE_STRING* GetImageInfoFromModule(HMODULE module, uint32* flags) { | |
| 369 UNICODE_STRING* out_name = NULL; | |
| 370 __try { | |
| 371 do { | |
| 372 *flags = 0; | |
| 373 base::win::PEImage pe(module); | |
| 374 | |
| 375 if (!pe.VerifyMagic()) | |
| 376 break; | |
| 377 *flags |= MODULE_IS_PE_IMAGE; | |
| 378 | |
| 379 PIMAGE_EXPORT_DIRECTORY exports = pe.GetExportDirectory(); | |
| 380 if (exports) { | |
| 381 char* name = reinterpret_cast<char*>(pe.RVAToAddr(exports->Name)); | |
| 382 out_name = AnsiToUnicode(name); | |
| 383 } | |
| 384 | |
| 385 PIMAGE_NT_HEADERS headers = pe.GetNTHeaders(); | |
| 386 if (headers) { | |
| 387 if (headers->OptionalHeader.AddressOfEntryPoint) | |
| 388 *flags |= MODULE_HAS_ENTRY_POINT; | |
| 389 if (headers->OptionalHeader.SizeOfCode) | |
| 390 *flags |= MODULE_HAS_CODE; | |
| 391 } | |
| 392 } while (false); | |
| 393 } __except(EXCEPTION_EXECUTE_HANDLER) { | |
| 394 } | |
| 395 | |
| 396 return out_name; | |
| 397 } | |
| 398 | |
| 399 UNICODE_STRING* GetBackingFilePath(PVOID address) { | |
| 400 // We'll start with something close to max_path charactes for the name. | |
| 401 ULONG buffer_bytes = MAX_PATH * 2; | |
| 402 | |
| 403 for (;;) { | |
| 404 MEMORY_SECTION_NAME* section_name = reinterpret_cast<MEMORY_SECTION_NAME*>( | |
| 405 new(NT_ALLOC) char[buffer_bytes]); | |
| 406 | |
| 407 if (!section_name) | |
| 408 return NULL; | |
| 409 | |
| 410 ULONG returned_bytes; | |
| 411 NTSTATUS ret = g_nt.QueryVirtualMemory(NtCurrentProcess, address, | |
| 412 MemorySectionName, section_name, | |
| 413 buffer_bytes, &returned_bytes); | |
| 414 | |
| 415 if (STATUS_BUFFER_OVERFLOW == ret) { | |
| 416 // Retry the call with the given buffer size. | |
| 417 operator delete(section_name, NT_ALLOC); | |
| 418 section_name = NULL; | |
| 419 buffer_bytes = returned_bytes; | |
| 420 continue; | |
| 421 } | |
| 422 if (!NT_SUCCESS(ret)) { | |
| 423 operator delete(section_name, NT_ALLOC); | |
| 424 return NULL; | |
| 425 } | |
| 426 | |
| 427 return reinterpret_cast<UNICODE_STRING*>(section_name); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path) { | |
| 432 if ((!module_path) || (!module_path->Buffer)) | |
| 433 return NULL; | |
| 434 | |
| 435 wchar_t* sep = NULL; | |
| 436 int start_pos = module_path->Length / sizeof(wchar_t) - 1; | |
| 437 int ix = start_pos; | |
| 438 | |
| 439 for (; ix >= 0; --ix) { | |
| 440 if (module_path->Buffer[ix] == L'\\') { | |
| 441 sep = &module_path->Buffer[ix]; | |
| 442 break; | |
| 443 } | |
| 444 } | |
| 445 | |
| 446 // Ends with path separator. Not a valid module name. | |
| 447 if ((ix == start_pos) && sep) | |
| 448 return NULL; | |
| 449 | |
| 450 // No path separator found. Use the entire name. | |
| 451 if (!sep) { | |
| 452 sep = &module_path->Buffer[-1]; | |
| 453 } | |
| 454 | |
| 455 // Add one to the size so we can null terminate the string. | |
| 456 size_t size_bytes = (start_pos - ix + 1) * sizeof(wchar_t); | |
| 457 | |
| 458 // Based on the code above, size_bytes should always be small enough | |
| 459 // to make the static_cast below safe. | |
| 460 DCHECK_NT(kuint16max > size_bytes); | |
| 461 char* str_buffer = new(NT_ALLOC) char[size_bytes + sizeof(UNICODE_STRING)]; | |
| 462 if (!str_buffer) | |
| 463 return NULL; | |
| 464 | |
| 465 UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>(str_buffer); | |
| 466 out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]); | |
| 467 out_string->Length = static_cast<USHORT>(size_bytes - sizeof(wchar_t)); | |
| 468 out_string->MaximumLength = static_cast<USHORT>(size_bytes); | |
| 469 | |
| 470 NTSTATUS ret = CopyData(out_string->Buffer, &sep[1], out_string->Length); | |
| 471 if (!NT_SUCCESS(ret)) { | |
| 472 operator delete(out_string, NT_ALLOC); | |
| 473 return NULL; | |
| 474 } | |
| 475 | |
| 476 out_string->Buffer[out_string->Length / sizeof(wchar_t)] = L'\0'; | |
| 477 return out_string; | |
| 478 } | |
| 479 | |
| 480 NTSTATUS AutoProtectMemory::ChangeProtection(void* address, size_t bytes, | |
| 481 ULONG protect) { | |
| 482 DCHECK_NT(!changed_); | |
| 483 SIZE_T new_bytes = bytes; | |
| 484 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address, | |
| 485 &new_bytes, protect, &old_protect_); | |
| 486 if (NT_SUCCESS(ret)) { | |
| 487 changed_ = true; | |
| 488 address_ = address; | |
| 489 bytes_ = new_bytes; | |
| 490 } | |
| 491 | |
| 492 return ret; | |
| 493 } | |
| 494 | |
| 495 NTSTATUS AutoProtectMemory::RevertProtection() { | |
| 496 if (!changed_) | |
| 497 return STATUS_SUCCESS; | |
| 498 | |
| 499 DCHECK_NT(address_); | |
| 500 DCHECK_NT(bytes_); | |
| 501 | |
| 502 SIZE_T new_bytes = bytes_; | |
| 503 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address_, | |
| 504 &new_bytes, old_protect_, | |
| 505 &old_protect_); | |
| 506 DCHECK_NT(NT_SUCCESS(ret)); | |
| 507 | |
| 508 changed_ = false; | |
| 509 address_ = NULL; | |
| 510 bytes_ = 0; | |
| 511 old_protect_ = 0; | |
| 512 | |
| 513 return ret; | |
| 514 } | |
| 515 | |
| 516 bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info, DWORD length, | |
| 517 uint32 file_info_class) { | |
| 518 if (FileRenameInformation != file_info_class) | |
| 519 return false; | |
| 520 | |
| 521 if (length < sizeof(FILE_RENAME_INFORMATION)) | |
| 522 return false; | |
| 523 | |
| 524 // Make sure file name length doesn't exceed the message length | |
| 525 if (length - offsetof(FILE_RENAME_INFORMATION, FileName) < | |
| 526 file_info->FileNameLength) | |
| 527 return false; | |
| 528 | |
| 529 // We don't support a root directory. | |
| 530 if (file_info->RootDirectory) | |
| 531 return false; | |
| 532 | |
| 533 // Check if it starts with \\??\\. We don't support relative paths. | |
| 534 if (file_info->FileNameLength < 4 || file_info->FileNameLength > kuint16max) | |
| 535 return false; | |
| 536 | |
| 537 if (file_info->FileName[0] != L'\\' || | |
| 538 file_info->FileName[1] != L'?' || | |
| 539 file_info->FileName[2] != L'?' || | |
| 540 file_info->FileName[3] != L'\\') | |
| 541 return false; | |
| 542 | |
| 543 return true; | |
| 544 } | |
| 545 | |
| 546 } // namespace sandbox | |
| 547 | |
| 548 void* operator new(size_t size, sandbox::AllocationType type, | |
| 549 void* near_to) { | |
| 550 using namespace sandbox; | |
| 551 | |
| 552 if (NT_ALLOC == type) { | |
| 553 if (!InitHeap()) | |
| 554 return NULL; | |
| 555 | |
| 556 // Use default flags for the allocation. | |
| 557 return g_nt.RtlAllocateHeap(sandbox::g_heap, 0, size); | |
| 558 } else if (NT_PAGE == type) { | |
| 559 return AllocateNearTo(near_to, size); | |
| 560 } | |
| 561 NOTREACHED_NT(); | |
| 562 return NULL; | |
| 563 } | |
| 564 | |
| 565 void operator delete(void* memory, sandbox::AllocationType type) { | |
| 566 using namespace sandbox; | |
| 567 | |
| 568 if (NT_ALLOC == type) { | |
| 569 // Use default flags. | |
| 570 VERIFY(g_nt.RtlFreeHeap(sandbox::g_heap, 0, memory)); | |
| 571 } else if (NT_PAGE == type) { | |
| 572 void* base = memory; | |
| 573 SIZE_T size = 0; | |
| 574 VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size, | |
| 575 MEM_RELEASE)); | |
| 576 } else { | |
| 577 NOTREACHED_NT(); | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 void operator delete(void* memory, sandbox::AllocationType type, | |
| 582 void* near_to) { | |
| 583 UNREFERENCED_PARAMETER(near_to); | |
| 584 operator delete(memory, type); | |
| 585 } | |
| 586 | |
| 587 void* __cdecl operator new(size_t size, void* buffer, | |
| 588 sandbox::AllocationType type) { | |
| 589 UNREFERENCED_PARAMETER(size); | |
| 590 UNREFERENCED_PARAMETER(type); | |
| 591 return buffer; | |
| 592 } | |
| 593 | |
| 594 void __cdecl operator delete(void* memory, void* buffer, | |
| 595 sandbox::AllocationType type) { | |
| 596 UNREFERENCED_PARAMETER(memory); | |
| 597 UNREFERENCED_PARAMETER(buffer); | |
| 598 UNREFERENCED_PARAMETER(type); | |
| 599 } | |
| OLD | NEW |