summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/base/win
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/chromium/base/win')
-rw-r--r--security/sandbox/chromium/base/win/pe_image.cc580
-rw-r--r--security/sandbox/chromium/base/win/pe_image.h265
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle.cc248
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle.h182
-rw-r--r--security/sandbox/chromium/base/win/scoped_process_information.cc147
-rw-r--r--security/sandbox/chromium/base/win/scoped_process_information.h83
-rw-r--r--security/sandbox/chromium/base/win/startup_information.cc109
-rw-r--r--security/sandbox/chromium/base/win/startup_information.h51
-rw-r--r--security/sandbox/chromium/base/win/windows_version.cc225
-rw-r--r--security/sandbox/chromium/base/win/windows_version.h133
10 files changed, 2023 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/win/pe_image.cc b/security/sandbox/chromium/base/win/pe_image.cc
new file mode 100644
index 000000000..4b5d62099
--- /dev/null
+++ b/security/sandbox/chromium/base/win/pe_image.cc
@@ -0,0 +1,580 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file implements PEImage, a generic class to manipulate PE files.
+// This file was adapted from GreenBorder's Code.
+
+#include <stddef.h>
+
+#include "base/win/pe_image.h"
+
+namespace base {
+namespace win {
+
+// Structure to perform imports enumerations.
+struct EnumAllImportsStorage {
+ PEImage::EnumImportsFunction callback;
+ PVOID cookie;
+};
+
+namespace {
+
+// PdbInfo Signature
+const DWORD kPdbInfoSignature = 'SDSR';
+
+// Compare two strings byte by byte on an unsigned basis.
+// if s1 == s2, return 0
+// if s1 < s2, return negative
+// if s1 > s2, return positive
+// Exception if inputs are invalid.
+int StrCmpByByte(LPCSTR s1, LPCSTR s2) {
+ while (*s1 != '\0' && *s1 == *s2) {
+ ++s1;
+ ++s2;
+ }
+
+ return (*reinterpret_cast<const unsigned char*>(s1) -
+ *reinterpret_cast<const unsigned char*>(s2));
+}
+
+struct PdbInfo {
+ DWORD Signature;
+ GUID Guid;
+ DWORD Age;
+ char PdbFileName[1];
+};
+
+} // namespace
+
+// Callback used to enumerate imports. See EnumImportChunksFunction.
+bool ProcessImportChunk(const PEImage &image, LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat, PVOID cookie) {
+ EnumAllImportsStorage& storage =
+ *reinterpret_cast<EnumAllImportsStorage*>(cookie);
+
+ return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
+ storage.cookie);
+}
+
+// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction.
+bool ProcessDelayImportChunk(const PEImage& image,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) {
+ EnumAllImportsStorage& storage =
+ *reinterpret_cast<EnumAllImportsStorage*>(cookie);
+
+ return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
+ module, name_table, iat, storage.cookie);
+}
+
+void PEImage::set_module(HMODULE module) {
+ module_ = module;
+}
+
+PIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
+ return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
+}
+
+PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
+ PIMAGE_DOS_HEADER dos_header = GetDosHeader();
+
+ return reinterpret_cast<PIMAGE_NT_HEADERS>(
+ reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+ PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
+
+ if (section < nt_headers->FileHeader.NumberOfSections)
+ return first_section + section;
+ else
+ return NULL;
+}
+
+WORD PEImage::GetNumSections() const {
+ return GetNTHeaders()->FileHeader.NumberOfSections;
+}
+
+DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+
+ return nt_headers->OptionalHeader.DataDirectory[directory].Size;
+}
+
+PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+
+ return RVAToAddr(
+ nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress);
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
+ PBYTE target = reinterpret_cast<PBYTE>(address);
+ PIMAGE_SECTION_HEADER section;
+
+ for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) {
+ // Don't use the virtual RVAToAddr.
+ PBYTE start = reinterpret_cast<PBYTE>(
+ PEImage::RVAToAddr(section->VirtualAddress));
+
+ DWORD size = section->Misc.VirtualSize;
+
+ if ((start <= target) && (start + size > target))
+ return section;
+ }
+
+ return NULL;
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
+ LPCSTR section_name) const {
+ if (NULL == section_name)
+ return NULL;
+
+ PIMAGE_SECTION_HEADER ret = NULL;
+ int num_sections = GetNumSections();
+
+ for (int i = 0; i < num_sections; i++) {
+ PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
+ if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
+ sizeof(section->Name))) {
+ ret = section;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+bool PEImage::GetDebugId(LPGUID guid, LPDWORD age) const {
+ if (NULL == guid || NULL == age) {
+ return false;
+ }
+
+ DWORD debug_directory_size =
+ GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG);
+ PIMAGE_DEBUG_DIRECTORY debug_directory =
+ reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG));
+
+ size_t directory_count =
+ debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ for (size_t index = 0; index < directory_count; ++index) {
+ if (debug_directory[index].Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
+ PdbInfo* pdb_info = reinterpret_cast<PdbInfo*>(
+ RVAToAddr(debug_directory[index].AddressOfRawData));
+ if (pdb_info->Signature != kPdbInfoSignature) {
+ // Unsupported PdbInfo signature
+ return false;
+ }
+ *guid = pdb_info->Guid;
+ *age = pdb_info->Age;
+ return true;
+ }
+ }
+ return false;
+}
+
+PDWORD PEImage::GetExportEntry(LPCSTR name) const {
+ PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
+
+ if (NULL == exports)
+ return NULL;
+
+ WORD ordinal = 0;
+ if (!GetProcOrdinal(name, &ordinal))
+ return NULL;
+
+ PDWORD functions = reinterpret_cast<PDWORD>(
+ RVAToAddr(exports->AddressOfFunctions));
+
+ return functions + ordinal - exports->Base;
+}
+
+FARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
+ PDWORD export_entry = GetExportEntry(function_name);
+ if (NULL == export_entry)
+ return NULL;
+
+ PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
+
+ PBYTE exports = reinterpret_cast<PBYTE>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
+
+ // Check for forwarded exports as a special case.
+ if (exports <= function && exports + size > function)
+ return reinterpret_cast<FARPROC>(-1);
+
+ return reinterpret_cast<FARPROC>(function);
+}
+
+bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const {
+ if (NULL == ordinal)
+ return false;
+
+ PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
+
+ if (NULL == exports)
+ return false;
+
+ if (IsOrdinal(function_name)) {
+ *ordinal = ToOrdinal(function_name);
+ } else {
+ PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
+ PDWORD lower = names;
+ PDWORD upper = names + exports->NumberOfNames;
+ int cmp = -1;
+
+ // Binary Search for the name.
+ while (lower != upper) {
+ PDWORD middle = lower + (upper - lower) / 2;
+ LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
+
+ // This may be called by sandbox before MSVCRT dll loads, so can't use
+ // CRT function here.
+ cmp = StrCmpByByte(function_name, name);
+
+ if (cmp == 0) {
+ lower = middle;
+ break;
+ }
+
+ if (cmp > 0)
+ lower = middle + 1;
+ else
+ upper = middle;
+ }
+
+ if (cmp != 0)
+ return false;
+
+
+ PWORD ordinals = reinterpret_cast<PWORD>(
+ RVAToAddr(exports->AddressOfNameOrdinals));
+
+ *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
+ }
+
+ return true;
+}
+
+bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+ UINT num_sections = nt_headers->FileHeader.NumberOfSections;
+ PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
+
+ for (UINT i = 0; i < num_sections; i++, section++) {
+ PVOID section_start = RVAToAddr(section->VirtualAddress);
+ DWORD size = section->Misc.VirtualSize;
+
+ if (!callback(*this, section, section_start, size, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
+ PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
+
+ // Check if there are any exports at all.
+ if (NULL == directory || 0 == size)
+ return true;
+
+ PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
+ directory);
+ UINT ordinal_base = exports->Base;
+ UINT num_funcs = exports->NumberOfFunctions;
+ UINT num_names = exports->NumberOfNames;
+ PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr(
+ exports->AddressOfFunctions));
+ PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
+ PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr(
+ exports->AddressOfNameOrdinals));
+
+ for (UINT count = 0; count < num_funcs; count++) {
+ PVOID func = RVAToAddr(functions[count]);
+ if (NULL == func)
+ continue;
+
+ // Check for a name.
+ LPCSTR name = NULL;
+ UINT hint;
+ for (hint = 0; hint < num_names; hint++) {
+ if (ordinals[hint] == count) {
+ name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
+ break;
+ }
+ }
+
+ if (name == NULL)
+ hint = 0;
+
+ // Check for forwarded exports.
+ LPCSTR forward = NULL;
+ if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
+ reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) +
+ size) {
+ forward = reinterpret_cast<LPCSTR>(func);
+ func = 0;
+ }
+
+ if (!callback(*this, ordinal_base + count, hint, name, func, forward,
+ cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
+ PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
+ directory);
+
+ if (!directory)
+ return true;
+
+ while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock &&
+ size >= base->SizeOfBlock) {
+ PWORD reloc = reinterpret_cast<PWORD>(base + 1);
+ UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
+ sizeof(WORD);
+
+ for (UINT i = 0; i < num_relocs; i++, reloc++) {
+ WORD type = *reloc >> 12;
+ PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
+
+ if (!callback(*this, type, address, cookie))
+ return false;
+ }
+
+ size -= base->SizeOfBlock;
+ base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
+ reinterpret_cast<char*>(base) + base->SizeOfBlock);
+ }
+
+ return true;
+}
+
+bool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
+ PVOID cookie) const {
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
+ PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
+
+ if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
+ return true;
+
+ for (; import->FirstThunk; import++) {
+ LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
+ PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(import->OriginalFirstThunk));
+ PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(import->FirstThunk));
+
+ if (!callback(*this, module_name, name_table, iat, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat, PVOID cookie) const {
+ if (NULL == name_table)
+ return false;
+
+ for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
+ LPCSTR name = NULL;
+ WORD ordinal = 0;
+ WORD hint = 0;
+
+ if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
+ ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
+ } else {
+ PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ RVAToAddr(name_table->u1.ForwarderString));
+
+ hint = import->Hint;
+ name = reinterpret_cast<LPCSTR>(&import->Name);
+ }
+
+ if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const {
+ EnumAllImportsStorage temp = { callback, cookie };
+ return EnumImportChunks(ProcessImportChunk, &temp);
+}
+
+bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
+ PVOID cookie) const {
+ PVOID directory = GetImageDirectoryEntryAddr(
+ IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+ PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
+
+ if (directory == NULL || size == 0)
+ return true;
+
+ for (; delay_descriptor->rvaHmod; delay_descriptor++) {
+ PIMAGE_THUNK_DATA name_table;
+ PIMAGE_THUNK_DATA iat;
+ LPCSTR module_name;
+
+ // check if VC7-style imports, using RVAs instead of
+ // VC6-style addresses.
+ bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
+
+ if (rvas) {
+ module_name =
+ reinterpret_cast<LPCSTR>(RVAToAddr(delay_descriptor->rvaDLLName));
+ name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(delay_descriptor->rvaINT));
+ iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(delay_descriptor->rvaIAT));
+ } else {
+ // Values in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT are 32-bit, even on 64-bit
+ // platforms. See section 4.8 of PECOFF image spec rev 8.3.
+ module_name = reinterpret_cast<LPCSTR>(
+ static_cast<uintptr_t>(delay_descriptor->rvaDLLName));
+ name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ static_cast<uintptr_t>(delay_descriptor->rvaINT));
+ iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ static_cast<uintptr_t>(delay_descriptor->rvaIAT));
+ }
+
+ if (!callback(*this, delay_descriptor, module_name, name_table, iat,
+ cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const {
+ for (; name_table->u1.Ordinal; name_table++, iat++) {
+ LPCSTR name = NULL;
+ WORD ordinal = 0;
+ WORD hint = 0;
+
+ if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
+ ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
+ } else {
+ PIMAGE_IMPORT_BY_NAME import;
+ bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
+
+ if (rvas) {
+ import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ RVAToAddr(name_table->u1.ForwarderString));
+ } else {
+ import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ name_table->u1.ForwarderString);
+ }
+
+ hint = import->Hint;
+ name = reinterpret_cast<LPCSTR>(&import->Name);
+ }
+
+ if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
+ PVOID cookie) const {
+ EnumAllImportsStorage temp = { callback, cookie };
+ return EnumDelayImportChunks(ProcessDelayImportChunk, &temp);
+}
+
+bool PEImage::VerifyMagic() const {
+ PIMAGE_DOS_HEADER dos_header = GetDosHeader();
+
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
+ return false;
+
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+
+ if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
+ return false;
+
+ if (nt_headers->FileHeader.SizeOfOptionalHeader !=
+ sizeof(IMAGE_OPTIONAL_HEADER))
+ return false;
+
+ if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+ return false;
+
+ return true;
+}
+
+bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD* on_disk_offset) const {
+ LPVOID address = RVAToAddr(rva);
+ return ImageAddrToOnDiskOffset(address, on_disk_offset);
+}
+
+bool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
+ DWORD* on_disk_offset) const {
+ if (NULL == address)
+ return false;
+
+ // Get the section that this address belongs to.
+ PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
+ if (NULL == section_header)
+ return false;
+
+ // Don't follow the virtual RVAToAddr, use the one on the base.
+ DWORD offset_within_section =
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(address)) -
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(
+ PEImage::RVAToAddr(section_header->VirtualAddress)));
+
+ *on_disk_offset = section_header->PointerToRawData + offset_within_section;
+ return true;
+}
+
+PVOID PEImage::RVAToAddr(DWORD rva) const {
+ if (rva == 0)
+ return NULL;
+
+ return reinterpret_cast<char*>(module_) + rva;
+}
+
+PVOID PEImageAsData::RVAToAddr(DWORD rva) const {
+ if (rva == 0)
+ return NULL;
+
+ PVOID in_memory = PEImage::RVAToAddr(rva);
+ DWORD disk_offset;
+
+ if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
+ return NULL;
+
+ return PEImage::RVAToAddr(disk_offset);
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/pe_image.h b/security/sandbox/chromium/base/win/pe_image.h
new file mode 100644
index 000000000..4c36bcf85
--- /dev/null
+++ b/security/sandbox/chromium/base/win/pe_image.h
@@ -0,0 +1,265 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file was adapted from GreenBorder's Code.
+// To understand what this class is about (for other than well known functions
+// as GetProcAddress), a good starting point is "An In-Depth Look into the
+// Win32 Portable Executable File Format" by Matt Pietrek:
+// http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx
+
+#ifndef BASE_WIN_PE_IMAGE_H_
+#define BASE_WIN_PE_IMAGE_H_
+
+#include <windows.h>
+
+#if defined(_WIN32_WINNT_WIN8)
+// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h.
+#undef FACILITY_VISUALCPP
+#endif
+#include <DelayIMP.h>
+
+namespace base {
+namespace win {
+
+// This class is a wrapper for the Portable Executable File Format (PE).
+// Its main purpose is to provide an easy way to work with imports and exports
+// from a file, mapped in memory as image.
+class PEImage {
+ public:
+ // Callback to enumerate sections.
+ // cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumSectionsFunction)(const PEImage &image,
+ PIMAGE_SECTION_HEADER header,
+ PVOID section_start, DWORD section_size,
+ PVOID cookie);
+
+ // Callback to enumerate exports.
+ // function is the actual address of the symbol. If forward is not null, it
+ // contains the dll and symbol to forward this export to. cookie is the value
+ // passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumExportsFunction)(const PEImage &image, DWORD ordinal,
+ DWORD hint, LPCSTR name, PVOID function,
+ LPCSTR forward, PVOID cookie);
+
+ // Callback to enumerate import blocks.
+ // name_table and iat point to the imports name table and address table for
+ // this block. cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumImportChunksFunction)(const PEImage &image, LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat, PVOID cookie);
+
+ // Callback to enumerate imports.
+ // module is the dll that exports this symbol. cookie is the value passed to
+ // the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumImportsFunction)(const PEImage &image, LPCSTR module,
+ DWORD ordinal, LPCSTR name, DWORD hint,
+ PIMAGE_THUNK_DATA iat, PVOID cookie);
+
+ // Callback to enumerate dalayed import blocks.
+ // module is the dll that exports this block of symbols. cookie is the value
+ // passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumDelayImportChunksFunction)(const PEImage &image,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie);
+
+ // Callback to enumerate relocations.
+ // cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ typedef bool (*EnumRelocsFunction)(const PEImage &image, WORD type,
+ PVOID address, PVOID cookie);
+
+ explicit PEImage(HMODULE module) : module_(module) {}
+ explicit PEImage(const void* module) {
+ module_ = reinterpret_cast<HMODULE>(const_cast<void*>(module));
+ }
+
+ virtual ~PEImage() {}
+
+ // Gets the HMODULE for this object.
+ HMODULE module() const;
+
+ // Sets this object's HMODULE.
+ void set_module(HMODULE module);
+
+ // Checks if this symbol is actually an ordinal.
+ static bool IsOrdinal(LPCSTR name);
+
+ // Converts a named symbol to the corresponding ordinal.
+ static WORD ToOrdinal(LPCSTR name);
+
+ // Returns the DOS_HEADER for this PE.
+ PIMAGE_DOS_HEADER GetDosHeader() const;
+
+ // Returns the NT_HEADER for this PE.
+ PIMAGE_NT_HEADERS GetNTHeaders() const;
+
+ // Returns number of sections of this PE.
+ WORD GetNumSections() const;
+
+ // Returns the header for a given section.
+ // returns NULL if there is no such section.
+ PIMAGE_SECTION_HEADER GetSectionHeader(UINT section) const;
+
+ // Returns the size of a given directory entry.
+ DWORD GetImageDirectoryEntrySize(UINT directory) const;
+
+ // Returns the address of a given directory entry.
+ PVOID GetImageDirectoryEntryAddr(UINT directory) const;
+
+ // Returns the section header for a given address.
+ // Use: s = image.GetImageSectionFromAddr(a);
+ // Post: 's' is the section header of the section that contains 'a'
+ // or NULL if there is no such section.
+ PIMAGE_SECTION_HEADER GetImageSectionFromAddr(PVOID address) const;
+
+ // Returns the section header for a given section.
+ PIMAGE_SECTION_HEADER GetImageSectionHeaderByName(LPCSTR section_name) const;
+
+ // Returns the first block of imports.
+ PIMAGE_IMPORT_DESCRIPTOR GetFirstImportChunk() const;
+
+ // Returns the exports directory.
+ PIMAGE_EXPORT_DIRECTORY GetExportDirectory() const;
+
+ // Returns the debug id (guid+age).
+ bool GetDebugId(LPGUID guid, LPDWORD age) const;
+
+ // Returns a given export entry.
+ // Use: e = image.GetExportEntry(f);
+ // Pre: 'f' is either a zero terminated string or ordinal
+ // Post: 'e' is a pointer to the export directory entry
+ // that contains 'f's export RVA, or NULL if 'f'
+ // is not exported from this image
+ PDWORD GetExportEntry(LPCSTR name) const;
+
+ // Returns the address for a given exported symbol.
+ // Use: p = image.GetProcAddress(f);
+ // Pre: 'f' is either a zero terminated string or ordinal.
+ // Post: if 'f' is a non-forwarded export from image, 'p' is
+ // the exported function. If 'f' is a forwarded export
+ // then p is the special value -1. In this case
+ // RVAToAddr(*GetExportEntry) can be used to resolve
+ // the string that describes the forward.
+ FARPROC GetProcAddress(LPCSTR function_name) const;
+
+ // Retrieves the ordinal for a given exported symbol.
+ // Returns true if the symbol was found.
+ bool GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const;
+
+ // Enumerates PE sections.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumSections(EnumSectionsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE exports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumExports(EnumExportsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE imports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumAllImports(EnumImportsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE import blocks.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumImportChunks(EnumImportChunksFunction callback, PVOID cookie) const;
+
+ // Enumerates the imports from a single PE import block.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumOneImportChunk(EnumImportsFunction callback, LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table, PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const;
+
+
+ // Enumerates PE delay imports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumAllDelayImports(EnumImportsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE delay import blocks.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
+ PVOID cookie) const;
+
+ // Enumerates imports from a single PE delay import block.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumOneDelayImportChunk(EnumImportsFunction callback,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const;
+
+ // Enumerates PE relocation entries.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const;
+
+ // Verifies the magic values on the PE file.
+ // Returns true if all values are correct.
+ bool VerifyMagic() const;
+
+ // Converts an rva value to the appropriate address.
+ virtual PVOID RVAToAddr(DWORD rva) const;
+
+ // Converts an rva value to an offset on disk.
+ // Returns true on success.
+ bool ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const;
+
+ // Converts an address to an offset on disk.
+ // Returns true on success.
+ bool ImageAddrToOnDiskOffset(LPVOID address, DWORD *on_disk_offset) const;
+
+ private:
+ HMODULE module_;
+};
+
+// This class is an extension to the PEImage class that allows working with PE
+// files mapped as data instead of as image file.
+class PEImageAsData : public PEImage {
+ public:
+ explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {}
+
+ PVOID RVAToAddr(DWORD rva) const override;
+};
+
+inline bool PEImage::IsOrdinal(LPCSTR name) {
+ return reinterpret_cast<uintptr_t>(name) <= 0xFFFF;
+}
+
+inline WORD PEImage::ToOrdinal(LPCSTR name) {
+ return static_cast<WORD>(reinterpret_cast<intptr_t>(name));
+}
+
+inline HMODULE PEImage::module() const {
+ return module_;
+}
+
+inline PIMAGE_IMPORT_DESCRIPTOR PEImage::GetFirstImportChunk() const {
+ return reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_IMPORT));
+}
+
+inline PIMAGE_EXPORT_DIRECTORY PEImage::GetExportDirectory() const {
+ return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
+}
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_PE_IMAGE_H_
diff --git a/security/sandbox/chromium/base/win/scoped_handle.cc b/security/sandbox/chromium/base/win/scoped_handle.cc
new file mode 100644
index 000000000..9c21603a0
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/scoped_handle.h"
+
+#include <stddef.h>
+
+#include <unordered_map>
+
+#include "base/debug/alias.h"
+#include "base/hash.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/synchronization/lock_impl.h"
+
+extern "C" {
+__declspec(dllexport) void* GetHandleVerifier();
+typedef void* (*GetHandleVerifierFn)();
+}
+
+namespace {
+
+struct HandleHash {
+ size_t operator()(const HANDLE& handle) const {
+ char buffer[sizeof(handle)];
+ memcpy(buffer, &handle, sizeof(handle));
+ return base::Hash(buffer, sizeof(buffer));
+ }
+};
+
+struct Info {
+ const void* owner;
+ const void* pc1;
+ const void* pc2;
+ DWORD thread_id;
+};
+typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
+
+// g_lock protects the handle map and setting g_active_verifier.
+typedef base::internal::LockImpl NativeLock;
+base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
+
+bool CloseHandleWrapper(HANDLE handle) {
+ if (!::CloseHandle(handle))
+ CHECK(false);
+ return true;
+}
+
+// Simple automatic locking using a native critical section so it supports
+// recursive locking.
+class AutoNativeLock {
+ public:
+ explicit AutoNativeLock(NativeLock& lock) : lock_(lock) {
+ lock_.Lock();
+ }
+
+ ~AutoNativeLock() {
+ lock_.Unlock();
+ }
+
+ private:
+ NativeLock& lock_;
+ DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
+};
+
+// Implements the actual object that is verifying handles for this process.
+// The active instance is shared across the module boundary but there is no
+// way to delete this object from the wrong side of it (or any side, actually).
+class ActiveVerifier {
+ public:
+ explicit ActiveVerifier(bool enabled)
+ : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
+ }
+
+ // Retrieves the current verifier.
+ static ActiveVerifier* Get();
+
+ // The methods required by HandleTraits. They are virtual because we need to
+ // forward the call execution to another module, instead of letting the
+ // compiler call the version that is linked in the current module.
+ virtual bool CloseHandle(HANDLE handle);
+ virtual void StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+ virtual void StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+ virtual void Disable();
+ virtual void OnHandleBeingClosed(HANDLE handle);
+
+ private:
+ ~ActiveVerifier(); // Not implemented.
+
+ static void InstallVerifier();
+
+ bool enabled_;
+ bool closing_;
+ NativeLock* lock_;
+ HandleMap map_;
+ DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
+};
+ActiveVerifier* g_active_verifier = NULL;
+
+// static
+ActiveVerifier* ActiveVerifier::Get() {
+ if (!g_active_verifier)
+ ActiveVerifier::InstallVerifier();
+
+ return g_active_verifier;
+}
+
+// static
+void ActiveVerifier::InstallVerifier() {
+#if defined(COMPONENT_BUILD)
+ AutoNativeLock lock(g_lock.Get());
+ g_active_verifier = new ActiveVerifier(true);
+#else
+ // If you are reading this, wondering why your process seems deadlocked, take
+ // a look at your DllMain code and remove things that should not be done
+ // there, like doing whatever gave you that nice windows handle you are trying
+ // to store in a ScopedHandle.
+ HMODULE main_module = ::GetModuleHandle(NULL);
+ GetHandleVerifierFn get_handle_verifier =
+ reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
+ main_module, "GetHandleVerifier"));
+
+ if (!get_handle_verifier) {
+ g_active_verifier = new ActiveVerifier(false);
+ return;
+ }
+
+ ActiveVerifier* verifier =
+ reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
+
+ // This lock only protects against races in this module, which is fine.
+ AutoNativeLock lock(g_lock.Get());
+ g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
+#endif
+}
+
+bool ActiveVerifier::CloseHandle(HANDLE handle) {
+ if (!enabled_)
+ return CloseHandleWrapper(handle);
+
+ AutoNativeLock lock(*lock_);
+ closing_ = true;
+ CloseHandleWrapper(handle);
+ closing_ = false;
+
+ return true;
+}
+
+void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ if (!enabled_)
+ return;
+
+ // Grab the thread id before the lock.
+ DWORD thread_id = GetCurrentThreadId();
+
+ AutoNativeLock lock(*lock_);
+
+ Info handle_info = { owner, pc1, pc2, thread_id };
+ std::pair<HANDLE, Info> item(handle, handle_info);
+ std::pair<HandleMap::iterator, bool> result = map_.insert(item);
+ if (!result.second) {
+ Info other = result.first->second;
+ base::debug::Alias(&other);
+ CHECK(false);
+ }
+}
+
+void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ if (!enabled_)
+ return;
+
+ AutoNativeLock lock(*lock_);
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end())
+ CHECK(false);
+
+ Info other = i->second;
+ if (other.owner != owner) {
+ base::debug::Alias(&other);
+ CHECK(false);
+ }
+
+ map_.erase(i);
+}
+
+void ActiveVerifier::Disable() {
+ enabled_ = false;
+}
+
+void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
+ if (!enabled_)
+ return;
+
+ AutoNativeLock lock(*lock_);
+ if (closing_)
+ return;
+
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end())
+ return;
+
+ Info other = i->second;
+ base::debug::Alias(&other);
+ CHECK(false);
+}
+
+} // namespace
+
+void* GetHandleVerifier() {
+ return g_active_verifier;
+}
+
+namespace base {
+namespace win {
+
+// Static.
+bool HandleTraits::CloseHandle(HANDLE handle) {
+ return ActiveVerifier::Get()->CloseHandle(handle);
+}
+
+// Static.
+void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2);
+}
+
+// Static.
+void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2);
+}
+
+void DisableHandleVerifier() {
+ return ActiveVerifier::Get()->Disable();
+}
+
+void OnHandleBeingClosed(HANDLE handle) {
+ return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/scoped_handle.h b/security/sandbox/chromium/base/win/scoped_handle.h
new file mode 100644
index 000000000..404ab6693
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle.h
@@ -0,0 +1,182 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_SCOPED_HANDLE_H_
+#define BASE_WIN_SCOPED_HANDLE_H_
+
+#include <windows.h>
+
+#include "base/base_export.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/move.h"
+
+// TODO(rvargas): remove this with the rest of the verifier.
+#if defined(COMPILER_MSVC)
+#include <intrin.h>
+#define BASE_WIN_GET_CALLER _ReturnAddress()
+#elif defined(COMPILER_GCC)
+#define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\
+ __builtin_return_address(0))
+#endif
+
+namespace base {
+namespace win {
+
+// Generic wrapper for raw handles that takes care of closing handles
+// automatically. The class interface follows the style of
+// the ScopedFILE class with two additions:
+// - IsValid() method can tolerate multiple invalid handle values such as NULL
+// and INVALID_HANDLE_VALUE (-1) for Win32 handles.
+// - Set() (and the constructors and assignment operators that call it)
+// preserve the Windows LastError code. This ensures that GetLastError() can
+// be called after stashing a handle in a GenericScopedHandle object. Doing
+// this explicitly is necessary because of bug 528394 and VC++ 2015.
+template <class Traits, class Verifier>
+class GenericScopedHandle {
+ MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle)
+
+ public:
+ typedef typename Traits::Handle Handle;
+
+ GenericScopedHandle() : handle_(Traits::NullHandle()) {}
+
+ explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
+ Set(handle);
+ }
+
+ GenericScopedHandle(GenericScopedHandle&& other)
+ : handle_(Traits::NullHandle()) {
+ Set(other.Take());
+ }
+
+ ~GenericScopedHandle() {
+ Close();
+ }
+
+ bool IsValid() const {
+ return Traits::IsHandleValid(handle_);
+ }
+
+ GenericScopedHandle& operator=(GenericScopedHandle&& other) {
+ DCHECK_NE(this, &other);
+ Set(other.Take());
+ return *this;
+ }
+
+ void Set(Handle handle) {
+ if (handle_ != handle) {
+ // Preserve old LastError to avoid bug 528394.
+ auto last_error = ::GetLastError();
+ Close();
+
+ if (Traits::IsHandleValid(handle)) {
+ handle_ = handle;
+ Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER,
+ tracked_objects::GetProgramCounter());
+ }
+ ::SetLastError(last_error);
+ }
+ }
+
+ Handle Get() const {
+ return handle_;
+ }
+
+ // Transfers ownership away from this object.
+ Handle Take() {
+ Handle temp = handle_;
+ handle_ = Traits::NullHandle();
+ if (Traits::IsHandleValid(temp)) {
+ Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER,
+ tracked_objects::GetProgramCounter());
+ }
+ return temp;
+ }
+
+ // Explicitly closes the owned handle.
+ void Close() {
+ if (Traits::IsHandleValid(handle_)) {
+ Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER,
+ tracked_objects::GetProgramCounter());
+
+ Traits::CloseHandle(handle_);
+ handle_ = Traits::NullHandle();
+ }
+ }
+
+ private:
+ Handle handle_;
+};
+
+#undef BASE_WIN_GET_CALLER
+
+// The traits class for Win32 handles that can be closed via CloseHandle() API.
+class HandleTraits {
+ public:
+ typedef HANDLE Handle;
+
+ // Closes the handle.
+ static bool BASE_EXPORT CloseHandle(HANDLE handle);
+
+ // Returns true if the handle value is valid.
+ static bool IsHandleValid(HANDLE handle) {
+ return handle != NULL && handle != INVALID_HANDLE_VALUE;
+ }
+
+ // Returns NULL handle value.
+ static HANDLE NullHandle() {
+ return NULL;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
+};
+
+// Do-nothing verifier.
+class DummyVerifierTraits {
+ public:
+ typedef HANDLE Handle;
+
+ static void StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {}
+ static void StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {}
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
+};
+
+// Performs actual run-time tracking.
+class BASE_EXPORT VerifierTraits {
+ public:
+ typedef HANDLE Handle;
+
+ static void StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+ static void StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
+};
+
+typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;
+
+// This function may be called by the embedder to disable the use of
+// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used
+// for ScopedHandle.
+void BASE_EXPORT DisableHandleVerifier();
+
+// This should be called whenever the OS is closing a handle, if extended
+// verification of improper handle closing is desired. If |handle| is being
+// tracked by the handle verifier and ScopedHandle is not the one closing it,
+// a CHECK is generated.
+void BASE_EXPORT OnHandleBeingClosed(HANDLE handle);
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_HANDLE_H_
diff --git a/security/sandbox/chromium/base/win/scoped_process_information.cc b/security/sandbox/chromium/base/win/scoped_process_information.cc
new file mode 100644
index 000000000..634a538ee
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_process_information.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/scoped_process_information.h"
+
+#include "base/logging.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+// Duplicates source into target, returning true upon success. |target| is
+// guaranteed to be untouched in case of failure. Succeeds with no side-effects
+// if source is NULL.
+bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) {
+ if (!source)
+ return true;
+
+ HANDLE temp = NULL;
+
+ // TODO(shrikant): Remove following code as soon as we gather some
+ // information regarding AppContainer related DuplicateHandle failures that
+ // only seem to happen on certain machine and only random launches (normally
+ // renderer launches seem to succeed even on those machines.)
+ if (base::win::GetVersion() == base::win::VERSION_WIN8 ||
+ base::win::GetVersion() == base::win::VERSION_WIN8_1) {
+ typedef LONG (WINAPI *NtDuplicateObject)(
+ IN HANDLE SourceProcess,
+ IN HANDLE SourceHandle,
+ IN HANDLE TargetProcess,
+ OUT PHANDLE TargetHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Attributes,
+ IN ULONG Options);
+
+ typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status);
+
+ NtDuplicateObject nt_duplicate_object =
+ reinterpret_cast<NtDuplicateObject>(::GetProcAddress(
+ GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject"));
+ if (nt_duplicate_object != NULL) {
+ LONG status = nt_duplicate_object(::GetCurrentProcess(), source,
+ ::GetCurrentProcess(), &temp,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (status < 0) {
+ DPLOG(ERROR) << "Failed to duplicate a handle.";
+ RtlNtStatusToDosError ntstatus_to_doserror =
+ reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress(
+ GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError"));
+ if (ntstatus_to_doserror != NULL) {
+ ::SetLastError(ntstatus_to_doserror(status));
+ }
+ return false;
+ }
+ }
+ } else {
+ if (!::DuplicateHandle(::GetCurrentProcess(), source,
+ ::GetCurrentProcess(), &temp, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ DPLOG(ERROR) << "Failed to duplicate a handle.";
+ return false;
+ }
+ }
+ target->Set(temp);
+ return true;
+}
+
+} // namespace
+
+ScopedProcessInformation::ScopedProcessInformation()
+ : process_id_(0), thread_id_(0) {
+}
+
+ScopedProcessInformation::ScopedProcessInformation(
+ const PROCESS_INFORMATION& process_info) : process_id_(0), thread_id_(0) {
+ Set(process_info);
+}
+
+ScopedProcessInformation::~ScopedProcessInformation() {
+ Close();
+}
+
+bool ScopedProcessInformation::IsValid() const {
+ return process_id_ || process_handle_.Get() ||
+ thread_id_ || thread_handle_.Get();
+}
+
+void ScopedProcessInformation::Close() {
+ process_handle_.Close();
+ thread_handle_.Close();
+ process_id_ = 0;
+ thread_id_ = 0;
+}
+
+void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
+ if (IsValid())
+ Close();
+
+ process_handle_.Set(process_info.hProcess);
+ thread_handle_.Set(process_info.hThread);
+ process_id_ = process_info.dwProcessId;
+ thread_id_ = process_info.dwThreadId;
+}
+
+bool ScopedProcessInformation::DuplicateFrom(
+ const ScopedProcessInformation& other) {
+ DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
+ DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
+
+ if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
+ CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
+ process_id_ = other.process_id();
+ thread_id_ = other.thread_id();
+ return true;
+ }
+
+ return false;
+}
+
+PROCESS_INFORMATION ScopedProcessInformation::Take() {
+ PROCESS_INFORMATION process_information = {};
+ process_information.hProcess = process_handle_.Take();
+ process_information.hThread = thread_handle_.Take();
+ process_information.dwProcessId = process_id();
+ process_information.dwThreadId = thread_id();
+ process_id_ = 0;
+ thread_id_ = 0;
+
+ return process_information;
+}
+
+HANDLE ScopedProcessInformation::TakeProcessHandle() {
+ process_id_ = 0;
+ return process_handle_.Take();
+}
+
+HANDLE ScopedProcessInformation::TakeThreadHandle() {
+ thread_id_ = 0;
+ return thread_handle_.Take();
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/scoped_process_information.h b/security/sandbox/chromium/base/win/scoped_process_information.h
new file mode 100644
index 000000000..01df861f0
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_process_information.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
+#define BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
+
+#include <windows.h>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/win/scoped_handle.h"
+
+namespace base {
+namespace win {
+
+// Manages the closing of process and thread handles from PROCESS_INFORMATION
+// structures. Allows clients to take ownership of either handle independently.
+class BASE_EXPORT ScopedProcessInformation {
+ public:
+ ScopedProcessInformation();
+ explicit ScopedProcessInformation(const PROCESS_INFORMATION& process_info);
+ ~ScopedProcessInformation();
+
+ // Returns true iff this instance is holding a thread and/or process handle.
+ bool IsValid() const;
+
+ // Closes the held thread and process handles, if any.
+ void Close();
+
+ // Populates this instance with the provided |process_info|.
+ void Set(const PROCESS_INFORMATION& process_info);
+
+ // Populates this instance with duplicate handles and the thread/process IDs
+ // from |other|. Returns false in case of failure, in which case this instance
+ // will be completely unpopulated.
+ bool DuplicateFrom(const ScopedProcessInformation& other);
+
+ // Transfers ownership of the held PROCESS_INFORMATION, if any, away from this
+ // instance.
+ PROCESS_INFORMATION Take();
+
+ // Transfers ownership of the held process handle, if any, away from this
+ // instance. Note that the related process_id will also be cleared.
+ HANDLE TakeProcessHandle();
+
+ // Transfers ownership of the held thread handle, if any, away from this
+ // instance. Note that the related thread_id will also be cleared.
+ HANDLE TakeThreadHandle();
+
+ // Returns the held process handle, if any, while retaining ownership.
+ HANDLE process_handle() const {
+ return process_handle_.Get();
+ }
+
+ // Returns the held thread handle, if any, while retaining ownership.
+ HANDLE thread_handle() const {
+ return thread_handle_.Get();
+ }
+
+ // Returns the held process id, if any.
+ DWORD process_id() const {
+ return process_id_;
+ }
+
+ // Returns the held thread id, if any.
+ DWORD thread_id() const {
+ return thread_id_;
+ }
+
+ private:
+ ScopedHandle process_handle_;
+ ScopedHandle thread_handle_;
+ DWORD process_id_;
+ DWORD thread_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedProcessInformation);
+};
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
diff --git a/security/sandbox/chromium/base/win/startup_information.cc b/security/sandbox/chromium/base/win/startup_information.cc
new file mode 100644
index 000000000..aff52eb79
--- /dev/null
+++ b/security/sandbox/chromium/base/win/startup_information.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/startup_information.h"
+
+#include "base/logging.h"
+#include "base/win/windows_version.h"
+
+namespace {
+
+typedef BOOL (WINAPI *InitializeProcThreadAttributeListFunction)(
+ LPPROC_THREAD_ATTRIBUTE_LIST attribute_list,
+ DWORD attribute_count,
+ DWORD flags,
+ PSIZE_T size);
+static InitializeProcThreadAttributeListFunction
+ initialize_proc_thread_attribute_list;
+
+typedef BOOL (WINAPI *UpdateProcThreadAttributeFunction)(
+ LPPROC_THREAD_ATTRIBUTE_LIST attribute_list,
+ DWORD flags,
+ DWORD_PTR attribute,
+ PVOID value,
+ SIZE_T size,
+ PVOID previous_value,
+ PSIZE_T return_size);
+static UpdateProcThreadAttributeFunction update_proc_thread_attribute_list;
+
+typedef VOID (WINAPI *DeleteProcThreadAttributeListFunction)(
+ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList);
+static DeleteProcThreadAttributeListFunction delete_proc_thread_attribute_list;
+
+} // namespace
+
+namespace base {
+namespace win {
+
+StartupInformation::StartupInformation() {
+ memset(&startup_info_, 0, sizeof(startup_info_));
+
+ // Pre Windows Vista doesn't support STARTUPINFOEX.
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ startup_info_.StartupInfo.cb = sizeof(STARTUPINFO);
+ return;
+ }
+
+ startup_info_.StartupInfo.cb = sizeof(startup_info_);
+
+ // Load the attribute API functions.
+ if (!initialize_proc_thread_attribute_list ||
+ !update_proc_thread_attribute_list ||
+ !delete_proc_thread_attribute_list) {
+ HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
+ initialize_proc_thread_attribute_list =
+ reinterpret_cast<InitializeProcThreadAttributeListFunction>(
+ ::GetProcAddress(module, "InitializeProcThreadAttributeList"));
+ update_proc_thread_attribute_list =
+ reinterpret_cast<UpdateProcThreadAttributeFunction>(
+ ::GetProcAddress(module, "UpdateProcThreadAttribute"));
+ delete_proc_thread_attribute_list =
+ reinterpret_cast<DeleteProcThreadAttributeListFunction>(
+ ::GetProcAddress(module, "DeleteProcThreadAttributeList"));
+ }
+}
+
+StartupInformation::~StartupInformation() {
+ if (startup_info_.lpAttributeList) {
+ delete_proc_thread_attribute_list(startup_info_.lpAttributeList);
+ delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList);
+ }
+}
+
+bool StartupInformation::InitializeProcThreadAttributeList(
+ DWORD attribute_count) {
+ if (startup_info_.StartupInfo.cb != sizeof(startup_info_) ||
+ startup_info_.lpAttributeList)
+ return false;
+
+ SIZE_T size = 0;
+ initialize_proc_thread_attribute_list(NULL, attribute_count, 0, &size);
+ if (size == 0)
+ return false;
+
+ startup_info_.lpAttributeList =
+ reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(new BYTE[size]);
+ if (!initialize_proc_thread_attribute_list(startup_info_.lpAttributeList,
+ attribute_count, 0, &size)) {
+ delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList);
+ startup_info_.lpAttributeList = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+bool StartupInformation::UpdateProcThreadAttribute(
+ DWORD_PTR attribute,
+ void* value,
+ size_t size) {
+ if (!startup_info_.lpAttributeList)
+ return false;
+ return !!update_proc_thread_attribute_list(startup_info_.lpAttributeList, 0,
+ attribute, value, size, NULL, NULL);
+}
+
+} // namespace win
+} // namespace base
+
diff --git a/security/sandbox/chromium/base/win/startup_information.h b/security/sandbox/chromium/base/win/startup_information.h
new file mode 100644
index 000000000..5b777baef
--- /dev/null
+++ b/security/sandbox/chromium/base/win/startup_information.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_STARTUP_INFORMATION_H_
+#define BASE_WIN_STARTUP_INFORMATION_H_
+
+#include <windows.h>
+#include <stddef.h>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace win {
+
+// Manages the lifetime of additional attributes in STARTUPINFOEX.
+class BASE_EXPORT StartupInformation {
+ public:
+ StartupInformation();
+
+ ~StartupInformation();
+
+ // Initialize the attribute list for the specified number of entries.
+ bool InitializeProcThreadAttributeList(DWORD attribute_count);
+
+ // Sets one entry in the initialized attribute list.
+ // |value| needs to live at least as long as the StartupInformation object
+ // this is called on.
+ bool UpdateProcThreadAttribute(DWORD_PTR attribute,
+ void* value,
+ size_t size);
+
+ LPSTARTUPINFOW startup_info() { return &startup_info_.StartupInfo; }
+ LPSTARTUPINFOW startup_info() const {
+ return const_cast<const LPSTARTUPINFOW>(&startup_info_.StartupInfo);
+ }
+
+ bool has_extended_startup_info() const {
+ return !!startup_info_.lpAttributeList;
+ }
+
+ private:
+ STARTUPINFOEXW startup_info_;
+ DISALLOW_COPY_AND_ASSIGN(StartupInformation);
+};
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_STARTUP_INFORMATION_H_
diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc
new file mode 100644
index 000000000..eb3f4993d
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_version.cc
@@ -0,0 +1,225 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/windows_version.h"
+
+#include <windows.h>
+
+#include "base/file_version_info_win.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+
+namespace {
+typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD);
+} // namespace
+
+namespace base {
+namespace win {
+
+namespace {
+
+// Helper to map a major.minor.x.build version (e.g. 6.1) to a Windows release.
+Version MajorMinorBuildToVersion(int major, int minor, int build) {
+ if ((major == 5) && (minor > 0)) {
+ // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
+ return (minor == 1) ? VERSION_XP : VERSION_SERVER_2003;
+ } else if (major == 6) {
+ switch (minor) {
+ case 0:
+ // Treat Windows Server 2008 the same as Windows Vista.
+ return VERSION_VISTA;
+ case 1:
+ // Treat Windows Server 2008 R2 the same as Windows 7.
+ return VERSION_WIN7;
+ case 2:
+ // Treat Windows Server 2012 the same as Windows 8.
+ return VERSION_WIN8;
+ default:
+ DCHECK_EQ(minor, 3);
+ return VERSION_WIN8_1;
+ }
+ } else if (major == 10) {
+ if (build < 10586) {
+ return VERSION_WIN10;
+ } else {
+ return VERSION_WIN10_TH2;
+ }
+ } else if (major > 6) {
+ NOTREACHED();
+ return VERSION_WIN_LAST;
+ }
+
+ return VERSION_PRE_XP;
+}
+
+// Retrieve a version from kernel32. This is useful because when running in
+// compatibility mode for a down-level version of the OS, the file version of
+// kernel32 will still be the "real" version.
+Version GetVersionFromKernel32() {
+ scoped_ptr<FileVersionInfoWin> file_version_info(
+ static_cast<FileVersionInfoWin*>(
+ FileVersionInfoWin::CreateFileVersionInfo(
+ base::FilePath(FILE_PATH_LITERAL("kernel32.dll")))));
+ if (file_version_info) {
+ const int major =
+ HIWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
+ const int minor =
+ LOWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
+ const int build =
+ HIWORD(file_version_info->fixed_file_info()->dwFileVersionLS);
+ return MajorMinorBuildToVersion(major, minor, build);
+ }
+
+ NOTREACHED();
+ return VERSION_WIN_LAST;
+}
+
+} // namespace
+
+// static
+OSInfo* OSInfo::GetInstance() {
+ // Note: we don't use the Singleton class because it depends on AtExitManager,
+ // and it's convenient for other modules to use this classs without it. This
+ // pattern is copied from gurl.cc.
+ static OSInfo* info;
+ if (!info) {
+ OSInfo* new_info = new OSInfo();
+ if (InterlockedCompareExchangePointer(
+ reinterpret_cast<PVOID*>(&info), new_info, NULL)) {
+ delete new_info;
+ }
+ }
+ return info;
+}
+
+OSInfo::OSInfo()
+ : version_(VERSION_PRE_XP),
+ kernel32_version_(VERSION_PRE_XP),
+ got_kernel32_version_(false),
+ architecture_(OTHER_ARCHITECTURE),
+ wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
+ OSVERSIONINFOEX version_info = { sizeof version_info };
+ ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
+ version_number_.major = version_info.dwMajorVersion;
+ version_number_.minor = version_info.dwMinorVersion;
+ version_number_.build = version_info.dwBuildNumber;
+ version_ = MajorMinorBuildToVersion(
+ version_number_.major, version_number_.minor, version_number_.build);
+ service_pack_.major = version_info.wServicePackMajor;
+ service_pack_.minor = version_info.wServicePackMinor;
+
+ SYSTEM_INFO system_info = {};
+ ::GetNativeSystemInfo(&system_info);
+ switch (system_info.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break;
+ case PROCESSOR_ARCHITECTURE_AMD64: architecture_ = X64_ARCHITECTURE; break;
+ case PROCESSOR_ARCHITECTURE_IA64: architecture_ = IA64_ARCHITECTURE; break;
+ }
+ processors_ = system_info.dwNumberOfProcessors;
+ allocation_granularity_ = system_info.dwAllocationGranularity;
+
+ GetProductInfoPtr get_product_info;
+ DWORD os_type;
+
+ if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) {
+ // Only present on Vista+.
+ get_product_info = reinterpret_cast<GetProductInfoPtr>(
+ ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "GetProductInfo"));
+
+ get_product_info(version_info.dwMajorVersion, version_info.dwMinorVersion,
+ 0, 0, &os_type);
+ switch (os_type) {
+ case PRODUCT_CLUSTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER:
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ case PRODUCT_STANDARD_SERVER:
+ case PRODUCT_STANDARD_SERVER_CORE:
+ case PRODUCT_WEB_SERVER:
+ version_type_ = SUITE_SERVER;
+ break;
+ case PRODUCT_PROFESSIONAL:
+ case PRODUCT_ULTIMATE:
+ case PRODUCT_ENTERPRISE:
+ case PRODUCT_BUSINESS:
+ version_type_ = SUITE_PROFESSIONAL;
+ break;
+ case PRODUCT_HOME_BASIC:
+ case PRODUCT_HOME_PREMIUM:
+ case PRODUCT_STARTER:
+ default:
+ version_type_ = SUITE_HOME;
+ break;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 2) {
+ if (version_info.wProductType == VER_NT_WORKSTATION &&
+ system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ version_type_ = SUITE_PROFESSIONAL;
+ } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER ) {
+ version_type_ = SUITE_HOME;
+ } else {
+ version_type_ = SUITE_SERVER;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 1) {
+ if(version_info.wSuiteMask & VER_SUITE_PERSONAL)
+ version_type_ = SUITE_HOME;
+ else
+ version_type_ = SUITE_PROFESSIONAL;
+ } else {
+ // Windows is pre XP so we don't care but pick a safe default.
+ version_type_ = SUITE_HOME;
+ }
+}
+
+OSInfo::~OSInfo() {
+}
+
+Version OSInfo::Kernel32Version() const {
+ if (!got_kernel32_version_) {
+ kernel32_version_ = GetVersionFromKernel32();
+ got_kernel32_version_ = true;
+ }
+ return kernel32_version_;
+}
+
+std::string OSInfo::processor_model_name() {
+ if (processor_model_name_.empty()) {
+ const wchar_t kProcessorNameString[] =
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
+ base::win::RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
+ string16 value;
+ key.ReadValue(L"ProcessorNameString", &value);
+ processor_model_name_ = UTF16ToUTF8(value);
+ }
+ return processor_model_name_;
+}
+
+// static
+OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) {
+ typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
+ IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
+ GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
+ if (!is_wow64_process)
+ return WOW64_DISABLED;
+ BOOL is_wow64 = FALSE;
+ if (!(*is_wow64_process)(process_handle, &is_wow64))
+ return WOW64_UNKNOWN;
+ return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
+}
+
+Version GetVersion() {
+ return OSInfo::GetInstance()->version();
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/windows_version.h b/security/sandbox/chromium/base/win/windows_version.h
new file mode 100644
index 000000000..7bc8b6fe5
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_version.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_WINDOWS_VERSION_H_
+#define BASE_WIN_WINDOWS_VERSION_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+typedef void* HANDLE;
+
+namespace base {
+namespace win {
+
+// The running version of Windows. This is declared outside OSInfo for
+// syntactic sugar reasons; see the declaration of GetVersion() below.
+// NOTE: Keep these in order so callers can do things like
+// "if (base::win::GetVersion() >= base::win::VERSION_VISTA) ...".
+//
+// This enum is used in metrics histograms, so they shouldn't be reordered or
+// removed. New values can be added before VERSION_WIN_LAST.
+enum Version {
+ VERSION_PRE_XP = 0, // Not supported.
+ VERSION_XP = 1,
+ VERSION_SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2.
+ VERSION_VISTA = 3, // Also includes Windows Server 2008.
+ VERSION_WIN7 = 4, // Also includes Windows Server 2008 R2.
+ VERSION_WIN8 = 5, // Also includes Windows Server 2012.
+ VERSION_WIN8_1 = 6, // Also includes Windows Server 2012 R2.
+ VERSION_WIN10 = 7, // Also includes Windows 10 Server.
+ VERSION_WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586.
+ VERSION_WIN_LAST, // Indicates error condition.
+};
+
+// A rough bucketing of the available types of versions of Windows. This is used
+// to distinguish enterprise enabled versions from home versions and potentially
+// server versions.
+enum VersionType {
+ SUITE_HOME,
+ SUITE_PROFESSIONAL,
+ SUITE_SERVER,
+ SUITE_LAST,
+};
+
+// A singleton that can be used to query various pieces of information about the
+// OS and process state. Note that this doesn't use the base Singleton class, so
+// it can be used without an AtExitManager.
+class BASE_EXPORT OSInfo {
+ public:
+ struct VersionNumber {
+ int major;
+ int minor;
+ int build;
+ };
+
+ struct ServicePack {
+ int major;
+ int minor;
+ };
+
+ // The processor architecture this copy of Windows natively uses. For
+ // example, given an x64-capable processor, we have three possibilities:
+ // 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE
+ // 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE
+ // 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE
+ enum WindowsArchitecture {
+ X86_ARCHITECTURE,
+ X64_ARCHITECTURE,
+ IA64_ARCHITECTURE,
+ OTHER_ARCHITECTURE,
+ };
+
+ // Whether a process is running under WOW64 (the wrapper that allows 32-bit
+ // processes to run on 64-bit versions of Windows). This will return
+ // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit
+ // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g.
+ // the process does not have sufficient access rights to determine this.
+ enum WOW64Status {
+ WOW64_DISABLED,
+ WOW64_ENABLED,
+ WOW64_UNKNOWN,
+ };
+
+ static OSInfo* GetInstance();
+
+ Version version() const { return version_; }
+ Version Kernel32Version() const;
+ // The next two functions return arrays of values, [major, minor(, build)].
+ VersionNumber version_number() const { return version_number_; }
+ VersionType version_type() const { return version_type_; }
+ ServicePack service_pack() const { return service_pack_; }
+ WindowsArchitecture architecture() const { return architecture_; }
+ int processors() const { return processors_; }
+ size_t allocation_granularity() const { return allocation_granularity_; }
+ WOW64Status wow64_status() const { return wow64_status_; }
+ std::string processor_model_name();
+
+ // Like wow64_status(), but for the supplied handle instead of the current
+ // process. This doesn't touch member state, so you can bypass the singleton.
+ static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle);
+
+ private:
+ OSInfo();
+ ~OSInfo();
+
+ Version version_;
+ mutable Version kernel32_version_;
+ mutable bool got_kernel32_version_;
+ VersionNumber version_number_;
+ VersionType version_type_;
+ ServicePack service_pack_;
+ WindowsArchitecture architecture_;
+ int processors_;
+ size_t allocation_granularity_;
+ WOW64Status wow64_status_;
+ std::string processor_model_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(OSInfo);
+};
+
+// Because this is by far the most commonly-requested value from the above
+// singleton, we add a global-scope accessor here as syntactic sugar.
+BASE_EXPORT Version GetVersion();
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_WINDOWS_VERSION_H_