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