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