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 { 277 WaitCursor() 278 { 279 _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT)); 280 } 281 282 ~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) 296 : _hwnd(hwnd) {} 297 298 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 { 309 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 316 ~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 { 328 CritSect() 329 { 330 InitializeCriticalSection(this); 331 } 332 333 ~CritSect() 334 { 335 DeleteCriticalSection(this); 336 } 337 }; 338 339 340 /// Lock protects a code section utilizing a critical section 341 342 struct Lock 343 { 344 Lock(CritSect& crit_sect) 345 : _crit_sect(crit_sect) 346 { 347 EnterCriticalSection(&crit_sect); 348 } 349 350 ~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 { 364 Thread() 365 : _alive(false), 366 _destroy(false) 367 { 368 _hThread = INVALID_HANDLE_VALUE; 369 _evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL); 370 } 371 372 virtual ~Thread() 373 { 374 Stop(); 375 376 CloseHandle(_evtFinish); 377 CloseHandle(_hThread); 378 379 if (_destroy) 380 delete this; 381 } 382 383 void Start() 384 { 385 if (!_alive) { 386 _alive = true; 387 _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL); 388 } 389 } 390 391 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 408 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 { 427 ClientRect(HWND hwnd) 428 { 429 GetClientRect(hwnd, this); 430 } 431 432 operator LPRECT() {return this;} 433 434 POINT& pos() {return *(LPPOINT)this;} 435 }; 436 437 /// ClientRect retreives the window rectangle of a window. 438 struct WindowRect : public RECT 439 { 440 WindowRect(HWND hwnd) 441 { 442 GetWindowRect(hwnd, this); 443 } 444 445 operator LPRECT() {return this;} 446 447 POINT& pos() {return *(LPPOINT)this;} 448 }; 449 450 /// PointL encapsulates the POINT structure into a C++ object. 451 struct Point : public POINT 452 { 453 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 460 Point(LPARAM lparam) 461 { 462 x = GET_X_LPARAM(lparam); 463 y = GET_Y_LPARAM(lparam); 464 } 465 466 operator LPPOINT() {return this;} 467 }; 468 469 470 /// transform coordinates in a RECT from client to screen coordiantes 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 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 { 482 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 { 498 PaintCanvas(HWND hwnd) 499 : _hwnd(hwnd) 500 { 501 BeginPaint(hwnd, this); 502 } 503 504 ~PaintCanvas() 505 { 506 EndPaint(_hwnd, this); 507 } 508 509 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 { 518 Canvas(HDC hdc) : _hdc(hdc) {} 519 520 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 { 529 WindowCanvas(HWND hwnd) 530 : Canvas(GetDC(hwnd)), _hwnd(hwnd) {} 531 532 ~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) 545 : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);} 546 547 ~MemCanvas() {DeleteDC(_hdc);} 548 }; 549 550 /// SelectedBitmap is used to localy select bitmaps into device contexts. 551 struct SelectedBitmap 552 { 553 SelectedBitmap(HDC hdc, HBITMAP hbmp) 554 : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {} 555 556 ~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 { 566 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 571 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) 586 : BufferCanvas(hdc, x, y, w, h), _mode(mode) {} 587 588 BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY) 589 : BufferCanvas(hdc, rect), _mode(mode) {} 590 591 ~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 { 599 BufferedPaintCanvas(HWND hwnd) 600 : PaintCanvas(hwnd), 601 BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom) 602 { 603 } 604 605 operator HDC() {return BufferedCanvas::_hdc;} 606 }; 607 608 609 /// TextColor locally selects a text color for drawing. 610 struct TextColor 611 { 612 TextColor(HDC hdc, COLORREF color) 613 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {} 614 615 ~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 { 625 BkMode(HDC hdc, int bkmode) 626 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {} 627 628 ~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 { 638 FontSelection(HDC hdc, HFONT hFont) 639 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {} 640 641 ~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 { 651 BitmapSelection(HDC hdc, HBITMAP hBmp) 652 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {} 653 654 ~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 { 664 BrushSelection(HDC hdc, HBRUSH hBrush) 665 : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {} 666 667 ~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 { 678 PopupMenu() 679 : _hmenu(CreatePopupMenu()) 680 { 681 } 682 683 ~PopupMenu() 684 { 685 DestroyMenu(_hmenu); 686 } 687 688 PopupMenu(UINT nid); 689 690 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 { 732 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 { 746 BStr() 747 { 748 _p = NULL; 749 } 750 751 BStr(const BSTR s) 752 { 753 _p = SysAllocString(s); 754 } 755 756 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 766 BStr(LPCWSTR s) 767 { 768 _p = SysAllocString(s); 769 } 770 771 BStr(const VARIANT& var) 772 : _p(NULL) 773 { 774 assign(var); 775 } 776 777 ~BStr() 778 { 779 SysFreeString(_p); 780 } 781 782 void assign(BSTR s); 783 void assign(const VARIANT& var); 784 785 operator BSTR() const 786 { 787 return _p? _p: (BSTR)L""; 788 } 789 790 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 814 String() {} 815 816 String(LPCTSTR s) {if (s) super::assign(s);} 817 String(LPCTSTR s, int l) : super(s, l) {} 818 819 String(const super& other) : super(other) {} 820 String(const String& other) : super(other) {} 821 822 #ifdef UNICODE 823 String(LPCSTR s) {assign(s);} 824 String(LPCSTR s, int l) {assign(s, l);} 825 String(const string& other) {assign(other.c_str());} 826 String& operator=(LPCSTR s) {assign(s); return *this;} 827 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();} 828 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();} 829 void assign(const BStr& s) {int l = s.length(); super::assign(s, l);} 830 #else 831 String(LPCWSTR s) {assign(s);} 832 String(LPCWSTR s, int l) {assign(s, l);} 833 String(const wstring& other) {assign(other.c_str());} 834 String& operator=(LPCWSTR s) {assign(s); return *this;} 835 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();} 836 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();} 837 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 839 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;} 844 void assign(LPCTSTR s) {super::assign(s);} 845 void assign(LPCTSTR s, int l) {super::assign(s, l);} 846 847 operator LPCTSTR() const {return c_str();} 848 849 #ifdef UNICODE 850 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 852 operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);} 853 #endif 854 855 LPTSTR str() {return (LPTSTR)data();} /// return modifyable character string pointer 856 857 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 869 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 878 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 890 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 899 void toLower() 900 { 901 if (!empty()) 902 CharLower(str()); 903 } 904 }; 905 906 #define _STRING_DEFINED 907 908 909 struct FmtString : public String 910 { 911 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 { 926 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 935 ~ANS() 936 { 937 free(_str); 938 } 939 940 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 { 954 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 963 ~UNC() 964 { 965 free(_str); 966 } 967 968 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 { 984 DynamicFct(LPCTSTR moduleName, UINT ordinal) 985 { 986 HMODULE hModule = GetModuleHandle(moduleName); 987 988 _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal); 989 } 990 991 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 { 1009 DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal) 1010 { 1011 _hModule = LoadLibrary(moduleName); 1012 1013 _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal); 1014 } 1015 1016 DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name) 1017 { 1018 _hModule = LoadLibrary(moduleName); 1019 1020 _fct = (FCT) GetProcAddress(_hModule, name); 1021 } 1022 1023 ~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 { 1039 Context(const char* ctx) 1040 : _ctx(ctx) 1041 { 1042 _last = s_current; 1043 s_current = this; 1044 } 1045 1046 Context(const char* ctx, LPCSTR obj) 1047 : _ctx(ctx), 1048 _obj(obj) 1049 { 1050 _last = s_current; 1051 s_current = this; 1052 } 1053 1054 Context(const char* ctx, LPCWSTR obj) 1055 : _ctx(ctx), 1056 _obj(obj) 1057 { 1058 _last = s_current; 1059 s_current = this; 1060 } 1061 1062 Context(const Context& other) 1063 : _ctx(other._ctx), 1064 _obj(other._obj) 1065 { 1066 _last = NULL; 1067 } 1068 1069 ~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 1083 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