1 // Copyright 2020 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 #ifndef CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
6 #define CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
7 
8 #include <windows.h>
9 #include <winhttp.h>
10 
11 #include "base/logging.h"
12 #include "base/strings/string16.h"
13 
14 namespace updater {
15 
16 // Wrapper class for the WINHTTP_PROXY_INFO structure.
17 // Note that certain Win32 APIs expected the strings to be allocated with
18 // with GlobalAlloc.
19 class ScopedWinHttpProxyInfo {
20  public:
ScopedWinHttpProxyInfo()21   ScopedWinHttpProxyInfo() {}
22 
23   ScopedWinHttpProxyInfo(const ScopedWinHttpProxyInfo& other) = delete;
24   ScopedWinHttpProxyInfo& operator=(const ScopedWinHttpProxyInfo& other) =
25       delete;
ScopedWinHttpProxyInfo(ScopedWinHttpProxyInfo && other)26   ScopedWinHttpProxyInfo(ScopedWinHttpProxyInfo&& other) {
27     proxy_info_.lpszProxy = other.proxy_info_.lpszProxy;
28     other.proxy_info_.lpszProxy = nullptr;
29 
30     proxy_info_.lpszProxyBypass = other.proxy_info_.lpszProxyBypass;
31     other.proxy_info_.lpszProxyBypass = nullptr;
32   }
33 
34   ScopedWinHttpProxyInfo& operator=(ScopedWinHttpProxyInfo&& other) {
35     proxy_info_.lpszProxy = other.proxy_info_.lpszProxy;
36     other.proxy_info_.lpszProxy = nullptr;
37 
38     proxy_info_.lpszProxyBypass = other.proxy_info_.lpszProxyBypass;
39     other.proxy_info_.lpszProxyBypass = nullptr;
40     return *this;
41   }
42 
~ScopedWinHttpProxyInfo()43   ~ScopedWinHttpProxyInfo() {
44     if (proxy_info_.lpszProxy)
45       ::GlobalFree(proxy_info_.lpszProxy);
46 
47     if (proxy_info_.lpszProxyBypass)
48       ::GlobalFree(proxy_info_.lpszProxyBypass);
49   }
50 
IsValid()51   bool IsValid() const { return proxy_info_.lpszProxy; }
52 
set_access_type(DWORD access_type)53   void set_access_type(DWORD access_type) {
54     proxy_info_.dwAccessType = access_type;
55   }
56 
proxy()57   base::char16* proxy() const { return proxy_info_.lpszProxy; }
58 
set_proxy(const base::string16 & proxy)59   void set_proxy(const base::string16& proxy) {
60     if (proxy.empty())
61       return;
62 
63     proxy_info_.lpszProxy = GlobalAlloc(proxy);
64   }
65 
set_proxy_bypass(const base::string16 & proxy_bypass)66   void set_proxy_bypass(const base::string16& proxy_bypass) {
67     if (proxy_bypass.empty())
68       return;
69 
70     proxy_info_.lpszProxyBypass = GlobalAlloc(proxy_bypass);
71   }
72 
73   // Return the raw pointer since WinHttpSetOption requires a non const pointer.
get()74   const WINHTTP_PROXY_INFO* get() const { return &proxy_info_; }
75 
receive()76   WINHTTP_PROXY_INFO* receive() { return &proxy_info_; }
77 
78  private:
GlobalAlloc(const base::string16 & str)79   base::char16* GlobalAlloc(const base::string16& str) {
80     const size_t size_in_bytes = (str.length() + 1) * sizeof(base::char16);
81     base::char16* string_mem =
82         reinterpret_cast<base::char16*>(::GlobalAlloc(GPTR, size_in_bytes));
83 
84     if (!string_mem) {
85       PLOG(ERROR) << "GlobalAlloc failed to allocate " << size_in_bytes
86                   << " bytes";
87       return nullptr;
88     }
89 
90     memcpy(string_mem, str.data(), size_in_bytes);
91     return string_mem;
92   }
93   WINHTTP_PROXY_INFO proxy_info_ = {};
94 };
95 
96 }  // namespace updater
97 
98 #endif  // CHROME_UPDATER_WIN_NET_SCOPED_WINTTP_PROXY_INFO_H_
99