| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 "chrome/install_static/policy_path_parser.h" | |
| 6 | |
| 7 #include <assert.h> | |
| 8 #include <shlobj.h> | |
| 9 #include <stddef.h> | |
| 10 #include <stdlib.h> | |
| 11 #include <wtsapi32.h> | |
| 12 | |
| 13 #include <memory> | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 const WCHAR* kMachineNamePolicyVarName = L"${machine_name}"; | |
| 18 const WCHAR* kUserNamePolicyVarName = L"${user_name}"; | |
| 19 const WCHAR* kWinDocumentsFolderVarName = L"${documents}"; | |
| 20 const WCHAR* kWinLocalAppDataFolderVarName = L"${local_app_data}"; | |
| 21 const WCHAR* kWinRoamingAppDataFolderVarName = L"${roaming_app_data}"; | |
| 22 const WCHAR* kWinProfileFolderVarName = L"${profile}"; | |
| 23 const WCHAR* kWinProgramDataFolderVarName = L"${global_app_data}"; | |
| 24 const WCHAR* kWinProgramFilesFolderVarName = L"${program_files}"; | |
| 25 const WCHAR* kWinWindowsFolderVarName = L"${windows}"; | |
| 26 const WCHAR* kWinClientName = L"${client_name}"; | |
| 27 const WCHAR* kWinSessionName = L"${session_name}"; | |
| 28 | |
| 29 struct WinFolderNamesToCSIDLMapping { | |
| 30 const WCHAR* name; | |
| 31 int id; | |
| 32 }; | |
| 33 | |
| 34 // Mapping from variable names to Windows CSIDL ids. | |
| 35 const WinFolderNamesToCSIDLMapping kWinFolderMapping[] = { | |
| 36 { kWinWindowsFolderVarName, CSIDL_WINDOWS}, | |
| 37 { kWinProgramFilesFolderVarName, CSIDL_PROGRAM_FILES}, | |
| 38 { kWinProgramDataFolderVarName, CSIDL_COMMON_APPDATA}, | |
| 39 { kWinProfileFolderVarName, CSIDL_PROFILE}, | |
| 40 { kWinLocalAppDataFolderVarName, CSIDL_LOCAL_APPDATA}, | |
| 41 { kWinRoamingAppDataFolderVarName, CSIDL_APPDATA}, | |
| 42 { kWinDocumentsFolderVarName, CSIDL_PERSONAL} | |
| 43 }; | |
| 44 | |
| 45 template <class FunctionType> | |
| 46 struct ScopedFunctionHelper { | |
| 47 ScopedFunctionHelper(const wchar_t* library_name, const char* function_name) { | |
| 48 library_ = LoadLibrary(library_name); | |
| 49 assert(library_); | |
| 50 if (library_) { | |
| 51 // Strip off any leading :: that may have come from stringifying the | |
| 52 // function's name. | |
| 53 if (function_name[0] == ':' && function_name[1] == ':' && | |
| 54 function_name[2] && function_name[2] != ':') { | |
| 55 function_name += 2; | |
| 56 } | |
| 57 function_ = reinterpret_cast<FunctionType *>( | |
| 58 GetProcAddress(library_, function_name)); | |
| 59 assert(function_); | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 ~ScopedFunctionHelper() { | |
| 64 if (library_) | |
| 65 FreeLibrary(library_); | |
| 66 } | |
| 67 | |
| 68 template <class... Args> auto operator()(Args... a) { | |
| 69 return function_(a...); | |
| 70 } | |
| 71 | |
| 72 private: | |
| 73 HMODULE library_; | |
| 74 FunctionType* function_; | |
| 75 }; | |
| 76 | |
| 77 #define SCOPED_LOAD_FUNCTION(library, function) \ | |
| 78 ScopedFunctionHelper<decltype(function)>(library, #function) | |
| 79 | |
| 80 } // namespace | |
| 81 | |
| 82 namespace install_static { | |
| 83 | |
| 84 // Replaces all variable occurances in the policy string with the respective | |
| 85 // system settings values. | |
| 86 // Note that this uses GetProcAddress to load DLLs that cannot be loaded before | |
| 87 // the blacklist in the DllMain of chrome_elf has been applied. This function | |
| 88 // should only be used after DllMain() has run. | |
| 89 std::wstring ExpandPathVariables( | |
| 90 const std::wstring& untranslated_string) { | |
| 91 std::wstring result(untranslated_string); | |
| 92 if (result.length() == 0) | |
| 93 return result; | |
| 94 // Sanitize quotes in case of any around the whole string. | |
| 95 if (result.length() > 1 && | |
| 96 ((result.front() == L'"' && result.back() == L'"') || | |
| 97 (result.front() == L'\'' && result.back() == L'\''))) { | |
| 98 // Strip first and last char which should be matching quotes now. | |
| 99 result.pop_back(); | |
| 100 result.erase(0, 1); | |
| 101 } | |
| 102 auto sh_get_special_folder_path = | |
| 103 SCOPED_LOAD_FUNCTION(L"shell32.dll", ::SHGetSpecialFolderPathW); | |
| 104 // First translate all path variables we recognize. | |
| 105 for (size_t i = 0; i < _countof(kWinFolderMapping); ++i) { | |
| 106 size_t position = result.find(kWinFolderMapping[i].name); | |
| 107 if (position != std::wstring::npos) { | |
| 108 WCHAR path[MAX_PATH]; | |
| 109 sh_get_special_folder_path(nullptr, path, kWinFolderMapping[i].id, false); | |
| 110 std::wstring path_string(path); | |
| 111 result.replace(position, wcslen(kWinFolderMapping[i].name), path_string); | |
| 112 } | |
| 113 } | |
| 114 // Next translate other windows specific variables. | |
| 115 auto get_user_name = SCOPED_LOAD_FUNCTION(L"advapi32.dll", ::GetUserNameW); | |
| 116 size_t position = result.find(kUserNamePolicyVarName); | |
| 117 if (position != std::wstring::npos) { | |
| 118 DWORD return_length = 0; | |
| 119 get_user_name(nullptr, &return_length); | |
| 120 if (return_length != 0) { | |
| 121 std::unique_ptr<WCHAR[]> username(new WCHAR[return_length]); | |
| 122 get_user_name(username.get(), &return_length); | |
| 123 std::wstring username_string(username.get()); | |
| 124 result.replace(position, wcslen(kUserNamePolicyVarName), username_string); | |
| 125 } | |
| 126 } | |
| 127 position = result.find(kMachineNamePolicyVarName); | |
| 128 if (position != std::wstring::npos) { | |
| 129 DWORD return_length = 0; | |
| 130 ::GetComputerNameEx(ComputerNamePhysicalDnsHostname, NULL, &return_length); | |
| 131 if (return_length != 0) { | |
| 132 std::unique_ptr<WCHAR[]> machinename(new WCHAR[return_length]); | |
| 133 ::GetComputerNameEx(ComputerNamePhysicalDnsHostname, | |
| 134 machinename.get(), &return_length); | |
| 135 std::wstring machinename_string(machinename.get()); | |
| 136 result.replace( | |
| 137 position, wcslen(kMachineNamePolicyVarName), machinename_string); | |
| 138 } | |
| 139 } | |
| 140 auto wts_query_session_information = | |
| 141 SCOPED_LOAD_FUNCTION(L"wtsapi32.dll", ::WTSQuerySessionInformationW); | |
| 142 auto wts_free_memory = SCOPED_LOAD_FUNCTION(L"wtsapi32.dll", ::WTSFreeMemory); | |
| 143 position = result.find(kWinClientName); | |
| 144 if (position != std::wstring::npos) { | |
| 145 LPWSTR buffer = NULL; | |
| 146 DWORD buffer_length = 0; | |
| 147 if (wts_query_session_information(WTS_CURRENT_SERVER, WTS_CURRENT_SESSION, | |
| 148 WTSClientName, &buffer, &buffer_length)) { | |
| 149 std::wstring clientname_string(buffer); | |
| 150 result.replace(position, wcslen(kWinClientName), clientname_string); | |
| 151 wts_free_memory(buffer); | |
| 152 } | |
| 153 } | |
| 154 position = result.find(kWinSessionName); | |
| 155 if (position != std::wstring::npos) { | |
| 156 LPWSTR buffer = NULL; | |
| 157 DWORD buffer_length = 0; | |
| 158 if (wts_query_session_information(WTS_CURRENT_SERVER, WTS_CURRENT_SESSION, | |
| 159 WTSWinStationName, &buffer, | |
| 160 &buffer_length)) { | |
| 161 std::wstring sessionname_string(buffer); | |
| 162 result.replace(position, wcslen(kWinSessionName), sessionname_string); | |
| 163 wts_free_memory(buffer); | |
| 164 } | |
| 165 } | |
| 166 // TODO(pastarmovj): Consider reorganizing this code once there are even more | |
| 167 // variables to be supported. The search for the var and its replacement can | |
| 168 // be extracted as common functionality. | |
| 169 | |
| 170 return result; | |
| 171 } | |
| 172 | |
| 173 } // namespace install_static | |
| OLD | NEW |