]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utils.cpp
handle correctly never/always shown scrollbars in GetClientSize()
[wxWidgets.git] / src / msw / utils.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
119f7bb7 2// Name: src/msw/utils.cpp
2bda0e17
KB
3// Purpose: Various utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
b568d04f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
a4f96412 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
27#ifndef WX_PRECOMP
a4f96412
VZ
28 #include "wx/utils.h"
29 #include "wx/app.h"
1f0500b3
VZ
30 #include "wx/intl.h"
31 #include "wx/log.h"
743e0a66 32#endif //WX_PRECOMP
2bda0e17 33
66d84d11 34#include "wx/msw/registry.h"
2739d4f0 35#include "wx/apptrait.h"
23ee4b48 36#include "wx/dynlib.h"
15cdcf6a 37#include "wx/dynload.h"
a45fb5b4 38#include "wx/scopeguard.h"
2739d4f0 39
2dc357ea
VZ
40#include "wx/confbase.h" // for wxExpandEnvVars()
41
b568d04f 42#include "wx/msw/private.h" // includes <windows.h>
a6c2e2c7 43#include "wx/msw/missing.h" // for CHARSET_HANGUL
b568d04f 44
f6afe7fd
RN
45#if defined(__CYGWIN__)
46 //CYGWIN gives annoying warning about runtime stuff if we don't do this
47# define USE_SYS_TYPES_FD_SET
48# include <sys/types.h>
49#endif
50
7acf6a92
JS
51// Doesn't work with Cygwin at present
52#if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
c1cb4153
VZ
53 // apparently we need to include winsock.h to get WSADATA and other stuff
54 // used in wxGetFullHostName() with the old mingw32 versions
55 #include <winsock.h>
56#endif
57
f172cb82 58#if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
a4f96412 59 #include <direct.h>
ce3ed50d 60
a4f96412
VZ
61 #ifndef __MWERKS__
62 #include <dos.h>
63 #endif
743e0a66 64#endif //GNUWIN32
2bda0e17 65
b39dbf34 66#if defined(__CYGWIN__)
a4f96412
VZ
67 #include <sys/unistd.h>
68 #include <sys/stat.h>
3ffbc733 69 #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path()
743e0a66
VZ
70#endif //GNUWIN32
71
2bda0e17
KB
72#ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
73 // this (3.1 I believe) and how to test for it.
74 // If this works for Borland 4.0 as well, then no worries.
a4f96412 75 #include <dir.h>
2bda0e17
KB
76#endif
77
a4f96412
VZ
78// VZ: there is some code using NetXXX() functions to get the full user name:
79// I don't think it's a good idea because they don't work under Win95 and
80// seem to return the same as wxGetUserId() under NT. If you really want
81// to use them, just #define USE_NET_API
82#undef USE_NET_API
83
84#ifdef USE_NET_API
85 #include <lm.h>
86#endif // USE_NET_API
87
4676948b 88#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2e38557f
JS
89 #ifndef __UNIX__
90 #include <io.h>
91 #endif
2bda0e17 92
a4f96412
VZ
93 #ifndef __GNUWIN32__
94 #include <shellapi.h>
95 #endif
2bda0e17
KB
96#endif
97
2bda0e17 98#ifndef __WATCOMC__
3f4a0c5b
VZ
99 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
100 #include <errno.h>
101 #endif
2bda0e17 102#endif
2bda0e17 103
e0f6b731
JS
104// For wxKillAllChildren
105#include <tlhelp32.h>
106
b568d04f
VZ
107// ----------------------------------------------------------------------------
108// constants
109// ----------------------------------------------------------------------------
110
2bda0e17 111// In the WIN.INI file
119f7bb7 112#if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
e7d9c398 113static const wxChar WX_SECTION[] = wxT("wxWindows");
119f7bb7
WS
114#endif
115
116#if (!defined(USE_NET_API) && !defined(__WXWINCE__))
b568d04f 117static const wxChar eUSERNAME[] = wxT("UserName");
119f7bb7 118#endif
b568d04f 119
b568d04f
VZ
120// ============================================================================
121// implementation
122// ============================================================================
2bda0e17 123
b568d04f
VZ
124// ----------------------------------------------------------------------------
125// get host name and related
126// ----------------------------------------------------------------------------
2bda0e17 127
1f0500b3 128// Get hostname only (without domain name)
7bea7b91
WS
129bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
130 int WXUNUSED_IN_WINCE(maxSize))
2bda0e17 131{
4676948b 132#if defined(__WXWINCE__)
040e5f77 133 // TODO-CE
7010702f 134 return false;
e408bf52 135#else
b568d04f
VZ
136 DWORD nSize = maxSize;
137 if ( !::GetComputerName(buf, &nSize) )
138 {
f6bcfd97 139 wxLogLastError(wxT("GetComputerName"));
b568d04f 140
7010702f 141 return false;
b568d04f
VZ
142 }
143
27d2dbbc 144 return true;
2bda0e17
KB
145#endif
146}
147
1f0500b3 148// get full hostname (with domain name if possible)
b568d04f
VZ
149bool wxGetFullHostName(wxChar *buf, int maxSize)
150{
a8ff046b 151#if !defined( __WXMICROWIN__) && wxUSE_DYNLIB_CLASS && wxUSE_SOCKETS
1f0500b3 152 // TODO should use GetComputerNameEx() when available
79180098 153
15cdcf6a 154 // we don't want to always link with Winsock DLL as we might not use it at
7b28e0ed
VZ
155 // all, so load it dynamically here if needed (and don't complain if it is
156 // missing, we handle this)
157 wxLogNull noLog;
158
15cdcf6a
VZ
159 wxDynamicLibrary dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM);
160 if ( dllWinsock.IsLoaded() )
1f0500b3 161 {
15cdcf6a
VZ
162 typedef int (PASCAL *WSAStartup_t)(WORD, WSADATA *);
163 typedef int (PASCAL *gethostname_t)(char *, int);
164 typedef hostent* (PASCAL *gethostbyname_t)(const char *);
165 typedef hostent* (PASCAL *gethostbyaddr_t)(const char *, int , int);
166 typedef int (PASCAL *WSACleanup_t)(void);
1f0500b3 167
15cdcf6a
VZ
168 #define LOAD_WINSOCK_FUNC(func) \
169 func ## _t \
170 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func))
1f0500b3 171
15cdcf6a
VZ
172 LOAD_WINSOCK_FUNC(WSAStartup);
173
174 WSADATA wsa;
175 if ( pfnWSAStartup && pfnWSAStartup(MAKEWORD(1, 1), &wsa) == 0 )
176 {
177 LOAD_WINSOCK_FUNC(gethostname);
178
179 wxString host;
180 if ( pfngethostname )
181 {
182 char bufA[256];
183 if ( pfngethostname(bufA, WXSIZEOF(bufA)) == 0 )
1f0500b3 184 {
15cdcf6a
VZ
185 // gethostname() won't usually include the DNS domain name,
186 // for this we need to work a bit more
187 if ( !strchr(bufA, '.') )
188 {
189 LOAD_WINSOCK_FUNC(gethostbyname);
190
191 struct hostent *pHostEnt = pfngethostbyname
192 ? pfngethostbyname(bufA)
193 : NULL;
194
195 if ( pHostEnt )
196 {
197 // Windows will use DNS internally now
198 LOAD_WINSOCK_FUNC(gethostbyaddr);
199
200 pHostEnt = pfngethostbyaddr
201 ? pfngethostbyaddr(pHostEnt->h_addr,
202 4, AF_INET)
203 : NULL;
204 }
205
206 if ( pHostEnt )
207 {
208 host = wxString::FromAscii(pHostEnt->h_name);
209 }
210 }
1f0500b3
VZ
211 }
212 }
1f0500b3 213
15cdcf6a
VZ
214 LOAD_WINSOCK_FUNC(WSACleanup);
215 if ( pfnWSACleanup )
216 pfnWSACleanup();
1f0500b3 217
1f0500b3 218
15cdcf6a
VZ
219 if ( !host.empty() )
220 {
64accea5 221 wxStrlcpy(buf, host.c_str(), maxSize);
15cdcf6a 222
27d2dbbc 223 return true;
15cdcf6a 224 }
1f0500b3
VZ
225 }
226 }
15cdcf6a 227#endif // !__WXMICROWIN__
1f0500b3 228
b568d04f
VZ
229 return wxGetHostName(buf, maxSize);
230}
231
2bda0e17 232// Get user ID e.g. jacs
7bea7b91
WS
233bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf),
234 int WXUNUSED_IN_WINCE(maxSize))
2bda0e17 235{
4676948b 236#if defined(__WXWINCE__)
040e5f77 237 // TODO-CE
7010702f 238 return false;
e408bf52 239#else
0a144271
VZ
240 DWORD nSize = maxSize;
241 if ( ::GetUserName(buf, &nSize) == 0 )
242 {
a4f96412 243 // actually, it does happen on Win9x if the user didn't log on
223d09f6 244 DWORD res = ::GetEnvironmentVariable(wxT("username"), buf, maxSize);
a4f96412
VZ
245 if ( res == 0 )
246 {
247 // not found
27d2dbbc 248 return false;
a4f96412 249 }
0a144271
VZ
250 }
251
27d2dbbc 252 return true;
2bda0e17
KB
253#endif
254}
255
256// Get user name e.g. Julian Smart
119f7bb7 257bool wxGetUserName(wxChar *buf, int maxSize)
2bda0e17 258{
119f7bb7
WS
259 wxCHECK_MSG( buf && ( maxSize > 0 ), false,
260 _T("empty buffer in wxGetUserName") );
f77c0fe3 261#if defined(__WXWINCE__) && wxUSE_REGKEY
66d84d11
WS
262 wxLogNull noLog;
263 wxRegKey key(wxRegKey::HKCU, wxT("ControlPanel\\Owner"));
119f7bb7
WS
264 if(!key.Open(wxRegKey::Read))
265 return false;
266 wxString name;
66d84d11 267 if(!key.QueryValue(wxT("Owner"),name))
119f7bb7 268 return false;
e408bf52 269 wxStrlcpy(buf, name.c_str(), maxSize);
119f7bb7 270 return true;
4676948b 271#elif defined(USE_NET_API)
3e3be693
VZ
272 CHAR szUserName[256];
273 if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
7010702f 274 return false;
a4f96412 275
3e3be693
VZ
276 // TODO how to get the domain name?
277 CHAR *szDomain = "";
a4f96412 278
3e3be693
VZ
279 // the code is based on the MSDN example (also see KB article Q119670)
280 WCHAR wszUserName[256]; // Unicode user name
281 WCHAR wszDomain[256];
282 LPBYTE ComputerName;
a4f96412 283
3e3be693 284 USER_INFO_2 *ui2; // User structure
a4f96412 285
3e3be693
VZ
286 // Convert ANSI user name and domain to Unicode
287 MultiByteToWideChar( CP_ACP, 0, szUserName, strlen(szUserName)+1,
288 wszUserName, WXSIZEOF(wszUserName) );
289 MultiByteToWideChar( CP_ACP, 0, szDomain, strlen(szDomain)+1,
290 wszDomain, WXSIZEOF(wszDomain) );
a4f96412 291
3e3be693
VZ
292 // Get the computer name of a DC for the domain.
293 if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
294 {
295 wxLogError(wxT("Can not find domain controller"));
a4f96412 296
3e3be693
VZ
297 goto error;
298 }
a4f96412 299
3e3be693
VZ
300 // Look up the user on the DC
301 NET_API_STATUS status = NetUserGetInfo( (LPWSTR)ComputerName,
302 (LPWSTR)&wszUserName,
303 2, // level - we want USER_INFO_2
304 (LPBYTE *) &ui2 );
305 switch ( status )
306 {
307 case NERR_Success:
308 // ok
309 break;
a4f96412 310
3e3be693
VZ
311 case NERR_InvalidComputer:
312 wxLogError(wxT("Invalid domain controller name."));
a4f96412 313
3e3be693 314 goto error;
a4f96412 315
3e3be693
VZ
316 case NERR_UserNotFound:
317 wxLogError(wxT("Invalid user name '%s'."), szUserName);
a4f96412 318
3e3be693 319 goto error;
a4f96412 320
3e3be693
VZ
321 default:
322 wxLogSysError(wxT("Can't get information about user"));
a4f96412 323
3e3be693
VZ
324 goto error;
325 }
a4f96412 326
3e3be693
VZ
327 // Convert the Unicode full name to ANSI
328 WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1,
329 buf, maxSize, NULL, NULL );
a4f96412 330
27d2dbbc 331 return true;
a4f96412
VZ
332
333error:
3e3be693 334 wxLogError(wxT("Couldn't look up full user name."));
a4f96412 335
27d2dbbc 336 return false;
a4f96412 337#else // !USE_NET_API
3e3be693 338 // Could use NIS, MS-Mail or other site specific programs
77ffb593 339 // Use wxWidgets configuration data
fda7962d 340 bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxEmptyString, buf, maxSize - 1) != 0;
3e3be693
VZ
341 if ( !ok )
342 {
343 ok = wxGetUserId(buf, maxSize);
344 }
0a144271 345
3e3be693
VZ
346 if ( !ok )
347 {
e408bf52 348 wxStrlcpy(buf, wxT("Unknown User"), maxSize);
b568d04f 349 }
0a144271 350
27d2dbbc 351 return true;
040e5f77 352#endif // Win32/16
2bda0e17
KB
353}
354
b568d04f 355const wxChar* wxGetHomeDir(wxString *pstr)
2bda0e17 356{
2dc357ea 357 wxString& strDir = *pstr;
2bda0e17 358
2dc357ea 359 // first branch is for Cygwin
dc484d49 360#if defined(__UNIX__) && !defined(__WINE__)
b568d04f
VZ
361 const wxChar *szHome = wxGetenv("HOME");
362 if ( szHome == NULL ) {
363 // we're homeless...
364 wxLogWarning(_("can't find user's HOME, using current directory."));
365 strDir = wxT(".");
366 }
367 else
368 strDir = szHome;
2bda0e17 369
b568d04f
VZ
370 // add a trailing slash if needed
371 if ( strDir.Last() != wxT('/') )
372 strDir << wxT('/');
3ffbc733 373
e02e8816 374 #ifdef __CYGWIN__
2dc357ea
VZ
375 // Cygwin returns unix type path but that does not work well
376 static wxChar windowsPath[MAX_PATH];
377 cygwin_conv_to_full_win32_path(strDir, windowsPath);
378 strDir = windowsPath;
3ffbc733 379 #endif
4676948b 380#elif defined(__WXWINCE__)
0367d339 381 strDir = wxT("\\");
4676948b 382#else
2dc357ea 383 strDir.clear();
96c21216 384
2dc357ea
VZ
385 // If we have a valid HOME directory, as is used on many machines that
386 // have unix utilities on them, we should use that.
387 const wxChar *szHome = wxGetenv(wxT("HOME"));
96c21216 388
2dc357ea
VZ
389 if ( szHome != NULL )
390 {
96c21216 391 strDir = szHome;
2dc357ea
VZ
392 }
393 else // no HOME, try HOMEDRIVE/PATH
394 {
395 szHome = wxGetenv(wxT("HOMEDRIVE"));
396 if ( szHome != NULL )
96c21216 397 strDir << szHome;
2dc357ea 398 szHome = wxGetenv(wxT("HOMEPATH"));
96c21216 399
2dc357ea
VZ
400 if ( szHome != NULL )
401 {
96c21216
VZ
402 strDir << szHome;
403
404 // the idea is that under NT these variables have default values
405 // of "%systemdrive%:" and "\\". As we don't want to create our
406 // config files in the root directory of the system drive, we will
407 // create it in our program's dir. However, if the user took care
408 // to set HOMEPATH to something other than "\\", we suppose that he
409 // knows what he is doing and use the supplied value.
410 if ( wxStrcmp(szHome, wxT("\\")) == 0 )
2dc357ea
VZ
411 strDir.clear();
412 }
413 }
96c21216 414
2dc357ea
VZ
415 if ( strDir.empty() )
416 {
417 // If we have a valid USERPROFILE directory, as is the case in
418 // Windows NT, 2000 and XP, we should use that as our home directory.
419 szHome = wxGetenv(wxT("USERPROFILE"));
2bda0e17 420
2dc357ea 421 if ( szHome != NULL )
96c21216 422 strDir = szHome;
2dc357ea 423 }
2bda0e17 424
2dc357ea
VZ
425 if ( !strDir.empty() )
426 {
427 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
428 // value once again, it shouldn't hurt anyhow
429 strDir = wxExpandEnvVars(strDir);
430 }
431 else // fall back to the program directory
432 {
77d8d6cd
VZ
433 // extract the directory component of the program file name
434 wxSplitPath(wxGetFullModuleName(), &strDir, NULL, NULL);
2dc357ea 435 }
4676948b 436#endif // UNIX/Win
b568d04f 437
2dc357ea 438 return strDir.c_str();
afb74891
VZ
439}
440
14d63513 441wxString wxGetUserHome(const wxString& user)
2bda0e17 442{
14d63513 443 wxString home;
2bda0e17 444
14d63513
VZ
445 if ( user.empty() || user == wxGetUserId() )
446 wxGetHomeDir(&home);
447
448 return home;
2bda0e17
KB
449}
450
7bea7b91 451bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path),
7ba7c4e6
VZ
452 wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pTotal),
453 wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pFree))
eadd7bd2 454{
4676948b 455#ifdef __WXWINCE__
040e5f77 456 // TODO-CE
7010702f 457 return false;
4676948b 458#else
eadd7bd2 459 if ( path.empty() )
7010702f 460 return false;
eadd7bd2 461
ee88cb34
MB
462// old w32api don't have ULARGE_INTEGER
463#if defined(__WIN32__) && \
464 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
eadd7bd2
VZ
465 // GetDiskFreeSpaceEx() is not available under original Win95, check for
466 // it
9ee966ec
VZ
467 typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
468 PULARGE_INTEGER,
469 PULARGE_INTEGER,
470 PULARGE_INTEGER);
eadd7bd2
VZ
471
472 GetDiskFreeSpaceEx_t
bb0e27ee 473 pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
eadd7bd2
VZ
474 (
475 ::GetModuleHandle(_T("kernel32.dll")),
476#if wxUSE_UNICODE
477 "GetDiskFreeSpaceExW"
478#else
479 "GetDiskFreeSpaceExA"
480#endif
481 );
482
483 if ( pGetDiskFreeSpaceEx )
484 {
485 ULARGE_INTEGER bytesFree, bytesTotal;
486
487 // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
e0a050e3 488 if ( !pGetDiskFreeSpaceEx(path.fn_str(),
eadd7bd2
VZ
489 &bytesFree,
490 &bytesTotal,
491 NULL) )
492 {
493 wxLogLastError(_T("GetDiskFreeSpaceEx"));
494
27d2dbbc 495 return false;
eadd7bd2
VZ
496 }
497
221e1181
VZ
498 // ULARGE_INTEGER is a union of a 64 bit value and a struct containing
499 // two 32 bit fields which may be or may be not named - try to make it
500 // compile in all cases
501#if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
502 #define UL(ul) ul.u
503#else // anon union
504 #define UL(ul) ul
505#endif
eadd7bd2
VZ
506 if ( pTotal )
507 {
7ba7c4e6
VZ
508#if wxUSE_LONGLONG
509 *pTotal = wxDiskspaceSize_t(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart);
510#else
511 *pTotal = wxDiskspaceSize_t(UL(bytesTotal).LowPart);
512#endif
eadd7bd2
VZ
513 }
514
515 if ( pFree )
516 {
7ba7c4e6 517#if wxUSE_LONGLONG
221e1181 518 *pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart);
7ba7c4e6
VZ
519#else
520 *pFree = wxDiskspaceSize_t(UL(bytesFree).LowPart);
521#endif
eadd7bd2
VZ
522 }
523 }
524 else
525#endif // Win32
526 {
bb0e27ee
VZ
527 // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
528 // should be used instead - but if it's not available, fall back on
529 // GetDiskFreeSpace() nevertheless...
530
eadd7bd2
VZ
531 DWORD lSectorsPerCluster,
532 lBytesPerSector,
533 lNumberOfFreeClusters,
534 lTotalNumberOfClusters;
535
536 // FIXME: this is wrong, we should extract the root drive from path
537 // instead, but this is the job for wxFileName...
e0a050e3 538 if ( !::GetDiskFreeSpace(path.fn_str(),
eadd7bd2
VZ
539 &lSectorsPerCluster,
540 &lBytesPerSector,
541 &lNumberOfFreeClusters,
542 &lTotalNumberOfClusters) )
543 {
544 wxLogLastError(_T("GetDiskFreeSpace"));
545
27d2dbbc 546 return false;
eadd7bd2
VZ
547 }
548
7ba7c4e6 549 wxDiskspaceSize_t lBytesPerCluster = (wxDiskspaceSize_t) lSectorsPerCluster;
eadd7bd2
VZ
550 lBytesPerCluster *= lBytesPerSector;
551
552 if ( pTotal )
553 {
554 *pTotal = lBytesPerCluster;
555 *pTotal *= lTotalNumberOfClusters;
556 }
557
558 if ( pFree )
559 {
560 *pFree = lBytesPerCluster;
561 *pFree *= lNumberOfFreeClusters;
562 }
563 }
564
27d2dbbc 565 return true;
4676948b
JS
566#endif
567 // __WXWINCE__
eadd7bd2
VZ
568}
569
308978f6
VZ
570// ----------------------------------------------------------------------------
571// env vars
572// ----------------------------------------------------------------------------
573
7bea7b91
WS
574bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var),
575 wxString *WXUNUSED_IN_WINCE(value))
308978f6 576{
4676948b 577#ifdef __WXWINCE__
040e5f77 578 // no environment variables under CE
27d2dbbc 579 return false;
e622dd68 580#else // Win32
308978f6 581 // first get the size of the buffer
dc874fb4 582 DWORD dwRet = ::GetEnvironmentVariable(var.t_str(), NULL, 0);
308978f6
VZ
583 if ( !dwRet )
584 {
585 // this means that there is no such variable
27d2dbbc 586 return false;
308978f6
VZ
587 }
588
589 if ( value )
590 {
dc874fb4 591 (void)::GetEnvironmentVariable(var.t_str(),
e0a050e3 592 wxStringBuffer(*value, dwRet),
de564874 593 dwRet);
308978f6
VZ
594 }
595
27d2dbbc 596 return true;
3a5bcc4d 597#endif // WinCE/32
308978f6
VZ
598}
599
90a77e64
VS
600bool wxDoSetEnv(const wxString& WXUNUSED_IN_WINCE(var),
601 const wxChar *WXUNUSED_IN_WINCE(value))
1fb45475
VZ
602{
603 // some compilers have putenv() or _putenv() or _wputenv() but it's better
604 // to always use Win32 function directly instead of dealing with them
7bea7b91
WS
605#ifdef __WXWINCE__
606 // no environment variables under CE
607 return false;
608#else
dc874fb4 609 if ( !::SetEnvironmentVariable(var.t_str(), value) )
1fb45475
VZ
610 {
611 wxLogLastError(_T("SetEnvironmentVariable"));
612
27d2dbbc 613 return false;
1fb45475
VZ
614 }
615
27d2dbbc 616 return true;
1fb45475
VZ
617#endif
618}
619
90a77e64
VS
620bool wxSetEnv(const wxString& variable, const wxString& value)
621{
dc874fb4 622 return wxDoSetEnv(variable, value.t_str());
90a77e64
VS
623}
624
625bool wxUnsetEnv(const wxString& variable)
626{
627 return wxDoSetEnv(variable, NULL);
628}
629
b568d04f
VZ
630// ----------------------------------------------------------------------------
631// process management
632// ----------------------------------------------------------------------------
633
50567b69
VZ
634// structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
635struct wxFindByPidParams
b568d04f 636{
50567b69
VZ
637 wxFindByPidParams() { hwnd = 0; pid = 0; }
638
639 // the HWND used to return the result
640 HWND hwnd;
641
642 // the PID we're looking from
643 DWORD pid;
22f3361e
VZ
644
645 DECLARE_NO_COPY_CLASS(wxFindByPidParams)
50567b69
VZ
646};
647
648// wxKill helper: EnumWindows() callback which is used to find the first (top
649// level) window belonging to the given process
650BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
651{
652 DWORD pid;
653 (void)::GetWindowThreadProcessId(hwnd, &pid);
654
655 wxFindByPidParams *params = (wxFindByPidParams *)lParam;
656 if ( pid == params->pid )
657 {
658 // remember the window we found
659 params->hwnd = hwnd;
660
661 // return FALSE to stop the enumeration
662 return FALSE;
663 }
664
665 // continue enumeration
666 return TRUE;
667}
e949bf13 668
e0f6b731
JS
669int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc);
670
671int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
50567b69 672{
e0f6b731
JS
673 if (flags & wxKILL_CHILDREN)
674 wxKillAllChildren(pid, sig, krc);
9d8aca48 675
50567b69
VZ
676 // get the process handle to operate on
677 HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
678 PROCESS_TERMINATE |
679 PROCESS_QUERY_INFORMATION,
680 FALSE, // not inheritable
681 (DWORD)pid);
682 if ( hProcess == NULL )
e949bf13 683 {
50567b69 684 if ( krc )
e949bf13 685 {
a45fb5b4
VZ
686 // recognize wxKILL_ACCESS_DENIED as special because this doesn't
687 // mean that the process doesn't exist and this is important for
688 // wxProcess::Exists()
689 *krc = ::GetLastError() == ERROR_ACCESS_DENIED
690 ? wxKILL_ACCESS_DENIED
691 : wxKILL_NO_PROCESS;
50567b69
VZ
692 }
693
694 return -1;
695 }
696
a45fb5b4
VZ
697 wxON_BLOCK_EXIT1(::CloseHandle, hProcess);
698
27d2dbbc 699 bool ok = true;
50567b69
VZ
700 switch ( sig )
701 {
702 case wxSIGKILL:
703 // kill the process forcefully returning -1 as error code
704 if ( !::TerminateProcess(hProcess, (UINT)-1) )
705 {
706 wxLogSysError(_("Failed to kill process %d"), pid);
707
708 if ( krc )
e949bf13 709 {
50567b69
VZ
710 // this is not supposed to happen if we could open the
711 // process
712 *krc = wxKILL_ERROR;
e949bf13 713 }
50567b69 714
27d2dbbc 715 ok = false;
e949bf13 716 }
50567b69
VZ
717 break;
718
719 case wxSIGNONE:
720 // do nothing, we just want to test for process existence
a45fb5b4
VZ
721 if ( krc )
722 *krc = wxKILL_OK;
723 return 0;
50567b69
VZ
724
725 default:
726 // any other signal means "terminate"
727 {
728 wxFindByPidParams params;
729 params.pid = (DWORD)pid;
730
731 // EnumWindows() has nice semantics: it returns 0 if it found
3103e8a9 732 // something or if an error occurred and non zero if it
50567b69
VZ
733 // enumerated all the window
734 if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)&params) )
735 {
736 // did we find any window?
737 if ( params.hwnd )
738 {
739 // tell the app to close
740 //
3103e8a9 741 // NB: this is the harshest way, the app won't have an
50567b69
VZ
742 // opportunity to save any files, for example, but
743 // this is probably what we want here. If not we
744 // can also use SendMesageTimeout(WM_CLOSE)
745 if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) )
746 {
747 wxLogLastError(_T("PostMessage(WM_QUIT)"));
748 }
749 }
750 else // it was an error then
751 {
752 wxLogLastError(_T("EnumWindows"));
753
27d2dbbc 754 ok = false;
50567b69
VZ
755 }
756 }
757 else // no windows for this PID
758 {
759 if ( krc )
50567b69 760 *krc = wxKILL_ERROR;
50567b69 761
27d2dbbc 762 ok = false;
50567b69
VZ
763 }
764 }
765 }
766
767 // the return code
a45fb5b4 768 DWORD rc wxDUMMY_INITIALIZE(0);
50567b69
VZ
769 if ( ok )
770 {
771 // as we wait for a short time, we can use just WaitForSingleObject()
772 // and not MsgWaitForMultipleObjects()
773 switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) )
774 {
775 case WAIT_OBJECT_0:
776 // process terminated
777 if ( !::GetExitCodeProcess(hProcess, &rc) )
778 {
779 wxLogLastError(_T("GetExitCodeProcess"));
780 }
781 break;
782
783 default:
784 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
785 // fall through
786
787 case WAIT_FAILED:
788 wxLogLastError(_T("WaitForSingleObject"));
789 // fall through
790
791 case WAIT_TIMEOUT:
792 if ( krc )
50567b69 793 *krc = wxKILL_ERROR;
50567b69
VZ
794
795 rc = STILL_ACTIVE;
796 break;
e949bf13
JS
797 }
798 }
799
b568d04f 800
50567b69
VZ
801 // the return code is the same as from Unix kill(): 0 if killed
802 // successfully or -1 on error
a45fb5b4
VZ
803 if ( !ok || rc == STILL_ACTIVE )
804 return -1;
b1a28eef 805
a45fb5b4
VZ
806 if ( krc )
807 *krc = wxKILL_OK;
50567b69 808
a45fb5b4 809 return 0;
2bda0e17
KB
810}
811
78a054f6
WS
812typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_t)(DWORD,DWORD);
813typedef BOOL (WINAPI *Process32_t)(HANDLE,LPPROCESSENTRY32);
814
815CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot;
816Process32_t lpfProcess32First, lpfProcess32Next;
9d8aca48 817
e0f6b731
JS
818static void InitToolHelp32()
819{
820 static bool s_initToolHelpDone = false;
9d8aca48 821
e0f6b731
JS
822 if (s_initToolHelpDone)
823 return;
9d8aca48 824
e0f6b731
JS
825 s_initToolHelpDone = true;
826
827 lpfCreateToolhelp32Snapshot = NULL;
828 lpfProcess32First = NULL;
829 lpfProcess32Next = NULL;
9d8aca48 830
32c0c61c
WS
831#if wxUSE_DYNLIB_CLASS
832
78a054f6 833 wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM);
9d8aca48 834
e0f6b731
JS
835 // Get procedure addresses.
836 // We are linking to these functions of Kernel32
837 // explicitly, because otherwise a module using
838 // this code would fail to load under Windows NT,
839 // which does not have the Toolhelp32
840 // functions in the Kernel 32.
78a054f6
WS
841 lpfCreateToolhelp32Snapshot =
842 (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
9d8aca48 843
78a054f6
WS
844 lpfProcess32First =
845 (Process32_t)dllKernel.RawGetSymbol(_T("Process32First"));
e0f6b731 846
78a054f6
WS
847 lpfProcess32Next =
848 (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next"));
32c0c61c
WS
849
850#endif // wxUSE_DYNLIB_CLASS
e0f6b731
JS
851}
852
853// By John Skiff
854int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
855{
856 InitToolHelp32();
9d8aca48 857
e0f6b731
JS
858 if (krc)
859 *krc = wxKILL_OK;
9d8aca48 860
e0f6b731
JS
861 // If not implemented for this platform (e.g. NT 4.0), silently ignore
862 if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next)
863 return 0;
9d8aca48 864
e0f6b731
JS
865 // Take a snapshot of all processes in the system.
866 HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
867 if (hProcessSnap == INVALID_HANDLE_VALUE) {
868 if (krc)
869 *krc = wxKILL_ERROR;
870 return -1;
871 }
9d8aca48 872
e0f6b731 873 //Fill in the size of the structure before using it.
04a18b0d
WS
874 PROCESSENTRY32 pe;
875 wxZeroMemory(pe);
e0f6b731 876 pe.dwSize = sizeof(PROCESSENTRY32);
9d8aca48 877
e0f6b731
JS
878 // Walk the snapshot of the processes, and for each process,
879 // kill it if its parent is pid.
880 if (!lpfProcess32First(hProcessSnap, &pe)) {
881 // Can't get first process.
882 if (krc)
883 *krc = wxKILL_ERROR;
884 CloseHandle (hProcessSnap);
885 return -1;
886 }
9d8aca48 887
e0f6b731
JS
888 do {
889 if (pe.th32ParentProcessID == (DWORD) pid) {
890 if (wxKill(pe.th32ProcessID, sig, krc))
891 return -1;
892 }
893 } while (lpfProcess32Next (hProcessSnap, &pe));
9d8aca48
WS
894
895
e0f6b731
JS
896 return 0;
897}
898
b568d04f
VZ
899// Execute a program in an Interactive Shell
900bool wxShell(const wxString& command)
2bda0e17 901{
7010702f
WS
902 wxString cmd;
903
4676948b 904#ifdef __WXWINCE__
7010702f 905 cmd = command;
4676948b 906#else
b568d04f
VZ
907 wxChar *shell = wxGetenv(wxT("COMSPEC"));
908 if ( !shell )
ba14d986 909 shell = (wxChar*) wxT("\\COMMAND.COM");
b568d04f 910
b568d04f
VZ
911 if ( !command )
912 {
913 // just the shell
914 cmd = shell;
915 }
916 else
917 {
918 // pass the command to execute to the command processor
919 cmd.Printf(wxT("%s /c %s"), shell, command.c_str());
920 }
7010702f 921#endif
b568d04f 922
011a524e 923 return wxExecute(cmd, wxEXEC_SYNC) == 0;
2bda0e17
KB
924}
925
d8c65cf4 926// Shutdown or reboot the PC
118a41d9 927bool wxShutdown(int WXUNUSED_IN_WINCE(flags))
f6ba47d9 928{
4676948b 929#ifdef __WXWINCE__
040e5f77 930 // TODO-CE
27d2dbbc 931 return false;
4676948b 932#elif defined(__WIN32__)
27d2dbbc 933 bool bOK = true;
f6ba47d9 934
406d283a 935 if ( wxGetOsVersion(NULL, NULL) == wxOS_WINDOWS_NT ) // if is NT or 2K
f6ba47d9 936 {
d8c65cf4
RD
937 // Get a token for this process.
938 HANDLE hToken;
f6ba47d9
VZ
939 bOK = ::OpenProcessToken(GetCurrentProcess(),
940 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
941 &hToken) != 0;
942 if ( bOK )
943 {
d8c65cf4 944 TOKEN_PRIVILEGES tkp;
f6ba47d9 945
d8c65cf4 946 // Get the LUID for the shutdown privilege.
a2e50fc2
VZ
947 bOK = ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
948 &tkp.Privileges[0].Luid) != 0;
f6ba47d9 949
a2e50fc2
VZ
950 if ( bOK )
951 {
952 tkp.PrivilegeCount = 1; // one privilege to set
953 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
954
955 // Get the shutdown privilege for this process.
956 ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
957 (PTOKEN_PRIVILEGES)NULL, 0);
f6ba47d9 958
a2e50fc2
VZ
959 // Cannot test the return value of AdjustTokenPrivileges.
960 bOK = ::GetLastError() == ERROR_SUCCESS;
961 }
f6ba47d9 962
a2e50fc2 963 ::CloseHandle(hToken);
f6ba47d9
VZ
964 }
965 }
966
967 if ( bOK )
968 {
118a41d9
VZ
969 UINT wFlags = 0;
970 if ( flags & wxSHUTDOWN_FORCE )
971 {
972 wFlags = EWX_FORCE;
973 flags &= ~wxSHUTDOWN_FORCE;
974 }
975
976 switch ( flags )
f6ba47d9
VZ
977 {
978 case wxSHUTDOWN_POWEROFF:
118a41d9 979 wFlags |= EWX_POWEROFF;
f6ba47d9
VZ
980 break;
981
982 case wxSHUTDOWN_REBOOT:
118a41d9
VZ
983 wFlags |= EWX_REBOOT;
984 break;
985
986 case wxSHUTDOWN_LOGOFF:
987 wFlags |= EWX_LOGOFF;
f6ba47d9
VZ
988 break;
989
990 default:
991 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
27d2dbbc 992 return false;
f6ba47d9
VZ
993 }
994
118a41d9 995 bOK = ::ExitWindowsEx(wFlags, 0) != 0;
f6ba47d9
VZ
996 }
997
998 return bOK;
118a41d9 999#endif // WinCE/!WinCE
f6ba47d9
VZ
1000}
1001
b568d04f
VZ
1002// ----------------------------------------------------------------------------
1003// misc
1004// ----------------------------------------------------------------------------
1005
1006// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
9d8aca48 1007wxMemorySize wxGetFreeMemory()
2bda0e17 1008{
9d8aca48
WS
1009#if defined(__WIN64__)
1010 MEMORYSTATUSEX memStatex;
106d80ad
JS
1011 memStatex.dwLength = sizeof (memStatex);
1012 ::GlobalMemoryStatusEx (&memStatex);
1013 return (wxMemorySize)memStatex.ullAvailPhys;
2b7295c9 1014#else /* if defined(__WIN32__) */
b568d04f
VZ
1015 MEMORYSTATUS memStatus;
1016 memStatus.dwLength = sizeof(MEMORYSTATUS);
2b7295c9 1017 ::GlobalMemoryStatus(&memStatus);
9d8aca48 1018 return (wxMemorySize)memStatus.dwAvailPhys;
b568d04f 1019#endif
2bda0e17
KB
1020}
1021
c1cb4153
VZ
1022unsigned long wxGetProcessId()
1023{
c1cb4153 1024 return ::GetCurrentProcessId();
c1cb4153
VZ
1025}
1026
2bda0e17 1027// Emit a beeeeeep
634903fd 1028void wxBell()
2bda0e17 1029{
b568d04f 1030 ::MessageBeep((UINT)-1); // default sound
2bda0e17
KB
1031}
1032
c50a4038
VZ
1033bool wxIsDebuggerRunning()
1034{
532d575b 1035#if wxUSE_DYNLIB_CLASS
c50a4038
VZ
1036 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1037 wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
1038
1039 typedef BOOL (WINAPI *IsDebuggerPresent_t)();
1040 if ( !dll.HasSymbol(_T("IsDebuggerPresent")) )
1041 {
1042 // no way to know, assume no
1043 return false;
1044 }
1045
1046 return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
532d575b
WS
1047#else
1048 return false;
1049#endif
c50a4038
VZ
1050}
1051
1052// ----------------------------------------------------------------------------
1053// OS version
1054// ----------------------------------------------------------------------------
1055
66930b35
VZ
1056// check if we're running under a server or workstation Windows system: it
1057// returns true or false with obvious meaning as well as -1 if the system type
1058// couldn't be determined
1059//
1060// this function is currently private but we may want to expose it later if
1061// it's really useful
1062namespace
1063{
1064
1065int wxIsWindowsServer()
1066{
1067#ifdef VER_NT_WORKSTATION
1068 OSVERSIONINFOEX info;
1069 wxZeroMemory(info);
1070
1071 info.dwOSVersionInfoSize = sizeof(info);
5c33522f 1072 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&info)) )
66930b35
VZ
1073 {
1074 switch ( info.wProductType )
1075 {
1076 case VER_NT_WORKSTATION:
1077 return false;
1078
1079 case VER_NT_SERVER:
1080 case VER_NT_DOMAIN_CONTROLLER:
1081 return true;
1082 }
1083 }
1084#endif // VER_NT_WORKSTATION
1085
1086 return -1;
1087}
1088
1089} // anonymous namespace
1090
bdc72a22 1091wxString wxGetOsDescription()
2bda0e17 1092{
bdc72a22
VZ
1093 wxString str;
1094
1095 OSVERSIONINFO info;
1096 wxZeroMemory(info);
1097
1098 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1099 if ( ::GetVersionEx(&info) )
1100 {
1101 switch ( info.dwPlatformId )
1102 {
84dc0006
WS
1103#ifdef VER_PLATFORM_WIN32_CE
1104 case VER_PLATFORM_WIN32_CE:
1105 str.Printf(_("Windows CE (%d.%d)"),
1106 info.dwMajorVersion,
1107 info.dwMinorVersion);
1108 break;
1109#endif
bdc72a22
VZ
1110 case VER_PLATFORM_WIN32s:
1111 str = _("Win32s on Windows 3.1");
1112 break;
1113
1114 case VER_PLATFORM_WIN32_WINDOWS:
db1d0193
VZ
1115 switch (info.dwMinorVersion)
1116 {
1117 case 0:
1118 if ( info.szCSDVersion[1] == 'B' ||
1119 info.szCSDVersion[1] == 'C' )
1120 {
1121 str = _("Windows 95 OSR2");
1122 }
1123 else
1124 {
1125 str = _("Windows 95");
1126 }
1127 break;
1128 case 10:
1129 if ( info.szCSDVersion[1] == 'B' ||
1130 info.szCSDVersion[1] == 'C' )
1131 {
1132 str = _("Windows 98 SE");
1133 }
1134 else
1135 {
1136 str = _("Windows 98");
1137 }
1138 break;
1139 case 90:
1140 str = _("Windows ME");
1141 break;
1142 default:
1143 str.Printf(_("Windows 9x (%d.%d)"),
1144 info.dwMajorVersion,
1145 info.dwMinorVersion);
1146 break;
1147 }
bdc72a22
VZ
1148 if ( !wxIsEmpty(info.szCSDVersion) )
1149 {
1150 str << _T(" (") << info.szCSDVersion << _T(')');
1151 }
1152 break;
1153
1154 case VER_PLATFORM_WIN32_NT:
a284cce8 1155 switch ( info.dwMajorVersion )
db1d0193 1156 {
a284cce8
VZ
1157 case 5:
1158 switch ( info.dwMinorVersion )
1159 {
1160 case 0:
1161 str.Printf(_("Windows 2000 (build %lu"),
1162 info.dwBuildNumber);
1163 break;
1164
66930b35
VZ
1165 case 2:
1166 // we can't distinguish between XP 64 and 2003
1167 // as they both are 5.2, so examine the product
1168 // type to resolve this ambiguity
575cabba 1169 if ( wxIsWindowsServer() == 1 )
66930b35
VZ
1170 {
1171 str.Printf(_("Windows Server 2003 (build %lu"),
1172 info.dwBuildNumber);
1173 break;
1174 }
1175 //else: must be XP, fall through
1176
a284cce8
VZ
1177 case 1:
1178 str.Printf(_("Windows XP (build %lu"),
1179 info.dwBuildNumber);
1180 break;
a284cce8
VZ
1181 }
1182 break;
1183
1184 case 6:
1185 if ( info.dwMinorVersion == 0 )
1186 {
1187 str.Printf(_("Windows Vista (build %lu"),
db1d0193 1188 info.dwBuildNumber);
a284cce8
VZ
1189 }
1190 break;
db1d0193 1191 }
a284cce8 1192
84dc0006 1193 if ( str.empty() )
db1d0193
VZ
1194 {
1195 str.Printf(_("Windows NT %lu.%lu (build %lu"),
bdc72a22
VZ
1196 info.dwMajorVersion,
1197 info.dwMinorVersion,
1198 info.dwBuildNumber);
db1d0193 1199 }
a284cce8 1200
bdc72a22
VZ
1201 if ( !wxIsEmpty(info.szCSDVersion) )
1202 {
1203 str << _T(", ") << info.szCSDVersion;
1204 }
1205 str << _T(')');
d4885e10
VZ
1206
1207 if ( wxIsPlatform64Bit() )
1208 str << _(", 64-bit edition");
bdc72a22
VZ
1209 break;
1210 }
1211 }
1212 else
1213 {
1214 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1215 }
1216
1217 return str;
bdc72a22 1218}
6f65e337 1219
8bb6b2c0 1220bool wxIsPlatform64Bit()
bdc72a22 1221{
8bb6b2c0
VZ
1222#if defined(_WIN64)
1223 return true; // 64-bit programs run only on Win64
a8ff046b 1224#elif wxUSE_DYNLIB_CLASS // Win32
6deb397d
VZ
1225 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1226 typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *);
1227
1228 wxDynamicLibrary dllKernel32(_T("kernel32.dll"));
b9d4a1b7
MW
1229 IsWow64Process_t pfnIsWow64Process =
1230 (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process"));
6deb397d
VZ
1231
1232 BOOL wow64 = FALSE;
1233 if ( pfnIsWow64Process )
1234 {
b9d4a1b7 1235 pfnIsWow64Process(::GetCurrentProcess(), &wow64);
6deb397d
VZ
1236 }
1237 //else: running under a system without Win64 support
1238
1239 return wow64 != FALSE;
a8ff046b
VZ
1240#else
1241 return false;
6deb397d 1242#endif // Win64/Win32
8bb6b2c0 1243}
ec5d7799 1244
8bb6b2c0
VZ
1245wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
1246{
5bc3ef05
VZ
1247 static struct
1248 {
1249 // this may be false, true or -1 if we tried to initialize but failed
1250 int initialized;
bdc72a22 1251
5bc3ef05
VZ
1252 wxOperatingSystemId os;
1253
1254 int verMaj,
1255 verMin;
1256 } s_version;
1257
1258 // query the OS info only once as it's not supposed to change
1259 if ( !s_version.initialized )
8bb6b2c0 1260 {
5bc3ef05
VZ
1261 OSVERSIONINFO info;
1262 wxZeroMemory(info);
1263 info.dwOSVersionInfoSize = sizeof(info);
1264 if ( ::GetVersionEx(&info) )
1265 {
1266 s_version.initialized = true;
1267
1268#if defined(__WXWINCE__)
1269 s_version.os = wxOS_WINDOWS_CE;
1270#elif defined(__WXMICROWIN__)
1271 s_version.os = wxOS_WINDOWS_MICRO;
1272#else // "normal" desktop Windows system, use run-time detection
1273 switch ( info.dwPlatformId )
1274 {
1275 case VER_PLATFORM_WIN32_NT:
1276 s_version.os = wxOS_WINDOWS_NT;
1277 break;
1278
1279 case VER_PLATFORM_WIN32_WINDOWS:
1280 s_version.os = wxOS_WINDOWS_9X;
1281 break;
1282 }
1283#endif // Windows versions
1284
1285 s_version.verMaj = info.dwMajorVersion;
1286 s_version.verMin = info.dwMinorVersion;
1287 }
1288 else // GetVersionEx() failed
1289 {
1290 s_version.initialized = -1;
1291 }
8bb6b2c0 1292 }
bdc72a22 1293
5bc3ef05 1294 if ( s_version.initialized == 1 )
8bb6b2c0 1295 {
5bc3ef05
VZ
1296 if ( verMaj )
1297 *verMaj = s_version.verMaj;
1298 if ( verMin )
1299 *verMin = s_version.verMin;
bdc72a22
VZ
1300 }
1301
5bc3ef05
VZ
1302 // this works even if we were not initialized successfully as the initial
1303 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1304 return s_version.os;
2bda0e17
KB
1305}
1306
4c5da5e4
VZ
1307wxWinVersion wxGetWinVersion()
1308{
1309 int verMaj,
1310 verMin;
1311 switch ( wxGetOsVersion(&verMaj, &verMin) )
1312 {
406d283a 1313 case wxOS_WINDOWS_9X:
4c5da5e4
VZ
1314 if ( verMaj == 4 )
1315 {
1316 switch ( verMin )
1317 {
1318 case 0:
1319 return wxWinVersion_95;
1320
1321 case 10:
1322 return wxWinVersion_98;
1323
1324 case 90:
1325 return wxWinVersion_ME;
1326 }
1327 }
1328 break;
1329
406d283a 1330 case wxOS_WINDOWS_NT:
4c5da5e4
VZ
1331 switch ( verMaj )
1332 {
1333 case 3:
1334 return wxWinVersion_NT3;
1335
1336 case 4:
1337 return wxWinVersion_NT4;
1338
1339 case 5:
1340 switch ( verMin )
1341 {
1342 case 0:
1343 return wxWinVersion_2000;
1344
1345 case 1:
1346 return wxWinVersion_XP;
1347
1348 case 2:
1349 return wxWinVersion_2003;
1350 }
1351 break;
1352
1353 case 6:
1354 return wxWinVersion_NT6;
1355 }
1356 break;
1357
449210a4
WS
1358 default:
1359 // Do nothing just to silence GCC warning
1360 break;
4c5da5e4
VZ
1361 }
1362
1363 return wxWinVersion_Unknown;
1364}
1365
b568d04f
VZ
1366// ----------------------------------------------------------------------------
1367// sleep functions
1368// ----------------------------------------------------------------------------
1369
08873d36 1370void wxMilliSleep(unsigned long milliseconds)
b568d04f
VZ
1371{
1372 ::Sleep(milliseconds);
1373}
1374
08873d36
VZ
1375void wxMicroSleep(unsigned long microseconds)
1376{
1377 wxMilliSleep(microseconds/1000);
1378}
1379
b568d04f
VZ
1380void wxSleep(int nSecs)
1381{
08873d36 1382 wxMilliSleep(1000*nSecs);
b568d04f
VZ
1383}
1384
b568d04f 1385// ----------------------------------------------------------------------------
e2478fde 1386// font encoding <-> Win32 codepage conversion functions
b568d04f
VZ
1387// ----------------------------------------------------------------------------
1388
bddd7a8d 1389extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
b568d04f 1390{
e2478fde 1391 switch ( encoding )
b568d04f 1392 {
e2478fde
VZ
1393 // although this function is supposed to return an exact match, do do
1394 // some mappings here for the most common case of "standard" encoding
1395 case wxFONTENCODING_SYSTEM:
1396 return DEFAULT_CHARSET;
2bda0e17 1397
e2478fde
VZ
1398 case wxFONTENCODING_ISO8859_1:
1399 case wxFONTENCODING_ISO8859_15:
1400 case wxFONTENCODING_CP1252:
1401 return ANSI_CHARSET;
2bda0e17 1402
e2478fde
VZ
1403#if !defined(__WXMICROWIN__)
1404 // The following four fonts are multi-byte charsets
1405 case wxFONTENCODING_CP932:
1406 return SHIFTJIS_CHARSET;
2bda0e17 1407
e2478fde
VZ
1408 case wxFONTENCODING_CP936:
1409 return GB2312_CHARSET;
2bda0e17 1410
90805c24 1411#ifndef __WXWINCE__
e2478fde
VZ
1412 case wxFONTENCODING_CP949:
1413 return HANGUL_CHARSET;
90805c24 1414#endif
634903fd 1415
e2478fde
VZ
1416 case wxFONTENCODING_CP950:
1417 return CHINESEBIG5_CHARSET;
2bda0e17 1418
e2478fde
VZ
1419 // The rest are single byte encodings
1420 case wxFONTENCODING_CP1250:
1421 return EASTEUROPE_CHARSET;
bfbd6dc1 1422
e2478fde
VZ
1423 case wxFONTENCODING_CP1251:
1424 return RUSSIAN_CHARSET;
2bda0e17 1425
e2478fde
VZ
1426 case wxFONTENCODING_CP1253:
1427 return GREEK_CHARSET;
b07135ba 1428
e2478fde
VZ
1429 case wxFONTENCODING_CP1254:
1430 return TURKISH_CHARSET;
2bda0e17 1431
e2478fde
VZ
1432 case wxFONTENCODING_CP1255:
1433 return HEBREW_CHARSET;
2bda0e17 1434
e2478fde
VZ
1435 case wxFONTENCODING_CP1256:
1436 return ARABIC_CHARSET;
b568d04f 1437
e2478fde
VZ
1438 case wxFONTENCODING_CP1257:
1439 return BALTIC_CHARSET;
634903fd 1440
e2478fde
VZ
1441 case wxFONTENCODING_CP874:
1442 return THAI_CHARSET;
5acc0d5f 1443#endif // !__WXMICROWIN__
cc2b7472 1444
e2478fde
VZ
1445 case wxFONTENCODING_CP437:
1446 return OEM_CHARSET;
ea28b885
VZ
1447
1448 default:
1449 // no way to translate this encoding into a Windows charset
69557827 1450 return -1;
e2478fde 1451 }
373658eb 1452}
7f555861 1453
e2478fde
VZ
1454// we have 2 versions of wxCharsetToCodepage(): the old one which directly
1455// looks up the vlaues in the registry and the new one which is more
1456// politically correct and has more chances to work on other Windows versions
1457// as well but the old version is still needed for !wxUSE_FONTMAP case
1458#if wxUSE_FONTMAP
c030b70f 1459
373658eb 1460#include "wx/fontmap.h"
c030b70f 1461
bddd7a8d 1462extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
c030b70f 1463{
b169661f
RR
1464 // There don't seem to be symbolic names for
1465 // these under Windows so I just copied the
1466 // values from MSDN.
04a18b0d 1467
fa78de82 1468 unsigned int ret;
04a18b0d 1469
b169661f 1470 switch (encoding)
373658eb 1471 {
fa78de82
RR
1472 case wxFONTENCODING_ISO8859_1: ret = 28591; break;
1473 case wxFONTENCODING_ISO8859_2: ret = 28592; break;
1474 case wxFONTENCODING_ISO8859_3: ret = 28593; break;
1475 case wxFONTENCODING_ISO8859_4: ret = 28594; break;
1476 case wxFONTENCODING_ISO8859_5: ret = 28595; break;
1477 case wxFONTENCODING_ISO8859_6: ret = 28596; break;
1478 case wxFONTENCODING_ISO8859_7: ret = 28597; break;
1479 case wxFONTENCODING_ISO8859_8: ret = 28598; break;
1480 case wxFONTENCODING_ISO8859_9: ret = 28599; break;
1481 case wxFONTENCODING_ISO8859_10: ret = 28600; break;
5df3dbf9 1482 case wxFONTENCODING_ISO8859_11: ret = 874; break;
b169661f 1483 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
04a18b0d 1484 case wxFONTENCODING_ISO8859_13: ret = 28603; break;
5fdf0363 1485 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
fa78de82 1486 case wxFONTENCODING_ISO8859_15: ret = 28605; break;
bd5c3968 1487
fa78de82
RR
1488 case wxFONTENCODING_KOI8: ret = 20866; break;
1489 case wxFONTENCODING_KOI8_U: ret = 21866; break;
bd5c3968 1490
fa78de82
RR
1491 case wxFONTENCODING_CP437: ret = 437; break;
1492 case wxFONTENCODING_CP850: ret = 850; break;
1493 case wxFONTENCODING_CP852: ret = 852; break;
1494 case wxFONTENCODING_CP855: ret = 855; break;
1495 case wxFONTENCODING_CP866: ret = 866; break;
1496 case wxFONTENCODING_CP874: ret = 874; break;
1497 case wxFONTENCODING_CP932: ret = 932; break;
1498 case wxFONTENCODING_CP936: ret = 936; break;
1499 case wxFONTENCODING_CP949: ret = 949; break;
1500 case wxFONTENCODING_CP950: ret = 950; break;
1501 case wxFONTENCODING_CP1250: ret = 1250; break;
1502 case wxFONTENCODING_CP1251: ret = 1251; break;
1503 case wxFONTENCODING_CP1252: ret = 1252; break;
1504 case wxFONTENCODING_CP1253: ret = 1253; break;
1505 case wxFONTENCODING_CP1254: ret = 1254; break;
1506 case wxFONTENCODING_CP1255: ret = 1255; break;
1507 case wxFONTENCODING_CP1256: ret = 1256; break;
1508 case wxFONTENCODING_CP1257: ret = 1257; break;
bd5c3968 1509
a50ca843 1510 case wxFONTENCODING_EUC_JP: ret = 20932; break;
bd5c3968 1511
fa78de82
RR
1512 case wxFONTENCODING_MACROMAN: ret = 10000; break;
1513 case wxFONTENCODING_MACJAPANESE: ret = 10001; break;
1514 case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
1515 case wxFONTENCODING_MACKOREAN: ret = 10003; break;
1516 case wxFONTENCODING_MACARABIC: ret = 10004; break;
1517 case wxFONTENCODING_MACHEBREW: ret = 10005; break;
1518 case wxFONTENCODING_MACGREEK: ret = 10006; break;
1519 case wxFONTENCODING_MACCYRILLIC: ret = 10007; break;
1520 case wxFONTENCODING_MACTHAI: ret = 10021; break;
1521 case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break;
1522 case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break;
1523 case wxFONTENCODING_MACCROATIAN: ret = 10082; break;
1524 case wxFONTENCODING_MACICELANDIC: ret = 10079; break;
1525 case wxFONTENCODING_MACROMANIAN: ret = 10009; break;
bd5c3968
VZ
1526
1527 case wxFONTENCODING_ISO2022_JP: ret = 50222; break;
1528
fa78de82
RR
1529 case wxFONTENCODING_UTF7: ret = 65000; break;
1530 case wxFONTENCODING_UTF8: ret = 65001; break;
bd5c3968 1531
fa78de82 1532 default: return -1;
373658eb 1533 }
04a18b0d 1534
fa78de82
RR
1535 if (::IsValidCodePage(ret) == 0)
1536 return -1;
04a18b0d 1537
fa78de82
RR
1538 CPINFO info;
1539 if (::GetCPInfo(ret, &info) == 0)
1540 return -1;
373658eb 1541
fa78de82 1542 return (long) ret;
c030b70f 1543}
373658eb 1544
86501081 1545extern long wxCharsetToCodepage(const char *name)
c030b70f 1546{
373658eb
VZ
1547 // first get the font encoding for this charset
1548 if ( !name )
1549 return -1;
1550
267e11c5 1551 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
373658eb
VZ
1552 if ( enc == wxFONTENCODING_SYSTEM )
1553 return -1;
1554
1555 // the use the helper function
1556 return wxEncodingToCodepage(enc);
c030b70f 1557}
c030b70f 1558
e2478fde 1559#else // !wxUSE_FONTMAP
373658eb
VZ
1560
1561#include "wx/msw/registry.h"
1562
1563// this should work if Internet Exploiter is installed
86501081 1564extern long wxCharsetToCodepage(const char *name)
04ef50df 1565{
373658eb
VZ
1566 if (!name)
1567 return GetACP();
1568
e2478fde 1569 long CP = -1;
373658eb 1570
f77c0fe3 1571#if wxUSE_REGKEY
e2478fde 1572 wxString path(wxT("MIME\\Database\\Charset\\"));
373658eb 1573 wxString cn(name);
373658eb 1574
e2478fde
VZ
1575 // follow the alias loop
1576 for ( ;; )
1577 {
1578 wxRegKey key(wxRegKey::HKCR, path + cn);
1579
1580 if (!key.Exists())
1581 break;
373658eb
VZ
1582
1583 // two cases: either there's an AliasForCharset string,
1584 // or there are Codepage and InternetEncoding dwords.
1585 // The InternetEncoding gives us the actual encoding,
1586 // the Codepage just says which Windows character set to
1587 // use when displaying the data.
1588 if (key.HasValue(wxT("InternetEncoding")) &&
e2478fde
VZ
1589 key.QueryValue(wxT("InternetEncoding"), &CP))
1590 break;
373658eb
VZ
1591
1592 // no encoding, see if it's an alias
1593 if (!key.HasValue(wxT("AliasForCharset")) ||
e2478fde
VZ
1594 !key.QueryValue(wxT("AliasForCharset"), cn))
1595 break;
1596 }
f77c0fe3 1597#endif // wxUSE_REGKEY
373658eb
VZ
1598
1599 return CP;
04ef50df 1600}
373658eb 1601
e2478fde 1602#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
c030b70f 1603
eccd1992
VZ
1604/*
1605 Creates a hidden window with supplied window proc registering the class for
1606 it if necesssary (i.e. the first time only). Caller is responsible for
1607 destroying the window and unregistering the class (note that this must be
77ffb593 1608 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
eccd1992
VZ
1609 multiple times into/from the same process so we cna't rely on automatic
1610 Windows class unregistration).
1611
1612 pclassname is a pointer to a caller stored classname, which must initially be
3103e8a9 1613 NULL. classname is the desired wndclass classname. If function successfully
eccd1992
VZ
1614 registers the class, pclassname will be set to classname.
1615 */
487f2d58 1616extern "C" WXDLLIMPEXP_BASE HWND
eccd1992
VZ
1617wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
1618{
1619 wxCHECK_MSG( classname && pclassname && wndproc, NULL,
1620 _T("NULL parameter in wxCreateHiddenWindow") );
1621
1622 // register the class fi we need to first
1623 if ( *pclassname == NULL )
1624 {
1625 WNDCLASS wndclass;
1626 wxZeroMemory(wndclass);
1627
1628 wndclass.lpfnWndProc = wndproc;
1629 wndclass.hInstance = wxGetInstance();
1630 wndclass.lpszClassName = classname;
1631
1632 if ( !::RegisterClass(&wndclass) )
1633 {
1634 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1635
1636 return NULL;
1637 }
1638
1639 *pclassname = classname;
1640 }
1641
1642 // next create the window
1643 HWND hwnd = ::CreateWindow
1644 (
1645 *pclassname,
1646 NULL,
1647 0, 0, 0, 0,
1648 0,
1649 (HWND) NULL,
1650 (HMENU)NULL,
1651 wxGetInstance(),
1652 (LPVOID) NULL
1653 );
1654
1655 if ( !hwnd )
1656 {
1657 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
1658 }
1659
1660 return hwnd;
1661}