1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright 2003, 2004, 2005 Martin Fuchs
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck  *
9*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*c2c66affSColin Finck  * Lesser General Public License for more details.
13*c2c66affSColin Finck  *
14*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck 
20*c2c66affSColin Finck  //
21*c2c66affSColin Finck  // Explorer clone
22*c2c66affSColin Finck  //
23*c2c66affSColin Finck  // utility.h
24*c2c66affSColin Finck  //
25*c2c66affSColin Finck  // Martin Fuchs, 23.07.2003
26*c2c66affSColin Finck  //
27*c2c66affSColin Finck 
28*c2c66affSColin Finck  // standard windows headers
29*c2c66affSColin Finck #define WIN32_LEAN_AND_MEAN
30*c2c66affSColin Finck #define WIN32_EXTRA_LEAN
31*c2c66affSColin Finck #define WIN32_NO_STATUS
32*c2c66affSColin Finck #define _INC_WINDOWS
33*c2c66affSColin Finck #define COM_NO_WINDOWS_H
34*c2c66affSColin Finck #include <stdarg.h>
35*c2c66affSColin Finck #include <windef.h>
36*c2c66affSColin Finck #include <winbase.h>
37*c2c66affSColin Finck #include <winuser.h>
38*c2c66affSColin Finck 
39*c2c66affSColin Finck //#include <undocuser.h>
40*c2c66affSColin Finck 
41*c2c66affSColin Finck  // Unicode support
42*c2c66affSColin Finck #if defined(UNICODE) && !defined(_UNICODE)
43*c2c66affSColin Finck #define	_UNICODE
44*c2c66affSColin Finck #endif
45*c2c66affSColin Finck #include <tchar.h>
46*c2c66affSColin Finck 
47*c2c66affSColin Finck #include <windowsx.h>	// for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ...
48*c2c66affSColin Finck #include <commctrl.h>
49*c2c66affSColin Finck 
50*c2c66affSColin Finck #include <objbase.h>
51*c2c66affSColin Finck //#include <oleauto.h>	// for VARIANT
52*c2c66affSColin Finck 
53*c2c66affSColin Finck //#include <malloc.h>		// for alloca()
54*c2c66affSColin Finck #include <assert.h>
55*c2c66affSColin Finck //#include <stdlib.h>		// for _MAX_DIR, ...
56*c2c66affSColin Finck #include <stdio.h>		// for sprintf()
57*c2c66affSColin Finck //#include <time.h>
58*c2c66affSColin Finck 
59*c2c66affSColin Finck #ifdef __cplusplus
60*c2c66affSColin Finck 
61*c2c66affSColin Finck #ifdef _MSC_VER
62*c2c66affSColin Finck #pragma warning(disable: 4786)	// disable warnings about too long debug information symbols
63*c2c66affSColin Finck #endif
64*c2c66affSColin Finck 
65*c2c66affSColin Finck  // STL headers for strings and streams
66*c2c66affSColin Finck #include <string>
67*c2c66affSColin Finck #include <iostream>
68*c2c66affSColin Finck using namespace std;
69*c2c66affSColin Finck 
70*c2c66affSColin Finck #endif /* __cplusplus */
71*c2c66affSColin Finck 
72*c2c66affSColin Finck #ifndef _MAX_PATH
73*c2c66affSColin Finck #define _MAX_DRIVE	3
74*c2c66affSColin Finck #define _MAX_FNAME	256
75*c2c66affSColin Finck #define _MAX_DIR	_MAX_FNAME
76*c2c66affSColin Finck #define _MAX_EXT	_MAX_FNAME
77*c2c66affSColin Finck #define _MAX_PATH	260
78*c2c66affSColin Finck #endif
79*c2c66affSColin Finck 
80*c2c66affSColin Finck #define	W_VER_NT 0	// constant for HIWORD(GetVersion())>>14
81*c2c66affSColin Finck 
82*c2c66affSColin Finck 
83*c2c66affSColin Finck #ifdef __cplusplus
84*c2c66affSColin Finck extern "C" {
85*c2c66affSColin Finck #endif
86*c2c66affSColin Finck 
87*c2c66affSColin Finck 
88*c2c66affSColin Finck #define	for if (0) {} else for
89*c2c66affSColin Finck 
90*c2c66affSColin Finck #ifdef _countof
91*c2c66affSColin Finck #define COUNTOF _countof
92*c2c66affSColin Finck #else
93*c2c66affSColin Finck #define	COUNTOF(x)	(sizeof(x)/sizeof(x[0]))
94*c2c66affSColin Finck #endif
95*c2c66affSColin Finck 
96*c2c66affSColin Finck 
97*c2c66affSColin Finck #define	BUFFER_LEN				2048
98*c2c66affSColin Finck 
99*c2c66affSColin Finck 
100*c2c66affSColin Finck extern void _log_(LPCTSTR txt);
101*c2c66affSColin Finck 
102*c2c66affSColin Finck #define	LOG(txt) _log_(txt)
103*c2c66affSColin Finck 
104*c2c66affSColin Finck 
105*c2c66affSColin Finck #ifdef _MSC_VER
106*c2c66affSColin Finck #define	LONGLONGARG TEXT("I64")
107*c2c66affSColin Finck #else
108*c2c66affSColin Finck #define	LONGLONGARG TEXT("L")
109*c2c66affSColin Finck #endif
110*c2c66affSColin Finck 
111*c2c66affSColin Finck 
112*c2c66affSColin Finck #ifndef _tcsrchr
113*c2c66affSColin Finck #ifdef UNICODE
114*c2c66affSColin Finck #define	_tcsrchr wcsrchr
115*c2c66affSColin Finck #else
116*c2c66affSColin Finck #define	_tcsrchr strrchr
117*c2c66affSColin Finck #endif
118*c2c66affSColin Finck #endif
119*c2c66affSColin Finck 
120*c2c66affSColin Finck #ifndef _stprintf
121*c2c66affSColin Finck #ifdef UNICODE
122*c2c66affSColin Finck #define	_stprintf wcsprintf
123*c2c66affSColin Finck #else
124*c2c66affSColin Finck #define	_stprintf sprintf
125*c2c66affSColin Finck #endif
126*c2c66affSColin Finck #endif
127*c2c66affSColin Finck 
128*c2c66affSColin Finck #define	U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL)
129*c2c66affSColin Finck #define	U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL)
130*c2c66affSColin Finck #define	A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l)
131*c2c66affSColin Finck #define	A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l)
132*c2c66affSColin Finck 
133*c2c66affSColin Finck 
134*c2c66affSColin Finck #ifdef __WINE__
135*c2c66affSColin Finck #ifdef UNICODE
136*c2c66affSColin Finck extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
137*c2c66affSColin Finck #else
138*c2c66affSColin Finck extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
139*c2c66affSColin Finck #endif
140*c2c66affSColin Finck #define	_tcsnicmp strncasecmp
141*c2c66affSColin Finck #define	_tcsicoll strcasecmp
142*c2c66affSColin Finck #endif
143*c2c66affSColin Finck 
144*c2c66affSColin Finck #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
145*c2c66affSColin Finck #define FILE_ATTRIBUTE_ENCRYPTED            0x00000040
146*c2c66affSColin Finck #define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200
147*c2c66affSColin Finck #define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400
148*c2c66affSColin Finck #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000
149*c2c66affSColin Finck #endif
150*c2c66affSColin Finck 
151*c2c66affSColin Finck 
152*c2c66affSColin Finck #define	SetDlgCtrlID(hwnd, id) SetWindowLongPtr(hwnd, GWL_ID, id)
153*c2c66affSColin Finck #define	SetWindowStyle(hwnd, val) (DWORD)SetWindowLongPtr(hwnd, GWL_STYLE, val)
154*c2c66affSColin Finck #define	SetWindowExStyle(h, val) (DWORD)SetWindowLongPtr(hwnd, GWL_EXSTYLE, val)
155*c2c66affSColin Finck #define	Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
156*c2c66affSColin Finck 
157*c2c66affSColin Finck 
158*c2c66affSColin Finck  // center window in respect to its parent window
159*c2c66affSColin Finck extern void CenterWindow(HWND hwnd);
160*c2c66affSColin Finck 
161*c2c66affSColin Finck  // move window into visibility
162*c2c66affSColin Finck extern void MoveVisible(HWND hwnd);
163*c2c66affSColin Finck 
164*c2c66affSColin Finck  // display error message
165*c2c66affSColin Finck extern void display_error(HWND hwnd, DWORD error);
166*c2c66affSColin Finck 
167*c2c66affSColin Finck  // convert time_t to WIN32 FILETIME
168*c2c66affSColin Finck extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
169*c2c66affSColin Finck 
170*c2c66affSColin Finck  // search for windows of a specific classname
171*c2c66affSColin Finck extern int find_window_class(LPCTSTR classname);
172*c2c66affSColin Finck 
173*c2c66affSColin Finck  // create a directory with all missing parent directories
174*c2c66affSColin Finck BOOL RecursiveCreateDirectory(LPCTSTR path_in);
175*c2c66affSColin Finck 
176*c2c66affSColin Finck  // read DWORD value from registry
177*c2c66affSColin Finck DWORD RegGetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD def);
178*c2c66affSColin Finck 
179*c2c66affSColin Finck  // write DWORD value to registry
180*c2c66affSColin Finck BOOL RegSetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD value);
181*c2c66affSColin Finck 
182*c2c66affSColin Finck  // test for existing directory
183*c2c66affSColin Finck BOOL exists_path(LPCTSTR path);
184*c2c66affSColin Finck 
185*c2c66affSColin Finck 
186*c2c66affSColin Finck #ifdef __cplusplus
187*c2c66affSColin Finck } // extern "C"
188*c2c66affSColin Finck #endif
189*c2c66affSColin Finck 
190*c2c66affSColin Finck 
191*c2c66affSColin Finck  // secure CRT functions
192*c2c66affSColin Finck //@@ _MS_VER: temporarily needed for the ReactOS build environment
193*c2c66affSColin Finck #if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER)	// for VS 2005: _MSC_VER>=1400
194*c2c66affSColin Finck 
195*c2c66affSColin Finck #define _stprintf_s1 _stprintf_s
196*c2c66affSColin Finck #define _stprintf_s2 _stprintf_s
197*c2c66affSColin Finck 
198*c2c66affSColin Finck #else	// __STDC_WANT_SECURE_LIB__
199*c2c66affSColin Finck 
200*c2c66affSColin Finck #define strcpy_s(d, l, s) strcpy(d, s)
201*c2c66affSColin Finck #define wcscpy_s(d, l, s) wcscpy(d, s)
202*c2c66affSColin Finck #define wcsncpy_s(d, l, s, n) wcsncpy(d, s, n)
203*c2c66affSColin Finck 
204*c2c66affSColin Finck #if defined(_tcscpy) && !defined(_tcscpy_s)
205*c2c66affSColin Finck #define _tcscpy_s(d, l, s) _tcscpy(d, s)
206*c2c66affSColin Finck #endif
207*c2c66affSColin Finck 
208*c2c66affSColin Finck #if defined(_tsplitpath) && !defined(_tsplitpath_s)
209*c2c66affSColin Finck #define _tsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _tsplitpath(f, d, p, n, e)
210*c2c66affSColin Finck #else
211*c2c66affSColin Finck #define _wsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _wsplitpath(f, d, p, n, e)
212*c2c66affSColin Finck #define _splitpath_s(f, d,dl, p,pl, n,nl, e,el) _splitpath(f, d, p, n, e)
213*c2c66affSColin Finck #endif
214*c2c66affSColin Finck 
215*c2c66affSColin Finck #define _stprintf_s1(b, l, f, p1) _stprintf(b, f, p1)
216*c2c66affSColin Finck #define _stprintf_s2(b, l, f, p1,p2) _stprintf(b, f, p1,p2)
217*c2c66affSColin Finck 
218*c2c66affSColin Finck #endif	// __STDC_WANT_SECURE_LIB__
219*c2c66affSColin Finck 
220*c2c66affSColin Finck 
221*c2c66affSColin Finck #ifdef __cplusplus
222*c2c66affSColin Finck 
223*c2c66affSColin Finck  // containers
224*c2c66affSColin Finck #include <map>
225*c2c66affSColin Finck #include <set>
226*c2c66affSColin Finck #include <list>
227*c2c66affSColin Finck #include <stack>
228*c2c66affSColin Finck #include <vector>
229*c2c66affSColin Finck 
230*c2c66affSColin Finck 
231*c2c66affSColin Finck /* not necessary with correct include file order for comdef.h ("<MS PSDK>\include" path first) */
232*c2c66affSColin Finck #if _MSC_VER>=1300	// VS.Net
233*c2c66affSColin Finck #define _NO_COMUTIL
234*c2c66affSColin Finck #endif
235*c2c66affSColin Finck 
236*c2c66affSColin Finck 
237*c2c66affSColin Finck #if defined(_MSC_VER) && !defined(_NO_COMUTIL)
238*c2c66affSColin Finck 
239*c2c66affSColin Finck  // COM utility headers
240*c2c66affSColin Finck #include <comdef.h>
241*c2c66affSColin Finck using namespace _com_util;
242*c2c66affSColin Finck 
243*c2c66affSColin Finck #endif	// _MSC_VER && !_NO_COMUTIL
244*c2c66affSColin Finck 
245*c2c66affSColin Finck 
246*c2c66affSColin Finck  // launch a program or document file
247*c2c66affSColin Finck extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCTSTR parameters=NULL);
248*c2c66affSColin Finck #ifdef UNICODE
249*c2c66affSColin Finck extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCSTR parameters=NULL);
250*c2c66affSColin Finck #else
251*c2c66affSColin Finck #define	launch_fileA launch_file
252*c2c66affSColin Finck #endif
253*c2c66affSColin Finck 
254*c2c66affSColin Finck  // call an DLL export like rundll32
255*c2c66affSColin Finck extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
256*c2c66affSColin Finck 
257*c2c66affSColin Finck  // launch control panel applet
258*c2c66affSColin Finck extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet);
259*c2c66affSColin Finck 
260*c2c66affSColin Finck 
261*c2c66affSColin Finck  /// initialization of windows common controls
262*c2c66affSColin Finck struct CommonControlInit
263*c2c66affSColin Finck {
264*c2c66affSColin Finck 	CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
265*c2c66affSColin Finck 	{
266*c2c66affSColin Finck 		INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
267*c2c66affSColin Finck 
268*c2c66affSColin Finck 		InitCommonControlsEx(&icc);
269*c2c66affSColin Finck 	}
270*c2c66affSColin Finck };
271*c2c66affSColin Finck 
272*c2c66affSColin Finck 
273*c2c66affSColin Finck  /// wait cursor
274*c2c66affSColin Finck 
275*c2c66affSColin Finck struct WaitCursor	///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
276*c2c66affSColin Finck {
WaitCursorWaitCursor277*c2c66affSColin Finck 	WaitCursor()
278*c2c66affSColin Finck 	{
279*c2c66affSColin Finck 		_old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
280*c2c66affSColin Finck 	}
281*c2c66affSColin Finck 
~WaitCursorWaitCursor282*c2c66affSColin Finck 	~WaitCursor()
283*c2c66affSColin Finck 	{
284*c2c66affSColin Finck 		SetCursor(_old_cursor);
285*c2c66affSColin Finck 	}
286*c2c66affSColin Finck 
287*c2c66affSColin Finck protected:
288*c2c66affSColin Finck 	HCURSOR	_old_cursor;
289*c2c66affSColin Finck };
290*c2c66affSColin Finck 
291*c2c66affSColin Finck 
292*c2c66affSColin Finck  /// base of all structures storing a window handle
293*c2c66affSColin Finck struct WindowHandle
294*c2c66affSColin Finck {
295*c2c66affSColin Finck 	WindowHandle(HWND hwnd=0)
_hwndWindowHandle296*c2c66affSColin Finck 	 :	_hwnd(hwnd) {}
297*c2c66affSColin Finck 
HWNDWindowHandle298*c2c66affSColin Finck 	operator HWND() const {return _hwnd;}
299*c2c66affSColin Finck 	HWND* operator&() {return &_hwnd;}
300*c2c66affSColin Finck 
301*c2c66affSColin Finck protected:
302*c2c66affSColin Finck 	HWND	_hwnd;
303*c2c66affSColin Finck };
304*c2c66affSColin Finck 
305*c2c66affSColin Finck 
306*c2c66affSColin Finck  /// locally hide a window
307*c2c66affSColin Finck struct HiddenWindow : public WindowHandle
308*c2c66affSColin Finck {
HiddenWindowHiddenWindow309*c2c66affSColin Finck 	HiddenWindow(HWND hwnd)
310*c2c66affSColin Finck 	 :	WindowHandle(IsWindowVisible(hwnd)? hwnd: 0)
311*c2c66affSColin Finck 	{
312*c2c66affSColin Finck 		if (_hwnd)
313*c2c66affSColin Finck 			SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
314*c2c66affSColin Finck 	}
315*c2c66affSColin Finck 
~HiddenWindowHiddenWindow316*c2c66affSColin Finck 	~HiddenWindow()
317*c2c66affSColin Finck 	{
318*c2c66affSColin Finck 		if (_hwnd)
319*c2c66affSColin Finck 			SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
320*c2c66affSColin Finck 	}
321*c2c66affSColin Finck };
322*c2c66affSColin Finck 
323*c2c66affSColin Finck 
324*c2c66affSColin Finck  /// critical section wrapper
325*c2c66affSColin Finck 
326*c2c66affSColin Finck struct CritSect : public CRITICAL_SECTION
327*c2c66affSColin Finck {
CritSectCritSect328*c2c66affSColin Finck 	CritSect()
329*c2c66affSColin Finck 	{
330*c2c66affSColin Finck 		InitializeCriticalSection(this);
331*c2c66affSColin Finck 	}
332*c2c66affSColin Finck 
~CritSectCritSect333*c2c66affSColin Finck 	~CritSect()
334*c2c66affSColin Finck 	{
335*c2c66affSColin Finck 		DeleteCriticalSection(this);
336*c2c66affSColin Finck 	}
337*c2c66affSColin Finck };
338*c2c66affSColin Finck 
339*c2c66affSColin Finck 
340*c2c66affSColin Finck  /// Lock protects a code section utilizing a critical section
341*c2c66affSColin Finck 
342*c2c66affSColin Finck struct Lock
343*c2c66affSColin Finck {
LockLock344*c2c66affSColin Finck 	Lock(CritSect& crit_sect)
345*c2c66affSColin Finck 	 :	_crit_sect(crit_sect)
346*c2c66affSColin Finck 	{
347*c2c66affSColin Finck 		EnterCriticalSection(&crit_sect);
348*c2c66affSColin Finck 	}
349*c2c66affSColin Finck 
~LockLock350*c2c66affSColin Finck 	~Lock()
351*c2c66affSColin Finck 	{
352*c2c66affSColin Finck 		LeaveCriticalSection(&_crit_sect);
353*c2c66affSColin Finck 	}
354*c2c66affSColin Finck 
355*c2c66affSColin Finck protected:
356*c2c66affSColin Finck 	CritSect&	_crit_sect;
357*c2c66affSColin Finck };
358*c2c66affSColin Finck 
359*c2c66affSColin Finck 
360*c2c66affSColin Finck  /// Thread base class
361*c2c66affSColin Finck 
362*c2c66affSColin Finck struct Thread
363*c2c66affSColin Finck {
ThreadThread364*c2c66affSColin Finck 	Thread()
365*c2c66affSColin Finck 	 :	_alive(false),
366*c2c66affSColin Finck 		_destroy(false)
367*c2c66affSColin Finck 	{
368*c2c66affSColin Finck 		_hThread = INVALID_HANDLE_VALUE;
369*c2c66affSColin Finck 		_evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
370*c2c66affSColin Finck 	}
371*c2c66affSColin Finck 
~ThreadThread372*c2c66affSColin Finck 	virtual ~Thread()
373*c2c66affSColin Finck 	{
374*c2c66affSColin Finck 		Stop();
375*c2c66affSColin Finck 
376*c2c66affSColin Finck 		CloseHandle(_evtFinish);
377*c2c66affSColin Finck 		CloseHandle(_hThread);
378*c2c66affSColin Finck 
379*c2c66affSColin Finck 		if (_destroy)
380*c2c66affSColin Finck 			delete this;
381*c2c66affSColin Finck 	}
382*c2c66affSColin Finck 
StartThread383*c2c66affSColin Finck 	void Start()
384*c2c66affSColin Finck 	{
385*c2c66affSColin Finck 		if (!_alive) {
386*c2c66affSColin Finck 			_alive = true;
387*c2c66affSColin Finck 			_hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
388*c2c66affSColin Finck 		}
389*c2c66affSColin Finck 	}
390*c2c66affSColin Finck 
StopThread391*c2c66affSColin Finck 	void Stop()
392*c2c66affSColin Finck 	{
393*c2c66affSColin Finck 		SetEvent(_evtFinish);
394*c2c66affSColin Finck 
395*c2c66affSColin Finck 		if (_alive) {
396*c2c66affSColin Finck 			{
397*c2c66affSColin Finck 			Lock lock(_crit_sect);
398*c2c66affSColin Finck 			_alive = false;
399*c2c66affSColin Finck 			}
400*c2c66affSColin Finck 
401*c2c66affSColin Finck 			 // wait for finishing
402*c2c66affSColin Finck 			WaitForSingleObject(_hThread, INFINITE);
403*c2c66affSColin Finck 		}
404*c2c66affSColin Finck 	}
405*c2c66affSColin Finck 
406*c2c66affSColin Finck 	virtual int Run() = 0;
407*c2c66affSColin Finck 
is_aliveThread408*c2c66affSColin Finck 	bool	is_alive() const {return _alive;}
409*c2c66affSColin Finck 
410*c2c66affSColin Finck 	CritSect _crit_sect;
411*c2c66affSColin Finck 
412*c2c66affSColin Finck protected:
413*c2c66affSColin Finck 	static DWORD WINAPI ThreadProc(void* para);
414*c2c66affSColin Finck 
415*c2c66affSColin Finck 	HANDLE	_hThread;
416*c2c66affSColin Finck 	HANDLE	_evtFinish;
417*c2c66affSColin Finck 	bool	_alive;
418*c2c66affSColin Finck 	bool	_destroy;
419*c2c66affSColin Finck };
420*c2c66affSColin Finck 
421*c2c66affSColin Finck 
422*c2c66affSColin Finck  // window utilities
423*c2c66affSColin Finck 
424*c2c66affSColin Finck  /// ClientRect retreives the client area rectangle of a window.
425*c2c66affSColin Finck struct ClientRect : public RECT
426*c2c66affSColin Finck {
ClientRectClientRect427*c2c66affSColin Finck 	ClientRect(HWND hwnd)
428*c2c66affSColin Finck 	{
429*c2c66affSColin Finck 		GetClientRect(hwnd, this);
430*c2c66affSColin Finck 	}
431*c2c66affSColin Finck 
LPRECTClientRect432*c2c66affSColin Finck 	operator LPRECT() {return this;}
433*c2c66affSColin Finck 
posClientRect434*c2c66affSColin Finck 	POINT& pos() {return *(LPPOINT)this;}
435*c2c66affSColin Finck };
436*c2c66affSColin Finck 
437*c2c66affSColin Finck  /// ClientRect retreives the window rectangle of a window.
438*c2c66affSColin Finck struct WindowRect : public RECT
439*c2c66affSColin Finck {
WindowRectWindowRect440*c2c66affSColin Finck 	WindowRect(HWND hwnd)
441*c2c66affSColin Finck 	{
442*c2c66affSColin Finck 		GetWindowRect(hwnd, this);
443*c2c66affSColin Finck 	}
444*c2c66affSColin Finck 
LPRECTWindowRect445*c2c66affSColin Finck 	operator LPRECT() {return this;}
446*c2c66affSColin Finck 
posWindowRect447*c2c66affSColin Finck 	POINT& pos() {return *(LPPOINT)this;}
448*c2c66affSColin Finck };
449*c2c66affSColin Finck 
450*c2c66affSColin Finck  /// PointL encapsulates the POINT structure into a C++ object.
451*c2c66affSColin Finck struct Point : public POINT
452*c2c66affSColin Finck {
PointPoint453*c2c66affSColin Finck 	Point(LONG x_, LONG y_)
454*c2c66affSColin Finck 	{
455*c2c66affSColin Finck 		x = x_;
456*c2c66affSColin Finck 		y = y_;
457*c2c66affSColin Finck 	}
458*c2c66affSColin Finck 
459*c2c66affSColin Finck 	 // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
PointPoint460*c2c66affSColin Finck 	Point(LPARAM lparam)
461*c2c66affSColin Finck 	{
462*c2c66affSColin Finck 		x = GET_X_LPARAM(lparam);
463*c2c66affSColin Finck 		y = GET_Y_LPARAM(lparam);
464*c2c66affSColin Finck 	}
465*c2c66affSColin Finck 
LPPOINTPoint466*c2c66affSColin Finck 	operator LPPOINT() {return this;}
467*c2c66affSColin Finck };
468*c2c66affSColin Finck 
469*c2c66affSColin Finck 
470*c2c66affSColin Finck  /// transform coordinates in a RECT from client to screen coordiantes
ClientToScreen(HWND hwnd,RECT * prect)471*c2c66affSColin Finck inline void ClientToScreen(HWND hwnd, RECT* prect)
472*c2c66affSColin Finck  {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
473*c2c66affSColin Finck 
474*c2c66affSColin Finck  /// transform coordinates in a RECT from screen to client coordiantes
ScreenToClient(HWND hwnd,RECT * prect)475*c2c66affSColin Finck inline void ScreenToClient(HWND hwnd, RECT* prect)
476*c2c66affSColin Finck  {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
477*c2c66affSColin Finck 
478*c2c66affSColin Finck 
479*c2c66affSColin Finck  /// structure containing information about full screen display of the frame window
480*c2c66affSColin Finck struct FullScreenParameters
481*c2c66affSColin Finck {
FullScreenParametersFullScreenParameters482*c2c66affSColin Finck 	FullScreenParameters()
483*c2c66affSColin Finck 	 :	_mode(FALSE)
484*c2c66affSColin Finck 	{
485*c2c66affSColin Finck 	}
486*c2c66affSColin Finck 
487*c2c66affSColin Finck 	BOOL	_mode;
488*c2c66affSColin Finck 	RECT	_orgPos;
489*c2c66affSColin Finck 	BOOL	_wasZoomed;
490*c2c66affSColin Finck };
491*c2c66affSColin Finck 
492*c2c66affSColin Finck 
493*c2c66affSColin Finck  // drawing utilities
494*c2c66affSColin Finck 
495*c2c66affSColin Finck  /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
496*c2c66affSColin Finck struct PaintCanvas : public PAINTSTRUCT
497*c2c66affSColin Finck {
PaintCanvasPaintCanvas498*c2c66affSColin Finck 	PaintCanvas(HWND hwnd)
499*c2c66affSColin Finck 	 :	_hwnd(hwnd)
500*c2c66affSColin Finck 	{
501*c2c66affSColin Finck 		BeginPaint(hwnd, this);
502*c2c66affSColin Finck 	}
503*c2c66affSColin Finck 
~PaintCanvasPaintCanvas504*c2c66affSColin Finck 	~PaintCanvas()
505*c2c66affSColin Finck 	{
506*c2c66affSColin Finck 		EndPaint(_hwnd, this);
507*c2c66affSColin Finck 	}
508*c2c66affSColin Finck 
HDCPaintCanvas509*c2c66affSColin Finck 	operator HDC() const {return hdc;}
510*c2c66affSColin Finck 
511*c2c66affSColin Finck protected:
512*c2c66affSColin Finck 	HWND	_hwnd;
513*c2c66affSColin Finck };
514*c2c66affSColin Finck 
515*c2c66affSColin Finck  /// Canvas is a encapsulation of device contexts.
516*c2c66affSColin Finck struct Canvas
517*c2c66affSColin Finck {
CanvasCanvas518*c2c66affSColin Finck 	Canvas(HDC hdc) : _hdc(hdc) {}
519*c2c66affSColin Finck 
HDCCanvas520*c2c66affSColin Finck 	operator HDC() {return _hdc;}
521*c2c66affSColin Finck 
522*c2c66affSColin Finck protected:
523*c2c66affSColin Finck 	HDC _hdc;
524*c2c66affSColin Finck };
525*c2c66affSColin Finck 
526*c2c66affSColin Finck  /// WindowCanvas is a encapsulation of client area device contexts.
527*c2c66affSColin Finck struct WindowCanvas : public Canvas
528*c2c66affSColin Finck {
WindowCanvasWindowCanvas529*c2c66affSColin Finck 	WindowCanvas(HWND hwnd)
530*c2c66affSColin Finck 	 :	Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
531*c2c66affSColin Finck 
~WindowCanvasWindowCanvas532*c2c66affSColin Finck 	~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
533*c2c66affSColin Finck 
534*c2c66affSColin Finck protected:
535*c2c66affSColin Finck 	HWND	_hwnd;
536*c2c66affSColin Finck };
537*c2c66affSColin Finck 
538*c2c66affSColin Finck 
539*c2c66affSColin Finck  // double buffering classes
540*c2c66affSColin Finck 
541*c2c66affSColin Finck  /// Memory Canvas creates and destroys memory devoce contexts.
542*c2c66affSColin Finck struct MemCanvas : public Canvas
543*c2c66affSColin Finck {
544*c2c66affSColin Finck 	MemCanvas(HDC hdc=0)
CanvasMemCanvas545*c2c66affSColin Finck 	 :	Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
546*c2c66affSColin Finck 
~MemCanvasMemCanvas547*c2c66affSColin Finck 	~MemCanvas() {DeleteDC(_hdc);}
548*c2c66affSColin Finck };
549*c2c66affSColin Finck 
550*c2c66affSColin Finck  /// SelectedBitmap is used to localy select bitmaps into device contexts.
551*c2c66affSColin Finck struct SelectedBitmap
552*c2c66affSColin Finck {
SelectedBitmapSelectedBitmap553*c2c66affSColin Finck 	SelectedBitmap(HDC hdc, HBITMAP hbmp)
554*c2c66affSColin Finck 	 :	_hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
555*c2c66affSColin Finck 
~SelectedBitmapSelectedBitmap556*c2c66affSColin Finck 	~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
557*c2c66affSColin Finck 
558*c2c66affSColin Finck protected:
559*c2c66affSColin Finck 	HDC		_hdc;
560*c2c66affSColin Finck 	HBITMAP	_old_hbmp;
561*c2c66affSColin Finck };
562*c2c66affSColin Finck 
563*c2c66affSColin Finck  /// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
564*c2c66affSColin Finck struct BufferCanvas : public MemCanvas
565*c2c66affSColin Finck {
BufferCanvasBufferCanvas566*c2c66affSColin Finck 	BufferCanvas(HDC hdc, int x, int y, int w, int h)
567*c2c66affSColin Finck 	 :	MemCanvas(hdc), _hdctarg(hdc),
568*c2c66affSColin Finck 		_x(x), _y(y), _w(w), _h(h),
569*c2c66affSColin Finck 		_bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
570*c2c66affSColin Finck 
BufferCanvasBufferCanvas571*c2c66affSColin Finck 	BufferCanvas(HDC hdc, const RECT& rect)
572*c2c66affSColin Finck 	 :	MemCanvas(hdc), _hdctarg(hdc),
573*c2c66affSColin Finck 		_x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
574*c2c66affSColin Finck 		_bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
575*c2c66affSColin Finck 
576*c2c66affSColin Finck protected:
577*c2c66affSColin Finck 	HDC 	_hdctarg;
578*c2c66affSColin Finck 	int 	_x, _y, _w, _h;
579*c2c66affSColin Finck 	SelectedBitmap _bmp;
580*c2c66affSColin Finck };
581*c2c66affSColin Finck 
582*c2c66affSColin Finck  /// BufferedCanvas enables double buffering for a device context.
583*c2c66affSColin Finck struct BufferedCanvas : public BufferCanvas
584*c2c66affSColin Finck {
585*c2c66affSColin Finck 	BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
BufferCanvasBufferedCanvas586*c2c66affSColin Finck 	 :	BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
587*c2c66affSColin Finck 
588*c2c66affSColin Finck 	BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
BufferCanvasBufferedCanvas589*c2c66affSColin Finck 	 :	BufferCanvas(hdc, rect), _mode(mode) {}
590*c2c66affSColin Finck 
~BufferedCanvasBufferedCanvas591*c2c66affSColin Finck 	~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
592*c2c66affSColin Finck 
593*c2c66affSColin Finck 	DWORD	_mode;
594*c2c66affSColin Finck };
595*c2c66affSColin Finck 
596*c2c66affSColin Finck  /// BufferedPaintCanvas extends PaintCanvas for double buffering.
597*c2c66affSColin Finck struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
598*c2c66affSColin Finck {
BufferedPaintCanvasBufferedPaintCanvas599*c2c66affSColin Finck 	BufferedPaintCanvas(HWND hwnd)
600*c2c66affSColin Finck 	 :	PaintCanvas(hwnd),
601*c2c66affSColin Finck 		BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
602*c2c66affSColin Finck 	{
603*c2c66affSColin Finck 	}
604*c2c66affSColin Finck 
HDCBufferedPaintCanvas605*c2c66affSColin Finck 	operator HDC() {return BufferedCanvas::_hdc;}
606*c2c66affSColin Finck };
607*c2c66affSColin Finck 
608*c2c66affSColin Finck 
609*c2c66affSColin Finck  /// TextColor locally selects a text color for drawing.
610*c2c66affSColin Finck struct TextColor
611*c2c66affSColin Finck {
TextColorTextColor612*c2c66affSColin Finck 	TextColor(HDC hdc, COLORREF color)
613*c2c66affSColin Finck 	 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
614*c2c66affSColin Finck 
~TextColorTextColor615*c2c66affSColin Finck 	~TextColor() {SetTextColor(_hdc, _old_color);}
616*c2c66affSColin Finck 
617*c2c66affSColin Finck protected:
618*c2c66affSColin Finck 	HDC		 _hdc;
619*c2c66affSColin Finck 	COLORREF _old_color;
620*c2c66affSColin Finck };
621*c2c66affSColin Finck 
622*c2c66affSColin Finck  /// BkMode locally sets the background mode for drawing.
623*c2c66affSColin Finck struct BkMode
624*c2c66affSColin Finck {
BkModeBkMode625*c2c66affSColin Finck 	BkMode(HDC hdc, int bkmode)
626*c2c66affSColin Finck 	 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
627*c2c66affSColin Finck 
~BkModeBkMode628*c2c66affSColin Finck 	~BkMode() {SetBkMode(_hdc, _old_bkmode);}
629*c2c66affSColin Finck 
630*c2c66affSColin Finck protected:
631*c2c66affSColin Finck 	HDC		 _hdc;
632*c2c66affSColin Finck 	COLORREF _old_bkmode;
633*c2c66affSColin Finck };
634*c2c66affSColin Finck 
635*c2c66affSColin Finck  /// FontSelection locally selects a font for drawing.
636*c2c66affSColin Finck struct FontSelection
637*c2c66affSColin Finck {
FontSelectionFontSelection638*c2c66affSColin Finck 	FontSelection(HDC hdc, HFONT hFont)
639*c2c66affSColin Finck 	 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
640*c2c66affSColin Finck 
~FontSelectionFontSelection641*c2c66affSColin Finck 	~FontSelection() {SelectFont(_hdc, _old_hFont);}
642*c2c66affSColin Finck 
643*c2c66affSColin Finck protected:
644*c2c66affSColin Finck 	HDC		_hdc;
645*c2c66affSColin Finck 	HFONT	_old_hFont;
646*c2c66affSColin Finck };
647*c2c66affSColin Finck 
648*c2c66affSColin Finck  /// BitmapSelection locally selects a bitmap into a device context.
649*c2c66affSColin Finck struct BitmapSelection
650*c2c66affSColin Finck {
BitmapSelectionBitmapSelection651*c2c66affSColin Finck 	BitmapSelection(HDC hdc, HBITMAP hBmp)
652*c2c66affSColin Finck 	 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
653*c2c66affSColin Finck 
~BitmapSelectionBitmapSelection654*c2c66affSColin Finck 	~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
655*c2c66affSColin Finck 
656*c2c66affSColin Finck protected:
657*c2c66affSColin Finck 	HDC		_hdc;
658*c2c66affSColin Finck 	HBITMAP	_old_hBmp;
659*c2c66affSColin Finck };
660*c2c66affSColin Finck 
661*c2c66affSColin Finck  /// BrushSelection locally selects a brush into a device context.
662*c2c66affSColin Finck struct BrushSelection
663*c2c66affSColin Finck {
BrushSelectionBrushSelection664*c2c66affSColin Finck 	BrushSelection(HDC hdc, HBRUSH hBrush)
665*c2c66affSColin Finck 	 : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {}
666*c2c66affSColin Finck 
~BrushSelectionBrushSelection667*c2c66affSColin Finck 	~BrushSelection() {SelectBrush(_hdc, _old_hBrush);}
668*c2c66affSColin Finck 
669*c2c66affSColin Finck protected:
670*c2c66affSColin Finck 	HDC		_hdc;
671*c2c66affSColin Finck 	HBRUSH	_old_hBrush;
672*c2c66affSColin Finck };
673*c2c66affSColin Finck 
674*c2c66affSColin Finck 
675*c2c66affSColin Finck  /// Popup Menus
676*c2c66affSColin Finck struct PopupMenu
677*c2c66affSColin Finck {
PopupMenuPopupMenu678*c2c66affSColin Finck 	PopupMenu()
679*c2c66affSColin Finck 	 :	_hmenu(CreatePopupMenu())
680*c2c66affSColin Finck 	{
681*c2c66affSColin Finck 	}
682*c2c66affSColin Finck 
~PopupMenuPopupMenu683*c2c66affSColin Finck 	~PopupMenu()
684*c2c66affSColin Finck 	{
685*c2c66affSColin Finck 		DestroyMenu(_hmenu);
686*c2c66affSColin Finck 	}
687*c2c66affSColin Finck 
688*c2c66affSColin Finck 	PopupMenu(UINT nid);
689*c2c66affSColin Finck 
HMENUPopupMenu690*c2c66affSColin Finck 	operator HMENU() {return _hmenu;}
691*c2c66affSColin Finck 
692*c2c66affSColin Finck 	void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING)
693*c2c66affSColin Finck 	{
694*c2c66affSColin Finck 		AppendMenu(_hmenu, flags, id, str);
695*c2c66affSColin Finck 	}
696*c2c66affSColin Finck 
697*c2c66affSColin Finck 	int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) {
698*c2c66affSColin Finck 	 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm);
699*c2c66affSColin Finck 	}
700*c2c66affSColin Finck 
701*c2c66affSColin Finck 	int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
702*c2c66affSColin Finck 	 POINT pt;
703*c2c66affSColin Finck 	 pt.x = pos.x;
704*c2c66affSColin Finck 	 pt.y = pos.y;
705*c2c66affSColin Finck 	 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
706*c2c66affSColin Finck 	}
707*c2c66affSColin Finck 
708*c2c66affSColin Finck 	int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
709*c2c66affSColin Finck 	 POINT pt;
710*c2c66affSColin Finck 	 pt.x = pos.x;
711*c2c66affSColin Finck 	 pt.y = pos.y;
712*c2c66affSColin Finck 	 ClientToScreen(hwnd, &pt);
713*c2c66affSColin Finck 	 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
714*c2c66affSColin Finck 	}
715*c2c66affSColin Finck 
716*c2c66affSColin Finck 	int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) {
717*c2c66affSColin Finck 	 POINT pt; GetCursorPos(&pt);
718*c2c66affSColin Finck 	 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
719*c2c66affSColin Finck 	}
720*c2c66affSColin Finck 
721*c2c66affSColin Finck 	int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) {
722*c2c66affSColin Finck 	 return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL);
723*c2c66affSColin Finck 	}
724*c2c66affSColin Finck 
725*c2c66affSColin Finck protected:
726*c2c66affSColin Finck 	HMENU _hmenu;
727*c2c66affSColin Finck };
728*c2c66affSColin Finck 
729*c2c66affSColin Finck 
730*c2c66affSColin Finck struct Variant : public VARIANT
731*c2c66affSColin Finck {
VariantVariant732*c2c66affSColin Finck 	Variant() {VariantInit(this);}
733*c2c66affSColin Finck 	Variant(const VARIANT& var);
734*c2c66affSColin Finck 	Variant(const VARIANT* var);
735*c2c66affSColin Finck 	~Variant();
736*c2c66affSColin Finck 
737*c2c66affSColin Finck 	operator long() const;
738*c2c66affSColin Finck 	operator bool() const;
739*c2c66affSColin Finck 	operator VARIANT_BOOL() const;
740*c2c66affSColin Finck 	operator IDispatch*() const;
741*c2c66affSColin Finck };
742*c2c66affSColin Finck 
743*c2c66affSColin Finck 
744*c2c66affSColin Finck struct BStr
745*c2c66affSColin Finck {
BStrBStr746*c2c66affSColin Finck 	BStr()
747*c2c66affSColin Finck 	{
748*c2c66affSColin Finck 		_p = NULL;
749*c2c66affSColin Finck 	}
750*c2c66affSColin Finck 
BStrBStr751*c2c66affSColin Finck 	BStr(const BSTR s)
752*c2c66affSColin Finck 	{
753*c2c66affSColin Finck 		_p = SysAllocString(s);
754*c2c66affSColin Finck 	}
755*c2c66affSColin Finck 
BStrBStr756*c2c66affSColin Finck 	BStr(LPCSTR s)
757*c2c66affSColin Finck 	{
758*c2c66affSColin Finck 		WCHAR b[BUFFER_LEN];
759*c2c66affSColin Finck 
760*c2c66affSColin Finck 		if (s)
761*c2c66affSColin Finck 			_p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);
762*c2c66affSColin Finck 		else
763*c2c66affSColin Finck 			_p = NULL;
764*c2c66affSColin Finck 	}
765*c2c66affSColin Finck 
BStrBStr766*c2c66affSColin Finck 	BStr(LPCWSTR s)
767*c2c66affSColin Finck 	{
768*c2c66affSColin Finck 		_p = SysAllocString(s);
769*c2c66affSColin Finck 	}
770*c2c66affSColin Finck 
BStrBStr771*c2c66affSColin Finck 	BStr(const VARIANT& var)
772*c2c66affSColin Finck 	 :	_p(NULL)
773*c2c66affSColin Finck 	{
774*c2c66affSColin Finck 		assign(var);
775*c2c66affSColin Finck 	}
776*c2c66affSColin Finck 
~BStrBStr777*c2c66affSColin Finck 	~BStr()
778*c2c66affSColin Finck 	{
779*c2c66affSColin Finck 		SysFreeString(_p);
780*c2c66affSColin Finck 	}
781*c2c66affSColin Finck 
782*c2c66affSColin Finck 	void assign(BSTR s);
783*c2c66affSColin Finck 	void assign(const VARIANT& var);
784*c2c66affSColin Finck 
BSTRBStr785*c2c66affSColin Finck 	operator BSTR() const
786*c2c66affSColin Finck 	{
787*c2c66affSColin Finck 		return _p? _p: (BSTR)L"";
788*c2c66affSColin Finck 	}
789*c2c66affSColin Finck 
lengthBStr790*c2c66affSColin Finck 	int length() const
791*c2c66affSColin Finck 	{
792*c2c66affSColin Finck 		return _p? wcslen(_p): 0;
793*c2c66affSColin Finck 	}
794*c2c66affSColin Finck 
795*c2c66affSColin Finck protected:
796*c2c66affSColin Finck 	BSTR	_p;
797*c2c66affSColin Finck };
798*c2c66affSColin Finck 
799*c2c66affSColin Finck 
800*c2c66affSColin Finck  /// string class for TCHAR strings
801*c2c66affSColin Finck struct String
802*c2c66affSColin Finck #ifdef UNICODE
803*c2c66affSColin Finck  : public wstring
804*c2c66affSColin Finck #else
805*c2c66affSColin Finck  : public string
806*c2c66affSColin Finck #endif
807*c2c66affSColin Finck {
808*c2c66affSColin Finck #ifdef UNICODE
809*c2c66affSColin Finck 	typedef wstring super;
810*c2c66affSColin Finck #else
811*c2c66affSColin Finck 	typedef string super;
812*c2c66affSColin Finck #endif
813*c2c66affSColin Finck 
StringString814*c2c66affSColin Finck 	String() {}
815*c2c66affSColin Finck 
StringString816*c2c66affSColin Finck 	String(LPCTSTR s) {if (s) super::assign(s);}
StringString817*c2c66affSColin Finck 	String(LPCTSTR s, int l) : super(s, l) {}
818*c2c66affSColin Finck 
StringString819*c2c66affSColin Finck 	String(const super& other) : super(other) {}
StringString820*c2c66affSColin Finck 	String(const String& other) : super(other) {}
821*c2c66affSColin Finck 
822*c2c66affSColin Finck #ifdef UNICODE
StringString823*c2c66affSColin Finck 	String(LPCSTR s) {assign(s);}
StringString824*c2c66affSColin Finck 	String(LPCSTR s, int l) {assign(s, l);}
StringString825*c2c66affSColin Finck 	String(const string& other) {assign(other.c_str());}
826*c2c66affSColin Finck 	String& operator=(LPCSTR s) {assign(s); return *this;}
assignString827*c2c66affSColin Finck 	void assign(LPCSTR s) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);} else erase();}
assignString828*c2c66affSColin Finck 	void assign(LPCSTR s, int l) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, BUFFER_LEN));} else erase();}
assignString829*c2c66affSColin Finck 	void assign(const BStr& s) {int l = s.length(); super::assign(s, l);}
830*c2c66affSColin Finck #else
StringString831*c2c66affSColin Finck 	String(LPCWSTR s) {assign(s);}
StringString832*c2c66affSColin Finck 	String(LPCWSTR s, int l) {assign(s, l);}
StringString833*c2c66affSColin Finck 	String(const wstring& other) {assign(other.c_str());}
834*c2c66affSColin Finck 	String& operator=(LPCWSTR s) {assign(s); return *this;}
assignString835*c2c66affSColin Finck 	void assign(LPCWSTR s) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, -1, b, BUFFER_LEN, 0, 0)-1);} else erase();}
assignString836*c2c66affSColin Finck 	void assign(LPCWSTR s, int l) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
assignString837*c2c66affSColin Finck 	void assign(const BStr& s) {int l = s.length(); if (l) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
838*c2c66affSColin Finck #endif
StringString839*c2c66affSColin Finck 	String(const BStr& s) {assign(s);}
840*c2c66affSColin Finck 	String& operator=(const BStr& s) {assign(s); return *this;}
841*c2c66affSColin Finck 
842*c2c66affSColin Finck 	String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
843*c2c66affSColin Finck 	String& operator=(const super& s) {super::assign(s); return *this;}
assignString844*c2c66affSColin Finck 	void assign(LPCTSTR s) {super::assign(s);}
assignString845*c2c66affSColin Finck 	void assign(LPCTSTR s, int l) {super::assign(s, l);}
846*c2c66affSColin Finck 
LPCTSTRString847*c2c66affSColin Finck 	operator LPCTSTR() const {return c_str();}
848*c2c66affSColin Finck 
849*c2c66affSColin Finck #ifdef UNICODE
stringString850*c2c66affSColin Finck 	operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);}
851*c2c66affSColin Finck #else
wstringString852*c2c66affSColin Finck 	operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);}
853*c2c66affSColin Finck #endif
854*c2c66affSColin Finck 
strString855*c2c66affSColin Finck 	LPTSTR str() {return (LPTSTR)data();}	/// return modifyable character string pointer
856*c2c66affSColin Finck 
printfString857*c2c66affSColin Finck 	String& printf(LPCTSTR fmt, ...)
858*c2c66affSColin Finck 	{
859*c2c66affSColin Finck 		va_list l;
860*c2c66affSColin Finck 		TCHAR b[BUFFER_LEN];
861*c2c66affSColin Finck 
862*c2c66affSColin Finck 		va_start(l, fmt);
863*c2c66affSColin Finck 		super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
864*c2c66affSColin Finck 		va_end(l);
865*c2c66affSColin Finck 
866*c2c66affSColin Finck 		return *this;
867*c2c66affSColin Finck 	}
868*c2c66affSColin Finck 
vprintfString869*c2c66affSColin Finck 	String& vprintf(LPCTSTR fmt, va_list l)
870*c2c66affSColin Finck 	{
871*c2c66affSColin Finck 		TCHAR b[BUFFER_LEN];
872*c2c66affSColin Finck 
873*c2c66affSColin Finck 		super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
874*c2c66affSColin Finck 
875*c2c66affSColin Finck 		return *this;
876*c2c66affSColin Finck 	}
877*c2c66affSColin Finck 
appendfString878*c2c66affSColin Finck 	String& appendf(LPCTSTR fmt, ...)
879*c2c66affSColin Finck 	{
880*c2c66affSColin Finck 		va_list l;
881*c2c66affSColin Finck 		TCHAR b[BUFFER_LEN];
882*c2c66affSColin Finck 
883*c2c66affSColin Finck 		va_start(l, fmt);
884*c2c66affSColin Finck 		super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
885*c2c66affSColin Finck 		va_end(l);
886*c2c66affSColin Finck 
887*c2c66affSColin Finck 		return *this;
888*c2c66affSColin Finck 	}
889*c2c66affSColin Finck 
vappendfString890*c2c66affSColin Finck 	String& vappendf(LPCTSTR fmt, va_list l)
891*c2c66affSColin Finck 	{
892*c2c66affSColin Finck 		TCHAR b[BUFFER_LEN];
893*c2c66affSColin Finck 
894*c2c66affSColin Finck 		super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
895*c2c66affSColin Finck 
896*c2c66affSColin Finck 		return *this;
897*c2c66affSColin Finck 	}
898*c2c66affSColin Finck 
toLowerString899*c2c66affSColin Finck 	void toLower()
900*c2c66affSColin Finck 	{
901*c2c66affSColin Finck 		if (!empty())
902*c2c66affSColin Finck 			CharLower(str());
903*c2c66affSColin Finck 	}
904*c2c66affSColin Finck };
905*c2c66affSColin Finck 
906*c2c66affSColin Finck #define	_STRING_DEFINED
907*c2c66affSColin Finck 
908*c2c66affSColin Finck 
909*c2c66affSColin Finck struct FmtString : public String
910*c2c66affSColin Finck {
FmtStringFmtString911*c2c66affSColin Finck 	FmtString(LPCTSTR fmt, ...)
912*c2c66affSColin Finck 	{
913*c2c66affSColin Finck 		va_list l;
914*c2c66affSColin Finck 
915*c2c66affSColin Finck 		va_start(l, fmt);
916*c2c66affSColin Finck 		vprintf(fmt, l);
917*c2c66affSColin Finck 		va_end(l);
918*c2c66affSColin Finck 	}
919*c2c66affSColin Finck };
920*c2c66affSColin Finck 
921*c2c66affSColin Finck 
922*c2c66affSColin Finck #ifdef UNICODE
923*c2c66affSColin Finck 
924*c2c66affSColin Finck struct ANS
925*c2c66affSColin Finck {
ANSANS926*c2c66affSColin Finck 	ANS(LPCWSTR s)
927*c2c66affSColin Finck 	{
928*c2c66affSColin Finck 		int l = wcslen(s) + 1;
929*c2c66affSColin Finck 		_str = (LPSTR) malloc(2*l);
930*c2c66affSColin Finck 
931*c2c66affSColin Finck 		if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
932*c2c66affSColin Finck 			*_str = '\0';
933*c2c66affSColin Finck 	}
934*c2c66affSColin Finck 
~ANSANS935*c2c66affSColin Finck 	~ANS()
936*c2c66affSColin Finck 	{
937*c2c66affSColin Finck 		free(_str);
938*c2c66affSColin Finck 	}
939*c2c66affSColin Finck 
LPCSTRANS940*c2c66affSColin Finck 	operator LPCSTR() {return _str;}
941*c2c66affSColin Finck 
942*c2c66affSColin Finck protected:
943*c2c66affSColin Finck 	LPSTR	_str;
944*c2c66affSColin Finck };
945*c2c66affSColin Finck 
946*c2c66affSColin Finck #define	UNC(x) ((LPCWSTR)(x))
947*c2c66affSColin Finck 
948*c2c66affSColin Finck #else
949*c2c66affSColin Finck 
950*c2c66affSColin Finck #define	ANS(x) ((LPCSTR)(x))
951*c2c66affSColin Finck 
952*c2c66affSColin Finck struct UNC
953*c2c66affSColin Finck {
UNCUNC954*c2c66affSColin Finck 	UNC(LPCSTR s)
955*c2c66affSColin Finck 	{
956*c2c66affSColin Finck 		int l = strlen(s) + 1;
957*c2c66affSColin Finck 		_str = (LPWSTR) malloc(2*l);
958*c2c66affSColin Finck 
959*c2c66affSColin Finck 		if (_str && MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
960*c2c66affSColin Finck 			*_str = '\0';
961*c2c66affSColin Finck 	}
962*c2c66affSColin Finck 
~UNCUNC963*c2c66affSColin Finck 	~UNC()
964*c2c66affSColin Finck 	{
965*c2c66affSColin Finck 		free(_str);
966*c2c66affSColin Finck 	}
967*c2c66affSColin Finck 
LPCWSTRUNC968*c2c66affSColin Finck 	operator LPCWSTR() {return _str;}
969*c2c66affSColin Finck 
970*c2c66affSColin Finck protected:
971*c2c66affSColin Finck 	LPWSTR	_str;
972*c2c66affSColin Finck };
973*c2c66affSColin Finck 
974*c2c66affSColin Finck #endif
975*c2c66affSColin Finck 
976*c2c66affSColin Finck 
977*c2c66affSColin Finck  // determine windows version string
978*c2c66affSColin Finck String get_windows_version_str();
979*c2c66affSColin Finck 
980*c2c66affSColin Finck 
981*c2c66affSColin Finck  /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
982*c2c66affSColin Finck template<typename FCT> struct DynamicFct
983*c2c66affSColin Finck {
DynamicFctDynamicFct984*c2c66affSColin Finck 	DynamicFct(LPCTSTR moduleName, UINT ordinal)
985*c2c66affSColin Finck 	{
986*c2c66affSColin Finck 		HMODULE hModule = GetModuleHandle(moduleName);
987*c2c66affSColin Finck 
988*c2c66affSColin Finck 		_fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
989*c2c66affSColin Finck 	}
990*c2c66affSColin Finck 
DynamicFctDynamicFct991*c2c66affSColin Finck 	DynamicFct(LPCTSTR moduleName, LPCSTR name)
992*c2c66affSColin Finck 	{
993*c2c66affSColin Finck 		HMODULE hModule = GetModuleHandle(moduleName);
994*c2c66affSColin Finck 
995*c2c66affSColin Finck 		_fct = (FCT) GetProcAddress(hModule, name);
996*c2c66affSColin Finck 	}
997*c2c66affSColin Finck 
998*c2c66affSColin Finck 	FCT operator*() const {return _fct;}
999*c2c66affSColin Finck 	operator bool() const {return _fct? true: false;}
1000*c2c66affSColin Finck 
1001*c2c66affSColin Finck protected:
1002*c2c66affSColin Finck 	FCT	_fct;
1003*c2c66affSColin Finck };
1004*c2c66affSColin Finck 
1005*c2c66affSColin Finck 
1006*c2c66affSColin Finck  /// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
1007*c2c66affSColin Finck template<typename FCT> struct DynamicLoadLibFct
1008*c2c66affSColin Finck {
DynamicLoadLibFctDynamicLoadLibFct1009*c2c66affSColin Finck 	DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
1010*c2c66affSColin Finck 	{
1011*c2c66affSColin Finck 		_hModule = LoadLibrary(moduleName);
1012*c2c66affSColin Finck 
1013*c2c66affSColin Finck 		_fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
1014*c2c66affSColin Finck 	}
1015*c2c66affSColin Finck 
DynamicLoadLibFctDynamicLoadLibFct1016*c2c66affSColin Finck 	DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
1017*c2c66affSColin Finck 	{
1018*c2c66affSColin Finck 		_hModule = LoadLibrary(moduleName);
1019*c2c66affSColin Finck 
1020*c2c66affSColin Finck 		_fct = (FCT) GetProcAddress(_hModule, name);
1021*c2c66affSColin Finck 	}
1022*c2c66affSColin Finck 
~DynamicLoadLibFctDynamicLoadLibFct1023*c2c66affSColin Finck 	~DynamicLoadLibFct()
1024*c2c66affSColin Finck 	{
1025*c2c66affSColin Finck 		FreeLibrary(_hModule);
1026*c2c66affSColin Finck 	}
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck 	FCT operator*() const {return _fct;}
1029*c2c66affSColin Finck 	operator bool() const {return _fct? true: false;}
1030*c2c66affSColin Finck 
1031*c2c66affSColin Finck protected:
1032*c2c66affSColin Finck 	HMODULE _hModule;
1033*c2c66affSColin Finck 	FCT	_fct;
1034*c2c66affSColin Finck };
1035*c2c66affSColin Finck 
1036*c2c66affSColin Finck 
1037*c2c66affSColin Finck struct Context
1038*c2c66affSColin Finck {
ContextContext1039*c2c66affSColin Finck 	Context(const char* ctx)
1040*c2c66affSColin Finck 	 :	_ctx(ctx)
1041*c2c66affSColin Finck 	{
1042*c2c66affSColin Finck 		_last = s_current;
1043*c2c66affSColin Finck 		s_current = this;
1044*c2c66affSColin Finck 	}
1045*c2c66affSColin Finck 
ContextContext1046*c2c66affSColin Finck 	Context(const char* ctx, LPCSTR obj)
1047*c2c66affSColin Finck 	 :	_ctx(ctx),
1048*c2c66affSColin Finck 		_obj(obj)
1049*c2c66affSColin Finck 	{
1050*c2c66affSColin Finck 		_last = s_current;
1051*c2c66affSColin Finck 		s_current = this;
1052*c2c66affSColin Finck 	}
1053*c2c66affSColin Finck 
ContextContext1054*c2c66affSColin Finck 	Context(const char* ctx, LPCWSTR obj)
1055*c2c66affSColin Finck 	 :	_ctx(ctx),
1056*c2c66affSColin Finck 		_obj(obj)
1057*c2c66affSColin Finck 	{
1058*c2c66affSColin Finck 		_last = s_current;
1059*c2c66affSColin Finck 		s_current = this;
1060*c2c66affSColin Finck 	}
1061*c2c66affSColin Finck 
ContextContext1062*c2c66affSColin Finck 	Context(const Context& other)
1063*c2c66affSColin Finck 	 :	_ctx(other._ctx),
1064*c2c66affSColin Finck 		_obj(other._obj)
1065*c2c66affSColin Finck 	{
1066*c2c66affSColin Finck 		_last = NULL;
1067*c2c66affSColin Finck 	}
1068*c2c66affSColin Finck 
~ContextContext1069*c2c66affSColin Finck 	~Context()
1070*c2c66affSColin Finck 	{
1071*c2c66affSColin Finck 		if (_last) {
1072*c2c66affSColin Finck 			s_current = _last;
1073*c2c66affSColin Finck 			_last = NULL;
1074*c2c66affSColin Finck 		}
1075*c2c66affSColin Finck 	}
1076*c2c66affSColin Finck 
1077*c2c66affSColin Finck 	String toString() const;
1078*c2c66affSColin Finck 	String getStackTrace() const;
1079*c2c66affSColin Finck 
1080*c2c66affSColin Finck 	const char* _ctx;
1081*c2c66affSColin Finck 	String	_obj;
1082*c2c66affSColin Finck 
currentContext1083*c2c66affSColin Finck 	static Context& current() {return *s_current;}
1084*c2c66affSColin Finck 
1085*c2c66affSColin Finck protected:
1086*c2c66affSColin Finck 	Context* _last;
1087*c2c66affSColin Finck 
1088*c2c66affSColin Finck 	static Context*	s_current;	///@todo use TLS
1089*c2c66affSColin Finck 	static Context	s_main;
1090*c2c66affSColin Finck };
1091*c2c66affSColin Finck 
1092*c2c66affSColin Finck #define	CONTEXT_OBJ __ctx__._obj
1093*c2c66affSColin Finck #define	CONTEXT(c) Context __ctx__(c)
1094*c2c66affSColin Finck #define	CURRENT_CONTEXT Context::current()
1095*c2c66affSColin Finck #define	OBJ_CONTEXT(c, o) Context __ctx__(c, o)
1096*c2c66affSColin Finck 
1097*c2c66affSColin Finck 
1098*c2c66affSColin Finck extern bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out);
1099*c2c66affSColin Finck 
1100*c2c66affSColin Finck 
1101*c2c66affSColin Finck #endif // __cplusplus
1102