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