51c7cf188a5f3e276d90dbe1918af90b23bfcc6a
[reactos.git] / reactos / subsys / system / explorer / utility / utility.h
1 /*
2 * Copyright 2003, 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // utility.h
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 // standard windows headers
30 #define WIN32_LEAN_AND_MEAN
31 #define WIN32_EXTRA_LEAN
32 #include <windows.h>
33
34 // Unicode support
35 #ifdef UNICODE
36 #define _UNICODE
37 #endif
38 #include <tchar.h>
39
40 #include <windowsx.h> // for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ...
41 #include <commctrl.h>
42
43 #ifndef _MSC_VER
44 #include <objbase.h>
45 #endif
46 #include <oleauto.h> // for VARIANT
47
48 #include <malloc.h> // for alloca()
49 #include <assert.h>
50 #include <stdlib.h> // for _MAX_DIR, ...
51 #include <stdio.h> // for sprintf()
52 #include <time.h>
53
54 #ifndef _MAX_PATH
55 #define _MAX_DRIVE 3
56 #define _MAX_FNAME 256
57 #define _MAX_DIR _MAX_FNAME
58 #define _MAX_EXT _MAX_FNAME
59 #define _MAX_PATH 260
60 #endif
61
62 #define W_VER_NT 0 // constant for HIWORD(GetVersion())>>14
63
64
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68
69
70 #define for if (0) {} else for
71
72 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
73
74
75 #define BUFFER_LEN 2048
76
77
78 extern void _log_(LPCTSTR txt);
79
80 #define LOG(txt) _log_(txt)
81
82
83 #ifdef _MSC_VER
84 #define LONGLONGARG TEXT("I64")
85 #else
86 #define LONGLONGARG TEXT("L")
87 #endif
88
89
90 #ifndef _tcsrchr
91 #ifdef UNICODE
92 #define _tcsrchr wcsrchr
93 #else
94 #define _tcsrchr strrchr
95 #endif
96 #endif
97
98 #ifndef _stprintf
99 #ifdef UNICODE
100 #define _stprintf wcsprintf
101 #else
102 #define _stprintf sprintf
103 #endif
104 #endif
105
106 #define U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL)
107 #define U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL)
108 #define A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l)
109 #define A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l)
110
111
112 #ifdef __WINE__
113 #ifdef UNICODE
114 extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
115 #else
116 extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
117 #endif
118 #define _tcsnicmp strncasecmp
119 #define _tcsicoll strcasecmp
120 #endif
121
122 #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
123 #define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
124 #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
125 #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
126 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
127 #endif
128
129
130 #define SetDlgCtrlID(hwnd, id) SetWindowLong(hwnd, GWL_ID, id)
131 #define SetWindowStyle(hwnd, val) (DWORD)SetWindowLong(hwnd, GWL_STYLE, val)
132 #define SetWindowExStyle(h, val) (DWORD)SetWindowLong(hwnd, GWL_EXSTYLE, val)
133 #define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
134
135
136 // center window in respect to its parent window
137 extern void CenterWindow(HWND hwnd);
138
139 // move window into visibility
140 extern void MoveVisible(HWND hwnd);
141
142 // display error message
143 extern void display_error(HWND hwnd, DWORD error);
144
145 // convert time_t to WIN32 FILETIME
146 extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
147
148 // search for windows of a specific classname
149 extern int find_window_class(LPCTSTR classname);
150
151 // create a directory with all missing parent directories
152 BOOL RecursiveCreateDirectory(LPCTSTR path_in);
153
154 // read DWORD value from registry
155 DWORD RegGetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD def);
156
157 // write DWORD value to registry
158 BOOL RegSetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD value);
159
160 // test for existing directory
161 BOOL exists_path(LPCTSTR path);
162
163
164 #ifdef __cplusplus
165 } // extern "C"
166 #endif
167
168
169 #ifdef __cplusplus
170
171 #ifdef _MSC_VER
172 #pragma warning(disable: 4786) // disable warnings about too long debug information symbols
173 #endif
174
175 // STL headers for strings and streams
176 #include <string>
177 #include <iostream>
178 using namespace std;
179
180 // containers
181 #include <map>
182 #include <set>
183 #include <list>
184 #include <stack>
185 #include <vector>
186
187
188 #if _MSC_VER>=1300 // VS.Net
189 #define _NO_COMUTIL //@@
190 #endif
191
192 #if defined(_MSC_VER) && !defined(_NO_COMUTIL)
193
194 // COM utility headers
195 #include <comdef.h>
196 using namespace _com_util;
197
198 #endif // _MSC_VER && !_NO_COMUTIL
199
200
201 // launch a program or document file
202 extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCTSTR parameters=NULL);
203 #ifdef UNICODE
204 extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCSTR parameters=NULL);
205 #else
206 #define launch_fileA launch_file
207 #endif
208
209 // call an DLL export like rundll32
210 extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
211
212 // launch control panel applet
213 extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet);
214
215
216 /// initialization of windows common controls
217 struct CommonControlInit
218 {
219 CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
220 {
221 INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
222
223 InitCommonControlsEx(&icc);
224 }
225 };
226
227
228 /// wait cursor
229
230 struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
231 {
232 WaitCursor()
233 {
234 _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
235 }
236
237 ~WaitCursor()
238 {
239 SetCursor(_old_cursor);
240 }
241
242 protected:
243 HCURSOR _old_cursor;
244 };
245
246
247 /// base of all structures storing a window handle
248 struct WindowHandle
249 {
250 WindowHandle(HWND hwnd=0)
251 : _hwnd(hwnd) {}
252
253 operator HWND() const {return _hwnd;}
254 HWND* operator&() {return &_hwnd;}
255
256 protected:
257 HWND _hwnd;
258 };
259
260
261 /// locally hide a window
262 struct HiddenWindow : public WindowHandle
263 {
264 HiddenWindow(HWND hwnd)
265 : WindowHandle(IsWindowVisible(hwnd)? hwnd: 0)
266 {
267 if (_hwnd)
268 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
269 }
270
271 ~HiddenWindow()
272 {
273 if (_hwnd)
274 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
275 }
276 };
277
278
279 /// critical section wrapper
280
281 struct CritSect : public CRITICAL_SECTION
282 {
283 CritSect()
284 {
285 InitializeCriticalSection(this);
286 }
287
288 ~CritSect()
289 {
290 DeleteCriticalSection(this);
291 }
292 };
293
294
295 /// Lock protects a code section utilizing a critical section
296
297 struct Lock
298 {
299 Lock(CritSect& crit_sect)
300 : _crit_sect(crit_sect)
301 {
302 EnterCriticalSection(&crit_sect);
303 }
304
305 ~Lock()
306 {
307 LeaveCriticalSection(&_crit_sect);
308 }
309
310 protected:
311 CritSect& _crit_sect;
312 };
313
314
315 /// Thread base class
316
317 struct Thread
318 {
319 Thread()
320 : _alive(false),
321 _destroy(false)
322 {
323 _hThread = INVALID_HANDLE_VALUE;
324 _evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
325 }
326
327 virtual ~Thread()
328 {
329 Stop();
330
331 CloseHandle(_evtFinish);
332 CloseHandle(_hThread);
333
334 if (_destroy)
335 delete this;
336 }
337
338 void Start()
339 {
340 if (!_alive) {
341 _alive = true;
342 _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
343 }
344 }
345
346 void Stop()
347 {
348 SetEvent(_evtFinish);
349
350 if (_alive) {
351 {
352 Lock lock(_crit_sect);
353 _alive = false;
354 }
355
356 // wait for finishing
357 WaitForSingleObject(_hThread, INFINITE);
358 }
359 }
360
361 virtual int Run() = 0;
362
363 bool is_alive() const {return _alive;}
364
365 CritSect _crit_sect;
366
367 protected:
368 static DWORD WINAPI ThreadProc(void* para);
369
370 HANDLE _hThread;
371 HANDLE _evtFinish;
372 bool _alive;
373 bool _destroy;
374 };
375
376
377 // window utilities
378
379 /// ClientRect retreives the client area rectangle of a window.
380 struct ClientRect : public RECT
381 {
382 ClientRect(HWND hwnd)
383 {
384 GetClientRect(hwnd, this);
385 }
386
387 operator LPRECT() {return this;}
388
389 POINT& pos() {return *(LPPOINT)this;}
390 };
391
392 /// ClientRect retreives the window rectangle of a window.
393 struct WindowRect : public RECT
394 {
395 WindowRect(HWND hwnd)
396 {
397 GetWindowRect(hwnd, this);
398 }
399
400 operator LPRECT() {return this;}
401
402 POINT& pos() {return *(LPPOINT)this;}
403 };
404
405 /// PointL encapsulates the POINT structure into a C++ object.
406 struct Point : public POINT
407 {
408 Point(LONG x_, LONG y_)
409 {
410 x = x_;
411 y = y_;
412 }
413
414 // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
415 Point(LPARAM lparam)
416 {
417 x = GET_X_LPARAM(lparam);
418 y = GET_Y_LPARAM(lparam);
419 }
420
421 operator LPPOINT() {return this;}
422 };
423
424
425 /// transform coordinates in a RECT from client to screen coordiantes
426 inline void ClientToScreen(HWND hwnd, RECT* prect)
427 {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
428
429 /// transform coordinates in a RECT from screen to client coordiantes
430 inline void ScreenToClient(HWND hwnd, RECT* prect)
431 {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
432
433
434 /// structure containing information about full screen display of the frame window
435 struct FullScreenParameters
436 {
437 FullScreenParameters()
438 : _mode(FALSE)
439 {
440 }
441
442 BOOL _mode;
443 RECT _orgPos;
444 BOOL _wasZoomed;
445 };
446
447
448 // drawing utilities
449
450 /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
451 struct PaintCanvas : public PAINTSTRUCT
452 {
453 PaintCanvas(HWND hwnd)
454 : _hwnd(hwnd)
455 {
456 BeginPaint(hwnd, this);
457 }
458
459 ~PaintCanvas()
460 {
461 EndPaint(_hwnd, this);
462 }
463
464 operator HDC() const {return hdc;}
465
466 protected:
467 HWND _hwnd;
468 };
469
470 /// Canvas is a encapsulation of device contexts.
471 struct Canvas
472 {
473 Canvas(HDC hdc) : _hdc(hdc) {}
474
475 operator HDC() {return _hdc;}
476
477 protected:
478 HDC _hdc;
479 };
480
481 /// WindowCanvas is a encapsulation of client area device contexts.
482 struct WindowCanvas : public Canvas
483 {
484 WindowCanvas(HWND hwnd)
485 : Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
486
487 ~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
488
489 protected:
490 HWND _hwnd;
491 };
492
493
494 // double buffering classes
495
496 /// Memory Canvas creates and destroys memory devoce contexts.
497 struct MemCanvas : public Canvas
498 {
499 MemCanvas(HDC hdc=0)
500 : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
501
502 ~MemCanvas() {DeleteDC(_hdc);}
503 };
504
505 /// SelectedBitmap is used to localy select bitmaps into device contexts.
506 struct SelectedBitmap
507 {
508 SelectedBitmap(HDC hdc, HBITMAP hbmp)
509 : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
510
511 ~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
512
513 protected:
514 HDC _hdc;
515 HBITMAP _old_hbmp;
516 };
517
518 /// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
519 struct BufferCanvas : public MemCanvas
520 {
521 BufferCanvas(HDC hdc, int x, int y, int w, int h)
522 : MemCanvas(hdc), _hdctarg(hdc),
523 _x(x), _y(y), _w(w), _h(h),
524 _bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
525
526 BufferCanvas(HDC hdc, const RECT& rect)
527 : MemCanvas(hdc), _hdctarg(hdc),
528 _x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
529 _bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
530
531 protected:
532 HDC _hdctarg;
533 int _x, _y, _w, _h;
534 SelectedBitmap _bmp;
535 };
536
537 /// BufferedCanvas enables double buffering for a device context.
538 struct BufferedCanvas : public BufferCanvas
539 {
540 BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
541 : BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
542
543 BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
544 : BufferCanvas(hdc, rect), _mode(mode) {}
545
546 ~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
547
548 DWORD _mode;
549 };
550
551 /// BufferedPaintCanvas extends PaintCanvas for double buffering.
552 struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
553 {
554 BufferedPaintCanvas(HWND hwnd)
555 : PaintCanvas(hwnd),
556 BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
557 {
558 }
559
560 operator HDC() {return BufferedCanvas::_hdc;}
561 };
562
563
564 /// TextColor locally selects a text color for drawing.
565 struct TextColor
566 {
567 TextColor(HDC hdc, COLORREF color)
568 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
569
570 ~TextColor() {SetTextColor(_hdc, _old_color);}
571
572 protected:
573 HDC _hdc;
574 COLORREF _old_color;
575 };
576
577 /// BkMode locally sets the background mode for drawing.
578 struct BkMode
579 {
580 BkMode(HDC hdc, int bkmode)
581 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
582
583 ~BkMode() {SetBkMode(_hdc, _old_bkmode);}
584
585 protected:
586 HDC _hdc;
587 COLORREF _old_bkmode;
588 };
589
590 /// FontSelection locally selects a font for drawing.
591 struct FontSelection
592 {
593 FontSelection(HDC hdc, HFONT hFont)
594 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
595
596 ~FontSelection() {SelectFont(_hdc, _old_hFont);}
597
598 protected:
599 HDC _hdc;
600 HFONT _old_hFont;
601 };
602
603 /// BitmapSelection locally selects a bitmap into a device context.
604 struct BitmapSelection
605 {
606 BitmapSelection(HDC hdc, HBITMAP hBmp)
607 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
608
609 ~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
610
611 protected:
612 HDC _hdc;
613 HBITMAP _old_hBmp;
614 };
615
616 /// BrushSelection locally selects a brush into a device context.
617 struct BrushSelection
618 {
619 BrushSelection(HDC hdc, HBRUSH hBrush)
620 : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {}
621
622 ~BrushSelection() {SelectBrush(_hdc, _old_hBrush);}
623
624 protected:
625 HDC _hdc;
626 HBRUSH _old_hBrush;
627 };
628
629
630 /// Popup Menus
631 struct PopupMenu
632 {
633 PopupMenu()
634 : _hmenu(CreatePopupMenu())
635 {
636 }
637
638 PopupMenu(UINT nid);
639
640 operator HMENU() {return _hmenu;}
641
642 void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING)
643 {
644 AppendMenu(_hmenu, flags, id, str);
645 }
646
647 int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) {
648 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm);
649 }
650
651 int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
652 POINT pt; POINTSTOPOINT(pt, pos);
653 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
654 }
655
656 int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
657 POINT pt; POINTSTOPOINT(pt, pos);
658 ClientToScreen(hwnd, &pt);
659 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
660 }
661
662 int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) {
663 POINT pt; GetCursorPos(&pt);
664 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
665 }
666
667 int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) {
668 return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL);
669 }
670
671 protected:
672 HMENU _hmenu;
673 };
674
675
676 struct Variant : public VARIANT
677 {
678 Variant() {VariantInit(this);}
679 Variant(const VARIANT& var);
680 Variant(const VARIANT* var);
681 ~Variant();
682
683 operator long() const;
684 operator bool() const;
685 operator VARIANT_BOOL() const;
686 operator IDispatch*() const;
687 };
688
689
690 struct BStr
691 {
692 BStr()
693 {
694 _p = NULL;
695 }
696
697 BStr(const BSTR s)
698 {
699 _p = SysAllocString(s);
700 }
701
702 BStr(LPCSTR s)
703 {
704 WCHAR b[BUFFER_LEN];
705
706 if (s)
707 _p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);
708 else
709 _p = NULL;
710 }
711
712 BStr(LPCWSTR s)
713 {
714 _p = SysAllocString(s);
715 }
716
717 BStr(const VARIANT& var)
718 : _p(NULL)
719 {
720 assign(var);
721 }
722
723 ~BStr()
724 {
725 SysFreeString(_p);
726 }
727
728 void assign(BSTR s);
729 void assign(const VARIANT& var);
730
731 operator BSTR() const
732 {
733 return _p? _p: (BSTR)L"";
734 }
735
736 int length() const
737 {
738 return _p? wcslen(_p): 0;
739 }
740
741 protected:
742 BSTR _p;
743 };
744
745
746 /// string class for TCHAR strings
747 struct String
748 #ifdef UNICODE
749 : public wstring
750 #else
751 : public string
752 #endif
753 {
754 #ifdef UNICODE
755 typedef wstring super;
756 #else
757 typedef string super;
758 #endif
759
760 String() {}
761
762 String(LPCTSTR s) {if (s) super::assign(s);}
763 String(LPCTSTR s, int l) : super(s, l) {}
764
765 String(const super& other) : super(other) {}
766 String(const String& other) : super(other) {}
767
768 #ifdef UNICODE
769 String(LPCSTR s) {assign(s);}
770 String(LPCSTR s, int l) {assign(s, l);}
771 String(const string& other) {assign(other.c_str());}
772 String& operator=(LPCSTR s) {assign(s); return *this;}
773 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();}
774 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();}
775 void assign(const BStr& s) {int l = s.length(); super::assign(s, l);}
776 #else
777 String(LPCWSTR s) {assign(s);}
778 String(LPCWSTR s, int l) {assign(s, l);}
779 String(const wstring& other) {assign(other.c_str());}
780 String& operator=(LPCWSTR s) {assign(s); return *this;}
781 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();}
782 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();}
783 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();}
784 #endif
785 String(const BStr& s) {assign(s);}
786 String& operator=(const BStr& s) {assign(s); return *this;}
787
788 String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
789 String& operator=(const super& s) {super::assign(s); return *this;}
790 void assign(LPCTSTR s) {super::assign(s);}
791 void assign(LPCTSTR s, int l) {super::assign(s, l);}
792
793 operator LPCTSTR() const {return c_str();}
794
795 #ifdef UNICODE
796 operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);}
797 #else
798 operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);}
799 #endif
800
801 String& printf(LPCTSTR fmt, ...)
802 {
803 va_list l;
804 TCHAR b[BUFFER_LEN];
805
806 va_start(l, fmt);
807 super::assign(b, _vstprintf(b, fmt, l));
808 va_end(l);
809
810 return *this;
811 }
812
813 String& vprintf(LPCTSTR fmt, va_list l)
814 {
815 TCHAR b[BUFFER_LEN];
816
817 super::assign(b, _vstprintf(b, fmt, l));
818
819 return *this;
820 }
821
822 String& appendf(LPCTSTR fmt, ...)
823 {
824 va_list l;
825 TCHAR b[BUFFER_LEN];
826
827 va_start(l, fmt);
828 super::append(b, _vstprintf(b, fmt, l));
829 va_end(l);
830
831 return *this;
832 }
833
834 String& vappendf(LPCTSTR fmt, va_list l)
835 {
836 TCHAR b[BUFFER_LEN];
837
838 super::append(b, _vstprintf(b, fmt, l));
839
840 return *this;
841 }
842 };
843
844 #define _STRING_DEFINED
845
846
847 struct FmtString : public String
848 {
849 FmtString(LPCTSTR fmt, ...)
850 {
851 va_list l;
852
853 va_start(l, fmt);
854 vprintf(fmt, l);
855 va_end(l);
856 }
857 };
858
859
860 #ifdef UNICODE
861
862 struct ANS
863 {
864 ANS(LPCWSTR s)
865 {
866 int l = wcslen(s) + 1;
867 _str = (LPSTR) malloc(2*l);
868
869 if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
870 *_str = '\0';
871 }
872
873 ~ANS()
874 {
875 free(_str);
876 }
877
878 operator LPCSTR() {return _str;}
879
880 protected:
881 LPSTR _str;
882 };
883
884 #define UNC(x) ((LPCWSTR)(x))
885
886 #else
887
888 #define ANS(x) ((LPCSTR)(x))
889
890 struct UNC
891 {
892 UNC(LPCSTR s)
893 {
894 int l = strlen(s) + 1;
895 _str = (LPWSTR) malloc(2*l);
896
897 if (MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
898 *_str = '\0';
899 }
900
901 ~UNC()
902 {
903 free(_str);
904 }
905
906 operator LPCWSTR() {return _str;}
907
908 protected:
909 LPWSTR _str;
910 };
911
912 #endif
913
914
915 // determine windows version string
916 String get_windows_version_str();
917
918
919 /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
920 template<typename FCT> struct DynamicFct
921 {
922 DynamicFct(LPCTSTR moduleName, UINT ordinal)
923 {
924 HMODULE hModule = GetModuleHandle(moduleName);
925
926 _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
927 }
928
929 DynamicFct(LPCTSTR moduleName, LPCSTR name)
930 {
931 HMODULE hModule = GetModuleHandle(moduleName);
932
933 _fct = (FCT) GetProcAddress(hModule, name);
934 }
935
936 FCT operator*() const {return _fct;}
937 operator bool() const {return _fct? true: false;}
938
939 protected:
940 FCT _fct;
941 };
942
943
944 /// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
945 template<typename FCT> struct DynamicLoadLibFct
946 {
947 DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
948 {
949 _hModule = LoadLibrary(moduleName);
950
951 _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
952 }
953
954 DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
955 {
956 _hModule = LoadLibrary(moduleName);
957
958 _fct = (FCT) GetProcAddress(_hModule, name);
959 }
960
961 ~DynamicLoadLibFct()
962 {
963 FreeLibrary(_hModule);
964 }
965
966 FCT operator*() const {return _fct;}
967 operator bool() const {return _fct? true: false;}
968
969 protected:
970 HMODULE _hModule;
971 FCT _fct;
972 };
973
974
975 struct Context
976 {
977 Context(const char* ctx)
978 : _ctx(ctx)
979 {
980 _last = s_current;
981 s_current = this;
982 }
983
984 Context(const char* ctx, LPCSTR obj)
985 : _ctx(ctx),
986 _obj(obj)
987 {
988 _last = s_current;
989 s_current = this;
990 }
991
992 Context(const char* ctx, LPCWSTR obj)
993 : _ctx(ctx),
994 _obj(obj)
995 {
996 _last = s_current;
997 s_current = this;
998 }
999
1000 Context(const Context& other)
1001 : _ctx(other._ctx),
1002 _obj(other._obj)
1003 {
1004 _last = NULL;
1005 }
1006
1007 ~Context()
1008 {
1009 if (_last) {
1010 s_current = _last;
1011 _last = NULL;
1012 }
1013 }
1014
1015 String toString() const;
1016 String getStackTrace() const;
1017
1018 const char* _ctx;
1019 String _obj;
1020
1021 static Context& current() {return *s_current;}
1022
1023 protected:
1024 Context* _last;
1025
1026 static Context* s_current; ///@todo use TLS
1027 static Context s_main;
1028 };
1029
1030 #define CONTEXT_OBJ __ctx__._obj
1031 #define CONTEXT(c) Context __ctx__(c)
1032 #define CURRENT_CONTEXT Context::current()
1033 #define OBJ_CONTEXT(c, o) Context __ctx__(c, o)
1034
1035
1036 extern bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out);
1037
1038
1039 #endif // __cplusplus