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