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 "base/win/startup_information.h"
6
7#include "base/logging.h"
8#include "base/win/windows_version.h"
9
10namespace {
11
12typedef BOOL (WINAPI *InitializeProcThreadAttributeListFunction)(
13    LPPROC_THREAD_ATTRIBUTE_LIST attribute_list,
14    DWORD attribute_count,
15    DWORD flags,
16    PSIZE_T size);
17static InitializeProcThreadAttributeListFunction
18    initialize_proc_thread_attribute_list;
19
20typedef BOOL (WINAPI *UpdateProcThreadAttributeFunction)(
21    LPPROC_THREAD_ATTRIBUTE_LIST attribute_list,
22    DWORD flags,
23    DWORD_PTR attribute,
24    PVOID value,
25    SIZE_T size,
26    PVOID previous_value,
27    PSIZE_T return_size);
28static UpdateProcThreadAttributeFunction update_proc_thread_attribute_list;
29
30typedef VOID (WINAPI *DeleteProcThreadAttributeListFunction)(
31    LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList);
32static DeleteProcThreadAttributeListFunction delete_proc_thread_attribute_list;
33
34}  // namespace
35
36namespace base {
37namespace win {
38
39StartupInformation::StartupInformation() {
40  memset(&startup_info_, 0, sizeof(startup_info_));
41
42  // Pre Windows Vista doesn't support STARTUPINFOEX.
43  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
44    startup_info_.StartupInfo.cb = sizeof(STARTUPINFO);
45    return;
46  }
47
48  startup_info_.StartupInfo.cb = sizeof(startup_info_);
49
50  // Load the attribute API functions.
51  if (!initialize_proc_thread_attribute_list ||
52      !update_proc_thread_attribute_list ||
53      !delete_proc_thread_attribute_list) {
54    HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
55    initialize_proc_thread_attribute_list =
56        reinterpret_cast<InitializeProcThreadAttributeListFunction>(
57            ::GetProcAddress(module, "InitializeProcThreadAttributeList"));
58    update_proc_thread_attribute_list =
59        reinterpret_cast<UpdateProcThreadAttributeFunction>(
60            ::GetProcAddress(module, "UpdateProcThreadAttribute"));
61    delete_proc_thread_attribute_list =
62        reinterpret_cast<DeleteProcThreadAttributeListFunction>(
63            ::GetProcAddress(module, "DeleteProcThreadAttributeList"));
64  }
65}
66
67StartupInformation::~StartupInformation() {
68  if (startup_info_.lpAttributeList) {
69    delete_proc_thread_attribute_list(startup_info_.lpAttributeList);
70    delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList);
71  }
72}
73
74bool StartupInformation::InitializeProcThreadAttributeList(
75    DWORD attribute_count) {
76  if (startup_info_.StartupInfo.cb != sizeof(startup_info_) ||
77      startup_info_.lpAttributeList)
78    return false;
79
80  SIZE_T size = 0;
81  initialize_proc_thread_attribute_list(NULL, attribute_count, 0, &size);
82  if (size == 0)
83    return false;
84
85  startup_info_.lpAttributeList =
86      reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(new BYTE[size]);
87  if (!initialize_proc_thread_attribute_list(startup_info_.lpAttributeList,
88                                           attribute_count, 0, &size)) {
89    delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList);
90    startup_info_.lpAttributeList = NULL;
91    return false;
92  }
93
94  return true;
95}
96
97bool StartupInformation::UpdateProcThreadAttribute(
98    DWORD_PTR attribute,
99    void* value,
100    size_t size) {
101  if (!startup_info_.lpAttributeList)
102    return false;
103  return !!update_proc_thread_attribute_list(startup_info_.lpAttributeList, 0,
104                                       attribute, value, size, NULL, NULL);
105}
106
107}  // namespace win
108}  // namespace base
109
110