]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utils.cpp
add wxVector(size_t size[, const value_type& value]) ctors
[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 {
e408bf52 221 wxStrlcpy(buf, host, 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.
f6ba47d9 947 ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
d8c65cf4 948 &tkp.Privileges[0].Luid);
f6ba47d9 949
d8c65cf4
RD
950 tkp.PrivilegeCount = 1; // one privilege to set
951 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
f6ba47d9 952
d8c65cf4 953 // Get the shutdown privilege for this process.
f6ba47d9 954 ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
d8c65cf4 955 (PTOKEN_PRIVILEGES)NULL, 0);
f6ba47d9 956
d8c65cf4 957 // Cannot test the return value of AdjustTokenPrivileges.
f6ba47d9
VZ
958 bOK = ::GetLastError() == ERROR_SUCCESS;
959 }
960 }
961
962 if ( bOK )
963 {
118a41d9
VZ
964 UINT wFlags = 0;
965 if ( flags & wxSHUTDOWN_FORCE )
966 {
967 wFlags = EWX_FORCE;
968 flags &= ~wxSHUTDOWN_FORCE;
969 }
970
971 switch ( flags )
f6ba47d9
VZ
972 {
973 case wxSHUTDOWN_POWEROFF:
118a41d9 974 wFlags |= EWX_POWEROFF;
f6ba47d9
VZ
975 break;
976
977 case wxSHUTDOWN_REBOOT:
118a41d9
VZ
978 wFlags |= EWX_REBOOT;
979 break;
980
981 case wxSHUTDOWN_LOGOFF:
982 wFlags |= EWX_LOGOFF;
f6ba47d9
VZ
983 break;
984
985 default:
986 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
27d2dbbc 987 return false;
f6ba47d9
VZ
988 }
989
118a41d9 990 bOK = ::ExitWindowsEx(wFlags, 0) != 0;
f6ba47d9
VZ
991 }
992
993 return bOK;
118a41d9 994#endif // WinCE/!WinCE
f6ba47d9
VZ
995}
996
b568d04f
VZ
997// ----------------------------------------------------------------------------
998// misc
999// ----------------------------------------------------------------------------
1000
1001// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
9d8aca48 1002wxMemorySize wxGetFreeMemory()
2bda0e17 1003{
9d8aca48
WS
1004#if defined(__WIN64__)
1005 MEMORYSTATUSEX memStatex;
106d80ad
JS
1006 memStatex.dwLength = sizeof (memStatex);
1007 ::GlobalMemoryStatusEx (&memStatex);
1008 return (wxMemorySize)memStatex.ullAvailPhys;
2b7295c9 1009#else /* if defined(__WIN32__) */
b568d04f
VZ
1010 MEMORYSTATUS memStatus;
1011 memStatus.dwLength = sizeof(MEMORYSTATUS);
2b7295c9 1012 ::GlobalMemoryStatus(&memStatus);
9d8aca48 1013 return (wxMemorySize)memStatus.dwAvailPhys;
b568d04f 1014#endif
2bda0e17
KB
1015}
1016
c1cb4153
VZ
1017unsigned long wxGetProcessId()
1018{
c1cb4153 1019 return ::GetCurrentProcessId();
c1cb4153
VZ
1020}
1021
2bda0e17 1022// Emit a beeeeeep
634903fd 1023void wxBell()
2bda0e17 1024{
b568d04f 1025 ::MessageBeep((UINT)-1); // default sound
2bda0e17
KB
1026}
1027
c50a4038
VZ
1028bool wxIsDebuggerRunning()
1029{
532d575b 1030#if wxUSE_DYNLIB_CLASS
c50a4038
VZ
1031 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1032 wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
1033
1034 typedef BOOL (WINAPI *IsDebuggerPresent_t)();
1035 if ( !dll.HasSymbol(_T("IsDebuggerPresent")) )
1036 {
1037 // no way to know, assume no
1038 return false;
1039 }
1040
1041 return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
532d575b
WS
1042#else
1043 return false;
1044#endif
c50a4038
VZ
1045}
1046
1047// ----------------------------------------------------------------------------
1048// OS version
1049// ----------------------------------------------------------------------------
1050
66930b35
VZ
1051// check if we're running under a server or workstation Windows system: it
1052// returns true or false with obvious meaning as well as -1 if the system type
1053// couldn't be determined
1054//
1055// this function is currently private but we may want to expose it later if
1056// it's really useful
1057namespace
1058{
1059
1060int wxIsWindowsServer()
1061{
1062#ifdef VER_NT_WORKSTATION
1063 OSVERSIONINFOEX info;
1064 wxZeroMemory(info);
1065
1066 info.dwOSVersionInfoSize = sizeof(info);
5c33522f 1067 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&info)) )
66930b35
VZ
1068 {
1069 switch ( info.wProductType )
1070 {
1071 case VER_NT_WORKSTATION:
1072 return false;
1073
1074 case VER_NT_SERVER:
1075 case VER_NT_DOMAIN_CONTROLLER:
1076 return true;
1077 }
1078 }
1079#endif // VER_NT_WORKSTATION
1080
1081 return -1;
1082}
1083
1084} // anonymous namespace
1085
bdc72a22 1086wxString wxGetOsDescription()
2bda0e17 1087{
bdc72a22
VZ
1088 wxString str;
1089
1090 OSVERSIONINFO info;
1091 wxZeroMemory(info);
1092
1093 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1094 if ( ::GetVersionEx(&info) )
1095 {
1096 switch ( info.dwPlatformId )
1097 {
84dc0006
WS
1098#ifdef VER_PLATFORM_WIN32_CE
1099 case VER_PLATFORM_WIN32_CE:
1100 str.Printf(_("Windows CE (%d.%d)"),
1101 info.dwMajorVersion,
1102 info.dwMinorVersion);
1103 break;
1104#endif
bdc72a22
VZ
1105 case VER_PLATFORM_WIN32s:
1106 str = _("Win32s on Windows 3.1");
1107 break;
1108
1109 case VER_PLATFORM_WIN32_WINDOWS:
db1d0193
VZ
1110 switch (info.dwMinorVersion)
1111 {
1112 case 0:
1113 if ( info.szCSDVersion[1] == 'B' ||
1114 info.szCSDVersion[1] == 'C' )
1115 {
1116 str = _("Windows 95 OSR2");
1117 }
1118 else
1119 {
1120 str = _("Windows 95");
1121 }
1122 break;
1123 case 10:
1124 if ( info.szCSDVersion[1] == 'B' ||
1125 info.szCSDVersion[1] == 'C' )
1126 {
1127 str = _("Windows 98 SE");
1128 }
1129 else
1130 {
1131 str = _("Windows 98");
1132 }
1133 break;
1134 case 90:
1135 str = _("Windows ME");
1136 break;
1137 default:
1138 str.Printf(_("Windows 9x (%d.%d)"),
1139 info.dwMajorVersion,
1140 info.dwMinorVersion);
1141 break;
1142 }
bdc72a22
VZ
1143 if ( !wxIsEmpty(info.szCSDVersion) )
1144 {
1145 str << _T(" (") << info.szCSDVersion << _T(')');
1146 }
1147 break;
1148
1149 case VER_PLATFORM_WIN32_NT:
a284cce8 1150 switch ( info.dwMajorVersion )
db1d0193 1151 {
a284cce8
VZ
1152 case 5:
1153 switch ( info.dwMinorVersion )
1154 {
1155 case 0:
1156 str.Printf(_("Windows 2000 (build %lu"),
1157 info.dwBuildNumber);
1158 break;
1159
66930b35
VZ
1160 case 2:
1161 // we can't distinguish between XP 64 and 2003
1162 // as they both are 5.2, so examine the product
1163 // type to resolve this ambiguity
575cabba 1164 if ( wxIsWindowsServer() == 1 )
66930b35
VZ
1165 {
1166 str.Printf(_("Windows Server 2003 (build %lu"),
1167 info.dwBuildNumber);
1168 break;
1169 }
1170 //else: must be XP, fall through
1171
a284cce8
VZ
1172 case 1:
1173 str.Printf(_("Windows XP (build %lu"),
1174 info.dwBuildNumber);
1175 break;
a284cce8
VZ
1176 }
1177 break;
1178
1179 case 6:
1180 if ( info.dwMinorVersion == 0 )
1181 {
1182 str.Printf(_("Windows Vista (build %lu"),
db1d0193 1183 info.dwBuildNumber);
a284cce8
VZ
1184 }
1185 break;
db1d0193 1186 }
a284cce8 1187
84dc0006 1188 if ( str.empty() )
db1d0193
VZ
1189 {
1190 str.Printf(_("Windows NT %lu.%lu (build %lu"),
bdc72a22
VZ
1191 info.dwMajorVersion,
1192 info.dwMinorVersion,
1193 info.dwBuildNumber);
db1d0193 1194 }
a284cce8 1195
bdc72a22
VZ
1196 if ( !wxIsEmpty(info.szCSDVersion) )
1197 {
1198 str << _T(", ") << info.szCSDVersion;
1199 }
1200 str << _T(')');
d4885e10
VZ
1201
1202 if ( wxIsPlatform64Bit() )
1203 str << _(", 64-bit edition");
bdc72a22
VZ
1204 break;
1205 }
1206 }
1207 else
1208 {
1209 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1210 }
1211
1212 return str;
bdc72a22 1213}
6f65e337 1214
8bb6b2c0 1215bool wxIsPlatform64Bit()
bdc72a22 1216{
8bb6b2c0
VZ
1217#if defined(_WIN64)
1218 return true; // 64-bit programs run only on Win64
a8ff046b 1219#elif wxUSE_DYNLIB_CLASS // Win32
6deb397d
VZ
1220 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1221 typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *);
1222
1223 wxDynamicLibrary dllKernel32(_T("kernel32.dll"));
b9d4a1b7
MW
1224 IsWow64Process_t pfnIsWow64Process =
1225 (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process"));
6deb397d
VZ
1226
1227 BOOL wow64 = FALSE;
1228 if ( pfnIsWow64Process )
1229 {
b9d4a1b7 1230 pfnIsWow64Process(::GetCurrentProcess(), &wow64);
6deb397d
VZ
1231 }
1232 //else: running under a system without Win64 support
1233
1234 return wow64 != FALSE;
a8ff046b
VZ
1235#else
1236 return false;
6deb397d 1237#endif // Win64/Win32
8bb6b2c0 1238}
ec5d7799 1239
8bb6b2c0
VZ
1240wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
1241{
5bc3ef05
VZ
1242 static struct
1243 {
1244 // this may be false, true or -1 if we tried to initialize but failed
1245 int initialized;
bdc72a22 1246
5bc3ef05
VZ
1247 wxOperatingSystemId os;
1248
1249 int verMaj,
1250 verMin;
1251 } s_version;
1252
1253 // query the OS info only once as it's not supposed to change
1254 if ( !s_version.initialized )
8bb6b2c0 1255 {
5bc3ef05
VZ
1256 OSVERSIONINFO info;
1257 wxZeroMemory(info);
1258 info.dwOSVersionInfoSize = sizeof(info);
1259 if ( ::GetVersionEx(&info) )
1260 {
1261 s_version.initialized = true;
1262
1263#if defined(__WXWINCE__)
1264 s_version.os = wxOS_WINDOWS_CE;
1265#elif defined(__WXMICROWIN__)
1266 s_version.os = wxOS_WINDOWS_MICRO;
1267#else // "normal" desktop Windows system, use run-time detection
1268 switch ( info.dwPlatformId )
1269 {
1270 case VER_PLATFORM_WIN32_NT:
1271 s_version.os = wxOS_WINDOWS_NT;
1272 break;
1273
1274 case VER_PLATFORM_WIN32_WINDOWS:
1275 s_version.os = wxOS_WINDOWS_9X;
1276 break;
1277 }
1278#endif // Windows versions
1279
1280 s_version.verMaj = info.dwMajorVersion;
1281 s_version.verMin = info.dwMinorVersion;
1282 }
1283 else // GetVersionEx() failed
1284 {
1285 s_version.initialized = -1;
1286 }
8bb6b2c0 1287 }
bdc72a22 1288
5bc3ef05 1289 if ( s_version.initialized == 1 )
8bb6b2c0 1290 {
5bc3ef05
VZ
1291 if ( verMaj )
1292 *verMaj = s_version.verMaj;
1293 if ( verMin )
1294 *verMin = s_version.verMin;
bdc72a22
VZ
1295 }
1296
5bc3ef05
VZ
1297 // this works even if we were not initialized successfully as the initial
1298 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1299 return s_version.os;
2bda0e17
KB
1300}
1301
4c5da5e4
VZ
1302wxWinVersion wxGetWinVersion()
1303{
1304 int verMaj,
1305 verMin;
1306 switch ( wxGetOsVersion(&verMaj, &verMin) )
1307 {
406d283a 1308 case wxOS_WINDOWS_9X:
4c5da5e4
VZ
1309 if ( verMaj == 4 )
1310 {
1311 switch ( verMin )
1312 {
1313 case 0:
1314 return wxWinVersion_95;
1315
1316 case 10:
1317 return wxWinVersion_98;
1318
1319 case 90:
1320 return wxWinVersion_ME;
1321 }
1322 }
1323 break;
1324
406d283a 1325 case wxOS_WINDOWS_NT:
4c5da5e4
VZ
1326 switch ( verMaj )
1327 {
1328 case 3:
1329 return wxWinVersion_NT3;
1330
1331 case 4:
1332 return wxWinVersion_NT4;
1333
1334 case 5:
1335 switch ( verMin )
1336 {
1337 case 0:
1338 return wxWinVersion_2000;
1339
1340 case 1:
1341 return wxWinVersion_XP;
1342
1343 case 2:
1344 return wxWinVersion_2003;
1345 }
1346 break;
1347
1348 case 6:
1349 return wxWinVersion_NT6;
1350 }
1351 break;
1352
449210a4
WS
1353 default:
1354 // Do nothing just to silence GCC warning
1355 break;
4c5da5e4
VZ
1356 }
1357
1358 return wxWinVersion_Unknown;
1359}
1360
b568d04f
VZ
1361// ----------------------------------------------------------------------------
1362// sleep functions
1363// ----------------------------------------------------------------------------
1364
08873d36 1365void wxMilliSleep(unsigned long milliseconds)
b568d04f
VZ
1366{
1367 ::Sleep(milliseconds);
1368}
1369
08873d36
VZ
1370void wxMicroSleep(unsigned long microseconds)
1371{
1372 wxMilliSleep(microseconds/1000);
1373}
1374
b568d04f
VZ
1375void wxSleep(int nSecs)
1376{
08873d36 1377 wxMilliSleep(1000*nSecs);
b568d04f
VZ
1378}
1379
b568d04f 1380// ----------------------------------------------------------------------------
e2478fde 1381// font encoding <-> Win32 codepage conversion functions
b568d04f
VZ
1382// ----------------------------------------------------------------------------
1383
bddd7a8d 1384extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
b568d04f 1385{
e2478fde 1386 switch ( encoding )
b568d04f 1387 {
e2478fde
VZ
1388 // although this function is supposed to return an exact match, do do
1389 // some mappings here for the most common case of "standard" encoding
1390 case wxFONTENCODING_SYSTEM:
1391 return DEFAULT_CHARSET;
2bda0e17 1392
e2478fde
VZ
1393 case wxFONTENCODING_ISO8859_1:
1394 case wxFONTENCODING_ISO8859_15:
1395 case wxFONTENCODING_CP1252:
1396 return ANSI_CHARSET;
2bda0e17 1397
e2478fde
VZ
1398#if !defined(__WXMICROWIN__)
1399 // The following four fonts are multi-byte charsets
1400 case wxFONTENCODING_CP932:
1401 return SHIFTJIS_CHARSET;
2bda0e17 1402
e2478fde
VZ
1403 case wxFONTENCODING_CP936:
1404 return GB2312_CHARSET;
2bda0e17 1405
90805c24 1406#ifndef __WXWINCE__
e2478fde
VZ
1407 case wxFONTENCODING_CP949:
1408 return HANGUL_CHARSET;
90805c24 1409#endif
634903fd 1410
e2478fde
VZ
1411 case wxFONTENCODING_CP950:
1412 return CHINESEBIG5_CHARSET;
2bda0e17 1413
e2478fde
VZ
1414 // The rest are single byte encodings
1415 case wxFONTENCODING_CP1250:
1416 return EASTEUROPE_CHARSET;
bfbd6dc1 1417
e2478fde
VZ
1418 case wxFONTENCODING_CP1251:
1419 return RUSSIAN_CHARSET;
2bda0e17 1420
e2478fde
VZ
1421 case wxFONTENCODING_CP1253:
1422 return GREEK_CHARSET;
b07135ba 1423
e2478fde
VZ
1424 case wxFONTENCODING_CP1254:
1425 return TURKISH_CHARSET;
2bda0e17 1426
e2478fde
VZ
1427 case wxFONTENCODING_CP1255:
1428 return HEBREW_CHARSET;
2bda0e17 1429
e2478fde
VZ
1430 case wxFONTENCODING_CP1256:
1431 return ARABIC_CHARSET;
b568d04f 1432
e2478fde
VZ
1433 case wxFONTENCODING_CP1257:
1434 return BALTIC_CHARSET;
634903fd 1435
e2478fde
VZ
1436 case wxFONTENCODING_CP874:
1437 return THAI_CHARSET;
5acc0d5f 1438#endif // !__WXMICROWIN__
cc2b7472 1439
e2478fde
VZ
1440 case wxFONTENCODING_CP437:
1441 return OEM_CHARSET;
ea28b885
VZ
1442
1443 default:
1444 // no way to translate this encoding into a Windows charset
69557827 1445 return -1;
e2478fde 1446 }
373658eb 1447}
7f555861 1448
e2478fde
VZ
1449// we have 2 versions of wxCharsetToCodepage(): the old one which directly
1450// looks up the vlaues in the registry and the new one which is more
1451// politically correct and has more chances to work on other Windows versions
1452// as well but the old version is still needed for !wxUSE_FONTMAP case
1453#if wxUSE_FONTMAP
c030b70f 1454
373658eb 1455#include "wx/fontmap.h"
c030b70f 1456
bddd7a8d 1457extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
c030b70f 1458{
b169661f
RR
1459 // There don't seem to be symbolic names for
1460 // these under Windows so I just copied the
1461 // values from MSDN.
04a18b0d 1462
fa78de82 1463 unsigned int ret;
04a18b0d 1464
b169661f 1465 switch (encoding)
373658eb 1466 {
fa78de82
RR
1467 case wxFONTENCODING_ISO8859_1: ret = 28591; break;
1468 case wxFONTENCODING_ISO8859_2: ret = 28592; break;
1469 case wxFONTENCODING_ISO8859_3: ret = 28593; break;
1470 case wxFONTENCODING_ISO8859_4: ret = 28594; break;
1471 case wxFONTENCODING_ISO8859_5: ret = 28595; break;
1472 case wxFONTENCODING_ISO8859_6: ret = 28596; break;
1473 case wxFONTENCODING_ISO8859_7: ret = 28597; break;
1474 case wxFONTENCODING_ISO8859_8: ret = 28598; break;
1475 case wxFONTENCODING_ISO8859_9: ret = 28599; break;
1476 case wxFONTENCODING_ISO8859_10: ret = 28600; break;
5df3dbf9 1477 case wxFONTENCODING_ISO8859_11: ret = 874; break;
b169661f 1478 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
04a18b0d 1479 case wxFONTENCODING_ISO8859_13: ret = 28603; break;
5fdf0363 1480 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
fa78de82 1481 case wxFONTENCODING_ISO8859_15: ret = 28605; break;
bd5c3968 1482
fa78de82
RR
1483 case wxFONTENCODING_KOI8: ret = 20866; break;
1484 case wxFONTENCODING_KOI8_U: ret = 21866; break;
bd5c3968 1485
fa78de82
RR
1486 case wxFONTENCODING_CP437: ret = 437; break;
1487 case wxFONTENCODING_CP850: ret = 850; break;
1488 case wxFONTENCODING_CP852: ret = 852; break;
1489 case wxFONTENCODING_CP855: ret = 855; break;
1490 case wxFONTENCODING_CP866: ret = 866; break;
1491 case wxFONTENCODING_CP874: ret = 874; break;
1492 case wxFONTENCODING_CP932: ret = 932; break;
1493 case wxFONTENCODING_CP936: ret = 936; break;
1494 case wxFONTENCODING_CP949: ret = 949; break;
1495 case wxFONTENCODING_CP950: ret = 950; break;
1496 case wxFONTENCODING_CP1250: ret = 1250; break;
1497 case wxFONTENCODING_CP1251: ret = 1251; break;
1498 case wxFONTENCODING_CP1252: ret = 1252; break;
1499 case wxFONTENCODING_CP1253: ret = 1253; break;
1500 case wxFONTENCODING_CP1254: ret = 1254; break;
1501 case wxFONTENCODING_CP1255: ret = 1255; break;
1502 case wxFONTENCODING_CP1256: ret = 1256; break;
1503 case wxFONTENCODING_CP1257: ret = 1257; break;
bd5c3968 1504
a50ca843 1505 case wxFONTENCODING_EUC_JP: ret = 20932; break;
bd5c3968 1506
fa78de82
RR
1507 case wxFONTENCODING_MACROMAN: ret = 10000; break;
1508 case wxFONTENCODING_MACJAPANESE: ret = 10001; break;
1509 case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
1510 case wxFONTENCODING_MACKOREAN: ret = 10003; break;
1511 case wxFONTENCODING_MACARABIC: ret = 10004; break;
1512 case wxFONTENCODING_MACHEBREW: ret = 10005; break;
1513 case wxFONTENCODING_MACGREEK: ret = 10006; break;
1514 case wxFONTENCODING_MACCYRILLIC: ret = 10007; break;
1515 case wxFONTENCODING_MACTHAI: ret = 10021; break;
1516 case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break;
1517 case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break;
1518 case wxFONTENCODING_MACCROATIAN: ret = 10082; break;
1519 case wxFONTENCODING_MACICELANDIC: ret = 10079; break;
1520 case wxFONTENCODING_MACROMANIAN: ret = 10009; break;
bd5c3968
VZ
1521
1522 case wxFONTENCODING_ISO2022_JP: ret = 50222; break;
1523
fa78de82
RR
1524 case wxFONTENCODING_UTF7: ret = 65000; break;
1525 case wxFONTENCODING_UTF8: ret = 65001; break;
bd5c3968 1526
fa78de82 1527 default: return -1;
373658eb 1528 }
04a18b0d 1529
fa78de82
RR
1530 if (::IsValidCodePage(ret) == 0)
1531 return -1;
04a18b0d 1532
fa78de82
RR
1533 CPINFO info;
1534 if (::GetCPInfo(ret, &info) == 0)
1535 return -1;
373658eb 1536
fa78de82 1537 return (long) ret;
c030b70f 1538}
373658eb 1539
86501081 1540extern long wxCharsetToCodepage(const char *name)
c030b70f 1541{
373658eb
VZ
1542 // first get the font encoding for this charset
1543 if ( !name )
1544 return -1;
1545
267e11c5 1546 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
373658eb
VZ
1547 if ( enc == wxFONTENCODING_SYSTEM )
1548 return -1;
1549
1550 // the use the helper function
1551 return wxEncodingToCodepage(enc);
c030b70f 1552}
c030b70f 1553
e2478fde 1554#else // !wxUSE_FONTMAP
373658eb
VZ
1555
1556#include "wx/msw/registry.h"
1557
1558// this should work if Internet Exploiter is installed
86501081 1559extern long wxCharsetToCodepage(const char *name)
04ef50df 1560{
373658eb
VZ
1561 if (!name)
1562 return GetACP();
1563
e2478fde 1564 long CP = -1;
373658eb 1565
f77c0fe3 1566#if wxUSE_REGKEY
e2478fde 1567 wxString path(wxT("MIME\\Database\\Charset\\"));
373658eb 1568 wxString cn(name);
373658eb 1569
e2478fde
VZ
1570 // follow the alias loop
1571 for ( ;; )
1572 {
1573 wxRegKey key(wxRegKey::HKCR, path + cn);
1574
1575 if (!key.Exists())
1576 break;
373658eb
VZ
1577
1578 // two cases: either there's an AliasForCharset string,
1579 // or there are Codepage and InternetEncoding dwords.
1580 // The InternetEncoding gives us the actual encoding,
1581 // the Codepage just says which Windows character set to
1582 // use when displaying the data.
1583 if (key.HasValue(wxT("InternetEncoding")) &&
e2478fde
VZ
1584 key.QueryValue(wxT("InternetEncoding"), &CP))
1585 break;
373658eb
VZ
1586
1587 // no encoding, see if it's an alias
1588 if (!key.HasValue(wxT("AliasForCharset")) ||
e2478fde
VZ
1589 !key.QueryValue(wxT("AliasForCharset"), cn))
1590 break;
1591 }
f77c0fe3 1592#endif // wxUSE_REGKEY
373658eb
VZ
1593
1594 return CP;
04ef50df 1595}
373658eb 1596
e2478fde 1597#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
c030b70f 1598
eccd1992
VZ
1599/*
1600 Creates a hidden window with supplied window proc registering the class for
1601 it if necesssary (i.e. the first time only). Caller is responsible for
1602 destroying the window and unregistering the class (note that this must be
77ffb593 1603 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
eccd1992
VZ
1604 multiple times into/from the same process so we cna't rely on automatic
1605 Windows class unregistration).
1606
1607 pclassname is a pointer to a caller stored classname, which must initially be
3103e8a9 1608 NULL. classname is the desired wndclass classname. If function successfully
eccd1992
VZ
1609 registers the class, pclassname will be set to classname.
1610 */
487f2d58 1611extern "C" WXDLLIMPEXP_BASE HWND
eccd1992
VZ
1612wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
1613{
1614 wxCHECK_MSG( classname && pclassname && wndproc, NULL,
1615 _T("NULL parameter in wxCreateHiddenWindow") );
1616
1617 // register the class fi we need to first
1618 if ( *pclassname == NULL )
1619 {
1620 WNDCLASS wndclass;
1621 wxZeroMemory(wndclass);
1622
1623 wndclass.lpfnWndProc = wndproc;
1624 wndclass.hInstance = wxGetInstance();
1625 wndclass.lpszClassName = classname;
1626
1627 if ( !::RegisterClass(&wndclass) )
1628 {
1629 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1630
1631 return NULL;
1632 }
1633
1634 *pclassname = classname;
1635 }
1636
1637 // next create the window
1638 HWND hwnd = ::CreateWindow
1639 (
1640 *pclassname,
1641 NULL,
1642 0, 0, 0, 0,
1643 0,
1644 (HWND) NULL,
1645 (HMENU)NULL,
1646 wxGetInstance(),
1647 (LPVOID) NULL
1648 );
1649
1650 if ( !hwnd )
1651 {
1652 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
1653 }
1654
1655 return hwnd;
1656}