KiCad PCB EDA Suite
Loading...
Searching...
No Matches
msw/environment.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Ian McInerney <Ian.S.McInerney at ieee.org>
5 * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
22#include <wx/intl.h>
23#include <wx/filename.h>
24#include <wx/stdpaths.h>
25#include <wx/string.h>
26#include <wx/tokenzr.h>
27#include <wx/app.h>
28
29#include <Windows.h>
30#include <shellapi.h>
31#include <shlwapi.h>
32#include <winhttp.h>
33
34#include <Softpub.h>
35#include <wincrypt.h>
36#include <wintrust.h>
37
38
40{
41 // No tasks for this platform
42}
43
44
45bool KIPLATFORM::ENV::MoveToTrash( const wxString& aPath, wxString& aError )
46{
47 // The filename field must be a double-null terminated string
48 wxString temp = aPath + '\0';
49
50 SHFILEOPSTRUCT fileOp;
51 ::ZeroMemory( &fileOp, sizeof( fileOp ) );
52
53 fileOp.hwnd = nullptr; // Set to null since there is no progress dialog
54 fileOp.wFunc = FO_DELETE;
55 fileOp.pFrom = temp.c_str();
56 fileOp.pTo = nullptr; // Set to to NULL since we aren't moving the file
57 fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT;
58
59 int eVal = SHFileOperation( &fileOp );
60
61 if( eVal != 0 )
62 {
63 aError = wxString::Format( _( "Error code: %d" ), eVal );
64 return false;
65 }
66
67 return true;
68}
69
70
71bool KIPLATFORM::ENV::IsNetworkPath( const wxString& aPath )
72{
73 return ::PathIsNetworkPathW( aPath.wc_str() );
74}
75
76
78{
79 // If called by a python script in stand-alone (outside KiCad), wxStandardPaths::Get()
80 // complains about not existing app. so use a dummy app
81 if( wxTheApp == nullptr )
82 {
83 wxApp dummy;
84 return wxStandardPaths::Get().GetDocumentsDir();
85 }
86
87 return wxStandardPaths::Get().GetDocumentsDir();
88}
89
90
92{
93 // If called by a python script in stand-alone (outside KiCad), wxStandardPaths::Get()
94 // complains about not existing app. so use a dummy app
95 if( wxTheApp == nullptr )
96 {
97 wxApp dummy;
98 return wxStandardPaths::Get().GetUserConfigDir();
99 }
100
101 return wxStandardPaths::Get().GetUserConfigDir();
102}
103
104
106{
107 // If called by a python script in stand-alone (outside KiCad), wxStandardPaths::Get()
108 // complains about not existing app. so use a dummy app
109 if( wxTheApp == nullptr )
110 {
111 wxApp dummy;
112 return wxStandardPaths::Get().GetUserDataDir();
113 }
114
115 return wxStandardPaths::Get().GetUserDataDir();
116}
117
118
120{
121 // If called by a python script in stand-alone (outside KiCad), wxStandardPaths::Get()
122 // complains about not existing app. so use a dummy app
123 if( wxTheApp == nullptr )
124 {
125 wxApp dummy;
126 return wxStandardPaths::Get().GetUserLocalDataDir();
127 }
128
129 return wxStandardPaths::Get().GetUserLocalDataDir();
130}
131
132
134{
135 // Unfortunately AppData/Local is the closest analog to "Cache" directories of other platforms
136
137 // Make sure we don't include the "appinfo" (appended app name)
138
139 // If called by a python script in stand-alone (outside KiCad), wxStandardPaths::Get()
140 // complains about not existing app. so use a dummy app
141 if( wxTheApp == nullptr )
142 {
143 wxApp dummy;
144 wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
145
146 return wxStandardPaths::Get().GetUserLocalDataDir();
147 }
148
149 wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
150
151 return wxStandardPaths::Get().GetUserLocalDataDir();
152}
153
154
155bool KIPLATFORM::ENV::GetSystemProxyConfig( const wxString& aURL, PROXY_CONFIG& aCfg )
156{
157 // Original source from Microsoft sample (public domain)
158 // https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/WinhttpProxy/cpp/GetProxy.cpp#L844
159 bool autoProxyDetect = false;
160 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig = { 0 };
161 WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = { 0 };
162 WINHTTP_PROXY_INFO autoProxyInfo = { 0 };
163 HINTERNET proxyResolveSession = NULL;
164 bool success = false;
165
166 if( WinHttpGetIEProxyConfigForCurrentUser( &ieProxyConfig ) )
167 {
168 // welcome to the wonderful world of IE
169 // we use the ie config simply to handle it off to the other win32 api
170 if( ieProxyConfig.fAutoDetect )
171 {
172 autoProxyDetect = true;
173 }
174
175 if( ieProxyConfig.lpszAutoConfigUrl != NULL )
176 {
177 autoProxyDetect = true;
178 autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl;
179 }
180 }
181 else if( GetLastError() == ERROR_FILE_NOT_FOUND )
182 {
183 // this is the only error code where we want to continue attempting to find a proxy
184 autoProxyDetect = true;
185 }
186
187 if( autoProxyDetect )
188 {
189 proxyResolveSession =
190 WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME,
191 WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC );
192
193 if( proxyResolveSession )
194 {
195 // either we use the ie url or we set the auto detect mode
196 if( autoProxyOptions.lpszAutoConfigUrl != NULL )
197 {
198 autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
199 }
200 else
201 {
202 autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
203 autoProxyOptions.dwAutoDetectFlags =
204 WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
205 }
206
207 // dont do auto logon at first, this allows windows to use an cache
208 // per https://docs.microsoft.com/en-us/windows/win32/winhttp/autoproxy-cache
209 autoProxyOptions.fAutoLogonIfChallenged = FALSE;
210
211 autoProxyDetect = WinHttpGetProxyForUrl( proxyResolveSession, aURL.c_str(),
212 &autoProxyOptions, &autoProxyInfo );
213
214 if( !autoProxyDetect && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE )
215 {
216 autoProxyOptions.fAutoLogonIfChallenged = TRUE;
217
218 // try again with auto login now
219 autoProxyDetect = WinHttpGetProxyForUrl( proxyResolveSession, aURL.c_str(),
220 &autoProxyOptions, &autoProxyInfo );
221 }
222
223 WinHttpCloseHandle( proxyResolveSession );
224 }
225
226 }
227
228 if( autoProxyDetect )
229 {
230 if( autoProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY )
231 {
232 // autoProxyInfo will return a list of proxies that are semicolon delimited
233 // todo...maybe figure out better selection logic
234 wxString proxyList = autoProxyInfo.lpszProxy;
235 wxStringTokenizer tokenizer( proxyList, wxT( ";" ) );
236
237 if( tokenizer.HasMoreTokens() )
238 {
239 aCfg.host = tokenizer.GetNextToken();
240 }
241
242 success = true;
243 }
244 }
245 else
246 {
247 if( ieProxyConfig.lpszProxy != NULL )
248 {
249 // ie proxy configs may return : or :: for an empty proxy
250
251 aCfg.host = ieProxyConfig.lpszProxy;
252
253 if(aCfg.host != ":" && aCfg.host != "::")
254 {
255 success = true;
256 }
257 }
258 }
259
260 // We have to clean up the strings the win32 api returned
261 if( autoProxyInfo.lpszProxy )
262 {
263 GlobalFree( autoProxyInfo.lpszProxy );
264 autoProxyInfo.lpszProxy = NULL;
265 }
266
267 if( autoProxyInfo.lpszProxyBypass )
268 {
269 GlobalFree( autoProxyInfo.lpszProxyBypass );
270 autoProxyInfo.lpszProxyBypass = NULL;
271 }
272
273 if( ieProxyConfig.lpszAutoConfigUrl != NULL )
274 {
275 GlobalFree( ieProxyConfig.lpszAutoConfigUrl );
276 ieProxyConfig.lpszAutoConfigUrl = NULL;
277 }
278
279 if( ieProxyConfig.lpszProxy != NULL )
280 {
281 GlobalFree( ieProxyConfig.lpszProxy );
282 ieProxyConfig.lpszProxy = NULL;
283 }
284
285 if( ieProxyConfig.lpszProxyBypass != NULL )
286 {
287 GlobalFree( ieProxyConfig.lpszProxyBypass );
288 ieProxyConfig.lpszProxyBypass = NULL;
289 }
290
291 return success;
292}
293
294
295bool KIPLATFORM::ENV::VerifyFileSignature( const wxString& aPath )
296{
297 WINTRUST_FILE_INFO fileData;
298 memset( &fileData, 0, sizeof( fileData ) );
299 fileData.cbStruct = sizeof( WINTRUST_FILE_INFO );
300 fileData.pcwszFilePath = aPath.wc_str();
301
302 // verifies entire certificate chain
303 GUID policy = WINTRUST_ACTION_GENERIC_VERIFY_V2;
304
305 WINTRUST_DATA trustData;
306 memset( &trustData, 0, sizeof( trustData ) );
307
308 trustData.cbStruct = sizeof( trustData );
309 trustData.dwUIChoice = WTD_UI_NONE;
310 // revocation checking incurs latency penalities due to need for online queries
311 trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
312 trustData.dwUnionChoice = WTD_CHOICE_FILE;
313 trustData.dwStateAction = WTD_STATEACTION_VERIFY;
314 trustData.pFile = &fileData;
315
316
317 bool verified = false;
318 LONG status = WinVerifyTrust( NULL, &policy, &trustData );
319
320 verified = ( status == ERROR_SUCCESS );
321
322 // Cleanup/release (yes its weird looking)
323 trustData.dwStateAction = WTD_STATEACTION_CLOSE;
324 WinVerifyTrust( NULL, &policy, &trustData );
325
326 return verified;
327}
#define _(s)
bool IsNetworkPath(const wxString &aPath)
Determines if a given path is a network shared file apth On Windows for example, any form of path is ...
void Init()
Perform environment initialization tasks.
bool GetSystemProxyConfig(const wxString &aURL, PROXY_CONFIG &aCfg)
Retrieves platform level proxying requirements to reach the given url.
wxString GetUserDataPath()
Retrieves the operating system specific path for a user's data store.
wxString GetDocumentsPath()
Retrieves the operating system specific path for a user's documents.
bool MoveToTrash(const wxString &aPath, wxString &aError)
Move the specified file/directory to the trash bin/recycle bin.
wxString GetUserLocalDataPath()
Retrieves the operating system specific path for a user's local data store.
wxString GetUserConfigPath()
Retrieves the operating system specific path for a user's configuration store.
wxString GetUserCachePath()
Retrieves the operating system specific path for user's application cache.
bool VerifyFileSignature(const wxString &aPath)
Validates the code signing signature of a given file This is most likely only ever going to be applic...
std::vector< FAB_LAYER_COLOR > dummy