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