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