]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utils.cpp
export wxSettableHeaderColumn from DLL
[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, 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 wxSplitPath(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 ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
948 &tkp.Privileges[0].Luid);
949
950 tkp.PrivilegeCount = 1; // one privilege to set
951 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
952
953 // Get the shutdown privilege for this process.
954 ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
955 (PTOKEN_PRIVILEGES)NULL, 0);
956
957 // Cannot test the return value of AdjustTokenPrivileges.
958 bOK = ::GetLastError() == ERROR_SUCCESS;
959 }
960 }
961
962 if ( bOK )
963 {
964 UINT wFlags = 0;
965 if ( flags & wxSHUTDOWN_FORCE )
966 {
967 wFlags = EWX_FORCE;
968 flags &= ~wxSHUTDOWN_FORCE;
969 }
970
971 switch ( flags )
972 {
973 case wxSHUTDOWN_POWEROFF:
974 wFlags |= EWX_POWEROFF;
975 break;
976
977 case wxSHUTDOWN_REBOOT:
978 wFlags |= EWX_REBOOT;
979 break;
980
981 case wxSHUTDOWN_LOGOFF:
982 wFlags |= EWX_LOGOFF;
983 break;
984
985 default:
986 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
987 return false;
988 }
989
990 bOK = ::ExitWindowsEx(wFlags, 0) != 0;
991 }
992
993 return bOK;
994 #endif // WinCE/!WinCE
995 }
996
997 // ----------------------------------------------------------------------------
998 // misc
999 // ----------------------------------------------------------------------------
1000
1001 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1002 wxMemorySize wxGetFreeMemory()
1003 {
1004 #if defined(__WIN64__)
1005 MEMORYSTATUSEX memStatex;
1006 memStatex.dwLength = sizeof (memStatex);
1007 ::GlobalMemoryStatusEx (&memStatex);
1008 return (wxMemorySize)memStatex.ullAvailPhys;
1009 #else /* if defined(__WIN32__) */
1010 MEMORYSTATUS memStatus;
1011 memStatus.dwLength = sizeof(MEMORYSTATUS);
1012 ::GlobalMemoryStatus(&memStatus);
1013 return (wxMemorySize)memStatus.dwAvailPhys;
1014 #endif
1015 }
1016
1017 unsigned long wxGetProcessId()
1018 {
1019 return ::GetCurrentProcessId();
1020 }
1021
1022 // Emit a beeeeeep
1023 void wxBell()
1024 {
1025 ::MessageBeep((UINT)-1); // default sound
1026 }
1027
1028 bool wxIsDebuggerRunning()
1029 {
1030 #if wxUSE_DYNLIB_CLASS
1031 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1032 wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
1033
1034 typedef BOOL (WINAPI *IsDebuggerPresent_t)();
1035 if ( !dll.HasSymbol(_T("IsDebuggerPresent")) )
1036 {
1037 // no way to know, assume no
1038 return false;
1039 }
1040
1041 return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1042 #else
1043 return false;
1044 #endif
1045 }
1046
1047 // ----------------------------------------------------------------------------
1048 // OS version
1049 // ----------------------------------------------------------------------------
1050
1051 // check if we're running under a server or workstation Windows system: it
1052 // returns true or false with obvious meaning as well as -1 if the system type
1053 // couldn't be determined
1054 //
1055 // this function is currently private but we may want to expose it later if
1056 // it's really useful
1057 namespace
1058 {
1059
1060 int wxIsWindowsServer()
1061 {
1062 #ifdef VER_NT_WORKSTATION
1063 OSVERSIONINFOEX info;
1064 wxZeroMemory(info);
1065
1066 info.dwOSVersionInfoSize = sizeof(info);
1067 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&info)) )
1068 {
1069 switch ( info.wProductType )
1070 {
1071 case VER_NT_WORKSTATION:
1072 return false;
1073
1074 case VER_NT_SERVER:
1075 case VER_NT_DOMAIN_CONTROLLER:
1076 return true;
1077 }
1078 }
1079 #endif // VER_NT_WORKSTATION
1080
1081 return -1;
1082 }
1083
1084 } // anonymous namespace
1085
1086 wxString wxGetOsDescription()
1087 {
1088 wxString str;
1089
1090 OSVERSIONINFO info;
1091 wxZeroMemory(info);
1092
1093 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1094 if ( ::GetVersionEx(&info) )
1095 {
1096 switch ( info.dwPlatformId )
1097 {
1098 #ifdef VER_PLATFORM_WIN32_CE
1099 case VER_PLATFORM_WIN32_CE:
1100 str.Printf(_("Windows CE (%d.%d)"),
1101 info.dwMajorVersion,
1102 info.dwMinorVersion);
1103 break;
1104 #endif
1105 case VER_PLATFORM_WIN32s:
1106 str = _("Win32s on Windows 3.1");
1107 break;
1108
1109 case VER_PLATFORM_WIN32_WINDOWS:
1110 switch (info.dwMinorVersion)
1111 {
1112 case 0:
1113 if ( info.szCSDVersion[1] == 'B' ||
1114 info.szCSDVersion[1] == 'C' )
1115 {
1116 str = _("Windows 95 OSR2");
1117 }
1118 else
1119 {
1120 str = _("Windows 95");
1121 }
1122 break;
1123 case 10:
1124 if ( info.szCSDVersion[1] == 'B' ||
1125 info.szCSDVersion[1] == 'C' )
1126 {
1127 str = _("Windows 98 SE");
1128 }
1129 else
1130 {
1131 str = _("Windows 98");
1132 }
1133 break;
1134 case 90:
1135 str = _("Windows ME");
1136 break;
1137 default:
1138 str.Printf(_("Windows 9x (%d.%d)"),
1139 info.dwMajorVersion,
1140 info.dwMinorVersion);
1141 break;
1142 }
1143 if ( !wxIsEmpty(info.szCSDVersion) )
1144 {
1145 str << _T(" (") << info.szCSDVersion << _T(')');
1146 }
1147 break;
1148
1149 case VER_PLATFORM_WIN32_NT:
1150 switch ( info.dwMajorVersion )
1151 {
1152 case 5:
1153 switch ( info.dwMinorVersion )
1154 {
1155 case 0:
1156 str.Printf(_("Windows 2000 (build %lu"),
1157 info.dwBuildNumber);
1158 break;
1159
1160 case 2:
1161 // we can't distinguish between XP 64 and 2003
1162 // as they both are 5.2, so examine the product
1163 // type to resolve this ambiguity
1164 if ( wxIsWindowsServer() == 1 )
1165 {
1166 str.Printf(_("Windows Server 2003 (build %lu"),
1167 info.dwBuildNumber);
1168 break;
1169 }
1170 //else: must be XP, fall through
1171
1172 case 1:
1173 str.Printf(_("Windows XP (build %lu"),
1174 info.dwBuildNumber);
1175 break;
1176 }
1177 break;
1178
1179 case 6:
1180 if ( info.dwMinorVersion == 0 )
1181 {
1182 str.Printf(_("Windows Vista (build %lu"),
1183 info.dwBuildNumber);
1184 }
1185 break;
1186 }
1187
1188 if ( str.empty() )
1189 {
1190 str.Printf(_("Windows NT %lu.%lu (build %lu"),
1191 info.dwMajorVersion,
1192 info.dwMinorVersion,
1193 info.dwBuildNumber);
1194 }
1195
1196 if ( !wxIsEmpty(info.szCSDVersion) )
1197 {
1198 str << _T(", ") << info.szCSDVersion;
1199 }
1200 str << _T(')');
1201
1202 if ( wxIsPlatform64Bit() )
1203 str << _(", 64-bit edition");
1204 break;
1205 }
1206 }
1207 else
1208 {
1209 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1210 }
1211
1212 return str;
1213 }
1214
1215 bool wxIsPlatform64Bit()
1216 {
1217 #if defined(_WIN64)
1218 return true; // 64-bit programs run only on Win64
1219 #elif wxUSE_DYNLIB_CLASS // Win32
1220 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1221 typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *);
1222
1223 wxDynamicLibrary dllKernel32(_T("kernel32.dll"));
1224 IsWow64Process_t pfnIsWow64Process =
1225 (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process"));
1226
1227 BOOL wow64 = FALSE;
1228 if ( pfnIsWow64Process )
1229 {
1230 pfnIsWow64Process(::GetCurrentProcess(), &wow64);
1231 }
1232 //else: running under a system without Win64 support
1233
1234 return wow64 != FALSE;
1235 #else
1236 return false;
1237 #endif // Win64/Win32
1238 }
1239
1240 wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
1241 {
1242 static struct
1243 {
1244 // this may be false, true or -1 if we tried to initialize but failed
1245 int initialized;
1246
1247 wxOperatingSystemId os;
1248
1249 int verMaj,
1250 verMin;
1251 } s_version;
1252
1253 // query the OS info only once as it's not supposed to change
1254 if ( !s_version.initialized )
1255 {
1256 OSVERSIONINFO info;
1257 wxZeroMemory(info);
1258 info.dwOSVersionInfoSize = sizeof(info);
1259 if ( ::GetVersionEx(&info) )
1260 {
1261 s_version.initialized = true;
1262
1263 #if defined(__WXWINCE__)
1264 s_version.os = wxOS_WINDOWS_CE;
1265 #elif defined(__WXMICROWIN__)
1266 s_version.os = wxOS_WINDOWS_MICRO;
1267 #else // "normal" desktop Windows system, use run-time detection
1268 switch ( info.dwPlatformId )
1269 {
1270 case VER_PLATFORM_WIN32_NT:
1271 s_version.os = wxOS_WINDOWS_NT;
1272 break;
1273
1274 case VER_PLATFORM_WIN32_WINDOWS:
1275 s_version.os = wxOS_WINDOWS_9X;
1276 break;
1277 }
1278 #endif // Windows versions
1279
1280 s_version.verMaj = info.dwMajorVersion;
1281 s_version.verMin = info.dwMinorVersion;
1282 }
1283 else // GetVersionEx() failed
1284 {
1285 s_version.initialized = -1;
1286 }
1287 }
1288
1289 if ( s_version.initialized == 1 )
1290 {
1291 if ( verMaj )
1292 *verMaj = s_version.verMaj;
1293 if ( verMin )
1294 *verMin = s_version.verMin;
1295 }
1296
1297 // this works even if we were not initialized successfully as the initial
1298 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1299 return s_version.os;
1300 }
1301
1302 wxWinVersion wxGetWinVersion()
1303 {
1304 int verMaj,
1305 verMin;
1306 switch ( wxGetOsVersion(&verMaj, &verMin) )
1307 {
1308 case wxOS_WINDOWS_9X:
1309 if ( verMaj == 4 )
1310 {
1311 switch ( verMin )
1312 {
1313 case 0:
1314 return wxWinVersion_95;
1315
1316 case 10:
1317 return wxWinVersion_98;
1318
1319 case 90:
1320 return wxWinVersion_ME;
1321 }
1322 }
1323 break;
1324
1325 case wxOS_WINDOWS_NT:
1326 switch ( verMaj )
1327 {
1328 case 3:
1329 return wxWinVersion_NT3;
1330
1331 case 4:
1332 return wxWinVersion_NT4;
1333
1334 case 5:
1335 switch ( verMin )
1336 {
1337 case 0:
1338 return wxWinVersion_2000;
1339
1340 case 1:
1341 return wxWinVersion_XP;
1342
1343 case 2:
1344 return wxWinVersion_2003;
1345 }
1346 break;
1347
1348 case 6:
1349 return wxWinVersion_NT6;
1350 }
1351 break;
1352
1353 default:
1354 // Do nothing just to silence GCC warning
1355 break;
1356 }
1357
1358 return wxWinVersion_Unknown;
1359 }
1360
1361 // ----------------------------------------------------------------------------
1362 // sleep functions
1363 // ----------------------------------------------------------------------------
1364
1365 void wxMilliSleep(unsigned long milliseconds)
1366 {
1367 ::Sleep(milliseconds);
1368 }
1369
1370 void wxMicroSleep(unsigned long microseconds)
1371 {
1372 wxMilliSleep(microseconds/1000);
1373 }
1374
1375 void wxSleep(int nSecs)
1376 {
1377 wxMilliSleep(1000*nSecs);
1378 }
1379
1380 // ----------------------------------------------------------------------------
1381 // font encoding <-> Win32 codepage conversion functions
1382 // ----------------------------------------------------------------------------
1383
1384 extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
1385 {
1386 switch ( encoding )
1387 {
1388 // although this function is supposed to return an exact match, do do
1389 // some mappings here for the most common case of "standard" encoding
1390 case wxFONTENCODING_SYSTEM:
1391 return DEFAULT_CHARSET;
1392
1393 case wxFONTENCODING_ISO8859_1:
1394 case wxFONTENCODING_ISO8859_15:
1395 case wxFONTENCODING_CP1252:
1396 return ANSI_CHARSET;
1397
1398 #if !defined(__WXMICROWIN__)
1399 // The following four fonts are multi-byte charsets
1400 case wxFONTENCODING_CP932:
1401 return SHIFTJIS_CHARSET;
1402
1403 case wxFONTENCODING_CP936:
1404 return GB2312_CHARSET;
1405
1406 #ifndef __WXWINCE__
1407 case wxFONTENCODING_CP949:
1408 return HANGUL_CHARSET;
1409 #endif
1410
1411 case wxFONTENCODING_CP950:
1412 return CHINESEBIG5_CHARSET;
1413
1414 // The rest are single byte encodings
1415 case wxFONTENCODING_CP1250:
1416 return EASTEUROPE_CHARSET;
1417
1418 case wxFONTENCODING_CP1251:
1419 return RUSSIAN_CHARSET;
1420
1421 case wxFONTENCODING_CP1253:
1422 return GREEK_CHARSET;
1423
1424 case wxFONTENCODING_CP1254:
1425 return TURKISH_CHARSET;
1426
1427 case wxFONTENCODING_CP1255:
1428 return HEBREW_CHARSET;
1429
1430 case wxFONTENCODING_CP1256:
1431 return ARABIC_CHARSET;
1432
1433 case wxFONTENCODING_CP1257:
1434 return BALTIC_CHARSET;
1435
1436 case wxFONTENCODING_CP874:
1437 return THAI_CHARSET;
1438 #endif // !__WXMICROWIN__
1439
1440 case wxFONTENCODING_CP437:
1441 return OEM_CHARSET;
1442
1443 default:
1444 // no way to translate this encoding into a Windows charset
1445 return -1;
1446 }
1447 }
1448
1449 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1450 // looks up the vlaues in the registry and the new one which is more
1451 // politically correct and has more chances to work on other Windows versions
1452 // as well but the old version is still needed for !wxUSE_FONTMAP case
1453 #if wxUSE_FONTMAP
1454
1455 #include "wx/fontmap.h"
1456
1457 extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
1458 {
1459 // There don't seem to be symbolic names for
1460 // these under Windows so I just copied the
1461 // values from MSDN.
1462
1463 unsigned int ret;
1464
1465 switch (encoding)
1466 {
1467 case wxFONTENCODING_ISO8859_1: ret = 28591; break;
1468 case wxFONTENCODING_ISO8859_2: ret = 28592; break;
1469 case wxFONTENCODING_ISO8859_3: ret = 28593; break;
1470 case wxFONTENCODING_ISO8859_4: ret = 28594; break;
1471 case wxFONTENCODING_ISO8859_5: ret = 28595; break;
1472 case wxFONTENCODING_ISO8859_6: ret = 28596; break;
1473 case wxFONTENCODING_ISO8859_7: ret = 28597; break;
1474 case wxFONTENCODING_ISO8859_8: ret = 28598; break;
1475 case wxFONTENCODING_ISO8859_9: ret = 28599; break;
1476 case wxFONTENCODING_ISO8859_10: ret = 28600; break;
1477 case wxFONTENCODING_ISO8859_11: ret = 874; break;
1478 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1479 case wxFONTENCODING_ISO8859_13: ret = 28603; break;
1480 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1481 case wxFONTENCODING_ISO8859_15: ret = 28605; break;
1482
1483 case wxFONTENCODING_KOI8: ret = 20866; break;
1484 case wxFONTENCODING_KOI8_U: ret = 21866; break;
1485
1486 case wxFONTENCODING_CP437: ret = 437; break;
1487 case wxFONTENCODING_CP850: ret = 850; break;
1488 case wxFONTENCODING_CP852: ret = 852; break;
1489 case wxFONTENCODING_CP855: ret = 855; break;
1490 case wxFONTENCODING_CP866: ret = 866; break;
1491 case wxFONTENCODING_CP874: ret = 874; break;
1492 case wxFONTENCODING_CP932: ret = 932; break;
1493 case wxFONTENCODING_CP936: ret = 936; break;
1494 case wxFONTENCODING_CP949: ret = 949; break;
1495 case wxFONTENCODING_CP950: ret = 950; break;
1496 case wxFONTENCODING_CP1250: ret = 1250; break;
1497 case wxFONTENCODING_CP1251: ret = 1251; break;
1498 case wxFONTENCODING_CP1252: ret = 1252; break;
1499 case wxFONTENCODING_CP1253: ret = 1253; break;
1500 case wxFONTENCODING_CP1254: ret = 1254; break;
1501 case wxFONTENCODING_CP1255: ret = 1255; break;
1502 case wxFONTENCODING_CP1256: ret = 1256; break;
1503 case wxFONTENCODING_CP1257: ret = 1257; break;
1504
1505 case wxFONTENCODING_EUC_JP: ret = 20932; break;
1506
1507 case wxFONTENCODING_MACROMAN: ret = 10000; break;
1508 case wxFONTENCODING_MACJAPANESE: ret = 10001; break;
1509 case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
1510 case wxFONTENCODING_MACKOREAN: ret = 10003; break;
1511 case wxFONTENCODING_MACARABIC: ret = 10004; break;
1512 case wxFONTENCODING_MACHEBREW: ret = 10005; break;
1513 case wxFONTENCODING_MACGREEK: ret = 10006; break;
1514 case wxFONTENCODING_MACCYRILLIC: ret = 10007; break;
1515 case wxFONTENCODING_MACTHAI: ret = 10021; break;
1516 case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break;
1517 case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break;
1518 case wxFONTENCODING_MACCROATIAN: ret = 10082; break;
1519 case wxFONTENCODING_MACICELANDIC: ret = 10079; break;
1520 case wxFONTENCODING_MACROMANIAN: ret = 10009; break;
1521
1522 case wxFONTENCODING_ISO2022_JP: ret = 50222; break;
1523
1524 case wxFONTENCODING_UTF7: ret = 65000; break;
1525 case wxFONTENCODING_UTF8: ret = 65001; break;
1526
1527 default: return -1;
1528 }
1529
1530 if (::IsValidCodePage(ret) == 0)
1531 return -1;
1532
1533 CPINFO info;
1534 if (::GetCPInfo(ret, &info) == 0)
1535 return -1;
1536
1537 return (long) ret;
1538 }
1539
1540 extern long wxCharsetToCodepage(const char *name)
1541 {
1542 // first get the font encoding for this charset
1543 if ( !name )
1544 return -1;
1545
1546 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
1547 if ( enc == wxFONTENCODING_SYSTEM )
1548 return -1;
1549
1550 // the use the helper function
1551 return wxEncodingToCodepage(enc);
1552 }
1553
1554 #else // !wxUSE_FONTMAP
1555
1556 #include "wx/msw/registry.h"
1557
1558 // this should work if Internet Exploiter is installed
1559 extern long wxCharsetToCodepage(const char *name)
1560 {
1561 if (!name)
1562 return GetACP();
1563
1564 long CP = -1;
1565
1566 #if wxUSE_REGKEY
1567 wxString path(wxT("MIME\\Database\\Charset\\"));
1568 wxString cn(name);
1569
1570 // follow the alias loop
1571 for ( ;; )
1572 {
1573 wxRegKey key(wxRegKey::HKCR, path + cn);
1574
1575 if (!key.Exists())
1576 break;
1577
1578 // two cases: either there's an AliasForCharset string,
1579 // or there are Codepage and InternetEncoding dwords.
1580 // The InternetEncoding gives us the actual encoding,
1581 // the Codepage just says which Windows character set to
1582 // use when displaying the data.
1583 if (key.HasValue(wxT("InternetEncoding")) &&
1584 key.QueryValue(wxT("InternetEncoding"), &CP))
1585 break;
1586
1587 // no encoding, see if it's an alias
1588 if (!key.HasValue(wxT("AliasForCharset")) ||
1589 !key.QueryValue(wxT("AliasForCharset"), cn))
1590 break;
1591 }
1592 #endif // wxUSE_REGKEY
1593
1594 return CP;
1595 }
1596
1597 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1598
1599 /*
1600 Creates a hidden window with supplied window proc registering the class for
1601 it if necesssary (i.e. the first time only). Caller is responsible for
1602 destroying the window and unregistering the class (note that this must be
1603 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1604 multiple times into/from the same process so we cna't rely on automatic
1605 Windows class unregistration).
1606
1607 pclassname is a pointer to a caller stored classname, which must initially be
1608 NULL. classname is the desired wndclass classname. If function successfully
1609 registers the class, pclassname will be set to classname.
1610 */
1611 extern "C" WXDLLIMPEXP_BASE HWND
1612 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
1613 {
1614 wxCHECK_MSG( classname && pclassname && wndproc, NULL,
1615 _T("NULL parameter in wxCreateHiddenWindow") );
1616
1617 // register the class fi we need to first
1618 if ( *pclassname == NULL )
1619 {
1620 WNDCLASS wndclass;
1621 wxZeroMemory(wndclass);
1622
1623 wndclass.lpfnWndProc = wndproc;
1624 wndclass.hInstance = wxGetInstance();
1625 wndclass.lpszClassName = classname;
1626
1627 if ( !::RegisterClass(&wndclass) )
1628 {
1629 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1630
1631 return NULL;
1632 }
1633
1634 *pclassname = classname;
1635 }
1636
1637 // next create the window
1638 HWND hwnd = ::CreateWindow
1639 (
1640 *pclassname,
1641 NULL,
1642 0, 0, 0, 0,
1643 0,
1644 (HWND) NULL,
1645 (HMENU)NULL,
1646 wxGetInstance(),
1647 (LPVOID) NULL
1648 );
1649
1650 if ( !hwnd )
1651 {
1652 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
1653 }
1654
1655 return hwnd;
1656 }