]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utils.cpp
Correction in comment in closing #endif. Is VC++ 4 supported?
[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
732 // something or if an error occured and non zero if it
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 //
741 // NB: this is the harshest way, the app won't have
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;
1048 statex.dwLength = sizeof (statex);
2b7295c9 1049 ::GlobalMemoryStatusEx (&statex);
9d8aca48 1050 return (wxMemorySize)memStatus.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{
1072 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1073 wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
1074
1075 typedef BOOL (WINAPI *IsDebuggerPresent_t)();
1076 if ( !dll.HasSymbol(_T("IsDebuggerPresent")) )
1077 {
1078 // no way to know, assume no
1079 return false;
1080 }
1081
1082 return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1083}
1084
1085// ----------------------------------------------------------------------------
1086// OS version
1087// ----------------------------------------------------------------------------
1088
bdc72a22 1089wxString wxGetOsDescription()
2bda0e17 1090{
bdc72a22
VZ
1091 wxString str;
1092
1093 OSVERSIONINFO info;
1094 wxZeroMemory(info);
1095
1096 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1097 if ( ::GetVersionEx(&info) )
1098 {
1099 switch ( info.dwPlatformId )
1100 {
1101 case VER_PLATFORM_WIN32s:
1102 str = _("Win32s on Windows 3.1");
1103 break;
1104
1105 case VER_PLATFORM_WIN32_WINDOWS:
db1d0193
VZ
1106 switch (info.dwMinorVersion)
1107 {
1108 case 0:
1109 if ( info.szCSDVersion[1] == 'B' ||
1110 info.szCSDVersion[1] == 'C' )
1111 {
1112 str = _("Windows 95 OSR2");
1113 }
1114 else
1115 {
1116 str = _("Windows 95");
1117 }
1118 break;
1119 case 10:
1120 if ( info.szCSDVersion[1] == 'B' ||
1121 info.szCSDVersion[1] == 'C' )
1122 {
1123 str = _("Windows 98 SE");
1124 }
1125 else
1126 {
1127 str = _("Windows 98");
1128 }
1129 break;
1130 case 90:
1131 str = _("Windows ME");
1132 break;
1133 default:
1134 str.Printf(_("Windows 9x (%d.%d)"),
1135 info.dwMajorVersion,
1136 info.dwMinorVersion);
1137 break;
1138 }
bdc72a22
VZ
1139 if ( !wxIsEmpty(info.szCSDVersion) )
1140 {
1141 str << _T(" (") << info.szCSDVersion << _T(')');
1142 }
1143 break;
1144
1145 case VER_PLATFORM_WIN32_NT:
db1d0193
VZ
1146 if ( info.dwMajorVersion == 5 )
1147 {
1148 switch ( info.dwMinorVersion )
1149 {
1150 case 0:
1151 str.Printf(_("Windows 2000 (build %lu"),
1152 info.dwBuildNumber);
1153 break;
1154 case 1:
1155 str.Printf(_("Windows XP (build %lu"),
1156 info.dwBuildNumber);
1157 break;
1158 case 2:
1159 str.Printf(_("Windows Server 2003 (build %lu"),
1160 info.dwBuildNumber);
1161 break;
1162 }
1163 }
1164 if ( wxIsEmpty(str) )
1165 {
1166 str.Printf(_("Windows NT %lu.%lu (build %lu"),
bdc72a22
VZ
1167 info.dwMajorVersion,
1168 info.dwMinorVersion,
1169 info.dwBuildNumber);
db1d0193 1170 }
bdc72a22
VZ
1171 if ( !wxIsEmpty(info.szCSDVersion) )
1172 {
1173 str << _T(", ") << info.szCSDVersion;
1174 }
1175 str << _T(')');
1176 break;
1177 }
1178 }
1179 else
1180 {
1181 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1182 }
1183
1184 return str;
bdc72a22 1185}
6f65e337 1186
324899f6 1187wxToolkitInfo& wxAppTraits::GetToolkitInfo()
bdc72a22 1188{
2739d4f0
VZ
1189 // cache the version info, it's not going to change
1190 //
1191 // NB: this is MT-safe, we may use these static vars from different threads
1192 // but as they always have the same value it doesn't matter
1193 static int s_ver = -1,
1194 s_major = -1,
1195 s_minor = -1;
96c21216 1196
2739d4f0 1197 if ( s_ver == -1 )
bdc72a22 1198 {
6af638ed
VS
1199 OSVERSIONINFO info;
1200 wxZeroMemory(info);
ec5d7799 1201
2739d4f0 1202 s_ver = wxWINDOWS;
6af638ed
VS
1203 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1204 if ( ::GetVersionEx(&info) )
bdc72a22 1205 {
2739d4f0
VZ
1206 s_major = info.dwMajorVersion;
1207 s_minor = info.dwMinorVersion;
bdc72a22 1208
c75d190a
JS
1209#ifdef __SMARTPHONE__
1210 s_ver = wxWINDOWS_SMARTPHONE;
1211#elif defined(__POCKETPC__)
1212 s_ver = wxWINDOWS_POCKETPC;
1213#else
6af638ed
VS
1214 switch ( info.dwPlatformId )
1215 {
1216 case VER_PLATFORM_WIN32s:
2739d4f0 1217 s_ver = wxWIN32S;
6af638ed 1218 break;
bdc72a22 1219
6af638ed 1220 case VER_PLATFORM_WIN32_WINDOWS:
2739d4f0 1221 s_ver = wxWIN95;
6af638ed
VS
1222 break;
1223
1224 case VER_PLATFORM_WIN32_NT:
2739d4f0 1225 s_ver = wxWINDOWS_NT;
6af638ed 1226 break;
1f867767 1227#ifdef __WXWINCE__
f07dc2e2
JS
1228 case VER_PLATFORM_WIN32_CE:
1229 s_ver = wxWINDOWS_CE;
27b2dd53 1230#endif
6af638ed 1231 }
27b2dd53 1232#endif
bdc72a22
VZ
1233 }
1234 }
1235
eccd1992 1236 static wxToolkitInfo info;
a8eaaeb2
VS
1237 info.versionMajor = s_major;
1238 info.versionMinor = s_minor;
1239 info.os = s_ver;
1240 info.name = _T("wxBase");
324899f6 1241 return info;
2bda0e17
KB
1242}
1243
b568d04f
VZ
1244// ----------------------------------------------------------------------------
1245// sleep functions
1246// ----------------------------------------------------------------------------
1247
08873d36 1248void wxMilliSleep(unsigned long milliseconds)
b568d04f
VZ
1249{
1250 ::Sleep(milliseconds);
1251}
1252
08873d36
VZ
1253void wxMicroSleep(unsigned long microseconds)
1254{
1255 wxMilliSleep(microseconds/1000);
1256}
1257
b568d04f
VZ
1258void wxSleep(int nSecs)
1259{
08873d36 1260 wxMilliSleep(1000*nSecs);
b568d04f
VZ
1261}
1262
b568d04f 1263// ----------------------------------------------------------------------------
e2478fde 1264// font encoding <-> Win32 codepage conversion functions
b568d04f
VZ
1265// ----------------------------------------------------------------------------
1266
bddd7a8d 1267extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
b568d04f 1268{
e2478fde 1269 switch ( encoding )
b568d04f 1270 {
e2478fde
VZ
1271 // although this function is supposed to return an exact match, do do
1272 // some mappings here for the most common case of "standard" encoding
1273 case wxFONTENCODING_SYSTEM:
1274 return DEFAULT_CHARSET;
2bda0e17 1275
e2478fde
VZ
1276 case wxFONTENCODING_ISO8859_1:
1277 case wxFONTENCODING_ISO8859_15:
1278 case wxFONTENCODING_CP1252:
1279 return ANSI_CHARSET;
2bda0e17 1280
e2478fde
VZ
1281#if !defined(__WXMICROWIN__)
1282 // The following four fonts are multi-byte charsets
1283 case wxFONTENCODING_CP932:
1284 return SHIFTJIS_CHARSET;
2bda0e17 1285
e2478fde
VZ
1286 case wxFONTENCODING_CP936:
1287 return GB2312_CHARSET;
2bda0e17 1288
e2478fde
VZ
1289 case wxFONTENCODING_CP949:
1290 return HANGUL_CHARSET;
634903fd 1291
e2478fde
VZ
1292 case wxFONTENCODING_CP950:
1293 return CHINESEBIG5_CHARSET;
2bda0e17 1294
e2478fde
VZ
1295 // The rest are single byte encodings
1296 case wxFONTENCODING_CP1250:
1297 return EASTEUROPE_CHARSET;
bfbd6dc1 1298
e2478fde
VZ
1299 case wxFONTENCODING_CP1251:
1300 return RUSSIAN_CHARSET;
2bda0e17 1301
e2478fde
VZ
1302 case wxFONTENCODING_CP1253:
1303 return GREEK_CHARSET;
b07135ba 1304
e2478fde
VZ
1305 case wxFONTENCODING_CP1254:
1306 return TURKISH_CHARSET;
2bda0e17 1307
e2478fde
VZ
1308 case wxFONTENCODING_CP1255:
1309 return HEBREW_CHARSET;
2bda0e17 1310
e2478fde
VZ
1311 case wxFONTENCODING_CP1256:
1312 return ARABIC_CHARSET;
b568d04f 1313
e2478fde
VZ
1314 case wxFONTENCODING_CP1257:
1315 return BALTIC_CHARSET;
634903fd 1316
e2478fde
VZ
1317 case wxFONTENCODING_CP874:
1318 return THAI_CHARSET;
5acc0d5f 1319#endif // !__WXMICROWIN__
cc2b7472 1320
e2478fde
VZ
1321 case wxFONTENCODING_CP437:
1322 return OEM_CHARSET;
ea28b885
VZ
1323
1324 default:
1325 // no way to translate this encoding into a Windows charset
69557827 1326 return -1;
e2478fde 1327 }
373658eb 1328}
7f555861 1329
e2478fde
VZ
1330// we have 2 versions of wxCharsetToCodepage(): the old one which directly
1331// looks up the vlaues in the registry and the new one which is more
1332// politically correct and has more chances to work on other Windows versions
1333// as well but the old version is still needed for !wxUSE_FONTMAP case
1334#if wxUSE_FONTMAP
c030b70f 1335
373658eb 1336#include "wx/fontmap.h"
c030b70f 1337
bddd7a8d 1338extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
c030b70f 1339{
b169661f
RR
1340 // There don't seem to be symbolic names for
1341 // these under Windows so I just copied the
1342 // values from MSDN.
04a18b0d 1343
fa78de82 1344 unsigned int ret;
04a18b0d 1345
b169661f 1346 switch (encoding)
373658eb 1347 {
fa78de82
RR
1348 case wxFONTENCODING_ISO8859_1: ret = 28591; break;
1349 case wxFONTENCODING_ISO8859_2: ret = 28592; break;
1350 case wxFONTENCODING_ISO8859_3: ret = 28593; break;
1351 case wxFONTENCODING_ISO8859_4: ret = 28594; break;
1352 case wxFONTENCODING_ISO8859_5: ret = 28595; break;
1353 case wxFONTENCODING_ISO8859_6: ret = 28596; break;
1354 case wxFONTENCODING_ISO8859_7: ret = 28597; break;
1355 case wxFONTENCODING_ISO8859_8: ret = 28598; break;
1356 case wxFONTENCODING_ISO8859_9: ret = 28599; break;
1357 case wxFONTENCODING_ISO8859_10: ret = 28600; break;
1358 case wxFONTENCODING_ISO8859_11: ret = 28601; break;
b169661f 1359 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
04a18b0d 1360 case wxFONTENCODING_ISO8859_13: ret = 28603; break;
fa78de82
RR
1361 case wxFONTENCODING_ISO8859_14: ret = 28604; break;
1362 case wxFONTENCODING_ISO8859_15: ret = 28605; break;
1363 case wxFONTENCODING_KOI8: ret = 20866; break;
1364 case wxFONTENCODING_KOI8_U: ret = 21866; break;
1365 case wxFONTENCODING_CP437: ret = 437; break;
1366 case wxFONTENCODING_CP850: ret = 850; break;
1367 case wxFONTENCODING_CP852: ret = 852; break;
1368 case wxFONTENCODING_CP855: ret = 855; break;
1369 case wxFONTENCODING_CP866: ret = 866; break;
1370 case wxFONTENCODING_CP874: ret = 874; break;
1371 case wxFONTENCODING_CP932: ret = 932; break;
1372 case wxFONTENCODING_CP936: ret = 936; break;
1373 case wxFONTENCODING_CP949: ret = 949; break;
1374 case wxFONTENCODING_CP950: ret = 950; break;
1375 case wxFONTENCODING_CP1250: ret = 1250; break;
1376 case wxFONTENCODING_CP1251: ret = 1251; break;
1377 case wxFONTENCODING_CP1252: ret = 1252; break;
1378 case wxFONTENCODING_CP1253: ret = 1253; break;
1379 case wxFONTENCODING_CP1254: ret = 1254; break;
1380 case wxFONTENCODING_CP1255: ret = 1255; break;
1381 case wxFONTENCODING_CP1256: ret = 1256; break;
1382 case wxFONTENCODING_CP1257: ret = 1257; break;
1383 case wxFONTENCODING_EUC_JP: ret = 51932; break;
1384 case wxFONTENCODING_MACROMAN: ret = 10000; break;
1385 case wxFONTENCODING_MACJAPANESE: ret = 10001; break;
1386 case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
1387 case wxFONTENCODING_MACKOREAN: ret = 10003; break;
1388 case wxFONTENCODING_MACARABIC: ret = 10004; break;
1389 case wxFONTENCODING_MACHEBREW: ret = 10005; break;
1390 case wxFONTENCODING_MACGREEK: ret = 10006; break;
1391 case wxFONTENCODING_MACCYRILLIC: ret = 10007; break;
1392 case wxFONTENCODING_MACTHAI: ret = 10021; break;
1393 case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break;
1394 case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break;
1395 case wxFONTENCODING_MACCROATIAN: ret = 10082; break;
1396 case wxFONTENCODING_MACICELANDIC: ret = 10079; break;
1397 case wxFONTENCODING_MACROMANIAN: ret = 10009; break;
1398 case wxFONTENCODING_UTF7: ret = 65000; break;
1399 case wxFONTENCODING_UTF8: ret = 65001; break;
1400 default: return -1;
373658eb 1401 }
04a18b0d 1402
fa78de82
RR
1403 if (::IsValidCodePage(ret) == 0)
1404 return -1;
04a18b0d 1405
fa78de82
RR
1406 CPINFO info;
1407 if (::GetCPInfo(ret, &info) == 0)
1408 return -1;
373658eb 1409
fa78de82 1410 return (long) ret;
c030b70f 1411}
373658eb 1412
373658eb 1413extern long wxCharsetToCodepage(const wxChar *name)
c030b70f 1414{
373658eb
VZ
1415 // first get the font encoding for this charset
1416 if ( !name )
1417 return -1;
1418
267e11c5 1419 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
373658eb
VZ
1420 if ( enc == wxFONTENCODING_SYSTEM )
1421 return -1;
1422
1423 // the use the helper function
1424 return wxEncodingToCodepage(enc);
c030b70f 1425}
c030b70f 1426
e2478fde 1427#else // !wxUSE_FONTMAP
373658eb
VZ
1428
1429#include "wx/msw/registry.h"
1430
1431// this should work if Internet Exploiter is installed
1432extern long wxCharsetToCodepage(const wxChar *name)
04ef50df 1433{
373658eb
VZ
1434 if (!name)
1435 return GetACP();
1436
e2478fde 1437 long CP = -1;
373658eb 1438
e2478fde 1439 wxString path(wxT("MIME\\Database\\Charset\\"));
373658eb 1440 wxString cn(name);
373658eb 1441
e2478fde
VZ
1442 // follow the alias loop
1443 for ( ;; )
1444 {
1445 wxRegKey key(wxRegKey::HKCR, path + cn);
1446
1447 if (!key.Exists())
1448 break;
373658eb
VZ
1449
1450 // two cases: either there's an AliasForCharset string,
1451 // or there are Codepage and InternetEncoding dwords.
1452 // The InternetEncoding gives us the actual encoding,
1453 // the Codepage just says which Windows character set to
1454 // use when displaying the data.
1455 if (key.HasValue(wxT("InternetEncoding")) &&
e2478fde
VZ
1456 key.QueryValue(wxT("InternetEncoding"), &CP))
1457 break;
373658eb
VZ
1458
1459 // no encoding, see if it's an alias
1460 if (!key.HasValue(wxT("AliasForCharset")) ||
e2478fde
VZ
1461 !key.QueryValue(wxT("AliasForCharset"), cn))
1462 break;
1463 }
373658eb
VZ
1464
1465 return CP;
04ef50df 1466}
373658eb 1467
e2478fde 1468#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
c030b70f 1469
eccd1992
VZ
1470/*
1471 Creates a hidden window with supplied window proc registering the class for
1472 it if necesssary (i.e. the first time only). Caller is responsible for
1473 destroying the window and unregistering the class (note that this must be
77ffb593 1474 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
eccd1992
VZ
1475 multiple times into/from the same process so we cna't rely on automatic
1476 Windows class unregistration).
1477
1478 pclassname is a pointer to a caller stored classname, which must initially be
1479 NULL. classname is the desired wndclass classname. If function succesfully
1480 registers the class, pclassname will be set to classname.
1481 */
487f2d58 1482extern "C" WXDLLIMPEXP_BASE HWND
eccd1992
VZ
1483wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
1484{
1485 wxCHECK_MSG( classname && pclassname && wndproc, NULL,
1486 _T("NULL parameter in wxCreateHiddenWindow") );
1487
1488 // register the class fi we need to first
1489 if ( *pclassname == NULL )
1490 {
1491 WNDCLASS wndclass;
1492 wxZeroMemory(wndclass);
1493
1494 wndclass.lpfnWndProc = wndproc;
1495 wndclass.hInstance = wxGetInstance();
1496 wndclass.lpszClassName = classname;
1497
1498 if ( !::RegisterClass(&wndclass) )
1499 {
1500 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1501
1502 return NULL;
1503 }
1504
1505 *pclassname = classname;
1506 }
1507
1508 // next create the window
1509 HWND hwnd = ::CreateWindow
1510 (
1511 *pclassname,
1512 NULL,
1513 0, 0, 0, 0,
1514 0,
1515 (HWND) NULL,
1516 (HMENU)NULL,
1517 wxGetInstance(),
1518 (LPVOID) NULL
1519 );
1520
1521 if ( !hwnd )
1522 {
1523 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
1524 }
1525
1526 return hwnd;
1527}
1528