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