Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5793 lines
105 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Wrappers.h
  5. Abstract:
  6. Contains some commonly used macros, inline utility functions and
  7. wrapper/helper classes
  8. Author:
  9. Hakki T. Bostanci (hakkib) 06-Apr-2000
  10. Revision History:
  11. --*/
  12. #ifndef _WRAPPERS_H_
  13. #define _WRAPPERS_H_
  14. //////////////////////////////////////////////////////////////////////////
  15. //
  16. // Cross references
  17. //
  18. #include <assert.h>
  19. #include "Conv.h"
  20. #include "Result.h"
  21. //////////////////////////////////////////////////////////////////////////
  22. //
  23. //
  24. //
  25. #ifndef ASSERT
  26. #define ASSERT assert
  27. #endif
  28. typedef CONST TCHAR *PCTSTR;
  29. #if !defined(NDEBUG) || defined(_DEBUG) || defined(DBG)
  30. #ifndef DEBUG
  31. #define DEBUG
  32. #endif //DEBUG
  33. #endif
  34. #ifdef DEBUG
  35. #define IFDEBUG(Statement) Statement
  36. #else //DEBUG
  37. #define IFDEBUG(Statement)
  38. #endif //DEBUG
  39. //////////////////////////////////////////////////////////////////////////
  40. //
  41. // COUNTOF
  42. //
  43. // Returns the number of elements in an array
  44. //
  45. #define COUNTOF(array) ( sizeof(array) / sizeof(array[0]) )
  46. //////////////////////////////////////////////////////////////////////////
  47. //
  48. // STRING
  49. //
  50. // Stringizing operator
  51. //
  52. #define STRING(arg) #arg
  53. //////////////////////////////////////////////////////////////////////////
  54. //
  55. // DISABLE_COPY_CONTRUCTION
  56. //
  57. // Declares copy construction operators as private to prevent outside access
  58. //
  59. #define DISABLE_COPY_CONTRUCTION(Class) \
  60. private: \
  61. Class(const Class&) { } \
  62. Class& operator =(const Class&) { return *this; } \
  63. //////////////////////////////////////////////////////////////////////////
  64. //
  65. // IS_NT
  66. //
  67. // Returns true on an NT based OS
  68. //
  69. #define IS_NT ( GetVersion() < 0x80000000 )
  70. //////////////////////////////////////////////////////////////////////////
  71. //
  72. // LONG_PATH
  73. //
  74. // Returns the \\?\ string (that can be used in file APIs) in UNICODE builds
  75. //
  76. #ifdef UNICODE
  77. #define LONG_PATH L"\\\\?\\"
  78. #else //UNICODE
  79. #define LONG_PATH
  80. #endif //UNICODE
  81. //////////////////////////////////////////////////////////////////////////
  82. //
  83. // AW, _AW
  84. //
  85. // Append a 'W' or 'A' depending on UNICODE or ANSI builds
  86. //
  87. #ifdef UNICODE
  88. #define AW(name) name##W
  89. #define _AW "W"
  90. #else //UNICODE
  91. #define AW(name) name##A
  92. #define _AW "A"
  93. #endif //UNICODE
  94. //////////////////////////////////////////////////////////////////////////
  95. //
  96. // IGNORE_EXCEPTIONS
  97. //
  98. // Ignores any exceptions thrown from the code block
  99. //
  100. #define IGNORE_EXCEPTIONS(Statement) try { Statement; } catch (...) {}
  101. //////////////////////////////////////////////////////////////////////////
  102. //
  103. // WAIT_AND_RETRY_ON_EXCEPTION
  104. //
  105. // Pauses and retries if an exception is thrown from the code block
  106. //
  107. #define WAIT_AND_RETRY_ON_EXCEPTION(func, nRetries, nWaitTime) \
  108. { \
  109. int nTrials = nRetries; \
  110. \
  111. while (1) \
  112. { \
  113. try \
  114. { \
  115. func; \
  116. break; \
  117. } \
  118. catch (...) \
  119. { \
  120. if (nTrials-- == 0) \
  121. { \
  122. throw; \
  123. } \
  124. \
  125. Sleep(nWaitTime); \
  126. } \
  127. } \
  128. } \
  129. //////////////////////////////////////////////////////////////////////////
  130. //
  131. // Abs
  132. //
  133. // Returns the absolute value of the variable
  134. //
  135. template <class T>
  136. inline const T Abs(const T& x)
  137. {
  138. return x < 0 ? -x : x;
  139. }
  140. //////////////////////////////////////////////////////////////////////////
  141. //
  142. // Sqr
  143. //
  144. // Returns x^2
  145. //
  146. template <class T>
  147. inline const T Sqr(const T& x)
  148. {
  149. return x * x;
  150. }
  151. //////////////////////////////////////////////////////////////////////////
  152. //
  153. // Cube
  154. //
  155. // Returns x^3
  156. //
  157. template <class T>
  158. inline const T Cube(const T& x)
  159. {
  160. return x * x * x;
  161. }
  162. //////////////////////////////////////////////////////////////////////////
  163. //
  164. // Swap
  165. //
  166. // Swaps the values of two variables
  167. //
  168. template <class T>
  169. inline void Swap(T& x, T& y)
  170. {
  171. T temp = x;
  172. x = y;
  173. y = temp;
  174. }
  175. //////////////////////////////////////////////////////////////////////////
  176. //
  177. // Min
  178. //
  179. // Returns the smaller of the two variables (based on "<" operator)
  180. //
  181. template <class T>
  182. inline const T Min(const T& x, const T& y)
  183. {
  184. return x < y ? x : y;
  185. }
  186. //////////////////////////////////////////////////////////////////////////
  187. //
  188. // Max
  189. //
  190. // Returns the larger of the two variables (based on "<" operator)
  191. //
  192. template <class T>
  193. inline const T Max(const T& x, const T& y)
  194. {
  195. return x < y ? y : x;
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. //
  199. // Cmp
  200. //
  201. // Compares two variables (based on "==" and "<" operators)
  202. //
  203. template <class T>
  204. inline int Cmp(const T& x, const T& y)
  205. {
  206. return x == y ? 0 : x < y ? -1 : 1;
  207. }
  208. //////////////////////////////////////////////////////////////////////////
  209. //
  210. // StructCmp
  211. //
  212. // Compares two structs byte by byte
  213. //
  214. template <class T>
  215. inline int StructCmp(const T *x, const T *y)
  216. {
  217. return memcmp(x, y, sizeof(T));
  218. }
  219. //////////////////////////////////////////////////////////////////////////
  220. //
  221. // CopyData
  222. //
  223. // Copies a number of data structures memory from one location to another
  224. // Source and destination blocks should not overlap
  225. //
  226. template <class T>
  227. inline void CopyData(T *x, const T *y, int n)
  228. {
  229. CopyMemory(x, y, n * sizeof(T));
  230. }
  231. //////////////////////////////////////////////////////////////////////////
  232. //
  233. // MoveData
  234. //
  235. // Copies a number of data structures memory from one location to another
  236. // Source and destination blocks may overlap
  237. //
  238. template <class T>
  239. inline void MoveData(T *x, const T *y, int n)
  240. {
  241. MoveMemory(x, y, n * sizeof(T));
  242. }
  243. //////////////////////////////////////////////////////////////////////////
  244. //
  245. // IsEqual
  246. //
  247. // Returns true if the two comperands are equal
  248. //
  249. template <class T>
  250. inline BOOL IsEqual(T lhs, T rhs)
  251. {
  252. return lhs == rhs;
  253. }
  254. template <class T>
  255. inline BOOL IsEqual(const T *lhs, const T *rhs)
  256. {
  257. return *lhs == *rhs;
  258. }
  259. template <>
  260. inline BOOL IsEqual(const CHAR *lhs, const CHAR *rhs)
  261. {
  262. return strcmp(lhs, rhs) == 0;
  263. }
  264. template <>
  265. inline BOOL IsEqual(const WCHAR *lhs, const WCHAR *rhs)
  266. {
  267. return wcscmp(lhs, rhs) == 0;
  268. }
  269. //////////////////////////////////////////////////////////////////////////
  270. //
  271. // CharLower
  272. //
  273. // Converts a single character to lowercase
  274. //
  275. inline TCHAR CharLower(TCHAR c)
  276. {
  277. return (TCHAR) CharLower((PTSTR) c);
  278. }
  279. //////////////////////////////////////////////////////////////////////////
  280. //
  281. // CharUpper
  282. //
  283. // Converts a single character to uppercase
  284. //
  285. inline TCHAR CharUpper(TCHAR c)
  286. {
  287. return (TCHAR) CharUpper((PTSTR) c);
  288. }
  289. //////////////////////////////////////////////////////////////////////////
  290. //
  291. // _tcssafecmp
  292. //
  293. // Compares two strings (that can be null)
  294. //
  295. inline int strsafecmp(PCSTR psz1, PCSTR psz2)
  296. {
  297. return psz1 != 0 ? (psz2 != 0 ? strcmp(psz1, psz2) : 1) : (psz2 != 0 ? -1 : 0);
  298. }
  299. inline int wcssafecmp(PCWSTR psz1, PCWSTR psz2)
  300. {
  301. return psz1 != 0 ? (psz2 != 0 ? wcscmp(psz1, psz2) : 1) : (psz2 != 0 ? -1 : 0);
  302. }
  303. #ifdef UNICODE
  304. #define _tcssafecmp wcssafecmp
  305. #else //UNICODE
  306. #define _tcssafecmp strsafecmp
  307. #endif //UNICODE
  308. //////////////////////////////////////////////////////////////////////////
  309. //
  310. // multiszlen
  311. //
  312. // Returns the length of a null terminated list of null terminated strings
  313. //
  314. inline size_t multiszlenA(PCSTR pszzStr)
  315. {
  316. PCSTR pszStr = pszzStr;
  317. if (pszStr)
  318. {
  319. while (*pszStr)
  320. {
  321. pszStr += strlen(pszStr) + 1;
  322. }
  323. }
  324. return pszStr - pszzStr;
  325. }
  326. inline size_t multiszlenW(PCWSTR pwszzStr)
  327. {
  328. PCWSTR pwszStr = pwszzStr;
  329. if (pwszStr)
  330. {
  331. while (*pwszStr)
  332. {
  333. pwszStr += wcslen(pwszStr) + 1;
  334. }
  335. }
  336. return pwszStr - pwszzStr;
  337. }
  338. #ifdef UNICODE
  339. #define multiszlen multiszlenW
  340. #else //UNICODE
  341. #define multiszlen multiszlenA
  342. #endif //UNICODE
  343. //////////////////////////////////////////////////////////////////////////
  344. //
  345. // FindFileNamePortion
  346. //
  347. // Returns a pointer to the file name portion of a full path name
  348. //
  349. inline PSTR FindFileNamePortionA(PCSTR pPathName)
  350. {
  351. PCSTR pFileName = pPathName ? strrchr(pPathName, '\\') : 0;
  352. return const_cast<PSTR>(pFileName ? pFileName + 1 : pPathName);
  353. }
  354. inline PWSTR FindFileNamePortionW(PCWSTR pPathName)
  355. {
  356. PCWSTR pFileName = pPathName ? wcsrchr(pPathName, '\\') : 0;
  357. return const_cast<PWSTR>(pFileName ? pFileName + 1 : pPathName);
  358. }
  359. #ifdef UNICODE
  360. #define FindFileNamePortion FindFileNamePortionW
  361. #else //UNICODE
  362. #define FindFileNamePortion FindFileNamePortionA
  363. #endif //UNICODE
  364. //////////////////////////////////////////////////////////////////////////
  365. //
  366. // FindEol
  367. //
  368. // Finds the first end-of-line character in a string
  369. //
  370. inline PTSTR FindEol(PCTSTR pStr)
  371. {
  372. while (*pStr != '\0' && *pStr != '\r' && *pStr != '\n')
  373. {
  374. pStr = CharNext(pStr);
  375. }
  376. return const_cast<PTSTR>(pStr);
  377. }
  378. #ifdef _SHLOBJ_H_
  379. //////////////////////////////////////////////////////////////////////////
  380. //
  381. // SHFree
  382. //
  383. // Frees a block of memory allocated through shell's IMalloc interface
  384. //
  385. inline void SHFree(PVOID pVoid)
  386. {
  387. LPMALLOC pMalloc;
  388. SHGetMalloc(&pMalloc);
  389. pMalloc->Free(pVoid);
  390. pMalloc->Release();
  391. }
  392. #endif //_SHLOBJ_H_
  393. //////////////////////////////////////////////////////////////////////////
  394. //
  395. // WriteConsole
  396. //
  397. // Writes a character string to a console screen
  398. //
  399. inline BOOL WriteConsole(PCTSTR pStr, DWORD nStdHandle = STD_OUTPUT_HANDLE)
  400. {
  401. DWORD dwNumWritten;
  402. return WriteConsole(
  403. GetStdHandle(nStdHandle),
  404. pStr,
  405. _tcslen(pStr),
  406. &dwNumWritten,
  407. 0
  408. );
  409. }
  410. #ifdef _INC_STDLIB
  411. //////////////////////////////////////////////////////////////////////////
  412. //
  413. // GetEnvironmentInt
  414. //
  415. // Retrieves the value of the specified variable from the environment block
  416. //
  417. inline BOOL GetEnvironmentInt(PCTSTR pName, PINT piValue)
  418. {
  419. TCHAR szValue[48];
  420. DWORD dwResult = GetEnvironmentVariable(pName, szValue, COUNTOF(szValue));
  421. if (dwResult > 0 && dwResult < COUNTOF(szValue))
  422. {
  423. if (piValue == 0)
  424. {
  425. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  426. return FALSE;
  427. }
  428. *piValue = _ttoi(szValue);
  429. return TRUE;
  430. }
  431. return FALSE;
  432. }
  433. #endif //_INC_STDLIB
  434. #ifdef _INC_STDIO
  435. //////////////////////////////////////////////////////////////////////////
  436. //
  437. // _tcsdupc
  438. //
  439. // Duplicates a string to a buffer allocated by new []
  440. //
  441. inline PTSTR _tcsdupc(PCTSTR pStrSource)
  442. {
  443. if (!pStrSource)
  444. {
  445. pStrSource = _T("");
  446. }
  447. PTSTR pStrDest = new TCHAR[_tcslen(pStrSource) + 1];
  448. if (pStrDest)
  449. {
  450. _tcscpy(pStrDest, pStrSource);
  451. }
  452. return pStrDest;
  453. }
  454. //////////////////////////////////////////////////////////////////////////
  455. //
  456. // bufvprintf, bufprintf
  457. //
  458. // Writes a printf style formatted string to a buffer allocated by new []
  459. //
  460. inline PTSTR bufvprintf(PCTSTR format, va_list arglist)
  461. {
  462. PTSTR pBuffer = 0;
  463. for (
  464. size_t nBufferSize = 1024;
  465. (pBuffer = new TCHAR[nBufferSize]) != 0 &&
  466. _vsntprintf(pBuffer, nBufferSize, format, arglist) < 0;
  467. delete [] pBuffer, nBufferSize *= 2
  468. )
  469. {
  470. // start with a 1KB buffer size
  471. // if buffer allocation fails, exit
  472. // if _vsntprintf succeeds, exit
  473. // otherwise, delete the buffer and retry with double size
  474. }
  475. return pBuffer;
  476. }
  477. inline PTSTR __cdecl bufprintf(PCTSTR format, ...)
  478. {
  479. va_list arglist;
  480. va_start(arglist, format);
  481. return bufvprintf(format, arglist);
  482. }
  483. //////////////////////////////////////////////////////////////////////////
  484. //
  485. // TextOutF
  486. //
  487. // Writes a printf style formatted string to the DC
  488. //
  489. inline BOOL __cdecl TextOutF(HDC hDC, int nX, int nY, PCTSTR format, ...)
  490. {
  491. va_list arglist;
  492. va_start(arglist, format);
  493. BOOL bResult = FALSE;
  494. PTSTR pStr = bufvprintf(format, arglist);
  495. if (pStr)
  496. {
  497. bResult = TextOut(hDC, nX, nY, pStr, _tcslen(pStr));
  498. delete [] pStr;
  499. }
  500. return bResult;
  501. }
  502. //////////////////////////////////////////////////////////////////////////
  503. //
  504. // OutputDebugStringF
  505. //
  506. // Outputs a printf style formatted string to the debug console
  507. //
  508. inline void __cdecl OutputDebugStringF(PCTSTR format, ...)
  509. {
  510. va_list arglist;
  511. va_start(arglist, format);
  512. PTSTR pStr = bufvprintf(format, arglist);
  513. if (pStr)
  514. {
  515. OutputDebugString(pStr);
  516. delete [] pStr;
  517. }
  518. va_end(arglist);
  519. }
  520. #ifdef DEBUG
  521. #define DEBUGMSG(x) OutputDebugString(x)
  522. #define DEBUGMSGF(x) OutputDebugStringF x
  523. #else //DEBUG
  524. #define DEBUGMSG(x)
  525. #define DEBUGMSGF(x)
  526. #endif //DEBUG
  527. //////////////////////////////////////////////////////////////////////////
  528. //
  529. // IsChildWindow
  530. //
  531. // Determines whether the second hWnd is a child of the first
  532. //
  533. inline BOOL IsChildWindow(HWND hWndParent, HWND hWnd)
  534. {
  535. while (hWnd)
  536. {
  537. hWnd = GetParent(hWnd);
  538. if (hWnd == hWndParent)
  539. {
  540. return TRUE;
  541. }
  542. }
  543. return FALSE;
  544. }
  545. #endif //_INC_STDIO
  546. #if defined(_INC_IO) && defined(_INC_FCNTL)
  547. //////////////////////////////////////////////////////////////////////////
  548. //
  549. // OpenOSHandle
  550. //
  551. // Associates a stream with an operating-system file handle
  552. //
  553. inline FILE *OpenOSHandle(HANDLE osfhandle, int flags, PCTSTR mode)
  554. {
  555. int hCrt = _open_osfhandle((intptr_t) osfhandle, flags);
  556. return hCrt ? _tfdopen(hCrt, mode) : 0;
  557. }
  558. //////////////////////////////////////////////////////////////////////////
  559. //
  560. // OpenStdHandle
  561. //
  562. // Assigns a stream to an operating-system file handle for standard I/O
  563. //
  564. inline void OpenStdHandle(HANDLE osfhandle, FILE *stream, PCTSTR mode)
  565. {
  566. *stream = *OpenOSHandle(osfhandle, _O_TEXT, mode);
  567. setvbuf(stream, 0, _IONBF, 0);
  568. }
  569. //////////////////////////////////////////////////////////////////////////
  570. //
  571. // AllocCRTConsole
  572. //
  573. // Allocates a new console and associates standard handles with this console
  574. //
  575. inline void AllocCRTConsole()
  576. {
  577. if (AllocConsole())
  578. {
  579. OpenStdHandle(GetStdHandle(STD_INPUT_HANDLE), stdin, _T("r"));
  580. OpenStdHandle(GetStdHandle(STD_OUTPUT_HANDLE), stdout, _T("w"));
  581. OpenStdHandle(GetStdHandle(STD_ERROR_HANDLE), stderr, _T("w"));
  582. }
  583. }
  584. #endif //defined(_INC_IO) && defined(_INC_FCNTL)
  585. #ifdef _INC_COMMCTRL
  586. //////////////////////////////////////////////////////////////////////////
  587. //
  588. // ListView_InsertColumn2
  589. //
  590. // Inserts a new column in a list view control
  591. //
  592. inline
  593. int
  594. ListView_InsertColumn2(
  595. HWND hWnd,
  596. int nCol,
  597. PCTSTR pszColumnHeading,
  598. int nFormat,
  599. int nWidth,
  600. int nSubItem
  601. )
  602. {
  603. LVCOLUMN column;
  604. column.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH|LVCF_SUBITEM;
  605. column.pszText = (PTSTR) pszColumnHeading;
  606. column.fmt = nFormat;
  607. column.cx = nWidth;
  608. column.iSubItem = nSubItem;
  609. return ListView_InsertColumn(hWnd, nCol, &column);
  610. }
  611. //////////////////////////////////////////////////////////////////////////
  612. //
  613. // ListView_GetItemData
  614. //
  615. // Returns the lParam value associated with a list view item
  616. //
  617. inline
  618. LPARAM
  619. ListView_GetItemData(HWND hWnd, int nItem)
  620. {
  621. LVITEM item;
  622. item.mask = LVIF_PARAM;
  623. item.iItem = nItem;
  624. item.iSubItem = 0;
  625. item.lParam = 0;
  626. ListView_GetItem(hWnd, &item);
  627. return item.lParam;
  628. }
  629. //////////////////////////////////////////////////////////////////////////
  630. //
  631. // ListView_GetItemData
  632. //
  633. // Sets the lParam value associated with a list view item
  634. //
  635. inline
  636. BOOL
  637. ListView_SetItemData(HWND hWnd, int nItem, LPARAM lParam)
  638. {
  639. LVITEM item;
  640. item.mask = LVIF_PARAM;
  641. item.iItem = nItem;
  642. item.iSubItem = 0;
  643. item.lParam = lParam;
  644. return ListView_SetItem(hWnd, &item);
  645. }
  646. //////////////////////////////////////////////////////////////////////////
  647. //
  648. // operator ==, operator !=
  649. //
  650. // Compares two TVITEM structs based on their contents
  651. //
  652. inline bool operator ==(const TVITEM &lhs, const TVITEM &rhs)
  653. {
  654. UINT mask = lhs.mask;
  655. return
  656. mask == rhs.mask &&
  657. (!(mask & TVIF_HANDLE) || lhs.hItem == rhs.hItem) &&
  658. (!(mask & TVIF_STATE) || (lhs.state == rhs.state && lhs.stateMask == rhs.stateMask)) &&
  659. (!(mask & TVIF_TEXT) || (lhs.pszText == rhs.pszText && lhs.cchTextMax == rhs.cchTextMax)) &&
  660. (!(mask & TVIF_IMAGE) || lhs.iImage == rhs.iImage) &&
  661. (!(mask & TVIF_SELECTEDIMAGE) || lhs.iSelectedImage == rhs.iSelectedImage) &&
  662. (!(mask & TVIF_CHILDREN) || lhs.cChildren == rhs.cChildren) &&
  663. (!(mask & TVIF_PARAM) || lhs.lParam == rhs.lParam);
  664. }
  665. inline bool operator !=(const TVITEM &lhs, const TVITEM &rhs)
  666. {
  667. return !(lhs == rhs);
  668. }
  669. #endif //_INC_COMMCTRL
  670. //////////////////////////////////////////////////////////////////////////
  671. //
  672. // ResizeDlgItem
  673. //
  674. // Changes the relative position and size of a dialog item
  675. //
  676. inline
  677. BOOL
  678. ResizeDlgItem(
  679. HWND hWnd,
  680. HWND hDlgItem,
  681. int dX,
  682. int dY,
  683. int dW,
  684. int dH,
  685. BOOL bRepaint = TRUE
  686. )
  687. {
  688. RECT r;
  689. return
  690. GetWindowRect(hDlgItem, &r) &&
  691. ScreenToClient(hWnd, (PPOINT) &r.left) &&
  692. ScreenToClient(hWnd, (PPOINT) &r.right) &&
  693. MoveWindow(
  694. hDlgItem,
  695. r.left + dX,
  696. r.top + dY,
  697. r.right - r.left + dW,
  698. r.bottom - r.top + dH,
  699. bRepaint
  700. );
  701. }
  702. //////////////////////////////////////////////////////////////////////////
  703. //
  704. // CLargeInteger
  705. //
  706. class CLargeInteger // union cannot be used as a base class
  707. {
  708. public:
  709. CLargeInteger(
  710. DWORD LowPart,
  711. LONG HighPart
  712. )
  713. {
  714. m_Int.LowPart = LowPart;
  715. m_Int.HighPart = HighPart;
  716. }
  717. CLargeInteger(
  718. LONGLONG QuadPart
  719. )
  720. {
  721. m_Int.QuadPart = QuadPart;
  722. }
  723. CLargeInteger(
  724. const LARGE_INTEGER& rhs
  725. )
  726. {
  727. m_Int.QuadPart = rhs.QuadPart;
  728. }
  729. LARGE_INTEGER * operator &()
  730. {
  731. return &m_Int;
  732. }
  733. const LARGE_INTEGER * operator &() const
  734. {
  735. return &m_Int;
  736. }
  737. operator LONGLONG&()
  738. {
  739. return m_Int.QuadPart;
  740. }
  741. operator const LONGLONG&() const
  742. {
  743. return m_Int.QuadPart;
  744. }
  745. private:
  746. LARGE_INTEGER m_Int;
  747. };
  748. //////////////////////////////////////////////////////////////////////////
  749. //
  750. // CULargeInteger
  751. //
  752. class CULargeInteger // union cannot be used as a base class
  753. {
  754. public:
  755. CULargeInteger(
  756. DWORD LowPart,
  757. DWORD HighPart
  758. )
  759. {
  760. m_Int.LowPart = LowPart;
  761. m_Int.HighPart = HighPart;
  762. }
  763. CULargeInteger(
  764. ULONGLONG QuadPart
  765. )
  766. {
  767. m_Int.QuadPart = QuadPart;
  768. }
  769. CULargeInteger(
  770. const ULARGE_INTEGER& rhs
  771. )
  772. {
  773. m_Int.QuadPart = rhs.QuadPart;
  774. }
  775. ULARGE_INTEGER * operator &()
  776. {
  777. return &m_Int;
  778. }
  779. const ULARGE_INTEGER * operator &() const
  780. {
  781. return &m_Int;
  782. }
  783. operator ULONGLONG&()
  784. {
  785. return m_Int.QuadPart;
  786. }
  787. operator const ULONGLONG&() const
  788. {
  789. return m_Int.QuadPart;
  790. }
  791. private:
  792. ULARGE_INTEGER m_Int;
  793. };
  794. //////////////////////////////////////////////////////////////////////////
  795. //
  796. // CFileTime
  797. //
  798. class CFileTime : public FILETIME
  799. {
  800. public:
  801. CFileTime()
  802. {
  803. }
  804. CFileTime(ULONGLONG Value)
  805. {
  806. ((ULARGE_INTEGER *)this)->QuadPart = Value;
  807. }
  808. };
  809. //////////////////////////////////////////////////////////////////////////
  810. //
  811. // CHandle
  812. //
  813. // Base class that handles reference counting
  814. //
  815. template <class T, class Child>
  816. class CHandle
  817. {
  818. public:
  819. CHandle()
  820. {
  821. m_pNext = 0;
  822. }
  823. explicit CHandle(const T &Value)
  824. {
  825. m_pNext = 0;
  826. Attach(Value);
  827. }
  828. CHandle(CHandle &rhs)
  829. {
  830. m_pNext = 0;
  831. Attach(rhs);
  832. }
  833. CHandle & operator =(const T &Value)
  834. {
  835. Detach();
  836. Attach(Value);
  837. return *this;
  838. }
  839. CHandle & operator =(CHandle &rhs)
  840. {
  841. if (&rhs != this)
  842. {
  843. Detach();
  844. Attach(rhs);
  845. }
  846. return *this;
  847. }
  848. ~CHandle()
  849. {
  850. Detach();
  851. }
  852. operator const T &() const
  853. {
  854. return m_Value;
  855. }
  856. // void Destroy()
  857. // {
  858. // must be defined in the derived class
  859. // }
  860. // bool IsValid()
  861. // {
  862. // must be defined in the derived class
  863. // }
  864. void Attach(const T &Value)
  865. {
  866. ASSERT(!IsAttached());
  867. m_Value = Value;
  868. CHECK(((Child *)this)->IsValid());
  869. m_pNext = this;
  870. m_pPrev = this;
  871. }
  872. void Attach(CHandle &rhs)
  873. {
  874. ASSERT(!IsAttached());
  875. if (rhs.IsAttached())
  876. {
  877. m_Value = rhs.m_Value;
  878. m_pPrev = &rhs;
  879. m_pNext = rhs.m_pNext;
  880. m_pPrev->m_pNext = this;
  881. m_pNext->m_pPrev = this;
  882. }
  883. }
  884. void Detach()
  885. {
  886. if (IsLastReference())
  887. {
  888. ((Child *)this)->Destroy();
  889. m_pNext = 0;
  890. }
  891. else
  892. {
  893. Unlink();
  894. }
  895. }
  896. void Unlink()
  897. {
  898. if (IsAttached())
  899. {
  900. m_pPrev->m_pNext = m_pNext;
  901. m_pNext->m_pPrev = m_pPrev;
  902. m_pNext = 0;
  903. }
  904. }
  905. bool IsLastReference() const
  906. {
  907. return m_pNext == this;
  908. }
  909. bool IsAttached() const
  910. {
  911. return m_pNext != 0;
  912. }
  913. private:
  914. T m_Value;
  915. CHandle *m_pNext;
  916. CHandle *m_pPrev;
  917. };
  918. //////////////////////////////////////////////////////////////////////////
  919. //
  920. // CKernelObject
  921. //
  922. // Base class for kernel objects that can be destroyed with CloseHandle()
  923. //
  924. template <class Child>
  925. class CKernelObject : public CHandle<HANDLE, Child>
  926. {
  927. typedef CHandle<HANDLE, Child> parent_type;
  928. protected:
  929. CKernelObject()
  930. {
  931. }
  932. explicit
  933. CKernelObject(
  934. HANDLE hHandle
  935. ) :
  936. parent_type(hHandle)
  937. {
  938. }
  939. public:
  940. void Destroy()
  941. {
  942. ::CloseHandle(*this);
  943. }
  944. bool IsValid()
  945. {
  946. return *this != 0;
  947. }
  948. DWORD
  949. WaitForSingleObject(
  950. DWORD dwMilliseconds = INFINITE,
  951. BOOL bAlertable = FALSE
  952. ) const
  953. {
  954. return ::WaitForSingleObjectEx(
  955. *this,
  956. dwMilliseconds,
  957. bAlertable
  958. );
  959. }
  960. bool IsSignaled() const
  961. {
  962. return WaitForSingleObject(0) == WAIT_OBJECT_0;
  963. }
  964. };
  965. //////////////////////////////////////////////////////////////////////////
  966. //
  967. // File
  968. //
  969. // Wrapper class for Win32 file handles
  970. //
  971. class File : public CKernelObject<File>
  972. {
  973. public:
  974. File()
  975. {
  976. }
  977. File(
  978. PCTSTR pFileName,
  979. DWORD dwDesiredAccess,
  980. DWORD dwShareMode,
  981. LPSECURITY_ATTRIBUTES pSecurityAttributes,
  982. DWORD dwCreationDisposition,
  983. DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
  984. HANDLE hTemplateFile = 0
  985. ) :
  986. CKernelObject<File>(::CreateFile(
  987. pFileName,
  988. dwDesiredAccess,
  989. dwShareMode,
  990. pSecurityAttributes,
  991. dwCreationDisposition,
  992. dwFlagsAndAttributes,
  993. hTemplateFile
  994. ))
  995. {
  996. }
  997. bool IsValid()
  998. {
  999. return (HANDLE) *this != INVALID_HANDLE_VALUE;
  1000. }
  1001. LARGE_INTEGER
  1002. GetFileSize() const
  1003. {
  1004. LARGE_INTEGER Result;
  1005. Result.LowPart = ::GetFileSize(
  1006. *this,
  1007. (PDWORD) &Result.HighPart
  1008. );
  1009. return Result;
  1010. }
  1011. DWORD
  1012. WriteFile(
  1013. CONST VOID *pBuffer,
  1014. DWORD nNumberOfBytesToWrite,
  1015. LPOVERLAPPED pOverlapped = 0
  1016. ) const
  1017. {
  1018. DWORD dwNumberOfBytesWritten;
  1019. CHECK(::WriteFile(
  1020. *this,
  1021. pBuffer,
  1022. nNumberOfBytesToWrite,
  1023. &dwNumberOfBytesWritten,
  1024. pOverlapped
  1025. ));
  1026. return dwNumberOfBytesWritten;
  1027. }
  1028. DWORD
  1029. ReadFile(
  1030. PVOID pBuffer,
  1031. DWORD nNumberOfBytesToRead,
  1032. LPOVERLAPPED pOverlapped = 0
  1033. ) const
  1034. {
  1035. DWORD dwNumberOfBytesRead;
  1036. CHECK(::ReadFile(
  1037. *this,
  1038. pBuffer,
  1039. nNumberOfBytesToRead,
  1040. &dwNumberOfBytesRead,
  1041. pOverlapped
  1042. ));
  1043. return dwNumberOfBytesRead;
  1044. }
  1045. };
  1046. //////////////////////////////////////////////////////////////////////////
  1047. //
  1048. // CInFile
  1049. //
  1050. // Read only file
  1051. //
  1052. class CInFile : public File
  1053. {
  1054. public:
  1055. CInFile()
  1056. {
  1057. }
  1058. explicit
  1059. CInFile(
  1060. PCTSTR pFileName,
  1061. DWORD dwDesiredAccess = GENERIC_READ,
  1062. DWORD dwShareMode = FILE_SHARE_READ,
  1063. LPSECURITY_ATTRIBUTES pSecurityAttributes = 0,
  1064. DWORD dwCreationDisposition = OPEN_EXISTING,
  1065. DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
  1066. HANDLE hTemplateFile = 0
  1067. ) :
  1068. File(
  1069. pFileName,
  1070. dwDesiredAccess,
  1071. dwShareMode,
  1072. pSecurityAttributes,
  1073. dwCreationDisposition,
  1074. dwFlagsAndAttributes,
  1075. hTemplateFile
  1076. )
  1077. {
  1078. }
  1079. };
  1080. //////////////////////////////////////////////////////////////////////////
  1081. //
  1082. // COutFile
  1083. //
  1084. // Write only file
  1085. //
  1086. class COutFile : public File
  1087. {
  1088. public:
  1089. COutFile()
  1090. {
  1091. }
  1092. explicit
  1093. COutFile(
  1094. PCTSTR pFileName,
  1095. DWORD dwDesiredAccess = GENERIC_WRITE,
  1096. DWORD dwShareMode = FILE_SHARE_READ,
  1097. LPSECURITY_ATTRIBUTES pSecurityAttributes = 0,
  1098. DWORD dwCreationDisposition = CREATE_ALWAYS,
  1099. DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
  1100. HANDLE hTemplateFile = 0
  1101. ) :
  1102. File(
  1103. pFileName,
  1104. dwDesiredAccess,
  1105. dwShareMode,
  1106. pSecurityAttributes,
  1107. dwCreationDisposition,
  1108. dwFlagsAndAttributes,
  1109. hTemplateFile
  1110. )
  1111. {
  1112. }
  1113. };
  1114. //////////////////////////////////////////////////////////////////////////
  1115. //
  1116. // CopyFileContents
  1117. //
  1118. // Copies the contents of one file to another
  1119. //
  1120. inline void CopyFileContents(const File &InFile, const File &OutFile)
  1121. {
  1122. BYTE Buffer[32*1024];
  1123. DWORD nNumRead;
  1124. do
  1125. {
  1126. nNumRead = InFile.ReadFile(Buffer, sizeof(Buffer));
  1127. OutFile.WriteFile(Buffer, nNumRead);
  1128. }
  1129. while (nNumRead == sizeof(Buffer));
  1130. }
  1131. #ifdef _INC_STDIO
  1132. #include <share.h>
  1133. //////////////////////////////////////////////////////////////////////////
  1134. //
  1135. // CCFile
  1136. //
  1137. // Wrapper class for C-runtime stream based file handles
  1138. //
  1139. class CCFile : public CHandle<FILE *, CCFile>
  1140. {
  1141. typedef CHandle<FILE *, CCFile> parent_type;
  1142. public:
  1143. CCFile()
  1144. {
  1145. }
  1146. CCFile(
  1147. PCTSTR filename,
  1148. PCTSTR mode,
  1149. int shflag = _SH_DENYNO
  1150. ) :
  1151. parent_type(::_tfsopen(
  1152. filename,
  1153. mode,
  1154. shflag
  1155. ))
  1156. {
  1157. }
  1158. void Destroy()
  1159. {
  1160. ::fclose(*this);
  1161. }
  1162. bool IsValid()
  1163. {
  1164. return *this != 0;
  1165. }
  1166. };
  1167. #endif _INC_STDIO
  1168. //////////////////////////////////////////////////////////////////////////
  1169. //
  1170. // CNamedPipe
  1171. //
  1172. // Wrapper class for named pipes
  1173. //
  1174. class CNamedPipe : public File
  1175. {
  1176. public:
  1177. CNamedPipe()
  1178. {
  1179. }
  1180. CNamedPipe(
  1181. PCTSTR pName,
  1182. DWORD dwOpenMode,
  1183. DWORD dwPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
  1184. DWORD nMaxInstances = PIPE_UNLIMITED_INSTANCES,
  1185. DWORD nOutBufferSize = 0,
  1186. DWORD nInBufferSize = 0,
  1187. DWORD nDefaultTimeOut = INFINITE,
  1188. LPSECURITY_ATTRIBUTES pSecurityAttributes = 0
  1189. )
  1190. {
  1191. Attach(::CreateNamedPipe(
  1192. pName,
  1193. dwOpenMode,
  1194. dwPipeMode,
  1195. nMaxInstances,
  1196. nOutBufferSize,
  1197. nInBufferSize,
  1198. nDefaultTimeOut,
  1199. pSecurityAttributes
  1200. ));
  1201. }
  1202. };
  1203. //////////////////////////////////////////////////////////////////////////
  1204. //
  1205. // CFileMapping
  1206. //
  1207. // Wrapper class for file mapping objects
  1208. //
  1209. class CFileMapping : public CKernelObject<CFileMapping>
  1210. {
  1211. public:
  1212. CFileMapping()
  1213. {
  1214. }
  1215. CFileMapping(
  1216. HANDLE hFile,
  1217. LPSECURITY_ATTRIBUTES pFileMappingAttributes,
  1218. DWORD flProtect,
  1219. DWORD dwMaximumSizeHigh = 0,
  1220. DWORD dwMaximumSizeLow = 0,
  1221. PCTSTR pName = 0
  1222. ) :
  1223. CKernelObject<CFileMapping>(::CreateFileMapping(
  1224. hFile,
  1225. pFileMappingAttributes,
  1226. flProtect,
  1227. dwMaximumSizeHigh,
  1228. dwMaximumSizeLow,
  1229. pName
  1230. ))
  1231. {
  1232. }
  1233. };
  1234. #ifdef _LZEXPAND_
  1235. //////////////////////////////////////////////////////////////////////////
  1236. //
  1237. // CLZFile
  1238. //
  1239. // Wrapper class for LZ compressed files
  1240. //
  1241. class CLZFile : public CHandle<INT, CLZFile>
  1242. {
  1243. typedef CHandle<INT, CLZFile> parent_type;
  1244. public:
  1245. CLZFile(
  1246. PTSTR pFileName,
  1247. WORD wStyle
  1248. ) :
  1249. parent_type(::LZOpenFile(
  1250. pFileName,
  1251. &m_of,
  1252. wStyle
  1253. ))
  1254. {
  1255. }
  1256. void Destroy()
  1257. {
  1258. ::LZClose(*this);
  1259. }
  1260. bool IsValid()
  1261. {
  1262. return *this >= 0;
  1263. }
  1264. private:
  1265. OFSTRUCT m_of;
  1266. };
  1267. #endif _LZEXPAND_
  1268. //////////////////////////////////////////////////////////////////////////
  1269. //
  1270. // CStartupInfo
  1271. //
  1272. // Wrapper class for the STARTUPINFO struct
  1273. //
  1274. class CStartupInfo : public STARTUPINFO
  1275. {
  1276. public:
  1277. CStartupInfo()
  1278. {
  1279. ZeroMemory(this, sizeof(STARTUPINFO));
  1280. cb = sizeof(STARTUPINFO);
  1281. }
  1282. void
  1283. UseStdHandles(
  1284. HANDLE _hStdInput = GetStdHandle(STD_INPUT_HANDLE),
  1285. HANDLE _hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
  1286. HANDLE _hStdError = GetStdHandle(STD_ERROR_HANDLE)
  1287. )
  1288. {
  1289. dwFlags |= STARTF_USESTDHANDLES;
  1290. hStdInput = _hStdInput;
  1291. hStdOutput = _hStdOutput;
  1292. hStdError = _hStdError;
  1293. }
  1294. void
  1295. UseShowWindow(WORD _wShowWindow)
  1296. {
  1297. dwFlags |= STARTF_USESHOWWINDOW;
  1298. wShowWindow = _wShowWindow;
  1299. }
  1300. };
  1301. //////////////////////////////////////////////////////////////////////////
  1302. //
  1303. // CProcess
  1304. //
  1305. // Wrapper class for process handles
  1306. //
  1307. class CProcess : public CHandle<PROCESS_INFORMATION, CProcess>
  1308. {
  1309. public:
  1310. CProcess()
  1311. {
  1312. }
  1313. explicit
  1314. CProcess(
  1315. PTSTR pCommandLine,
  1316. PSECURITY_ATTRIBUTES pProcessAttributes = 0,
  1317. PSECURITY_ATTRIBUTES pThreadAttributes = 0,
  1318. BOOL bInheritHandles = FALSE,
  1319. DWORD dwCreationFlags = 0,
  1320. PVOID pEnvironment = 0,
  1321. PCTSTR pCurrentDirectory = 0,
  1322. LPSTARTUPINFO psi = &CStartupInfo()
  1323. )
  1324. {
  1325. PROCESS_INFORMATION pi;
  1326. CHECK(::CreateProcess(
  1327. 0,
  1328. pCommandLine,
  1329. pProcessAttributes,
  1330. pThreadAttributes,
  1331. bInheritHandles,
  1332. dwCreationFlags,
  1333. pEnvironment,
  1334. pCurrentDirectory,
  1335. psi,
  1336. &pi
  1337. ));
  1338. Attach(pi);
  1339. }
  1340. CProcess(
  1341. HANDLE hToken,
  1342. PTSTR pCommandLine,
  1343. PSECURITY_ATTRIBUTES pProcessAttributes = 0,
  1344. PSECURITY_ATTRIBUTES pThreadAttributes = 0,
  1345. BOOL bInheritHandles = FALSE,
  1346. DWORD dwCreationFlags = 0,
  1347. PVOID pEnvironment = 0,
  1348. PCTSTR pCurrentDirectory = 0,
  1349. LPSTARTUPINFO psi = &CStartupInfo()
  1350. )
  1351. {
  1352. PROCESS_INFORMATION pi;
  1353. CHECK(::CreateProcessAsUser(
  1354. hToken,
  1355. 0,
  1356. pCommandLine,
  1357. pProcessAttributes,
  1358. pThreadAttributes,
  1359. bInheritHandles,
  1360. dwCreationFlags,
  1361. pEnvironment,
  1362. pCurrentDirectory,
  1363. psi,
  1364. &pi
  1365. ));
  1366. Attach(pi);
  1367. }
  1368. #if (_WIN32_WINNT >= 0x0500) && defined(UNICODE)
  1369. CProcess(
  1370. PCWSTR pUsername,
  1371. PCWSTR pDomain,
  1372. PCWSTR pPassword,
  1373. DWORD dwLogonFlags,
  1374. PWSTR pCommandLine,
  1375. DWORD dwCreationFlags = 0,
  1376. PVOID pEnvironment = 0,
  1377. PCWSTR pCurrentDirectory = 0,
  1378. LPSTARTUPINFO psi = &CStartupInfo()
  1379. )
  1380. {
  1381. PROCESS_INFORMATION pi;
  1382. CHECK(::CreateProcessWithLogonW(
  1383. pUsername,
  1384. pDomain,
  1385. pPassword,
  1386. dwLogonFlags,
  1387. 0,
  1388. pCommandLine,
  1389. dwCreationFlags,
  1390. pEnvironment,
  1391. pCurrentDirectory,
  1392. psi,
  1393. &pi
  1394. ));
  1395. Attach(pi);
  1396. }
  1397. #endif
  1398. void Destroy()
  1399. {
  1400. ::CloseHandle(((PROCESS_INFORMATION &)(*this)).hThread);
  1401. ::CloseHandle(((PROCESS_INFORMATION &)(*this)).hProcess);
  1402. }
  1403. bool IsValid()
  1404. {
  1405. return ((PROCESS_INFORMATION &)(*this)).hProcess != 0;
  1406. }
  1407. DWORD
  1408. WaitForInputIdle(
  1409. DWORD dwMilliseconds = INFINITE
  1410. ) const
  1411. {
  1412. return ::WaitForInputIdle(
  1413. ((PROCESS_INFORMATION &)(*this)).hProcess,
  1414. dwMilliseconds
  1415. );
  1416. }
  1417. DWORD
  1418. WaitForSingleObject(
  1419. DWORD dwMilliseconds = INFINITE
  1420. ) const
  1421. {
  1422. return ::WaitForSingleObject(
  1423. ((PROCESS_INFORMATION &)(*this)).hProcess,
  1424. dwMilliseconds
  1425. );
  1426. }
  1427. VOID
  1428. Terminate(
  1429. DWORD dwExitCode = 0
  1430. ) const
  1431. {
  1432. CHECK(::TerminateProcess(
  1433. ((PROCESS_INFORMATION &)(*this)).hProcess,
  1434. dwExitCode
  1435. ));
  1436. }
  1437. DWORD
  1438. GetExitCode() const
  1439. {
  1440. DWORD dwExitCode;
  1441. CHECK(::GetExitCodeProcess(
  1442. ((PROCESS_INFORMATION &)(*this)).hProcess,
  1443. &dwExitCode
  1444. ));
  1445. return dwExitCode;
  1446. }
  1447. };
  1448. //////////////////////////////////////////////////////////////////////////
  1449. //
  1450. // CThreadBase
  1451. //
  1452. // Base class for Win32 and CRT library style thread objects
  1453. //
  1454. class CThreadBase : public CKernelObject<CThreadBase>
  1455. {
  1456. protected:
  1457. CThreadBase()
  1458. {
  1459. }
  1460. explicit
  1461. CThreadBase(
  1462. HANDLE hHandle
  1463. ) :
  1464. CKernelObject<CThreadBase>(hHandle)
  1465. {
  1466. }
  1467. public:
  1468. operator DWORD() const
  1469. {
  1470. return m_dwThreadId;
  1471. }
  1472. VOID
  1473. Terminate(
  1474. DWORD dwExitCode = 0
  1475. ) const
  1476. {
  1477. CHECK(::TerminateThread(
  1478. *this,
  1479. dwExitCode
  1480. ));
  1481. }
  1482. DWORD
  1483. GetExitCode() const
  1484. {
  1485. DWORD dwExitCode;
  1486. CHECK(::GetExitCodeThread(
  1487. *this,
  1488. &dwExitCode
  1489. ));
  1490. return dwExitCode;
  1491. }
  1492. protected:
  1493. DWORD m_dwThreadId;
  1494. };
  1495. //////////////////////////////////////////////////////////////////////////
  1496. //
  1497. // CThread
  1498. //
  1499. // Wrapper class for Win32 thread handles
  1500. //
  1501. class CThread : public CThreadBase
  1502. {
  1503. public:
  1504. CThread()
  1505. {
  1506. }
  1507. explicit
  1508. CThread(
  1509. PTHREAD_START_ROUTINE pStartAddress,
  1510. PVOID pParameter = 0,
  1511. PSECURITY_ATTRIBUTES pThreadAttributes = 0,
  1512. DWORD dwStackSize = 0,
  1513. DWORD dwCreationFlags = 0
  1514. ) :
  1515. CThreadBase(::CreateThread(
  1516. pThreadAttributes,
  1517. dwStackSize,
  1518. pStartAddress,
  1519. pParameter,
  1520. dwCreationFlags,
  1521. &m_dwThreadId
  1522. ))
  1523. {
  1524. }
  1525. };
  1526. #ifdef _INC_PROCESS
  1527. //////////////////////////////////////////////////////////////////////////
  1528. //
  1529. // CCThread
  1530. //
  1531. // Wrapper class for C-runtime threads
  1532. //
  1533. class CCThread : public CThreadBase
  1534. {
  1535. public:
  1536. CCThread()
  1537. {
  1538. }
  1539. explicit
  1540. CCThread(
  1541. unsigned ( __stdcall *start_address )( void * ),
  1542. void *arglist = 0,
  1543. void *security = 0,
  1544. unsigned stack_size = 0,
  1545. unsigned initflag = 0
  1546. ) :
  1547. CThreadBase((HANDLE)(LONG_PTR) _beginthreadex(
  1548. security,
  1549. stack_size,
  1550. start_address,
  1551. arglist,
  1552. initflag,
  1553. (unsigned int *) &m_dwThreadId
  1554. ))
  1555. {
  1556. }
  1557. };
  1558. #endif //_INC_PROCESS
  1559. //////////////////////////////////////////////////////////////////////////
  1560. //
  1561. // Event
  1562. //
  1563. // Wrapper class for event handles
  1564. //
  1565. class Event : public CKernelObject<Event>
  1566. {
  1567. public:
  1568. Event()
  1569. {
  1570. }
  1571. Event(
  1572. BOOL bManualReset,
  1573. BOOL bInitialState,
  1574. LPCTSTR lpName = 0,
  1575. LPSECURITY_ATTRIBUTES lpEventAttributes = 0
  1576. ) :
  1577. CKernelObject<Event>(::CreateEvent(
  1578. lpEventAttributes,
  1579. bManualReset,
  1580. bInitialState,
  1581. lpName
  1582. ))
  1583. {
  1584. }
  1585. public:
  1586. VOID
  1587. Set() const
  1588. {
  1589. CHECK(::SetEvent(*this));
  1590. }
  1591. VOID
  1592. Reset() const
  1593. {
  1594. CHECK(::ResetEvent(*this));
  1595. }
  1596. };
  1597. //////////////////////////////////////////////////////////////////////////
  1598. //
  1599. // Mutex
  1600. //
  1601. // Wrapper class for mutex handles
  1602. //
  1603. class Mutex : public CKernelObject<Mutex>
  1604. {
  1605. public:
  1606. Mutex()
  1607. {
  1608. }
  1609. explicit
  1610. Mutex(
  1611. BOOL bInitialOwner,
  1612. PCTSTR pName = 0,
  1613. PSECURITY_ATTRIBUTES pMutexAttributes = 0
  1614. ) :
  1615. CKernelObject<Mutex>(::CreateMutex(
  1616. pMutexAttributes,
  1617. bInitialOwner,
  1618. pName
  1619. ))
  1620. {
  1621. }
  1622. public:
  1623. VOID
  1624. Release() const
  1625. {
  1626. CHECK(::ReleaseMutex(*this));
  1627. }
  1628. };
  1629. //////////////////////////////////////////////////////////////////////////
  1630. //
  1631. // Semaphore
  1632. //
  1633. // Wrapper class for semaphore handles
  1634. //
  1635. class Semaphore : public CKernelObject<Semaphore>
  1636. {
  1637. public:
  1638. Semaphore()
  1639. {
  1640. }
  1641. Semaphore(
  1642. LONG lInitialCount,
  1643. LONG lMaximumCount,
  1644. LPCTSTR lpName = 0,
  1645. LPSECURITY_ATTRIBUTES lpEventAttributes = 0
  1646. ) :
  1647. CKernelObject<Semaphore>(::CreateSemaphore(
  1648. lpEventAttributes,
  1649. lInitialCount,
  1650. lMaximumCount,
  1651. lpName
  1652. ))
  1653. {
  1654. }
  1655. public:
  1656. VOID
  1657. Release(
  1658. LONG lReleaseCount = 1,
  1659. PLONG pPreviousCount = 0
  1660. ) const
  1661. {
  1662. CHECK(::ReleaseSemaphore(*this, lReleaseCount, pPreviousCount));
  1663. }
  1664. VOID
  1665. WaitFor(
  1666. LONG lCount
  1667. ) const
  1668. {
  1669. for (int i = 0; i < lCount; ++i)
  1670. {
  1671. WaitForSingleObject();
  1672. }
  1673. Release(lCount);
  1674. }
  1675. };
  1676. #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
  1677. //////////////////////////////////////////////////////////////////////////
  1678. //
  1679. // CWaitableTimer
  1680. //
  1681. // Wrapper class for waitable timer handles
  1682. //
  1683. class CWaitableTimer : public CKernelObject<CWaitableTimer>
  1684. {
  1685. public:
  1686. CWaitableTimer()
  1687. {
  1688. }
  1689. explicit
  1690. CWaitableTimer(
  1691. BOOL bManualReset,
  1692. PCTSTR pTimerName = 0,
  1693. PSECURITY_ATTRIBUTES pTimerAttributes = 0
  1694. ) :
  1695. CKernelObject<CWaitableTimer>(::CreateWaitableTimer(
  1696. pTimerAttributes,
  1697. bManualReset,
  1698. pTimerName
  1699. ))
  1700. {
  1701. }
  1702. public:
  1703. VOID
  1704. Set(
  1705. const CLargeInteger &DueTime,
  1706. LONG lPeriod = 0,
  1707. PTIMERAPCROUTINE pfnCompletionRoutine = 0,
  1708. LPVOID lpArgToCompletionRoutine = 0,
  1709. BOOL fResume = FALSE
  1710. ) const
  1711. {
  1712. CHECK(::SetWaitableTimer(
  1713. *this,
  1714. &DueTime,
  1715. lPeriod,
  1716. pfnCompletionRoutine,
  1717. lpArgToCompletionRoutine,
  1718. fResume
  1719. ));
  1720. }
  1721. VOID
  1722. Cancel() const
  1723. {
  1724. CHECK(::CancelWaitableTimer(*this));
  1725. }
  1726. };
  1727. #endif
  1728. //////////////////////////////////////////////////////////////////////////
  1729. //
  1730. // CriticalSection
  1731. //
  1732. // Wrapper class for critical sections
  1733. //
  1734. class CriticalSection : private CRITICAL_SECTION
  1735. {
  1736. public:
  1737. CriticalSection()
  1738. {
  1739. ::InitializeCriticalSection(this);
  1740. }
  1741. ~CriticalSection()
  1742. {
  1743. ::DeleteCriticalSection(this);
  1744. }
  1745. #if _WIN32_WINNT >= 0x0400
  1746. BOOL
  1747. TryEnter()
  1748. {
  1749. return ::TryEnterCriticalSection(this);
  1750. }
  1751. #endif //_WIN32_WINNT >= 0x0400
  1752. VOID
  1753. Enter()
  1754. {
  1755. ::EnterCriticalSection(this);
  1756. }
  1757. VOID
  1758. Leave()
  1759. {
  1760. ::LeaveCriticalSection(this);
  1761. }
  1762. };
  1763. //////////////////////////////////////////////////////////////////////////
  1764. //
  1765. // CLibrary
  1766. //
  1767. // Wrapper class for loading DLL's
  1768. //
  1769. class CLibrary : public CHandle<HINSTANCE, CLibrary>
  1770. {
  1771. typedef CHandle<HINSTANCE, CLibrary> parent_type;
  1772. public:
  1773. CLibrary()
  1774. {
  1775. }
  1776. explicit
  1777. CLibrary(
  1778. PCTSTR pLibFileName,
  1779. DWORD dwFlags = 0
  1780. ) :
  1781. parent_type(::LoadLibraryEx(pLibFileName, 0, dwFlags))
  1782. {
  1783. }
  1784. void Destroy()
  1785. {
  1786. ::FreeLibrary(*this);
  1787. }
  1788. bool IsValid()
  1789. {
  1790. return *this != 0;
  1791. }
  1792. };
  1793. //////////////////////////////////////////////////////////////////////////
  1794. //
  1795. // CPointer
  1796. //
  1797. // Base class for pointer wrappers
  1798. //
  1799. #pragma warning(4: 4284) // return type for 'identifier::operator ->()' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
  1800. template <class T, class Child>
  1801. class CPointer : public CHandle<T *, Child >
  1802. {
  1803. typedef CHandle<T *, Child> parent_type;
  1804. typedef T *pointer_type;
  1805. public:
  1806. CPointer()
  1807. {
  1808. }
  1809. CPointer(
  1810. const T *pPointer
  1811. ) :
  1812. parent_type((pointer_type) pPointer)
  1813. {
  1814. }
  1815. CPointer & operator =(const T *pPointer)
  1816. {
  1817. return (CPointer &) parent_type::operator =((pointer_type) pPointer);
  1818. }
  1819. T * operator ->()
  1820. {
  1821. return *this;
  1822. }
  1823. bool IsValid()
  1824. {
  1825. return *this != 0;
  1826. }
  1827. };
  1828. //////////////////////////////////////////////////////////////////////////
  1829. //
  1830. // CCppMem
  1831. //
  1832. // Wrapper class for allocations through C++ new[] and delete[] operators
  1833. //
  1834. template <class T>
  1835. class CCppMem : public CPointer<T, CCppMem<T> >
  1836. {
  1837. typedef CPointer<T, CCppMem<T> > parent_type;
  1838. public:
  1839. CCppMem()
  1840. {
  1841. }
  1842. CCppMem(
  1843. const T *pPointer
  1844. ) :
  1845. parent_type(pPointer)
  1846. {
  1847. }
  1848. explicit
  1849. CCppMem(
  1850. size_t nSize,
  1851. BOOL bZeroInit = FALSE
  1852. ) :
  1853. parent_type(new T[nSize])
  1854. {
  1855. if (bZeroInit)
  1856. {
  1857. ZeroMemory(*this, sizeof(T) * nSize);
  1858. }
  1859. }
  1860. // bugbug: why isn't this inherited?
  1861. CCppMem & operator =(const T *pPointer)
  1862. {
  1863. return (CCppMem &) parent_type::operator =(pPointer);
  1864. }
  1865. void Destroy()
  1866. {
  1867. delete [] *this;
  1868. }
  1869. };
  1870. //////////////////////////////////////////////////////////////////////////
  1871. //
  1872. // CGlobalMem
  1873. //
  1874. // Wrapper class for allocations through GlobalAlloc() GlobalFree() APIs
  1875. //
  1876. template <class T>
  1877. class CGlobalMem : public CPointer<T, CGlobalMem<T> >
  1878. {
  1879. typedef CPointer<T, CGlobalMem<T> > parent_type;
  1880. public:
  1881. CGlobalMem()
  1882. {
  1883. }
  1884. CGlobalMem(
  1885. const T *pPointer
  1886. ) :
  1887. parent_type(pPointer)
  1888. {
  1889. }
  1890. explicit
  1891. CGlobalMem(
  1892. DWORD dwBytes,
  1893. UINT uFlags = GMEM_FIXED
  1894. ) :
  1895. parent_type((T *) ::GlobalAlloc(uFlags, dwBytes))
  1896. {
  1897. }
  1898. // bugbug: why isn't this inherited?
  1899. CGlobalMem & operator =(const T *pPointer)
  1900. {
  1901. return (CGlobalMem &) parent_type::operator =(pPointer);
  1902. }
  1903. void Destroy()
  1904. {
  1905. ::GlobalFree(*this);
  1906. }
  1907. };
  1908. //////////////////////////////////////////////////////////////////////////
  1909. //
  1910. // CLocalMem
  1911. //
  1912. // Wrapper class for allocations through LocalAlloc() LocalFree() APIs
  1913. //
  1914. template <class T>
  1915. class CLocalMem : public CPointer<T, CLocalMem<T> >
  1916. {
  1917. typedef CPointer<T, CLocalMem<T> > parent_type;
  1918. public:
  1919. CLocalMem()
  1920. {
  1921. }
  1922. CLocalMem(
  1923. const T *pPointer
  1924. ) :
  1925. parent_type(pPointer)
  1926. {
  1927. }
  1928. explicit
  1929. CLocalMem(
  1930. DWORD dwBytes,
  1931. UINT uFlags = LMEM_FIXED
  1932. ) :
  1933. parent_type((T *) ::LocalAlloc(uFlags, dwBytes))
  1934. {
  1935. }
  1936. // bugbug: why isn't this inherited?
  1937. CLocalMem & operator =(const T *pPointer)
  1938. {
  1939. return (CLocalMem &) parent_type::operator =(pPointer);
  1940. }
  1941. void Destroy()
  1942. {
  1943. ::LocalFree(*this);
  1944. }
  1945. };
  1946. //////////////////////////////////////////////////////////////////////////
  1947. //
  1948. // CMapViewOfFile
  1949. //
  1950. // Wrapper class for memory mapped file objects
  1951. //
  1952. template <class T>
  1953. class CMapViewOfFile : public CPointer<T, CMapViewOfFile<T> >
  1954. {
  1955. public:
  1956. CMapViewOfFile()
  1957. {
  1958. }
  1959. CMapViewOfFile(
  1960. HANDLE hFileMappingObject,
  1961. DWORD dwDesiredAccess,
  1962. DWORD dwFileOffsetHigh = 0,
  1963. DWORD dwFileOffsetLow = 0,
  1964. DWORD dwNumberOfBytesToMap = 0,
  1965. PVOID pBaseAddress = 0
  1966. ) :
  1967. CPointer<T, CMapViewOfFile<T> >((T *) ::MapViewOfFileEx(
  1968. hFileMappingObject,
  1969. dwDesiredAccess,
  1970. dwFileOffsetHigh,
  1971. dwFileOffsetLow,
  1972. dwNumberOfBytesToMap,
  1973. pBaseAddress
  1974. ))
  1975. {
  1976. }
  1977. void Destroy()
  1978. {
  1979. ::UnmapViewOfFile(*this);
  1980. }
  1981. };
  1982. //////////////////////////////////////////////////////////////////////////
  1983. //
  1984. // CMapFile
  1985. //
  1986. // Helper class for CreateFile(), CreateNamedPipe() and MapViewOfFileEx() APIs
  1987. //
  1988. // bugbug: these should be defined in class scope, but vc5 doesn't let me...
  1989. template <int> struct mapping_traits { };
  1990. template <> struct mapping_traits<FILE_MAP_READ>
  1991. {
  1992. enum
  1993. {
  1994. dwDesiredAccess = GENERIC_READ,
  1995. dwShareMode = FILE_SHARE_READ,
  1996. flProtect = PAGE_READONLY,
  1997. dwDesiredMapAccess = FILE_MAP_READ
  1998. };
  1999. };
  2000. template <> struct mapping_traits<FILE_MAP_WRITE>
  2001. {
  2002. enum
  2003. {
  2004. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,
  2005. dwShareMode = 0,
  2006. flProtect = PAGE_READWRITE,
  2007. dwDesiredMapAccess = FILE_MAP_WRITE
  2008. };
  2009. };
  2010. template <> struct mapping_traits<FILE_MAP_COPY>
  2011. {
  2012. enum
  2013. {
  2014. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,
  2015. dwShareMode = FILE_SHARE_READ,
  2016. flProtect = PAGE_WRITECOPY,
  2017. dwDesiredMapAccess = FILE_MAP_COPY
  2018. };
  2019. };
  2020. template <class T, int Access>
  2021. class CMapFile
  2022. {
  2023. public:
  2024. CMapFile(
  2025. PCTSTR pFileName
  2026. ) :
  2027. m_File(
  2028. pFileName, // PCTSTR pFileName
  2029. mapping_traits<Access>::dwDesiredAccess, // DWORD dwDesiredAccess
  2030. mapping_traits<Access>::dwShareMode, // DWORD dwShareMode
  2031. 0, // LPSECURITY_ATTRIBUTES
  2032. OPEN_EXISTING, // DWORD dwCreationDisposition
  2033. FILE_ATTRIBUTE_NORMAL, // DWORD dwFlagsAndAttributes
  2034. 0 // HANDLE hTemplateFile
  2035. ),
  2036. m_Mapping(
  2037. m_File, // HANDLE hFile
  2038. 0, // LPSECURITY_ATTRIBUTES
  2039. mapping_traits<Access>::flProtect, // DWORD flProtect
  2040. 0, // DWORD dwMaximumSizeHigh
  2041. 0, // DWORD dwMaximumSizeLow
  2042. 0 // PCTSTR pName
  2043. ),
  2044. m_ViewOfFile(
  2045. m_Mapping, // HANDLE hFileMappingObject
  2046. mapping_traits<Access>::dwDesiredMapAccess, // DWORD dwDesiredAccess
  2047. 0, // DWORD dwFileOffsetHigh
  2048. 0, // DWORD dwFileOffsetLow
  2049. 0, // DWORD dwNumberOfBytesToMap
  2050. 0 // PVOID pBaseAddress
  2051. )
  2052. {
  2053. }
  2054. operator T *()
  2055. {
  2056. return m_ViewOfFile;
  2057. }
  2058. private:
  2059. File m_File;
  2060. CFileMapping m_Mapping;
  2061. CMapViewOfFile<T> m_ViewOfFile;
  2062. };
  2063. //////////////////////////////////////////////////////////////////////////
  2064. //
  2065. // CSecurityDescriptor
  2066. //
  2067. // Wrapper class for SECURITY_DESCRIPTOR struct
  2068. //
  2069. class CSecurityDescriptor : public CCppMem<SECURITY_DESCRIPTOR>
  2070. {
  2071. public:
  2072. explicit
  2073. CSecurityDescriptor(
  2074. BOOL bDaclPresent = TRUE,
  2075. PACL pDacl = 0,
  2076. BOOL bDaclDefaulted = FALSE
  2077. ) :
  2078. CCppMem<SECURITY_DESCRIPTOR>(SECURITY_DESCRIPTOR_MIN_LENGTH)
  2079. {
  2080. CHECK(::InitializeSecurityDescriptor(
  2081. *this,
  2082. SECURITY_DESCRIPTOR_REVISION
  2083. ));
  2084. CHECK(::SetSecurityDescriptorDacl(
  2085. *this,
  2086. bDaclPresent,
  2087. pDacl,
  2088. bDaclDefaulted
  2089. ));
  2090. }
  2091. };
  2092. //////////////////////////////////////////////////////////////////////////
  2093. //
  2094. // CSecurityAttributes
  2095. //
  2096. // Wrapper class for the SECURITY_ATTRIBUTES struct
  2097. //
  2098. class CSecurityAttributes : public SECURITY_ATTRIBUTES
  2099. {
  2100. public:
  2101. explicit
  2102. CSecurityAttributes(
  2103. PSECURITY_DESCRIPTOR pSD,
  2104. BOOL bInheritHandle = TRUE
  2105. )
  2106. {
  2107. nLength = sizeof(SECURITY_ATTRIBUTES);
  2108. lpSecurityDescriptor = pSD;
  2109. bInheritHandle = bInheritHandle;
  2110. }
  2111. };
  2112. //////////////////////////////////////////////////////////////////////////
  2113. //
  2114. // CTokenPrivileges
  2115. //
  2116. // Wrapper class for the TOKEN_PRIVILEGES struct
  2117. //
  2118. #include <pshpack1.h>
  2119. template <int N>
  2120. struct CTokenPrivileges : public TOKEN_PRIVILEGES
  2121. {
  2122. CTokenPrivileges()
  2123. {
  2124. PrivilegeCount = N;
  2125. }
  2126. LUID_AND_ATTRIBUTES & operator [](int i)
  2127. {
  2128. ASSERT(i < N);
  2129. return Privileges[i];
  2130. }
  2131. private:
  2132. LUID_AND_ATTRIBUTES RemainingPrivileges[N - ANYSIZE_ARRAY];
  2133. };
  2134. #include <poppack.h>
  2135. //////////////////////////////////////////////////////////////////////////
  2136. //
  2137. // CLuid
  2138. //
  2139. // Wrapper class for the LUID struct
  2140. //
  2141. struct CLuid : public LUID
  2142. {
  2143. CLuid(
  2144. LPCTSTR lpSystemName,
  2145. LPCTSTR lpName
  2146. )
  2147. {
  2148. CHECK(::LookupPrivilegeValue(
  2149. lpSystemName,
  2150. lpName,
  2151. this
  2152. ));
  2153. }
  2154. };
  2155. //////////////////////////////////////////////////////////////////////////
  2156. //
  2157. // CLuidAndAttributes
  2158. //
  2159. // Wrapper class for the LUID_AND_ATTRIBUTES struct
  2160. //
  2161. struct CLuidAndAttributes : public LUID_AND_ATTRIBUTES
  2162. {
  2163. CLuidAndAttributes(
  2164. const LUID& _Luid,
  2165. DWORD _Attributes
  2166. )
  2167. {
  2168. Luid = _Luid;
  2169. Attributes = _Attributes;
  2170. }
  2171. };
  2172. //////////////////////////////////////////////////////////////////////////
  2173. //
  2174. // CProcessToken
  2175. //
  2176. // Wrapper class for the process token object
  2177. //
  2178. class CProcessToken : public CKernelObject<CProcessToken>
  2179. {
  2180. public:
  2181. CProcessToken()
  2182. {
  2183. }
  2184. CProcessToken(
  2185. HANDLE ProcessHandle,
  2186. DWORD DesiredAccess
  2187. )
  2188. {
  2189. HANDLE hHandle;
  2190. CHECK(::OpenProcessToken(
  2191. ProcessHandle,
  2192. DesiredAccess,
  2193. &hHandle
  2194. ));
  2195. Attach(hHandle);
  2196. }
  2197. VOID
  2198. AdjustTokenPrivileges(
  2199. BOOL DisableAllPrivileges,
  2200. PTOKEN_PRIVILEGES NewState,
  2201. DWORD BufferLength = 0,
  2202. PTOKEN_PRIVILEGES PreviousState = 0,
  2203. PDWORD ReturnLength = 0
  2204. ) const
  2205. {
  2206. CHECK(::AdjustTokenPrivileges(
  2207. *this,
  2208. DisableAllPrivileges,
  2209. NewState,
  2210. BufferLength,
  2211. PreviousState,
  2212. ReturnLength
  2213. ));
  2214. CHECK(GetLastError() == ERROR_SUCCESS);
  2215. }
  2216. };
  2217. //////////////////////////////////////////////////////////////////////////
  2218. //
  2219. // CLoggedOnUser
  2220. //
  2221. // Wrapper class for the logged on user object
  2222. //
  2223. class CLoggedOnUser : public CKernelObject<CLoggedOnUser>
  2224. {
  2225. public:
  2226. CLoggedOnUser()
  2227. {
  2228. }
  2229. CLoggedOnUser(
  2230. LPTSTR lpszUsername,
  2231. LPTSTR lpszDomain,
  2232. LPTSTR lpszPassword,
  2233. DWORD dwLogonType = LOGON32_LOGON_INTERACTIVE,
  2234. DWORD dwLogonProvider = LOGON32_PROVIDER_DEFAULT
  2235. )
  2236. {
  2237. HANDLE hHandle;
  2238. CHECK(::LogonUser(
  2239. lpszUsername,
  2240. lpszDomain,
  2241. lpszPassword,
  2242. dwLogonType,
  2243. dwLogonProvider,
  2244. &hHandle
  2245. ));
  2246. Attach(hHandle);
  2247. }
  2248. VOID
  2249. Impersonate() const
  2250. {
  2251. CHECK(::ImpersonateLoggedOnUser(*this));
  2252. }
  2253. };
  2254. //////////////////////////////////////////////////////////////////////////
  2255. //
  2256. // CEventSource
  2257. //
  2258. // Wrapper class for the event source object
  2259. //
  2260. class CEventSource : public CHandle<HANDLE, CEventSource>
  2261. {
  2262. typedef CHandle<HANDLE, CEventSource> parent_type;
  2263. public:
  2264. CEventSource()
  2265. {
  2266. }
  2267. CEventSource(
  2268. PCTSTR pUNCServerName,
  2269. PCTSTR pSourceName
  2270. ) :
  2271. parent_type(::RegisterEventSource(
  2272. pUNCServerName,
  2273. pSourceName
  2274. ))
  2275. {
  2276. }
  2277. void Destroy()
  2278. {
  2279. ::DeregisterEventSource(*this);
  2280. }
  2281. bool IsValid()
  2282. {
  2283. return *this != 0;
  2284. }
  2285. VOID
  2286. ReportEvent(
  2287. WORD wType,
  2288. WORD wCategory,
  2289. DWORD dwEventID,
  2290. PSID lpUserSid,
  2291. WORD wNumStrings,
  2292. DWORD dwDataSize,
  2293. PCTSTR *pStrings,
  2294. PVOID pRawData
  2295. ) const
  2296. {
  2297. CHECK(::ReportEvent(
  2298. *this,
  2299. wType,
  2300. wCategory,
  2301. dwEventID,
  2302. lpUserSid,
  2303. wNumStrings,
  2304. dwDataSize,
  2305. pStrings,
  2306. pRawData
  2307. ));
  2308. }
  2309. VOID
  2310. ReportEventText(
  2311. WORD wType,
  2312. PCTSTR pString,
  2313. DWORD dwEventID
  2314. ) const
  2315. {
  2316. PCTSTR pStrings[] = { pString };
  2317. ReportEvent(
  2318. wType,
  2319. 0,
  2320. dwEventID,
  2321. 0,
  2322. 1,
  2323. 0,
  2324. pStrings,
  2325. 0
  2326. );
  2327. }
  2328. };
  2329. //////////////////////////////////////////////////////////////////////////
  2330. //
  2331. // CKey
  2332. //
  2333. // Wrapper class for registry key objects and registry APIs
  2334. //
  2335. class CKey : public CHandle<HKEY, CKey>
  2336. {
  2337. public:
  2338. CKey()
  2339. {
  2340. }
  2341. CKey(
  2342. HKEY hKey
  2343. )
  2344. {
  2345. Attach(hKey);
  2346. }
  2347. CKey(
  2348. HKEY hKey,
  2349. PCTSTR pSubKey,
  2350. REGSAM samDesired = KEY_ALL_ACCESS
  2351. )
  2352. {
  2353. HKEY hHandle;
  2354. CHECK_REG(::RegOpenKeyEx(
  2355. hKey,
  2356. pSubKey,
  2357. 0,
  2358. samDesired,
  2359. &hHandle
  2360. ));
  2361. Attach(hHandle);
  2362. }
  2363. CKey(
  2364. PCTSTR pMachineName,
  2365. HKEY hKey
  2366. )
  2367. {
  2368. HKEY hHandle;
  2369. CHECK_REG(::RegConnectRegistry(
  2370. pMachineName,
  2371. hKey,
  2372. &hHandle
  2373. ));
  2374. Attach(hHandle);
  2375. }
  2376. CKey(
  2377. HKEY hKey,
  2378. PCTSTR pSubKey,
  2379. PTSTR pClass,
  2380. DWORD dwOptions,
  2381. REGSAM samDesired = KEY_ALL_ACCESS,
  2382. PSECURITY_ATTRIBUTES pSecurityAttributes = 0
  2383. )
  2384. {
  2385. HKEY hHandle;
  2386. DWORD dwDisposition;
  2387. CHECK_REG(::RegCreateKeyEx(
  2388. hKey,
  2389. pSubKey,
  2390. 0,
  2391. pClass,
  2392. dwOptions,
  2393. samDesired,
  2394. pSecurityAttributes,
  2395. &hHandle,
  2396. &dwDisposition
  2397. ));
  2398. Attach(hHandle);
  2399. }
  2400. void Destroy()
  2401. {
  2402. ::RegCloseKey(*this);
  2403. }
  2404. bool IsValid()
  2405. {
  2406. return *this != 0;
  2407. }
  2408. VOID
  2409. RegQueryValueEx(
  2410. PTSTR pValueName,
  2411. PDWORD pType,
  2412. PVOID pData,
  2413. PDWORD pcbData
  2414. ) const
  2415. {
  2416. CHECK_REG(::RegQueryValueEx(
  2417. *this,
  2418. pValueName,
  2419. 0,
  2420. pType,
  2421. (PBYTE) pData,
  2422. pcbData
  2423. ));
  2424. }
  2425. VOID
  2426. RegSetValueEx(
  2427. PTSTR pValueName,
  2428. DWORD dwType,
  2429. CONST VOID *pData,
  2430. DWORD cbData
  2431. ) const
  2432. {
  2433. CHECK_REG(::RegSetValueEx(
  2434. *this,
  2435. pValueName,
  2436. 0,
  2437. dwType,
  2438. (PBYTE) pData,
  2439. cbData
  2440. ));
  2441. }
  2442. BOOL
  2443. RegEnumKeyEx(
  2444. DWORD dwIndex,
  2445. PTSTR pName,
  2446. PDWORD pcbName,
  2447. PTSTR pClass = 0,
  2448. PDWORD pcbClass = 0,
  2449. PFILETIME pftLastWriteTime = 0
  2450. ) const
  2451. {
  2452. LONG bResult = ::RegEnumKeyEx(
  2453. *this,
  2454. dwIndex,
  2455. pName,
  2456. pcbName,
  2457. 0,
  2458. pClass,
  2459. pcbClass,
  2460. pftLastWriteTime
  2461. );
  2462. if (bResult == ERROR_NO_MORE_ITEMS)
  2463. {
  2464. return FALSE;
  2465. }
  2466. CHECK_REG(bResult);
  2467. return TRUE;
  2468. }
  2469. BOOL
  2470. RegEnumValue(
  2471. DWORD dwIndex,
  2472. PTSTR pValueName,
  2473. PDWORD pcbValueName,
  2474. PDWORD pType,
  2475. PBYTE pData,
  2476. PDWORD pcbData
  2477. ) const
  2478. {
  2479. LONG bResult = ::RegEnumValue(
  2480. *this,
  2481. dwIndex,
  2482. pValueName,
  2483. pcbValueName,
  2484. 0,
  2485. pType,
  2486. pData,
  2487. pcbData
  2488. );
  2489. if (bResult == ERROR_NO_MORE_ITEMS)
  2490. {
  2491. return FALSE;
  2492. }
  2493. CHECK_REG(bResult);
  2494. return TRUE;
  2495. }
  2496. typedef struct _REG_INFO_KEY
  2497. {
  2498. DWORD cSubKeys;
  2499. DWORD cbMaxSubKeyLen;
  2500. DWORD cbMaxClassLen;
  2501. DWORD cValues;
  2502. DWORD cbMaxValueNameLen;
  2503. DWORD cbMaxValueLen;
  2504. DWORD cbSecurityDescriptor;
  2505. FILETIME ftLastWriteTime;
  2506. } REG_INFO_KEY, *PREG_INFO_KEY;
  2507. REG_INFO_KEY
  2508. RegQueryInfoKey()
  2509. {
  2510. REG_INFO_KEY rik;
  2511. CHECK_REG(::RegQueryInfoKey(
  2512. *this,
  2513. 0,
  2514. 0,
  2515. 0,
  2516. &rik.cSubKeys,
  2517. &rik.cbMaxSubKeyLen,
  2518. &rik.cbMaxClassLen,
  2519. &rik.cValues,
  2520. &rik.cbMaxValueNameLen,
  2521. &rik.cbMaxValueLen,
  2522. &rik.cbSecurityDescriptor,
  2523. &rik.ftLastWriteTime
  2524. ));
  2525. return rik;
  2526. }
  2527. };
  2528. //////////////////////////////////////////////////////////////////////////
  2529. //
  2530. // CFindFile
  2531. //
  2532. // Wrapper class for directory search objects
  2533. //
  2534. class CFindFile : public WIN32_FIND_DATA, public CHandle<HANDLE, CFindFile>
  2535. {
  2536. public:
  2537. CFindFile(
  2538. PCTSTR pFileName
  2539. )
  2540. {
  2541. HANDLE hHandle = ::FindFirstFile(
  2542. pFileName,
  2543. this
  2544. );
  2545. if (hHandle == INVALID_HANDLE_VALUE)
  2546. {
  2547. m_bFound = FALSE;
  2548. }
  2549. else
  2550. {
  2551. m_bFound = TRUE;
  2552. Attach(hHandle);
  2553. }
  2554. }
  2555. void Destroy()
  2556. {
  2557. ::FindClose(*this);
  2558. }
  2559. bool IsValid()
  2560. {
  2561. return (HANDLE) *this != INVALID_HANDLE_VALUE;
  2562. }
  2563. VOID
  2564. FindNextFile()
  2565. {
  2566. m_bFound = ::FindNextFile(
  2567. *this,
  2568. this
  2569. );
  2570. CHECK(m_bFound || GetLastError() == ERROR_NO_MORE_FILES);
  2571. }
  2572. BOOL
  2573. Found() const
  2574. {
  2575. return m_bFound;
  2576. }
  2577. private:
  2578. BOOL m_bFound;
  2579. };
  2580. //////////////////////////////////////////////////////////////////////////
  2581. //
  2582. // FileExists
  2583. //
  2584. // Returns TRUE if the specified file exists
  2585. //
  2586. inline BOOL FileExists(PCTSTR pName)
  2587. {
  2588. CFindFile ff(pName);
  2589. return ff.Found();
  2590. }
  2591. //////////////////////////////////////////////////////////////////////////
  2592. //
  2593. // DirectoryExists
  2594. //
  2595. // Returns TRUE if the specified directory exists
  2596. //
  2597. inline BOOL DirectoryExists(PCTSTR pName)
  2598. {
  2599. TCHAR pRootDir[3];
  2600. // change "X:\" to "X:"
  2601. if (pName && pName[1] == _T(':') && pName[2] == _T('\\') && pName[3] == _T('\0'))
  2602. {
  2603. pRootDir[0] = pName[0];
  2604. pRootDir[1] = _T(':');
  2605. pRootDir[2] = _T('\0');
  2606. pName = pRootDir;
  2607. }
  2608. CFindFile ff(pName);
  2609. return ff.Found() && (ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
  2610. }
  2611. //////////////////////////////////////////////////////////////////////////
  2612. //
  2613. // GetFileSize
  2614. //
  2615. // Returns the size of the specified file
  2616. //
  2617. inline ULARGE_INTEGER GetFileSize(PCTSTR pFileName)
  2618. {
  2619. CFindFile ff(pFileName);
  2620. CHECK(ff.Found());
  2621. ULARGE_INTEGER nSize =
  2622. {
  2623. ff.nFileSizeLow,
  2624. ff.nFileSizeHigh
  2625. };
  2626. return nSize;
  2627. }
  2628. #ifdef _INC_TOOLHELP32
  2629. //////////////////////////////////////////////////////////////////////////
  2630. //
  2631. // CToolhelp32Snapshot
  2632. //
  2633. // Wrapper class for the toolhelp snapshot objects
  2634. //
  2635. class CToolhelp32Snapshot : public CKernelObject<CToolhelp32Snapshot>
  2636. {
  2637. typedef CKernelObject<CToolhelp32Snapshot> parent_type;
  2638. public:
  2639. explicit
  2640. CToolhelp32Snapshot(
  2641. DWORD dwFlags = TH32CS_SNAPALL,
  2642. DWORD th32ProcessID = 0
  2643. ) :
  2644. parent_type(CreateToolhelp32Snapshot(
  2645. dwFlags,
  2646. th32ProcessID
  2647. ))
  2648. {
  2649. }
  2650. };
  2651. //////////////////////////////////////////////////////////////////////////
  2652. //
  2653. // CFindHeapList, CFindModule, CFindProcess, CFindThread
  2654. //
  2655. // Wrapper classes for toolhelp find functions
  2656. //
  2657. // bugbug: this template declaration is better, but VC compiler cannot resolve it yet
  2658. //template <class T, BOOL (WINAPI *fnFindFirst)(HANDLE, T *), BOOL (WINAPI *fnFindNext)(HANDLE, T *)>
  2659. #define DECLARE_TOOLHELP32_FIND(CLASSNAME, STRUCT, FINDFIRST, FINDNEXT) \
  2660. \
  2661. class CLASSNAME : public STRUCT \
  2662. { \
  2663. public: \
  2664. CLASSNAME( \
  2665. HANDLE hSnapShot \
  2666. ) \
  2667. { \
  2668. m_hSnapShot = hSnapShot; \
  2669. dwSize = sizeof(STRUCT); \
  2670. m_bFound = FINDFIRST(m_hSnapShot, this); \
  2671. } \
  2672. \
  2673. VOID \
  2674. FindNext() \
  2675. { \
  2676. m_bFound = FINDNEXT(m_hSnapShot, this); \
  2677. } \
  2678. \
  2679. BOOL \
  2680. IsFound() const \
  2681. { \
  2682. return m_bFound; \
  2683. } \
  2684. \
  2685. private: \
  2686. HANDLE m_hSnapShot; \
  2687. BOOL m_bFound; \
  2688. }; \
  2689. DECLARE_TOOLHELP32_FIND(CFindHeapList, HEAPLIST32, Heap32ListFirst, Heap32ListNext);
  2690. DECLARE_TOOLHELP32_FIND(CFindModule, MODULEENTRY32, Module32First, Module32Next);
  2691. DECLARE_TOOLHELP32_FIND(CFindProcess, PROCESSENTRY32, Process32First, Process32Next);
  2692. DECLARE_TOOLHELP32_FIND(CFindThread, THREADENTRY32, Thread32First, Thread32Next);
  2693. //////////////////////////////////////////////////////////////////////////
  2694. //
  2695. // FindProcessId
  2696. //
  2697. // Returns the id of the process specified by name
  2698. //
  2699. inline DWORD FindProcessId(PCTSTR pProcessName)
  2700. {
  2701. CToolhelp32Snapshot Snapshot(TH32CS_SNAPPROCESS);
  2702. for (CFindProcess pe32(Snapshot); pe32.IsFound(); pe32.FindNext())
  2703. {
  2704. if (_tcsicmp(FindFileNamePortion(pe32.szExeFile), pProcessName) == 0)
  2705. {
  2706. return pe32.th32ProcessID;
  2707. }
  2708. }
  2709. return 0;
  2710. }
  2711. #endif //_INC_TOOLHELP32
  2712. //////////////////////////////////////////////////////////////////////////
  2713. //
  2714. // CFindWindow
  2715. //
  2716. // Wrapper class for finding child windows
  2717. //
  2718. class CFindWindow
  2719. {
  2720. public:
  2721. CFindWindow(
  2722. HWND hWnd
  2723. )
  2724. {
  2725. m_hChild = ::GetTopWindow(hWnd);
  2726. }
  2727. VOID
  2728. FindNext()
  2729. {
  2730. m_hChild = ::GetNextWindow(
  2731. m_hChild,
  2732. GW_HWNDNEXT
  2733. );
  2734. }
  2735. operator HWND() const
  2736. {
  2737. return m_hChild;
  2738. }
  2739. BOOL
  2740. IsFound() const
  2741. {
  2742. return m_hChild != 0;
  2743. }
  2744. private:
  2745. HWND m_hChild;
  2746. };
  2747. #ifdef _WINSVC_
  2748. //////////////////////////////////////////////////////////////////////////
  2749. //
  2750. // CService
  2751. //
  2752. // Wrapper class for service objects
  2753. //
  2754. class CService : public CHandle<SC_HANDLE, CService>
  2755. {
  2756. typedef CHandle<SC_HANDLE, CService> parent_type;
  2757. public:
  2758. CService()
  2759. {
  2760. }
  2761. CService(
  2762. SC_HANDLE hHandle
  2763. ) :
  2764. parent_type(hHandle)
  2765. {
  2766. }
  2767. void Destroy()
  2768. {
  2769. ::CloseServiceHandle(*this);
  2770. }
  2771. bool IsValid()
  2772. {
  2773. return *this != 0;
  2774. }
  2775. VOID
  2776. StartService(
  2777. DWORD dwNumServiceArgs = 0,
  2778. LPCTSTR *lpServiceArgVectors = 0
  2779. )
  2780. {
  2781. if (QueryServiceStatus().dwCurrentState != SERVICE_RUNNING)
  2782. {
  2783. CHECK(::StartService(
  2784. *this,
  2785. dwNumServiceArgs,
  2786. lpServiceArgVectors
  2787. ));
  2788. while (QueryServiceStatus().dwCurrentState != SERVICE_RUNNING)
  2789. {
  2790. //bugbug: this might cause a hang
  2791. }
  2792. }
  2793. }
  2794. SERVICE_STATUS &
  2795. QueryServiceStatus()
  2796. {
  2797. CHECK(::QueryServiceStatus(*this, &m_ss));
  2798. return m_ss;
  2799. }
  2800. VOID
  2801. DeleteService() const
  2802. {
  2803. CHECK(::DeleteService(*this));
  2804. }
  2805. VOID
  2806. ControlService(
  2807. DWORD dwControl
  2808. )
  2809. {
  2810. CHECK(::ControlService(*this, dwControl, &m_ss));
  2811. }
  2812. VOID
  2813. ChangeServiceState(
  2814. DWORD dwControl,
  2815. DWORD dwNewState
  2816. )
  2817. {
  2818. if (QueryServiceStatus().dwCurrentState != dwNewState)
  2819. {
  2820. ControlService(dwControl);
  2821. while (QueryServiceStatus().dwCurrentState != dwNewState)
  2822. {
  2823. //bugbug: this might cause a hang
  2824. }
  2825. }
  2826. }
  2827. VOID
  2828. StopService()
  2829. {
  2830. ChangeServiceState(SERVICE_CONTROL_STOP, SERVICE_STOPPED);
  2831. }
  2832. VOID
  2833. PauseService()
  2834. {
  2835. ChangeServiceState(SERVICE_CONTROL_PAUSE, SERVICE_PAUSED);
  2836. }
  2837. VOID
  2838. ContinueService()
  2839. {
  2840. ChangeServiceState(SERVICE_CONTROL_CONTINUE, SERVICE_RUNNING);
  2841. }
  2842. friend class CSCManager;
  2843. private:
  2844. SERVICE_STATUS m_ss;
  2845. };
  2846. //////////////////////////////////////////////////////////////////////////
  2847. //
  2848. // CSCManager
  2849. //
  2850. // Wrapper class for service control manager
  2851. //
  2852. class CSCManager : public CHandle<SC_HANDLE, CSCManager>
  2853. {
  2854. typedef CHandle<SC_HANDLE, CSCManager> parent_type;
  2855. public:
  2856. explicit
  2857. CSCManager(
  2858. PCTSTR pRemoteComputerName = 0,
  2859. PCTSTR pDatabaseName = SERVICES_ACTIVE_DATABASE,
  2860. DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS
  2861. ) :
  2862. parent_type(OpenSCManager(
  2863. pRemoteComputerName,
  2864. pDatabaseName,
  2865. dwDesiredAccess
  2866. ))
  2867. {
  2868. }
  2869. void Destroy()
  2870. {
  2871. CloseServiceHandle(*this);
  2872. }
  2873. bool IsValid()
  2874. {
  2875. return *this != 0;
  2876. }
  2877. public:
  2878. SC_HANDLE
  2879. CreateService(
  2880. PCTSTR pServiceName,
  2881. PCTSTR pDisplayName,
  2882. DWORD dwDesiredAccess,
  2883. DWORD dwServiceType,
  2884. DWORD dwStartType,
  2885. DWORD dwErrorControl,
  2886. PCTSTR pBinaryPathName,
  2887. PCTSTR pLoadOrderGroup = 0,
  2888. PDWORD pdwTagId = 0,
  2889. PCTSTR pDependencies = 0,
  2890. PCTSTR pServiceStartName = 0,
  2891. PCTSTR pPassword = 0
  2892. ) const
  2893. {
  2894. return ::CreateService(
  2895. *this,
  2896. pServiceName,
  2897. pDisplayName,
  2898. dwDesiredAccess,
  2899. dwServiceType,
  2900. dwStartType,
  2901. dwErrorControl,
  2902. pBinaryPathName,
  2903. pLoadOrderGroup,
  2904. pdwTagId,
  2905. pDependencies,
  2906. pServiceStartName,
  2907. pPassword
  2908. );
  2909. }
  2910. SC_HANDLE
  2911. OpenService(
  2912. PCTSTR pServiceName,
  2913. DWORD dwDesiredAccess = SERVICE_ALL_ACCESS
  2914. ) const
  2915. {
  2916. return ::OpenService(
  2917. *this,
  2918. pServiceName,
  2919. dwDesiredAccess
  2920. );
  2921. }
  2922. };
  2923. #endif //_WINSVC_
  2924. //////////////////////////////////////////////////////////////////////////
  2925. //
  2926. // CPath
  2927. //
  2928. // Base class for wrapper classes that deal with path names
  2929. //
  2930. #ifdef _IOSTREAM_
  2931. template <int N> class CPath;
  2932. template <int N> std::ostream &operator <<(std::ostream &os, const CPath<N> &rhs);
  2933. #endif //_IOSTREAM_
  2934. template <int N = MAX_PATH>
  2935. class CPath
  2936. {
  2937. public:
  2938. CPath()
  2939. {
  2940. m_szName[0] = _T('\0');
  2941. m_szName[1] = _T('\0');
  2942. m_dwLength = 0;
  2943. }
  2944. CPath(PCTSTR pName)
  2945. {
  2946. assign(pName);
  2947. }
  2948. CPath & operator =(PCTSTR pName)
  2949. {
  2950. return assign(pName);
  2951. }
  2952. CPath & assign(PCTSTR pName)
  2953. {
  2954. _tcsncpy(m_szName, pName, N);
  2955. FindLength();
  2956. return *this;
  2957. }
  2958. DWORD length() const
  2959. {
  2960. return m_dwLength;
  2961. }
  2962. bool empty() const
  2963. {
  2964. return m_szName[0] == _T('\0');
  2965. }
  2966. operator PCTSTR() const
  2967. {
  2968. return m_szName;
  2969. }
  2970. PCTSTR FileName() const
  2971. {
  2972. return m_szName + m_dwLength + 1;
  2973. }
  2974. CPath & operator +=(PCTSTR pName)
  2975. {
  2976. SetFileName(pName);
  2977. FindLength();
  2978. return *this;
  2979. }
  2980. CPath & SetFileName(PCTSTR pName)
  2981. {
  2982. m_szName[m_dwLength] = _T('\\');
  2983. _tcsncpy(m_szName + m_dwLength + 1, pName, N - m_dwLength - 1);
  2984. return *this;
  2985. }
  2986. CPath & StripFileName()
  2987. {
  2988. m_szName[m_dwLength] = _T('\0');
  2989. return *this;
  2990. }
  2991. void FindLength()
  2992. {
  2993. m_dwLength = _tcslen(m_szName);
  2994. while (m_dwLength && m_szName[m_dwLength-1] == _T('\\'))
  2995. {
  2996. m_szName[--m_dwLength] = _T('\0');
  2997. }
  2998. }
  2999. //bugbug: just to please the VC5 compiler, drop templates
  3000. //template <int M>
  3001. bool operator ==(const CPath/*<M>*/ &rhs) const
  3002. {
  3003. return
  3004. m_dwLength == rhs.m_dwLength &&
  3005. _tcscmp(m_szName, rhs.m_szName) == 0;
  3006. }
  3007. //template <int M>
  3008. bool operator !=(const CPath/*<M>*/ &rhs) const
  3009. {
  3010. return !(*this == rhs);
  3011. }
  3012. //template <int M>
  3013. bool operator >(const CPath/*<M>*/ &rhs) const
  3014. {
  3015. return
  3016. m_dwLength > rhs.m_dwLength ||
  3017. _tcscmp(m_szName, rhs.m_szName) > 0;
  3018. }
  3019. //template <int M>
  3020. bool operator <=(const CPath/*<M>*/ &rhs) const
  3021. {
  3022. return !(*this > rhs);
  3023. }
  3024. //template <int M>
  3025. bool operator <(const CPath/*<M>*/ &rhs) const
  3026. {
  3027. return
  3028. m_dwLength < rhs.m_dwLength ||
  3029. _tcscmp(m_szName, rhs.m_szName) < 0;
  3030. }
  3031. //template <int M>
  3032. bool operator >=(const CPath/*<M>*/ &rhs) const
  3033. {
  3034. return !(*this < rhs);
  3035. }
  3036. #ifdef _IOSTREAM_
  3037. friend std::ostream &operator <<(std::ostream &os, const CPath<N> &rhs)
  3038. {
  3039. return os << m_szName;
  3040. }
  3041. #endif //_IOSTREAM_
  3042. protected:
  3043. TCHAR m_szName[N];
  3044. DWORD m_dwLength;
  3045. };
  3046. //////////////////////////////////////////////////////////////////////////
  3047. //
  3048. // CWindowsDirectory
  3049. //
  3050. // Wrapper class for the GetWindowsDirectory() API
  3051. //
  3052. class CWindowsDirectory : public CPath<>
  3053. {
  3054. public:
  3055. CWindowsDirectory()
  3056. {
  3057. CHECK(::GetWindowsDirectory(
  3058. m_szName,
  3059. COUNTOF(m_szName)
  3060. ));
  3061. FindLength();
  3062. }
  3063. };
  3064. //////////////////////////////////////////////////////////////////////////
  3065. //
  3066. // CSystemWindowsDirectory
  3067. //
  3068. // Wrapper class for the GetSystemWindowsDirectory() API
  3069. //
  3070. class CSystemWindowsDirectory : public CPath<>
  3071. {
  3072. public:
  3073. CSystemWindowsDirectory()
  3074. {
  3075. typedef UINT (WINAPI *PFN)(LPTSTR lpBuffer, UINT uSize);
  3076. static PFN pfn = (PFN) GetProcAddress(
  3077. ::GetModuleHandle(_T("kernel32.dll")),
  3078. "GetSystemWindowsDirectory"_AW
  3079. );
  3080. if (pfn)
  3081. {
  3082. CHECK((*pfn)(
  3083. m_szName,
  3084. COUNTOF(m_szName)
  3085. ));
  3086. }
  3087. else
  3088. {
  3089. CHECK(::GetWindowsDirectory(
  3090. m_szName,
  3091. COUNTOF(m_szName)
  3092. ));
  3093. }
  3094. FindLength();
  3095. }
  3096. };
  3097. //////////////////////////////////////////////////////////////////////////
  3098. //
  3099. // CSystemDirectory
  3100. //
  3101. // Wrapper class for the GetSystemDirectory() API
  3102. //
  3103. class CSystemDirectory : public CPath<>
  3104. {
  3105. public:
  3106. CSystemDirectory()
  3107. {
  3108. CHECK(::GetSystemDirectory(
  3109. m_szName,
  3110. COUNTOF(m_szName)
  3111. ));
  3112. FindLength();
  3113. }
  3114. };
  3115. //////////////////////////////////////////////////////////////////////////
  3116. //
  3117. // CCurrentDirectory
  3118. //
  3119. // Wrapper class for the GetCurrentDirectory() API
  3120. //
  3121. class CCurrentDirectory : public CPath<>
  3122. {
  3123. public:
  3124. CCurrentDirectory()
  3125. {
  3126. CHECK(::GetCurrentDirectory(
  3127. COUNTOF(m_szName),
  3128. m_szName
  3129. ));
  3130. FindLength();
  3131. }
  3132. };
  3133. //////////////////////////////////////////////////////////////////////////
  3134. //
  3135. // CModuleFileName
  3136. //
  3137. // Wrapper class for the GetModuleFileName() API
  3138. //
  3139. class CModuleFileName : public CPath<>
  3140. {
  3141. public:
  3142. CModuleFileName(
  3143. HMODULE hModule = 0
  3144. )
  3145. {
  3146. CHECK(::GetModuleFileName(
  3147. hModule,
  3148. m_szName,
  3149. COUNTOF(m_szName)
  3150. ));
  3151. FindLength();
  3152. }
  3153. };
  3154. #ifdef _ICM_H_
  3155. //////////////////////////////////////////////////////////////////////////
  3156. //
  3157. // CColorDirectory
  3158. //
  3159. // Wrapper class for the GetColorDirectory() API
  3160. //
  3161. class CColorDirectory : public CPath<>
  3162. {
  3163. public:
  3164. explicit
  3165. CColorDirectory(
  3166. PCTSTR pMachineName = 0
  3167. )
  3168. {
  3169. m_dwLength = sizeof(m_szName);
  3170. CHECK(GetColorDirectory(
  3171. pMachineName,
  3172. m_szName,
  3173. &m_dwLength
  3174. ));
  3175. FindLength();
  3176. }
  3177. };
  3178. #endif //_ICM_H_
  3179. //////////////////////////////////////////////////////////////////////////
  3180. //
  3181. // CComputerName
  3182. //
  3183. // Wrapper class for the GetComputerName() API
  3184. //
  3185. class CComputerName : public CPath<2 + MAX_COMPUTERNAME_LENGTH + 1>
  3186. {
  3187. public:
  3188. CComputerName(
  3189. BOOL bUNC = FALSE
  3190. )
  3191. {
  3192. if (bUNC)
  3193. {
  3194. m_dwLength = COUNTOF(m_szName) - 2;
  3195. CHECK(::GetComputerName(
  3196. m_szName + 2,
  3197. &m_dwLength
  3198. ));
  3199. m_szName[0] = '\\';
  3200. m_szName[1] = '\\';
  3201. }
  3202. else
  3203. {
  3204. m_dwLength = COUNTOF(m_szName);
  3205. CHECK(::GetComputerName(
  3206. m_szName,
  3207. &m_dwLength
  3208. ));
  3209. }
  3210. FindLength();
  3211. }
  3212. };
  3213. //////////////////////////////////////////////////////////////////////////
  3214. //
  3215. // CFullPathName
  3216. //
  3217. // Wrapper class for the GetFullPathName() API
  3218. //
  3219. class CFullPathName : public CPath<>
  3220. {
  3221. public:
  3222. CFullPathName(
  3223. PCTSTR pFileName
  3224. )
  3225. {
  3226. if (pFileName && *pFileName)
  3227. {
  3228. PTSTR pFilePart;
  3229. CHECK(::GetFullPathName(
  3230. pFileName,
  3231. COUNTOF(m_szName),
  3232. m_szName,
  3233. &pFilePart
  3234. ));
  3235. m_dwLength = (DWORD)(pFilePart - m_szName - 1);
  3236. }
  3237. }
  3238. };
  3239. //////////////////////////////////////////////////////////////////////////
  3240. //
  3241. // CTempFileName
  3242. //
  3243. // Wrapper class for the GetTempPath() API
  3244. //
  3245. class CTempPath : public CPath<>
  3246. {
  3247. public:
  3248. CTempPath()
  3249. {
  3250. CHECK(::GetTempPath(
  3251. COUNTOF(m_szName),
  3252. m_szName
  3253. ));
  3254. FindLength();
  3255. }
  3256. };
  3257. //////////////////////////////////////////////////////////////////////////
  3258. //
  3259. // CTempFileName
  3260. //
  3261. // Wrapper class for the GetTempFileName() API
  3262. //
  3263. class CTempFileName : public CPath<>
  3264. {
  3265. public:
  3266. CTempFileName(
  3267. PCTSTR pPathName,
  3268. PCTSTR pPrefixString,
  3269. UINT uUnique = 0
  3270. )
  3271. {
  3272. CHECK(::GetTempFileName(
  3273. pPathName,
  3274. pPrefixString,
  3275. uUnique,
  3276. m_szName
  3277. ));
  3278. FindLength();
  3279. }
  3280. };
  3281. //////////////////////////////////////////////////////////////////////////
  3282. //
  3283. // CWindowText
  3284. //
  3285. // Wrapper class for the GetWindowText() API
  3286. //
  3287. class CWindowText : public CPath<1024> //bugbug
  3288. {
  3289. public:
  3290. CWindowText(
  3291. HWND hWnd
  3292. )
  3293. {
  3294. ::SetLastError(0);
  3295. CHECK(
  3296. ::GetWindowText(hWnd, m_szName, COUNTOF(m_szName)) ||
  3297. ::GetLastError() == 0
  3298. );
  3299. }
  3300. };
  3301. //////////////////////////////////////////////////////////////////////////
  3302. //
  3303. // CSafeWindowText
  3304. //
  3305. // Helper class for the GetClassName() API (that works better on Win9x)
  3306. //
  3307. class CSafeWindowText : public CPath<1024> //bugbug
  3308. {
  3309. public:
  3310. CSafeWindowText(
  3311. HWND hWnd
  3312. )
  3313. {
  3314. WNDPROC pfnWndProc = (WNDPROC) GetWindowLongPtr(
  3315. hWnd,
  3316. GWLP_WNDPROC
  3317. );
  3318. CallWindowProc(
  3319. pfnWndProc,
  3320. hWnd,
  3321. WM_GETTEXT,
  3322. COUNTOF(m_szName),
  3323. (LPARAM) m_szName
  3324. );
  3325. }
  3326. };
  3327. //////////////////////////////////////////////////////////////////////////
  3328. //
  3329. // CClassName
  3330. //
  3331. // Wrapper class for the GetClassName() API
  3332. //
  3333. class CClassName : public CPath<1024> //bugbug
  3334. {
  3335. public:
  3336. CClassName(
  3337. HWND hWnd
  3338. )
  3339. {
  3340. CHECK(::GetClassName(
  3341. hWnd,
  3342. m_szName,
  3343. COUNTOF(m_szName)
  3344. ));
  3345. }
  3346. };
  3347. //////////////////////////////////////////////////////////////////////////
  3348. //
  3349. // CConsoleTitle
  3350. //
  3351. // Wrapper class for the GetConsoleTitle() API
  3352. //
  3353. class CConsoleTitle : public CPath<1024> //bugbug
  3354. {
  3355. public:
  3356. CConsoleTitle()
  3357. {
  3358. CHECK(::GetConsoleTitle(
  3359. m_szName,
  3360. COUNTOF(m_szName)
  3361. ));
  3362. }
  3363. };
  3364. //////////////////////////////////////////////////////////////////////////
  3365. //
  3366. // CUserName
  3367. //
  3368. // Returns a handle to the console window
  3369. //
  3370. inline HWND GetConsoleHwnd()
  3371. {
  3372. HWND hConsoleWnd = 0;
  3373. try
  3374. {
  3375. // read the current console title
  3376. CConsoleTitle OldTitle;
  3377. // change the title to a supposedly random value
  3378. TCHAR szNewTitle[17];
  3379. wsprintf(
  3380. szNewTitle,
  3381. _T("%08x%08x"),
  3382. GetTickCount(),
  3383. GetCurrentProcessId()
  3384. );
  3385. SetConsoleTitle(szNewTitle);
  3386. Sleep(50);
  3387. // try find the window based on this new title
  3388. HWND hWnd = FindWindow(0, szNewTitle);
  3389. // restore the title
  3390. SetConsoleTitle(OldTitle);
  3391. Sleep(50);
  3392. // compare the title of the window we found against the console title
  3393. CWindowText HWndTitle(hWnd);
  3394. if (_tcscmp(OldTitle, HWndTitle) == 0)
  3395. {
  3396. hConsoleWnd = hWnd;
  3397. }
  3398. }
  3399. catch (const CError &)
  3400. {
  3401. }
  3402. return hConsoleWnd;
  3403. }
  3404. //////////////////////////////////////////////////////////////////////////
  3405. //
  3406. // CUserName
  3407. //
  3408. // Wrapper class for the GetUserName API
  3409. //
  3410. #ifndef UNLEN
  3411. #define UNLEN 256
  3412. #endif //UNLEN
  3413. class CUserName : public CPath<UNLEN + 1>
  3414. {
  3415. public:
  3416. CUserName()
  3417. {
  3418. m_dwLength = COUNTOF(m_szName);
  3419. CHECK(::GetUserName(
  3420. m_szName,
  3421. &m_dwLength
  3422. ));
  3423. }
  3424. };
  3425. //////////////////////////////////////////////////////////////////////////
  3426. //
  3427. // CRegString
  3428. //
  3429. // Helper class for reading a string with the RegQueryValueEx() API
  3430. //
  3431. template <int N>
  3432. class CRegString : public CPath<N>
  3433. {
  3434. public:
  3435. CRegString()
  3436. {
  3437. }
  3438. CRegString(
  3439. HKEY hKey,
  3440. PCTSTR pSubKey,
  3441. PTSTR pValueName,
  3442. BOOL bExpandEnvironmentStrings = TRUE
  3443. )
  3444. {
  3445. CKey Key(
  3446. hKey,
  3447. pSubKey,
  3448. KEY_READ
  3449. );
  3450. DWORD dwType;
  3451. m_dwLength = sizeof(m_szName);
  3452. Key.RegQueryValueEx(
  3453. pValueName,
  3454. &dwType,
  3455. m_szName,
  3456. &m_dwLength
  3457. );
  3458. if (dwType == REG_EXPAND_SZ && bExpandEnvironmentStrings)
  3459. {
  3460. TCHAR szExpanded[N];
  3461. CHECK(ExpandEnvironmentStrings(
  3462. m_szName,
  3463. szExpanded,
  3464. COUNTOF(szExpanded)
  3465. ));
  3466. _tcscpy(m_szName, szExpanded);
  3467. }
  3468. FindLength();
  3469. }
  3470. // bugbug: Aren't we supposed to inherit this?
  3471. CPath<N> &
  3472. operator =(
  3473. PCTSTR pName
  3474. )
  3475. {
  3476. return CPath<N>::operator =(pName);
  3477. }
  3478. };
  3479. //////////////////////////////////////////////////////////////////////////
  3480. //
  3481. // CResourceString
  3482. //
  3483. // Wrapper class for the LoadString() API
  3484. //
  3485. template <int N>
  3486. class CResourceString : public CPath<N>
  3487. {
  3488. public:
  3489. CResourceString()
  3490. {
  3491. }
  3492. explicit
  3493. CResourceString(
  3494. UINT uID,
  3495. HINSTANCE hInstance = 0
  3496. )
  3497. {
  3498. CHECK(m_dwLength = LoadString(
  3499. hInstance,
  3500. uID,
  3501. m_szName,
  3502. COUNTOF(m_szName)
  3503. ));
  3504. }
  3505. CResourceString(
  3506. UINT uID,
  3507. HINSTANCE hInstance,
  3508. PCTSTR pszDefault
  3509. )
  3510. {
  3511. m_dwLength = LoadString(
  3512. hInstance,
  3513. uID,
  3514. m_szName,
  3515. COUNTOF(m_szName)
  3516. );
  3517. if (m_dwLength == 0)
  3518. {
  3519. assign(pszDefault);
  3520. }
  3521. }
  3522. };
  3523. #ifdef _WINSPOOL_
  3524. //////////////////////////////////////////////////////////////////////////
  3525. //
  3526. // CPrinterDriverDirectory
  3527. //
  3528. // Wrapper class for the GetPrinterDriverDirectory() API
  3529. //
  3530. class CPrinterDriverDirectory : public CPath<>
  3531. {
  3532. public:
  3533. explicit
  3534. CPrinterDriverDirectory(
  3535. PTSTR pName = 0,
  3536. PTSTR pEnvironment = 0
  3537. )
  3538. {
  3539. m_dwLength = sizeof(m_szName);
  3540. CHECK(::GetPrinterDriverDirectory(
  3541. pName,
  3542. pEnvironment,
  3543. 1,
  3544. (PBYTE) m_szName,
  3545. m_dwLength,
  3546. &m_dwLength
  3547. ));
  3548. FindLength();
  3549. }
  3550. };
  3551. //////////////////////////////////////////////////////////////////////////
  3552. //
  3553. // CPrintProcessorDirectory
  3554. //
  3555. // Wrapper class for the GetPrintProcessorDirectory() API
  3556. //
  3557. class CPrintProcessorDirectory : public CPath<>
  3558. {
  3559. public:
  3560. explicit
  3561. CPrintProcessorDirectory(
  3562. PTSTR pName = 0,
  3563. PTSTR pEnvironment = 0
  3564. )
  3565. {
  3566. m_dwLength = sizeof(m_szName);
  3567. CHECK(::GetPrintProcessorDirectory(
  3568. pName,
  3569. pEnvironment,
  3570. 1,
  3571. (PBYTE) m_szName,
  3572. m_dwLength,
  3573. &m_dwLength
  3574. ));
  3575. FindLength();
  3576. }
  3577. };
  3578. //////////////////////////////////////////////////////////////////////////
  3579. //
  3580. // CDefaultPrinter
  3581. //
  3582. // Wrapper class for the GetDefaultPrinter() API
  3583. //
  3584. #ifndef INTERNET_MAX_HOST_NAME_LENGTH
  3585. #define INTERNET_MAX_HOST_NAME_LENGTH 256
  3586. #endif
  3587. class CDefaultPrinter : public CPath<2 + INTERNET_MAX_HOST_NAME_LENGTH + 1 + MAX_PATH + 1>
  3588. {
  3589. public:
  3590. CDefaultPrinter()
  3591. {
  3592. typedef BOOL (WINAPI *PFN)(LPTSTR, LPDWORD);
  3593. static PFN pfnGetDefaultPrinter = (PFN) GetProcAddress(
  3594. ::GetModuleHandle(_T("winspool.drv")),
  3595. "GetDefaultPrinter"_AW
  3596. );
  3597. m_dwLength = sizeof(m_szName);
  3598. if (pfnGetDefaultPrinter)
  3599. {
  3600. pfnGetDefaultPrinter(
  3601. m_szName,
  3602. &m_dwLength
  3603. );
  3604. }
  3605. else
  3606. {
  3607. GetProfileString(
  3608. _T("windows"),
  3609. _T("device"),
  3610. _T(",,,"),
  3611. m_szName,
  3612. COUNTOF(m_szName)
  3613. );
  3614. PTSTR pComma = _tcschr(m_szName, ',');
  3615. if (pComma)
  3616. {
  3617. *pComma = _T('\0');
  3618. }
  3619. }
  3620. FindLength();
  3621. }
  3622. };
  3623. //////////////////////////////////////////////////////////////////////////
  3624. //
  3625. // CPrinterDefaults
  3626. //
  3627. // Wrapper class for PRINTER_DEFAULTS struct
  3628. //
  3629. struct CPrinterDefaults : public PRINTER_DEFAULTS
  3630. {
  3631. CPrinterDefaults(
  3632. PTSTR _pDatatype = 0,
  3633. PDEVMODE _pDevMode = 0,
  3634. ACCESS_MASK _DesiredAccess = PRINTER_ALL_ACCESS
  3635. )
  3636. {
  3637. pDatatype = _pDatatype;
  3638. pDevMode = _pDevMode;
  3639. DesiredAccess = _DesiredAccess;
  3640. }
  3641. };
  3642. //////////////////////////////////////////////////////////////////////////
  3643. //
  3644. // printer_info_to_level, level_to_printer_info
  3645. //
  3646. // Traits classes to map PRINTER_INFO_XXX to level numbers and vice versa
  3647. //
  3648. template<class T> struct printer_info_to_level { };
  3649. template<> struct printer_info_to_level<PRINTER_INFO_1> { enum { level = 1 }; };
  3650. template<> struct printer_info_to_level<PRINTER_INFO_2> { enum { level = 2 }; };
  3651. template<> struct printer_info_to_level<PRINTER_INFO_3> { enum { level = 3 }; };
  3652. template<> struct printer_info_to_level<PRINTER_INFO_4> { enum { level = 4 }; };
  3653. template<> struct printer_info_to_level<PRINTER_INFO_5> { enum { level = 5 }; };
  3654. template<> struct printer_info_to_level<PRINTER_INFO_6> { enum { level = 6 }; };
  3655. template<> struct printer_info_to_level<PRINTER_INFO_7> { enum { level = 7 }; };
  3656. template<> struct printer_info_to_level<PRINTER_INFO_8> { enum { level = 8 }; };
  3657. template<> struct printer_info_to_level<PRINTER_INFO_9> { enum { level = 9 }; };
  3658. template<int N> struct level_to_printer_info { };
  3659. template<> struct level_to_printer_info<1> { typedef PRINTER_INFO_1 struct_type; };
  3660. template<> struct level_to_printer_info<2> { typedef PRINTER_INFO_2 struct_type; };
  3661. template<> struct level_to_printer_info<3> { typedef PRINTER_INFO_3 struct_type; };
  3662. template<> struct level_to_printer_info<4> { typedef PRINTER_INFO_4 struct_type; };
  3663. template<> struct level_to_printer_info<5> { typedef PRINTER_INFO_5 struct_type; };
  3664. template<> struct level_to_printer_info<6> { typedef PRINTER_INFO_6 struct_type; };
  3665. template<> struct level_to_printer_info<7> { typedef PRINTER_INFO_7 struct_type; };
  3666. template<> struct level_to_printer_info<8> { typedef PRINTER_INFO_8 struct_type; };
  3667. template<> struct level_to_printer_info<9> { typedef PRINTER_INFO_9 struct_type; };
  3668. //////////////////////////////////////////////////////////////////////////
  3669. //
  3670. // CPrinter
  3671. //
  3672. // Wrapper class for printer objects
  3673. //
  3674. class CPrinter : public CHandle<HANDLE, CPrinter>
  3675. {
  3676. typedef CHandle<HANDLE, CPrinter> parent_type;
  3677. public:
  3678. explicit
  3679. CPrinter(
  3680. PCTSTR pPrinterName,
  3681. const PRINTER_DEFAULTS *pDefault = &CPrinterDefaults()
  3682. )
  3683. {
  3684. HANDLE hHandle;
  3685. CHECK(::OpenPrinter(
  3686. const_cast<PTSTR>(pPrinterName),
  3687. &hHandle,
  3688. const_cast<PPRINTER_DEFAULTS>(pDefault)
  3689. ));
  3690. Attach(hHandle);
  3691. }
  3692. CPrinter(
  3693. PTSTR pServerName,
  3694. const PRINTER_INFO_2 *pPrinter
  3695. ) :
  3696. parent_type(::AddPrinter(
  3697. pServerName,
  3698. 2,
  3699. (PBYTE) pPrinter
  3700. ))
  3701. {
  3702. }
  3703. void Destroy()
  3704. {
  3705. ::ClosePrinter(*this);
  3706. }
  3707. bool IsValid()
  3708. {
  3709. return *this != 0;
  3710. }
  3711. VOID
  3712. Delete() const
  3713. {
  3714. CHECK(::DeletePrinter(*this));
  3715. }
  3716. template <class T>
  3717. VOID
  3718. SetPrinter(T *pPrinterInfo)
  3719. {
  3720. CHECK(::SetPrinter(
  3721. *this,
  3722. printer_info_to_level<T>::level,
  3723. (PBYTE) pPrinterInfo,
  3724. 0
  3725. ));
  3726. }
  3727. };
  3728. //////////////////////////////////////////////////////////////////////////
  3729. //
  3730. // DeletePrinterDriverExRetry
  3731. //
  3732. // Helper for DeletePrinterDriverEx() API that implements wait & retry
  3733. //
  3734. inline
  3735. BOOL
  3736. DeletePrinterDriverExRetry(
  3737. PTSTR pName,
  3738. PTSTR pEnvironment,
  3739. PTSTR pDriverName,
  3740. DWORD dwDeleteFlag,
  3741. DWORD dwVersionFlag,
  3742. int nMaxRetries = 3,
  3743. DWORD dwSleepMilliseconds = 1000
  3744. )
  3745. {
  3746. BOOL bResult = FALSE;
  3747. for (
  3748. int nRetries = 0;
  3749. (bResult = DeletePrinterDriverEx(
  3750. pName,
  3751. pEnvironment,
  3752. pDriverName,
  3753. dwDeleteFlag,
  3754. dwVersionFlag
  3755. )) == FALSE &&
  3756. GetLastError() == ERROR_PRINTER_DRIVER_IN_USE &&
  3757. nRetries < nMaxRetries;
  3758. ++nRetries
  3759. )
  3760. {
  3761. Sleep(dwSleepMilliseconds);
  3762. }
  3763. return bResult;
  3764. }
  3765. //////////////////////////////////////////////////////////////////////////
  3766. //
  3767. // AddMonitor
  3768. //
  3769. // Helper for AddMonitor() API that infers the struct level at compile time
  3770. //
  3771. template<class T> struct monitor_info_to_level { };
  3772. template<> struct monitor_info_to_level<MONITOR_INFO_1> { enum { level = 1 }; };
  3773. template<> struct monitor_info_to_level<MONITOR_INFO_2> { enum { level = 2 }; };
  3774. template <class T>
  3775. inline
  3776. BOOL
  3777. AddMonitor(
  3778. PTSTR pName,
  3779. T *pMonitors
  3780. )
  3781. {
  3782. return ::AddMonitor(
  3783. pName,
  3784. monitor_info_to_level<T>::level,
  3785. (PBYTE) pMonitors
  3786. );
  3787. }
  3788. //////////////////////////////////////////////////////////////////////////
  3789. //
  3790. // CPrinterChangeNotification
  3791. //
  3792. // Wrapper class for printer change notifications
  3793. //
  3794. class CPrinterChangeNotification : public CHandle<HANDLE, CPrinter>
  3795. {
  3796. typedef CHandle<HANDLE, CPrinter> parent_type;
  3797. public:
  3798. CPrinterChangeNotification(
  3799. HANDLE hPrinter,
  3800. DWORD fdwFlags,
  3801. PPRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions = 0
  3802. ) :
  3803. parent_type(::FindFirstPrinterChangeNotification(
  3804. hPrinter,
  3805. fdwFlags,
  3806. 0,
  3807. pPrinterNotifyOptions
  3808. ))
  3809. {
  3810. }
  3811. void Destroy()
  3812. {
  3813. ::FindClosePrinterChangeNotification(*this);
  3814. }
  3815. bool IsValid()
  3816. {
  3817. return (HANDLE) *this != INVALID_HANDLE_VALUE;
  3818. }
  3819. DWORD
  3820. FindNext(
  3821. PPRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions = 0,
  3822. PPRINTER_NOTIFY_INFO *ppPrinterNotifyInfo = 0
  3823. )
  3824. {
  3825. DWORD dwChange;
  3826. CHECK(::FindNextPrinterChangeNotification(
  3827. *this,
  3828. &dwChange,
  3829. pPrinterNotifyOptions,
  3830. (PVOID *) ppPrinterNotifyInfo
  3831. ));
  3832. return dwChange;
  3833. }
  3834. };
  3835. #endif //_WINSPOOL_
  3836. //////////////////////////////////////////////////////////////////////////
  3837. //
  3838. // CStringFileInfo
  3839. //
  3840. // Helper class for creating \StringFileInfo\lang-codepage\name type strings
  3841. //
  3842. class CStringFileInfo : public CPath<80>
  3843. {
  3844. public:
  3845. CStringFileInfo(
  3846. WORD wLang,
  3847. WORD wCodePage
  3848. )
  3849. {
  3850. _stprintf(
  3851. m_szName,
  3852. _T("\\StringFileInfo\\%04X%04X"),
  3853. wLang,
  3854. wCodePage
  3855. );
  3856. FindLength();
  3857. }
  3858. CStringFileInfo(
  3859. DWORD dwLangCodePage
  3860. )
  3861. {
  3862. _stprintf(
  3863. m_szName,
  3864. _T("\\StringFileInfo\\%04X%04X"),
  3865. LOWORD(dwLangCodePage),
  3866. HIWORD(dwLangCodePage)
  3867. );
  3868. FindLength();
  3869. }
  3870. };
  3871. //////////////////////////////////////////////////////////////////////////
  3872. //
  3873. // CVersionInfo
  3874. //
  3875. // Helper class for parsing version resource information
  3876. //
  3877. class CVersionInfo
  3878. {
  3879. public:
  3880. CVersionInfo(
  3881. PCTSTR pFileName = 0
  3882. )
  3883. {
  3884. CModuleFileName ModuleFileName;
  3885. if (!pFileName)
  3886. {
  3887. pFileName = ModuleFileName;
  3888. }
  3889. DWORD dwVerInfoSize;
  3890. DWORD dwHandle;
  3891. CHECK(dwVerInfoSize = GetFileVersionInfoSize(
  3892. const_cast<PTSTR>(pFileName),
  3893. &dwHandle
  3894. ));
  3895. CCppMem<BYTE> VerInfo(dwVerInfoSize);
  3896. CHECK(::GetFileVersionInfo(
  3897. const_cast<PTSTR>(pFileName),
  3898. dwHandle,
  3899. dwVerInfoSize,
  3900. VerInfo
  3901. ));
  3902. m_VerInfo = VerInfo;
  3903. }
  3904. PVOID
  3905. VerQueryValue(
  3906. PCTSTR pSubBlock
  3907. ) const
  3908. {
  3909. PVOID pBuffer;
  3910. UINT uLen;
  3911. CHECK(::VerQueryValue(
  3912. m_VerInfo,
  3913. const_cast<PTSTR>(pSubBlock),
  3914. &pBuffer,
  3915. &uLen
  3916. ));
  3917. return pBuffer;
  3918. }
  3919. VS_FIXEDFILEINFO *GetFixedFileInfo() const
  3920. {
  3921. return (VS_FIXEDFILEINFO *) VerQueryValue(_T("\\"));
  3922. }
  3923. PDWORD GetTranslation() const
  3924. {
  3925. return (PDWORD) VerQueryValue(_T("\\VarFileInfo\\Translation"));
  3926. }
  3927. PCTSTR
  3928. GetStringFileInfo(
  3929. WORD wLang,
  3930. WORD wCodePage,
  3931. PCTSTR pSubBlock
  3932. ) const
  3933. {
  3934. return (PCTSTR) VerQueryValue(CStringFileInfo(wLang, wCodePage).SetFileName(pSubBlock));
  3935. }
  3936. ULARGE_INTEGER
  3937. GetFileVersion() const
  3938. {
  3939. VS_FIXEDFILEINFO *pFixedFileInfo = GetFixedFileInfo();
  3940. ULARGE_INTEGER nVersion =
  3941. {
  3942. pFixedFileInfo->dwFileVersionLS,
  3943. pFixedFileInfo->dwFileVersionMS
  3944. };
  3945. return nVersion;
  3946. }
  3947. ULARGE_INTEGER
  3948. GetProductVersion() const
  3949. {
  3950. VS_FIXEDFILEINFO *pFixedFileInfo = GetFixedFileInfo();
  3951. ULARGE_INTEGER nVersion =
  3952. {
  3953. pFixedFileInfo->dwProductVersionLS,
  3954. pFixedFileInfo->dwProductVersionMS
  3955. };
  3956. return nVersion;
  3957. }
  3958. private:
  3959. CCppMem<BYTE> m_VerInfo;
  3960. };
  3961. //////////////////////////////////////////////////////////////////////////
  3962. //
  3963. // CResource
  3964. //
  3965. // Wrapper class for FindResourceEx(), LoadResource() and LockResource() APIs
  3966. //
  3967. class CResource
  3968. {
  3969. public:
  3970. CResource(
  3971. HMODULE hModule,
  3972. PCTSTR pType,
  3973. PCTSTR pName,
  3974. WORD wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
  3975. )
  3976. {
  3977. HRSRC hResInfo;
  3978. CHECK(hResInfo = FindResourceEx(hModule, pType, pName, wLanguage));
  3979. HGLOBAL hResData;
  3980. CHECK(hResData = LoadResource(hModule, hResInfo));
  3981. CHECK(m_pData = LockResource(hResData));
  3982. CHECK(m_nSize = SizeofResource(hModule, hResInfo));
  3983. }
  3984. PVOID Data()
  3985. {
  3986. return m_pData;
  3987. }
  3988. DWORD Size()
  3989. {
  3990. return m_nSize;
  3991. }
  3992. private:
  3993. PVOID m_pData;
  3994. DWORD m_nSize;
  3995. };
  3996. //////////////////////////////////////////////////////////////////////////
  3997. //
  3998. // CDialogResource
  3999. //
  4000. // Helper class for parsing a dialog resource
  4001. //
  4002. class CDialogResource
  4003. {
  4004. public:
  4005. CDialogResource(
  4006. HMODULE hModule,
  4007. PCTSTR pName,
  4008. WORD wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
  4009. )
  4010. {
  4011. CResource Dlg(hModule, RT_DIALOG, pName, wLanguage);
  4012. ParseDlgResource(Dlg.Data());
  4013. }
  4014. CDialogResource(
  4015. PVOID pDlgResource
  4016. )
  4017. {
  4018. ParseDlgResource(pDlgResource);
  4019. }
  4020. private:
  4021. class CParseDlgResource
  4022. {
  4023. public:
  4024. CParseDlgResource(
  4025. PVOID pDlgResource
  4026. )
  4027. {
  4028. Goto(pDlgResource);
  4029. }
  4030. void
  4031. Goto(PVOID pDlgResource)
  4032. {
  4033. m_pNextValue = (PBYTE) pDlgResource;
  4034. }
  4035. template <class T>
  4036. void Read(T &Value)
  4037. {
  4038. Value = *(T *) m_pNextValue;
  4039. m_pNextValue += sizeof(T);
  4040. }
  4041. template <>
  4042. void Read(PWSTR &pStr)
  4043. {
  4044. pStr = (PWSTR) m_pNextValue;
  4045. if (*pStr == MAXWORD)
  4046. {
  4047. pStr = (PWSTR) pStr[1];
  4048. m_pNextValue += 2 * sizeof(WCHAR);
  4049. }
  4050. else
  4051. {
  4052. m_pNextValue += (wcslen(pStr) + 1) * sizeof(WCHAR);
  4053. }
  4054. }
  4055. private:
  4056. PBYTE m_pNextValue;
  4057. };
  4058. private:
  4059. void ParseDlgResource(PVOID pDlgResource)
  4060. {
  4061. ZeroMemory(this, sizeof(*this));
  4062. CParseDlgResource Parser(pDlgResource);
  4063. Parser.Read(dlgVer);
  4064. Parser.Read(signature);
  4065. BOOL bIsExTemplate = dlgVer == 1 && signature == MAXWORD;
  4066. if (bIsExTemplate)
  4067. {
  4068. Parser.Read(helpID);
  4069. Parser.Read(exStyle);
  4070. Parser.Read(style);
  4071. }
  4072. else
  4073. {
  4074. Parser.Goto(pDlgResource);
  4075. Parser.Read(style);
  4076. Parser.Read(exStyle);
  4077. }
  4078. Parser.Read(cDlgItems);
  4079. Parser.Read(x);
  4080. Parser.Read(y);
  4081. Parser.Read(cx);
  4082. Parser.Read(cy);
  4083. Parser.Read(menu);
  4084. Parser.Read(windowClass);
  4085. Parser.Read(title);
  4086. if (style & DS_SHELLFONT)
  4087. {
  4088. if (bIsExTemplate)
  4089. {
  4090. Parser.Read(pointsize);
  4091. Parser.Read(weight);
  4092. Parser.Read(italic);
  4093. Parser.Read(charset);
  4094. Parser.Read(typeface);
  4095. }
  4096. else
  4097. {
  4098. Parser.Read(pointsize);
  4099. Parser.Read(typeface);
  4100. }
  4101. }
  4102. }
  4103. public:
  4104. WORD dlgVer;
  4105. WORD signature;
  4106. DWORD helpID;
  4107. DWORD exStyle;
  4108. DWORD style;
  4109. WORD cDlgItems;
  4110. short x;
  4111. short y;
  4112. short cx;
  4113. short cy;
  4114. PWSTR menu;
  4115. PWSTR windowClass;
  4116. PWSTR title;
  4117. WORD pointsize;
  4118. WORD weight;
  4119. BYTE italic;
  4120. BYTE charset;
  4121. PWSTR typeface;
  4122. };
  4123. //////////////////////////////////////////////////////////////////////////
  4124. //
  4125. // CStringTable
  4126. //
  4127. template <int nFirstId, int nLastId>
  4128. class CStringTable
  4129. {
  4130. public:
  4131. CStringTable(
  4132. HINSTANCE hInstance = GetModuleHandle(0)
  4133. )
  4134. {
  4135. TCHAR szBuffer[4098]; // max length of a resource string
  4136. for (int i = 0; i < m_nStrings; ++i)
  4137. {
  4138. int nLength = LoadString(
  4139. hInstance,
  4140. i + nFirstId,
  4141. szBuffer,
  4142. COUNTOF(szBuffer)
  4143. );
  4144. m_pTable[i] = new TCHAR[nLength + 1];
  4145. if (nLength && m_pTable[i])
  4146. {
  4147. CopyMemory(
  4148. m_pTable[i],
  4149. szBuffer,
  4150. nLength * sizeof(TCHAR)
  4151. );
  4152. }
  4153. }
  4154. }
  4155. ~CStringTable()
  4156. {
  4157. for (int i = 0; i < m_nStrings; ++i)
  4158. {
  4159. if (m_pTable[i])
  4160. {
  4161. delete [] m_pTable[i];
  4162. }
  4163. }
  4164. }
  4165. PCTSTR operator[](int i)
  4166. {
  4167. ASSERT(nFirstId <= i && i <= nLastId);
  4168. return m_pTable[i - nFirstId];
  4169. }
  4170. private:
  4171. enum { m_nStrings = nLastId - nFirstId + 1 };
  4172. PTSTR m_pTable[m_nStrings];
  4173. };
  4174. #ifdef _NTSECAPI_
  4175. //////////////////////////////////////////////////////////////////////////
  4176. //
  4177. // CLsaUnicodeString
  4178. //
  4179. // Wrapper class for LSA_UNICODE_STRING struct
  4180. //
  4181. class CLsaUnicodeString : public LSA_UNICODE_STRING
  4182. {
  4183. public:
  4184. CLsaUnicodeString(
  4185. PWSTR pStr
  4186. )
  4187. {
  4188. if (pStr)
  4189. {
  4190. Buffer = pStr;
  4191. Length = (USHORT) (wcslen(pStr) * sizeof(WCHAR));
  4192. MaximumLength = (USHORT) (Length + sizeof(WCHAR));
  4193. }
  4194. else
  4195. {
  4196. Buffer = 0;
  4197. Length = 0;
  4198. MaximumLength = 0;
  4199. }
  4200. }
  4201. };
  4202. #endif //_NTSECAPI_
  4203. //////////////////////////////////////////////////////////////////////////
  4204. //
  4205. // COSVersionInfo
  4206. //
  4207. // Wrapper class for GetVersion() API
  4208. //
  4209. class COSVersionInfo : public OSVERSIONINFO
  4210. {
  4211. public:
  4212. COSVersionInfo()
  4213. {
  4214. dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  4215. CHECK(GetVersionEx(this));
  4216. }
  4217. };
  4218. //////////////////////////////////////////////////////////////////////////
  4219. //
  4220. // COSVersionInfoEx
  4221. //
  4222. // Wrapper class for GetVersionEx() API
  4223. //
  4224. class COSVersionInfoEx : public OSVERSIONINFOEX
  4225. {
  4226. public:
  4227. COSVersionInfoEx()
  4228. {
  4229. dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  4230. CHECK(GetVersionEx((POSVERSIONINFO)this));
  4231. }
  4232. };
  4233. #ifdef _INC_CDERR
  4234. //////////////////////////////////////////////////////////////////////////
  4235. //
  4236. // COpenFileName
  4237. //
  4238. // Wrapper class for GetOpenFileName() and GetSaveFileName() APIs
  4239. //
  4240. template <int nFileNameLen = MAX_PATH, int nFileTitleSize = MAX_PATH, int nCustomFilterSize = MAX_PATH>
  4241. class COpenFileName : public OPENFILENAME
  4242. {
  4243. public:
  4244. COpenFileName(
  4245. HWND hWndOwner = 0,
  4246. PCTSTR pFilter = 0,
  4247. PCTSTR pInitialDir = 0,
  4248. PCTSTR pTitle = 0,
  4249. PCTSTR pDefExt = 0,
  4250. DWORD dwFlags = 0
  4251. )
  4252. {
  4253. ZeroMemory(this, sizeof(*this));
  4254. lStructSize = sizeof(OPENFILENAME);
  4255. hwndOwner = hWndOwner;
  4256. hInstance = 0;
  4257. lpstrFilter = pFilter;
  4258. lpstrCustomFilter = m_szCustomFilter;
  4259. nMaxCustFilter = COUNTOF(m_szCustomFilter);
  4260. nFilterIndex = 1;
  4261. lpstrFile = m_szFileName;
  4262. nMaxFile = COUNTOF(m_szFileName);
  4263. lpstrFileTitle = m_szFileTitle;
  4264. nMaxFileTitle = COUNTOF(m_szFileTitle);
  4265. lpstrInitialDir = pInitialDir;
  4266. lpstrTitle = pTitle;
  4267. Flags =
  4268. dwFlags |
  4269. OFN_EXPLORER |
  4270. OFN_HIDEREADONLY |
  4271. OFN_OVERWRITEPROMPT |
  4272. OFN_FILEMUSTEXIST;
  4273. lpstrDefExt = pDefExt;
  4274. }
  4275. BOOL
  4276. GetOpenFileName()
  4277. {
  4278. BOOL bResult = ::GetOpenFileName(this);
  4279. if (!bResult && CommDlgExtendedError() == CDERR_STRUCTSIZE)
  4280. {
  4281. lStructSize = OPENFILENAME_SIZE_VERSION_400;
  4282. bResult = ::GetOpenFileName(this);
  4283. }
  4284. return bResult;
  4285. }
  4286. BOOL
  4287. GetSaveFileName()
  4288. {
  4289. BOOL bResult = ::GetSaveFileName(this);
  4290. if (!bResult && CommDlgExtendedError() == CDERR_STRUCTSIZE)
  4291. {
  4292. lStructSize = OPENFILENAME_SIZE_VERSION_400;
  4293. bResult = ::GetSaveFileName(this);
  4294. }
  4295. return bResult;
  4296. }
  4297. private:
  4298. TCHAR m_szFileName[nFileNameLen];
  4299. TCHAR m_szFileTitle[nFileTitleSize];
  4300. TCHAR m_szCustomFilter[nCustomFilterSize];
  4301. };
  4302. #endif //_INC_CDERR
  4303. #ifdef _SHLOBJ_H_
  4304. //////////////////////////////////////////////////////////////////////////
  4305. //
  4306. // CBrowseInfo
  4307. //
  4308. // Wrapper class for SHBrowseForFolder() API
  4309. //
  4310. template <int nPathNameLen = MAX_PATH>
  4311. class CBrowseInfo : public BROWSEINFO
  4312. {
  4313. public:
  4314. CBrowseInfo(
  4315. HWND _hWndOwner = 0,
  4316. UINT _ulFlags = 0
  4317. )
  4318. {
  4319. ZeroMemory(this, sizeof(*this));
  4320. hwndOwner = _hWndOwner;
  4321. pszDisplayName = m_szPath;
  4322. ulFlags = _ulFlags;
  4323. }
  4324. BOOL
  4325. BrowseForFolder()
  4326. {
  4327. LPITEMIDLIST pidl = SHBrowseForFolder(this);
  4328. if (pidl)
  4329. {
  4330. TCHAR szPath[nPathNameLen];
  4331. if (SHGetPathFromIDList(pidl, szPath))
  4332. {
  4333. _tcscpy(m_szPath, szPath);
  4334. }
  4335. SHFree(pidl);
  4336. return TRUE;
  4337. }
  4338. return FALSE;
  4339. }
  4340. private:
  4341. TCHAR m_szPath[nPathNameLen];
  4342. };
  4343. #endif //_SHLOBJ_H_
  4344. #ifdef _INC_SETUPAPI
  4345. //////////////////////////////////////////////////////////////////////////
  4346. //
  4347. // CInf
  4348. //
  4349. // Wrapper class for Inf file parsing object and APIs
  4350. //
  4351. class CInf : public CHandle<HINF, CInf>
  4352. {
  4353. typedef CHandle<HINF, CInf> parent_type;
  4354. public:
  4355. CInf()
  4356. {
  4357. }
  4358. explicit
  4359. CInf(
  4360. PCTSTR FileName,
  4361. PCTSTR InfClass = 0,
  4362. DWORD InfStyle = INF_STYLE_WIN4,
  4363. PUINT ErrorLine = 0
  4364. ) :
  4365. parent_type(::SetupOpenInfFile(
  4366. FileName,
  4367. InfClass,
  4368. InfStyle,
  4369. ErrorLine
  4370. ))
  4371. {
  4372. }
  4373. public:
  4374. void Destroy()
  4375. {
  4376. ::SetupCloseInfFile(*this);
  4377. }
  4378. bool IsValid()
  4379. {
  4380. return *this != 0;
  4381. }
  4382. };
  4383. #endif //_INC_SETUPAPI
  4384. //////////////////////////////////////////////////////////////////////////
  4385. //
  4386. // CDisplayWaitCursor
  4387. //
  4388. // Helper class that displays the wait cursor
  4389. //
  4390. class CDisplayWaitCursor
  4391. {
  4392. DISABLE_COPY_CONTRUCTION(CDisplayWaitCursor)
  4393. public:
  4394. CDisplayWaitCursor()
  4395. {
  4396. m_hOldCursor = SetCursor(LoadCursor(0, IDC_WAIT));
  4397. }
  4398. ~CDisplayWaitCursor()
  4399. {
  4400. SetCursor(m_hOldCursor);
  4401. }
  4402. private:
  4403. HCURSOR m_hOldCursor;
  4404. };
  4405. //////////////////////////////////////////////////////////////////////////
  4406. //
  4407. // CSystemInfo
  4408. //
  4409. // Wrapper class for the GetSystemInfo() API
  4410. //
  4411. class CSystemInfo : public SYSTEM_INFO
  4412. {
  4413. public:
  4414. CSystemInfo()
  4415. {
  4416. GetSystemInfo(this);
  4417. }
  4418. };
  4419. //////////////////////////////////////////////////////////////////////////
  4420. //
  4421. // CProc
  4422. //
  4423. // Wrapper class for the GetProcAddress() API
  4424. //
  4425. template <class prototype>
  4426. class CProc
  4427. {
  4428. public:
  4429. CProc(
  4430. prototype pfnDefault = 0
  4431. ) :
  4432. m_pfnProc(pfnDefault)
  4433. {
  4434. }
  4435. CProc(
  4436. HMODULE hModule,
  4437. PCSTR pProcName
  4438. )
  4439. {
  4440. CHECK(m_pfnProc = (prototype) ::GetProcAddress(
  4441. hModule,
  4442. pProcName
  4443. ));
  4444. }
  4445. CProc(
  4446. HMODULE hModule,
  4447. PCSTR pProcName,
  4448. prototype pfnDefault
  4449. )
  4450. {
  4451. m_pfnProc = (prototype) ::GetProcAddress(
  4452. hModule,
  4453. pProcName
  4454. );
  4455. if (m_pfnProc == 0)
  4456. {
  4457. m_pfnProc = pfnDefault;
  4458. }
  4459. }
  4460. operator prototype() const
  4461. {
  4462. return m_pfnProc;
  4463. }
  4464. private:
  4465. prototype m_pfnProc;
  4466. };
  4467. //////////////////////////////////////////////////////////////////////////
  4468. //
  4469. // DECL_CWINAPI
  4470. //
  4471. // Creates wrapper classes for fail-safe API address loading
  4472. //
  4473. #define DECL_CWINAPI(return_type, decl_spec, func_name, args) \
  4474. \
  4475. class C##func_name : public CProc<return_type (decl_spec *) args> \
  4476. { \
  4477. public: \
  4478. typedef return_type (decl_spec *prototype) args; \
  4479. \
  4480. C##func_name() : \
  4481. CProc<prototype>(DefaultAPI) \
  4482. { \
  4483. } \
  4484. \
  4485. C##func_name( \
  4486. HMODULE hModule, \
  4487. PCSTR pProcName = #func_name \
  4488. ) : \
  4489. CProc<prototype>( \
  4490. hModule, \
  4491. pProcName, \
  4492. DefaultAPI \
  4493. ) \
  4494. { \
  4495. } \
  4496. \
  4497. protected: \
  4498. static return_type decl_spec DefaultAPI args \
  4499. { \
  4500. ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); \
  4501. return 0; \
  4502. } \
  4503. \
  4504. } func_name \
  4505. //////////////////////////////////////////////////////////////////////////
  4506. //
  4507. // CBlob
  4508. //
  4509. // Contains a binary block of data specified by its start address and size
  4510. //
  4511. struct CBlob
  4512. {
  4513. const void *pData;
  4514. SIZE_T cbData;
  4515. CBlob()
  4516. {
  4517. }
  4518. CBlob(const void *_pData, SIZE_T _cbData)
  4519. {
  4520. pData = _pData;
  4521. cbData = _cbData;
  4522. }
  4523. };
  4524. //////////////////////////////////////////////////////////////////////////
  4525. //
  4526. // CStrBlob
  4527. //
  4528. // Contains an ANSI or UNICODE string without a terminating NULL
  4529. //
  4530. struct CStrBlob : public CBlob
  4531. {
  4532. explicit CStrBlob(PCSTR pStr)
  4533. {
  4534. if (pStr)
  4535. {
  4536. pData = pStr;
  4537. cbData = strlen(pStr) * sizeof(CHAR);
  4538. }
  4539. else
  4540. {
  4541. pData = "";
  4542. cbData = 0;
  4543. }
  4544. }
  4545. explicit CStrBlob(PCWSTR pStr)
  4546. {
  4547. if (pStr)
  4548. {
  4549. pData = pStr;
  4550. cbData = wcslen(pStr) * sizeof(WCHAR);
  4551. }
  4552. else
  4553. {
  4554. pData = "";
  4555. cbData = 0;
  4556. }
  4557. }
  4558. };
  4559. //////////////////////////////////////////////////////////////////////////
  4560. //
  4561. // CSzBlob
  4562. //
  4563. // Contains an ANSI or UNICODE string with a terminating NULL
  4564. //
  4565. struct CSzBlob : public CStrBlob
  4566. {
  4567. explicit CSzBlob(PCSTR pStr) : CStrBlob(pStr)
  4568. {
  4569. cbData += sizeof(CHAR);
  4570. }
  4571. explicit CSzBlob(PCWSTR pStr) : CStrBlob(pStr)
  4572. {
  4573. cbData += sizeof(WCHAR);
  4574. }
  4575. };
  4576. //////////////////////////////////////////////////////////////////////////
  4577. //
  4578. // CMultiSzBlob
  4579. //
  4580. // Contains a NULL terminated list of ANSI or UNICODE NULL terminated strings
  4581. //
  4582. struct CMultiSzBlob : public CBlob
  4583. {
  4584. explicit CMultiSzBlob(PCSTR pStr)
  4585. {
  4586. if (pStr)
  4587. {
  4588. pData = pStr;
  4589. cbData = (multiszlenA(pStr) + 1) * sizeof(CHAR);
  4590. }
  4591. else
  4592. {
  4593. pData = "\0";
  4594. cbData = 2 * sizeof(CHAR);
  4595. }
  4596. }
  4597. explicit CMultiSzBlob(PCWSTR pStr)
  4598. {
  4599. if (pStr)
  4600. {
  4601. pData = pStr;
  4602. cbData = (multiszlenW(pStr) + 1) * sizeof(WCHAR);
  4603. }
  4604. else
  4605. {
  4606. pData = L"\0";
  4607. cbData = 2 * sizeof(WCHAR);
  4608. }
  4609. }
  4610. };
  4611. //////////////////////////////////////////////////////////////////////////
  4612. //
  4613. // CBufferFill
  4614. //
  4615. // Helper class for filling in a block of memory in an overflow safe way
  4616. //
  4617. class CBufferFill
  4618. {
  4619. public:
  4620. CBufferFill(PVOID pBuffer, SIZE_T cbBuffer)
  4621. {
  4622. m_pTop = (PBYTE) pBuffer;
  4623. m_pEnd = (PBYTE) pBuffer + cbBuffer;
  4624. }
  4625. INT_PTR BytesLeft() const
  4626. {
  4627. return m_pEnd - m_pTop;
  4628. }
  4629. PVOID AddTop(const CBlob &Blob)
  4630. {
  4631. PVOID pDest = m_pTop;
  4632. m_pTop += Blob.cbData;
  4633. if (BytesLeft() >= 0)
  4634. {
  4635. CopyMemory(pDest, Blob.pData, Blob.cbData);
  4636. }
  4637. return pDest;
  4638. }
  4639. PVOID AddEnd(const CBlob &Blob)
  4640. {
  4641. m_pEnd -= Blob.cbData;
  4642. if (BytesLeft() >= 0)
  4643. {
  4644. CopyMemory(m_pEnd, Blob.pData, Blob.cbData);
  4645. }
  4646. return m_pEnd;
  4647. }
  4648. private:
  4649. PBYTE m_pTop;
  4650. PBYTE m_pEnd;
  4651. };
  4652. #if 0 //bugbug: not ready for prime time yet
  4653. //////////////////////////////////////////////////////////////////////////
  4654. //
  4655. // _tstring
  4656. //
  4657. // Helper class that handles UNICODE to ANSI conversions
  4658. //
  4659. _STD_BEGIN
  4660. class _tstring : public basic_string<TCHAR>
  4661. {
  4662. public:
  4663. _tstring(PCOSTR pStr)
  4664. {
  4665. ostr = pStr;
  4666. }
  4667. _tstring &operator =(PCOSTR pStr)
  4668. {
  4669. ostr = pStr;
  4670. return *this;
  4671. }
  4672. operator PCTSTR() const
  4673. {
  4674. if (empty())
  4675. {
  4676. USES_CONVERSION;
  4677. assign(T2O(ostr.c_str()));
  4678. }
  4679. return c_str();
  4680. }
  4681. operator PCOSTR() const
  4682. {
  4683. if (ostr.empty())
  4684. {
  4685. USES_CONVERSION;
  4686. ostr = T2O(c_str());
  4687. }
  4688. return ostr.c_str();
  4689. }
  4690. private:
  4691. basic_string<OCHAR> ostr;
  4692. };
  4693. _STD_END
  4694. #endif
  4695. //////////////////////////////////////////////////////////////////////////
  4696. //
  4697. // CMySimpleCriticalSection
  4698. //
  4699. // Implementation for a simple critical section class that does not
  4700. // handle recursions
  4701. //
  4702. class CMySimpleCriticalSection
  4703. {
  4704. public:
  4705. CMySimpleCriticalSection()
  4706. {
  4707. m_lLockCount = -1;
  4708. m_hLockHandle = 0;
  4709. }
  4710. ~CMySimpleCriticalSection()
  4711. {
  4712. if (m_hLockHandle)
  4713. {
  4714. CloseHandle(m_hLockHandle);
  4715. }
  4716. }
  4717. VOID
  4718. Enter()
  4719. {
  4720. if (InterlockedIncrement(&m_lLockCount) != 0)
  4721. {
  4722. CheckLockHandle();
  4723. WaitForSingleObject(m_hLockHandle, INFINITE);
  4724. }
  4725. }
  4726. VOID
  4727. Leave()
  4728. {
  4729. if (InterlockedDecrement(&m_lLockCount) >= 0)
  4730. {
  4731. CheckLockHandle();
  4732. SetEvent(m_hLockHandle);
  4733. }
  4734. }
  4735. BOOL
  4736. TryEnter()
  4737. {
  4738. return InterlockedCompareExchange(&m_lLockCount, 0, -1) == -1;
  4739. }
  4740. protected:
  4741. VOID
  4742. CheckLockHandle()
  4743. {
  4744. if (!m_hLockHandle)
  4745. {
  4746. HANDLE hLockHandle;
  4747. CHECK(hLockHandle = CreateEvent(0, FALSE, FALSE, 0));
  4748. if (InterlockedCompareExchangePointer(&m_hLockHandle, hLockHandle, 0) != 0)
  4749. {
  4750. // another thread initialized and stored an hLockHandle
  4751. // before us, better close ours
  4752. CloseHandle(hLockHandle);
  4753. }
  4754. }
  4755. }
  4756. protected:
  4757. LONG m_lLockCount;
  4758. HANDLE m_hLockHandle;
  4759. };
  4760. //////////////////////////////////////////////////////////////////////////
  4761. //
  4762. // CMyCriticalSection
  4763. //
  4764. // Implementation for a full blown critical section class
  4765. //
  4766. class CMyCriticalSection : public CMySimpleCriticalSection
  4767. {
  4768. public:
  4769. CMyCriticalSection()
  4770. {
  4771. m_lRecursionCount = 0;
  4772. m_dwOwningThreadId = 0;
  4773. }
  4774. BOOL
  4775. Enter(
  4776. DWORD dwMilliseconds = INFINITE,
  4777. BOOL bAlertable = FALSE
  4778. )
  4779. {
  4780. DWORD dwCurrentThreadId = GetCurrentThreadId();
  4781. if (InterlockedIncrement(&m_lLockCount) == 0)
  4782. {
  4783. m_dwOwningThreadId = dwCurrentThreadId;
  4784. m_lRecursionCount = 1;
  4785. return TRUE;
  4786. }
  4787. else
  4788. {
  4789. if (m_dwOwningThreadId == dwCurrentThreadId)
  4790. {
  4791. ++m_lRecursionCount;
  4792. return TRUE;
  4793. }
  4794. else
  4795. {
  4796. CheckLockHandle();
  4797. DWORD dwWaitResult = WaitForSingleObjectEx(
  4798. m_hLockHandle,
  4799. dwMilliseconds,
  4800. bAlertable
  4801. );
  4802. if (dwWaitResult == WAIT_OBJECT_0)
  4803. {
  4804. m_dwOwningThreadId = dwCurrentThreadId;
  4805. m_lRecursionCount = 1;
  4806. return TRUE;
  4807. }
  4808. else
  4809. {
  4810. return FALSE;
  4811. }
  4812. }
  4813. }
  4814. }
  4815. VOID
  4816. Leave()
  4817. {
  4818. if (--m_lRecursionCount != 0)
  4819. {
  4820. InterlockedDecrement(&m_lLockCount);
  4821. }
  4822. else
  4823. {
  4824. m_dwOwningThreadId = 0;
  4825. if (InterlockedDecrement(&m_lLockCount) >= 0)
  4826. {
  4827. CheckLockHandle();
  4828. SetEvent(m_hLockHandle);
  4829. }
  4830. }
  4831. }
  4832. BOOL
  4833. TryEnter()
  4834. {
  4835. DWORD dwCurrentThreadId = GetCurrentThreadId();
  4836. if (InterlockedCompareExchange(&m_lLockCount, 0, -1) == -1)
  4837. {
  4838. m_dwOwningThreadId = dwCurrentThreadId;
  4839. m_lRecursionCount = 1;
  4840. return TRUE;
  4841. }
  4842. else
  4843. {
  4844. if (m_dwOwningThreadId == dwCurrentThreadId)
  4845. {
  4846. InterlockedIncrement(&m_lLockCount);
  4847. ++m_lRecursionCount;
  4848. return TRUE;
  4849. }
  4850. else
  4851. {
  4852. return FALSE;
  4853. }
  4854. }
  4855. }
  4856. protected:
  4857. LONG m_lRecursionCount;
  4858. DWORD m_dwOwningThreadId;
  4859. };
  4860. //////////////////////////////////////////////////////////////////////////
  4861. //
  4862. // CMultipleWait
  4863. //
  4864. // Wrapper class for the WaitForMultipleObjectsEx() API
  4865. //
  4866. class CMultipleWait : public CCppMem<HANDLE>
  4867. {
  4868. public:
  4869. CMultipleWait(
  4870. int nCount
  4871. ) :
  4872. m_nCount(nCount),
  4873. CCppMem<HANDLE>(nCount)
  4874. {
  4875. }
  4876. DWORD
  4877. WaitFor(
  4878. BOOL bWaitAll = TRUE,
  4879. DWORD dwMilliseconds = INFINITE,
  4880. BOOL bAlertable = FALSE
  4881. )
  4882. {
  4883. return WaitForMultipleObjectsEx(
  4884. m_nCount,
  4885. *this,
  4886. bWaitAll,
  4887. dwMilliseconds,
  4888. bAlertable
  4889. );
  4890. }
  4891. void
  4892. Erase(
  4893. int nFirstHandle,
  4894. int nNumHandles = 1
  4895. )
  4896. {
  4897. m_nCount -= nNumHandles;
  4898. MoveData(
  4899. *this + nFirstHandle,
  4900. *this + nFirstHandle + nNumHandles,
  4901. m_nCount - nFirstHandle
  4902. );
  4903. }
  4904. private:
  4905. int m_nCount;
  4906. };
  4907. //////////////////////////////////////////////////////////////////////////
  4908. #endif //_WRAPPERS_H_