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.

1378 lines
37 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/system/version_info.hpp (originally in MWVerInf.h, ::SynesisWin)
  3. *
  4. * Purpose: Helper for accessing version information.
  5. *
  6. * Created: 16th February 1998
  7. * Updated: 19th May 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1998-2010, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file winstl/system/version_info.hpp
  40. *
  41. * \brief [C++ only] Definition of the winstl::version_info class
  42. * template
  43. * (\ref group__library__system "System" Library).
  44. */
  45. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_VERSION_INFO
  46. #define WINSTL_INCL_WINSTL_SYSTEM_HPP_VERSION_INFO
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define WINSTL_VER_WINSTL_SYSTEM_HPP_VERSION_INFO_MAJOR 5
  49. # define WINSTL_VER_WINSTL_SYSTEM_HPP_VERSION_INFO_MINOR 2
  50. # define WINSTL_VER_WINSTL_SYSTEM_HPP_VERSION_INFO_REVISION 8
  51. # define WINSTL_VER_WINSTL_SYSTEM_HPP_VERSION_INFO_EDIT 126
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  57. # include <winstl/winstl.h>
  58. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  59. #ifndef WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS
  60. # include <winstl/error/exceptions.hpp>
  61. #endif /* !WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS */
  62. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  63. _MSC_VER < 1200
  64. # if defined(UNICODE) || \
  65. defined(_UNICODE)
  66. # error winstl::version_info is not supported on Visual C++ 5.0 (or previous) with UNICODE compilations
  67. # endif /* Unicode */
  68. # define WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER
  69. #else /* ? compiler */
  70. # ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER
  71. # include <winstl/filesystem/file_path_buffer.hpp>
  72. # endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER */
  73. #endif /* compiler */
  74. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  75. # include <winstl/memory/processheap_allocator.hpp>
  76. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  77. #ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST
  78. # include <stlsoft/conversion/sap_cast.hpp>
  79. #endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST */
  80. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  81. # include <stlsoft/shims/access/string.hpp>
  82. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  83. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  84. # include <stlsoft/util/std/iterator_helper.hpp>
  85. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  86. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  87. # include <stlsoft/collections/util/collections.hpp>
  88. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  89. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  90. # include <stdexcept> // for std::exception
  91. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  92. #ifndef STLSOFT_INCL_H_WCHAR
  93. # define STLSOFT_INCL_H_WCHAR
  94. # include <wchar.h>
  95. #endif /* !STLSOFT_INCL_H_WCHAR */
  96. #ifdef STLSOFT_UNITTEST
  97. # include <stdio.h>
  98. #endif /* STLSOFT_UNITTEST */
  99. /* /////////////////////////////////////////////////////////////////////////
  100. * Namespace
  101. */
  102. #ifndef _WINSTL_NO_NAMESPACE
  103. # if defined(_STLSOFT_NO_NAMESPACE) || \
  104. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  105. /* There is no stlsoft namespace, so must define ::winstl */
  106. namespace winstl
  107. {
  108. # else
  109. /* Define stlsoft::winstl_project */
  110. namespace stlsoft
  111. {
  112. namespace winstl_project
  113. {
  114. # endif /* _STLSOFT_NO_NAMESPACE */
  115. #endif /* !_WINSTL_NO_NAMESPACE */
  116. /* /////////////////////////////////////////////////////////////////////////
  117. * Structure headers
  118. */
  119. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  120. // The following bizarre construction is solely to avoid an ICE in VC6
  121. // that only raises its ugly head in large, non-trivial, compilation
  122. // contexts.
  123. template<ss_typename_param_k T>
  124. struct hdr
  125. {
  126. template<int N>
  127. struct hdr_
  128. {
  129. WORD wLength;
  130. WORD wValueLength;
  131. WORD wType;
  132. WCHAR szKey[1];
  133. };
  134. }; // namespace hdr
  135. typedef hdr<int>::hdr_<1> VS_VERSIONINFO_hdr;
  136. typedef hdr<int>::hdr_<2> StringFileInfo_hdr;
  137. typedef hdr<int>::hdr_<3> VarFileInfo_hdr;
  138. typedef hdr<int>::hdr_<4> Var_hdr;
  139. typedef hdr<int>::hdr_<5> StringTable_hdr;
  140. typedef hdr<int>::hdr_<6> String_hdr;
  141. template<ss_typename_param_k T>
  142. T* rounded_ptr(T* p, ss_size_t n)
  143. {
  144. union
  145. {
  146. T* p;
  147. ss_size_t cb;
  148. } u;
  149. u.p = p;
  150. u.cb = ((n - 1) + u.cb) & ~(n- 1);
  151. WINSTL_ASSERT(ptr_byte_diff(u.p, p) >= 0);
  152. return u.p;
  153. }
  154. template<ss_typename_param_k T>
  155. T* rounded_ptr(T* p, ss_ptrdiff_t byteOffset, ss_size_t n)
  156. {
  157. // 1. This has to be done in a ridiculously long-hand fashion because Borland is a *very* stupid compiler!
  158. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  159. void const* pv = &byteOffset[(char*)p];
  160. #else /* ? compiler */
  161. void const* pv = ptr_byte_offset(p, byteOffset);
  162. #endif /* compiler */
  163. WINSTL_ASSERT(((char*)pv - (char*)p) == byteOffset);
  164. T* p_ = static_cast<T*>(pv);
  165. T* r = rounded_ptr(p_, n);
  166. #ifdef STLSOFT_COMPILER_IS_BORLAND
  167. STLSOFT_SUPPRESS_UNUSED(p);
  168. STLSOFT_SUPPRESS_UNUSED(byteOffset);
  169. #endif /* compiler */
  170. WINSTL_ASSERT(ptr_byte_diff(r, p_) >= 0);
  171. return r;
  172. }
  173. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  174. /* /////////////////////////////////////////////////////////////////////////
  175. * Classes
  176. */
  177. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  178. /** \brief Exception thrown by the version_info class.
  179. *
  180. * \ingroup group__library__system
  181. */
  182. class version_info_exception
  183. : public windows_exception
  184. {
  185. /// \name Member Types
  186. /// @{
  187. public:
  188. typedef windows_exception parent_class_type;
  189. typedef version_info_exception class_type;
  190. /// @}
  191. /// \name Construction
  192. /// @{
  193. public:
  194. version_info_exception(char const* reason, error_code_type err)
  195. : parent_class_type(reason, err)
  196. {}
  197. /// @}
  198. };
  199. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  200. /** \brief Represents the fixed part of a version information block
  201. *
  202. * \ingroup group__library__system
  203. */
  204. class fixed_file_info
  205. {
  206. typedef fixed_file_info class_type;
  207. public:
  208. /// Constructor
  209. fixed_file_info(VS_FIXEDFILEINFO const* ffi);
  210. public:
  211. ws_uint16_t ApiVerHigh() const;
  212. ws_uint16_t ApiVerLow() const;
  213. /// The major part of the file version
  214. ws_uint16_t FileVerMajor() const;
  215. /// The minor part of the file version
  216. ws_uint16_t FileVerMinor() const;
  217. /// The revision part of the file version
  218. ws_uint16_t FileVerRevision() const;
  219. /// The build increment part of the file version
  220. ws_uint16_t FileVerBuild() const;
  221. /// The major part of the product version
  222. ws_uint16_t ProductVerMajor() const;
  223. /// The minor part of the product version
  224. ws_uint16_t ProductVerMinor() const;
  225. /// The revision part of the product version
  226. ws_uint16_t ProductVerRevision() const;
  227. /// The build increment part of the product version
  228. ws_uint16_t ProductVerBuild() const;
  229. /// The file flags mask
  230. ws_uint32_t FileFlagsMask() const;
  231. /// The file flags
  232. ws_uint32_t FileFlags() const;
  233. /// The file operating system
  234. ws_uint32_t FileOS() const;
  235. /// The file type
  236. ws_uint32_t FileType() const;
  237. /// The file subtype
  238. ws_uint32_t FileSubtype() const;
  239. /// The timestamp of the file
  240. FILETIME const& FileDateTime() const;
  241. private:
  242. static FILETIME calc_FileDateTime_(VS_FIXEDFILEINFO const* ffi);
  243. private:
  244. VS_FIXEDFILEINFO const* const m_ffi;
  245. FILETIME const m_fileDateTime;
  246. private:
  247. class_type& operator =(class_type const&);
  248. };
  249. /** \brief Represents a variable file part of a version information block
  250. *
  251. * \ingroup group__library__system
  252. */
  253. class VsVar
  254. {
  255. public:
  256. /// This type
  257. typedef VsVar class_type;
  258. /// Represents a language/code-page pair
  259. struct LangCodePage
  260. {
  261. /// The language
  262. ss_uint16_t language;
  263. /// The code-page
  264. ss_uint16_t codePage;
  265. };
  266. public:
  267. /// Constructor
  268. VsVar(Var_hdr const* p);
  269. /// The length of the variable
  270. ss_size_t length() const;
  271. /// Subscript operator
  272. LangCodePage const& operator [](ss_size_t index) const;
  273. private:
  274. Var_hdr const* m_p;
  275. LangCodePage const* m_values;
  276. };
  277. /** \brief Represents a string part of a version information block
  278. *
  279. * \ingroup group__library__system
  280. */
  281. class VsString
  282. {
  283. public:
  284. /// This type
  285. typedef VsString class_type;
  286. public:
  287. /// Constructor
  288. VsString(String_hdr const* p);
  289. /// The name of the variable
  290. wchar_t const* name() const;
  291. /// The value of the variable
  292. wchar_t const* value() const;
  293. private:
  294. wchar_t const* m_name;
  295. wchar_t const* m_value;
  296. };
  297. /** \brief Represents a string table
  298. *
  299. * \ingroup group__library__system
  300. */
  301. class VsStringTable
  302. : public stlsoft_ns_qual(stl_collection_tag)
  303. {
  304. public:
  305. /// This type
  306. typedef VsStringTable class_type;
  307. /// The value type
  308. typedef VsString value_type;
  309. public:
  310. /// Constructor
  311. VsStringTable(StringTable_hdr const* p);
  312. /// The key
  313. wchar_t const* Key() const;
  314. /// The non-mutating (const) iterator
  315. class const_iterator
  316. : public stlsoft_ns_qual(iterator_base)<winstl_ns_qual_std(forward_iterator_tag)
  317. , value_type
  318. , ws_ptrdiff_t
  319. , void // By-Value Temporary reference
  320. , value_type // By-Value Temporary reference
  321. >
  322. {
  323. public:
  324. /// This type
  325. typedef const_iterator class_type;
  326. /// The value type
  327. typedef VsString value_type;
  328. public:
  329. /// Constructor
  330. const_iterator(void const* p);
  331. /// Pre-increment operator
  332. class_type& operator ++();
  333. /// Post-increment operator
  334. class_type operator ++(int);
  335. value_type operator *() const;
  336. ws_bool_t operator ==(class_type const& rhs) const;
  337. ws_bool_t operator !=(class_type const& rhs) const;
  338. private:
  339. void const* m_p;
  340. };
  341. const_iterator begin() const;
  342. const_iterator end() const;
  343. private:
  344. StringTable_hdr const* m_p;
  345. void const* m_strings;
  346. };
  347. /** \brief Represents a variable file info part of a version information block
  348. *
  349. * \ingroup group__library__system
  350. */
  351. class VsVarFileInfo
  352. : public stlsoft_ns_qual(stl_collection_tag)
  353. {
  354. public:
  355. /// This type
  356. typedef VsVarFileInfo class_type;
  357. /// The value type
  358. typedef VsVar value_type;
  359. public:
  360. /// Constructor
  361. ///
  362. /// \param p The header of the block for which the instance will act
  363. VsVarFileInfo(VarFileInfo_hdr const* p);
  364. /// The Key property
  365. wchar_t const* Key() const;
  366. /// Iterator class
  367. class const_iterator
  368. : public stlsoft_ns_qual(iterator_base)<winstl_ns_qual_std(forward_iterator_tag)
  369. , value_type
  370. , ws_ptrdiff_t
  371. , void // By-Value Temporary reference
  372. , value_type // By-Value Temporary reference
  373. >
  374. {
  375. public:
  376. /// This type
  377. typedef const_iterator class_type;
  378. public:
  379. /// Constructor
  380. const_iterator(void const* p);
  381. /// Pre-increment operator
  382. class_type& operator ++();
  383. /// Post-increment operator
  384. class_type operator ++(int);
  385. value_type operator *() const;
  386. ws_bool_t operator ==(class_type const& rhs) const;
  387. ws_bool_t operator !=(class_type const& rhs) const;
  388. private:
  389. void const* m_p;
  390. };
  391. const_iterator begin() const;
  392. const_iterator end() const;
  393. private:
  394. VarFileInfo_hdr const* m_p;
  395. void const* m_vars;
  396. };
  397. /** \brief Represents a variable string part of a version information block
  398. *
  399. * \ingroup group__library__system
  400. */
  401. class VsStringFileInfo
  402. : public stlsoft_ns_qual(stl_collection_tag)
  403. {
  404. public:
  405. /// This type
  406. typedef VsStringFileInfo class_type;
  407. /// The value type
  408. typedef VsStringTable value_type;
  409. public:
  410. /// Constructor
  411. VsStringFileInfo(StringFileInfo_hdr const* p);
  412. /// The key of the StringFileInfo block
  413. wchar_t const* Key() const;
  414. /// Non-mutating (const) iterator type for the StringFileInfo block
  415. ///
  416. /// \note The value type is \c VsStringTable
  417. class const_iterator
  418. : public stlsoft_ns_qual(iterator_base)<winstl_ns_qual_std(forward_iterator_tag)
  419. , value_type
  420. , ws_ptrdiff_t
  421. , void // By-Value Temporary reference
  422. , value_type // By-Value Temporary reference
  423. >
  424. {
  425. public:
  426. /// The class type
  427. typedef const_iterator class_type;
  428. /// The value type
  429. typedef VsStringTable value_type;
  430. public:
  431. /// Constructor
  432. const_iterator(void const* p);
  433. /// Pre-increment operator
  434. class_type& operator ++();
  435. /// Post-increment operator
  436. class_type operator ++(int);
  437. value_type operator *() const;
  438. ws_bool_t operator ==(class_type const& rhs) const;
  439. ws_bool_t operator !=(class_type const& rhs) const;
  440. private:
  441. void const* m_p;
  442. };
  443. const_iterator begin() const;
  444. const_iterator end() const;
  445. private:
  446. StringFileInfo_hdr const* m_p;
  447. void const* m_vars;
  448. };
  449. /** \brief Provides convenient access to aspects of a module's version information
  450. *
  451. * \ingroup group__library__system
  452. */
  453. class version_info
  454. {
  455. private:
  456. typedef processheap_allocator<ws_byte_t> allocator_type;
  457. public:
  458. /// This type
  459. typedef version_info class_type;
  460. /// \name Construction
  461. /// @{
  462. public:
  463. /// Creates an instance corresponding to the version information from the given module
  464. ///
  465. /// \param moduleName The name of the module (.exe, .dll, etc.) to load
  466. ss_explicit_k version_info(ws_char_a_t const* moduleName);
  467. /// Creates an instance corresponding to the version information from the given module
  468. ///
  469. /// \param moduleName The name of the module (.exe, .dll, etc.) to load
  470. ss_explicit_k version_info(ws_char_w_t const* moduleName);
  471. /// Releases any allocated resources
  472. ~version_info() stlsoft_throw_0();
  473. /// @}
  474. /// \name Properties
  475. /// @{
  476. public:
  477. /// The length of the version information
  478. ws_size_t Length() const;
  479. /// The length of the value part of the version block
  480. ws_size_t ValueLength() const;
  481. /// The type field in the version block
  482. ws_size_t Type() const;
  483. /// The key of the version block
  484. wchar_t const* Key() const;
  485. /// The FixedFileInfo part of the block
  486. fixed_file_info FixedFileInfo() const;
  487. /// Indicates whether the module contains a VarFileInfo block
  488. ws_bool_t HasVarFileInfo() const;
  489. /// The VarFileInfo part of the block
  490. VsVarFileInfo VarFileInfo() const;
  491. /// Indicates whether the module contains a StringFileInfo block
  492. ws_bool_t HasStringFileInfo() const;
  493. /// The StringFileInfo part of the block
  494. VsStringFileInfo StringFileInfo() const;
  495. /// @}
  496. private:
  497. static VS_VERSIONINFO_hdr const* retrieve_module_info_block_(ws_char_a_t const* moduleName);
  498. static VS_VERSIONINFO_hdr const* retrieve_module_info_block_(ws_char_w_t const* moduleName);
  499. static wchar_t const* calc_key_(void const* pv);
  500. static VS_FIXEDFILEINFO const* calc_ffi_(wchar_t const* key);
  501. static WORD const* calc_children_(VS_FIXEDFILEINFO const* ffi);
  502. private:
  503. void init_();
  504. private:
  505. VS_VERSIONINFO_hdr const* const m_hdr;
  506. wchar_t const* const m_key;
  507. VS_FIXEDFILEINFO const* const m_ffi;
  508. WORD const* const m_children;
  509. StringFileInfo_hdr const* m_sfi;
  510. VarFileInfo_hdr const* m_vfi;
  511. // Not to be implemented
  512. private:
  513. version_info(class_type const& rhs);
  514. class_type& operator =(class_type const& rhs);
  515. };
  516. ////////////////////////////////////////////////////////////////////////////
  517. // Unit-testing
  518. #ifdef STLSOFT_UNITTEST
  519. # include "./unittest/version_info_unittest_.h"
  520. #endif /* STLSOFT_UNITTEST */
  521. /* /////////////////////////////////////////////////////////////////////////
  522. * Implementation
  523. */
  524. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  525. inline /* static */ FILETIME fixed_file_info::calc_FileDateTime_(VS_FIXEDFILEINFO const* ffi)
  526. {
  527. FILETIME ft = { ffi->dwFileDateLS, ffi->dwFileDateMS };
  528. return ft;
  529. }
  530. inline fixed_file_info::fixed_file_info(VS_FIXEDFILEINFO const* ffi)
  531. : m_ffi(ffi)
  532. , m_fileDateTime(calc_FileDateTime_(ffi))
  533. {}
  534. inline ws_uint16_t fixed_file_info::ApiVerHigh() const
  535. {
  536. return HIWORD(m_ffi->dwStrucVersion);
  537. }
  538. inline ws_uint16_t fixed_file_info::ApiVerLow() const
  539. {
  540. return LOWORD(m_ffi->dwStrucVersion);
  541. }
  542. inline ws_uint16_t fixed_file_info::FileVerMajor() const
  543. {
  544. return HIWORD(m_ffi->dwFileVersionMS);
  545. }
  546. inline ws_uint16_t fixed_file_info::FileVerMinor() const
  547. {
  548. return LOWORD(m_ffi->dwFileVersionMS);
  549. }
  550. inline ws_uint16_t fixed_file_info::FileVerRevision() const
  551. {
  552. return HIWORD(m_ffi->dwFileVersionLS);
  553. }
  554. inline ws_uint16_t fixed_file_info::FileVerBuild() const
  555. {
  556. return LOWORD(m_ffi->dwFileVersionLS);
  557. }
  558. inline ws_uint16_t fixed_file_info::ProductVerMajor() const
  559. {
  560. return HIWORD(m_ffi->dwProductVersionMS);
  561. }
  562. inline ws_uint16_t fixed_file_info::ProductVerMinor() const
  563. {
  564. return LOWORD(m_ffi->dwProductVersionMS);
  565. }
  566. inline ws_uint16_t fixed_file_info::ProductVerRevision() const
  567. {
  568. return HIWORD(m_ffi->dwProductVersionLS);
  569. }
  570. inline ws_uint16_t fixed_file_info::ProductVerBuild() const
  571. {
  572. return LOWORD(m_ffi->dwProductVersionLS);
  573. }
  574. inline ws_uint32_t fixed_file_info::FileFlagsMask() const
  575. {
  576. return m_ffi->dwFileFlagsMask;
  577. }
  578. inline ws_uint32_t fixed_file_info::FileFlags() const
  579. {
  580. return m_ffi->dwFileFlags;
  581. }
  582. inline ws_uint32_t fixed_file_info::FileOS() const
  583. {
  584. return m_ffi->dwFileOS;
  585. }
  586. inline ws_uint32_t fixed_file_info::FileType() const
  587. {
  588. return m_ffi->dwFileType;
  589. }
  590. inline ws_uint32_t fixed_file_info::FileSubtype() const
  591. {
  592. return m_ffi->dwFileSubtype;
  593. }
  594. inline FILETIME const& fixed_file_info::FileDateTime() const
  595. {
  596. return m_fileDateTime;
  597. }
  598. inline VsVar::VsVar(Var_hdr const* p)
  599. : m_p(p)
  600. {
  601. WINSTL_ASSERT(0 == ::wcsncmp(p->szKey, L"Translation", 12));
  602. m_values = sap_cast<LangCodePage const*>(rounded_ptr(&p->szKey[1 + ::wcslen(p->szKey)], 4));
  603. }
  604. inline ss_size_t VsVar::length() const
  605. {
  606. return m_p->wValueLength / sizeof(LangCodePage);
  607. }
  608. inline VsVar::LangCodePage const& VsVar::operator [](ss_size_t index) const
  609. {
  610. return m_values[index];
  611. }
  612. inline VsString::VsString(String_hdr const* p)
  613. : m_name(p->szKey)
  614. {
  615. m_value = sap_cast<wchar_t const*>(rounded_ptr(&p->szKey[1 + ::wcslen(p->szKey)], 4));
  616. }
  617. inline wchar_t const* VsString::name() const
  618. {
  619. return m_name;
  620. }
  621. inline wchar_t const* VsString::value() const
  622. {
  623. return m_value;
  624. }
  625. inline VsStringTable::VsStringTable(StringTable_hdr const* p)
  626. : m_p(p)
  627. {
  628. m_strings = rounded_ptr(&p->szKey[1 + ::wcslen(p->szKey)], 4);
  629. }
  630. inline wchar_t const* VsStringTable::Key() const
  631. {
  632. WINSTL_ASSERT(NULL != m_p);
  633. return m_p->szKey;
  634. }
  635. inline VsStringTable::const_iterator::const_iterator(void const* p)
  636. : m_p(p)
  637. {}
  638. inline VsStringTable::const_iterator::class_type& VsStringTable::const_iterator::operator ++()
  639. {
  640. String_hdr const* str = static_cast<String_hdr const*>(m_p);
  641. m_p = rounded_ptr(m_p, str->wLength, 4);
  642. return *this;
  643. }
  644. inline VsStringTable::const_iterator::class_type VsStringTable::const_iterator::operator ++(int)
  645. {
  646. const_iterator ret(*this);
  647. operator ++();
  648. return ret;
  649. }
  650. inline VsString VsStringTable::const_iterator::operator *() const
  651. {
  652. String_hdr const* str = static_cast<String_hdr const*>(m_p);
  653. return VsString(str);
  654. }
  655. inline ws_bool_t VsStringTable::const_iterator::operator ==(VsStringTable::const_iterator::class_type const& rhs) const
  656. {
  657. return m_p == rhs.m_p;
  658. }
  659. inline ws_bool_t VsStringTable::const_iterator::operator !=(VsStringTable::const_iterator::class_type const& rhs) const
  660. {
  661. return !operator ==(rhs);
  662. }
  663. inline VsStringTable::const_iterator VsStringTable::begin() const
  664. {
  665. return const_iterator(m_strings);
  666. }
  667. inline VsStringTable::const_iterator VsStringTable::end() const
  668. {
  669. return const_iterator(rounded_ptr(m_p, m_p->wLength, 4));
  670. }
  671. inline VsVarFileInfo::VsVarFileInfo(VarFileInfo_hdr const* p)
  672. : m_p(p)
  673. {
  674. WINSTL_ASSERT(0 == ::wcsncmp(p->szKey, L"VarFileInfo", 12));
  675. m_vars = rounded_ptr(&p->szKey[1 + ::wcslen(p->szKey)], 4);
  676. }
  677. inline wchar_t const* VsVarFileInfo::Key() const
  678. {
  679. WINSTL_ASSERT(NULL != m_p);
  680. return m_p->szKey;
  681. }
  682. inline VsVarFileInfo::const_iterator::const_iterator(void const* p)
  683. : m_p(p)
  684. {}
  685. inline VsVarFileInfo::const_iterator::class_type& VsVarFileInfo::const_iterator::operator ++()
  686. {
  687. Var_hdr const* var = static_cast<Var_hdr const*>(m_p);
  688. m_p = rounded_ptr(m_p, var->wLength, 4);
  689. return *this;
  690. }
  691. inline VsVarFileInfo::const_iterator::class_type VsVarFileInfo::const_iterator::operator ++(int)
  692. {
  693. const_iterator ret(*this);
  694. operator ++();
  695. return ret;
  696. }
  697. inline VsVar VsVarFileInfo::const_iterator::operator *() const
  698. {
  699. Var_hdr const* var = static_cast<Var_hdr const*>(m_p);
  700. return VsVar(var);
  701. }
  702. inline ws_bool_t VsVarFileInfo::const_iterator::operator ==(class_type const& rhs) const
  703. {
  704. return m_p == rhs.m_p;
  705. }
  706. inline ws_bool_t VsVarFileInfo::const_iterator::operator !=(class_type const& rhs) const
  707. {
  708. return !operator ==(rhs);
  709. }
  710. inline VsVarFileInfo::const_iterator VsVarFileInfo::begin() const
  711. {
  712. return const_iterator(m_vars);
  713. }
  714. inline VsVarFileInfo::const_iterator VsVarFileInfo::end() const
  715. {
  716. return const_iterator(rounded_ptr(m_p, m_p->wLength, 4));
  717. }
  718. inline VsStringFileInfo::VsStringFileInfo(StringFileInfo_hdr const* p)
  719. : m_p(p)
  720. {
  721. WINSTL_ASSERT(0 == ::wcsncmp(p->szKey, L"StringFileInfo", 15));
  722. m_vars = rounded_ptr(&p->szKey[1 + ::wcslen(p->szKey)], 4);
  723. }
  724. inline wchar_t const* VsStringFileInfo::Key() const
  725. {
  726. WINSTL_ASSERT(NULL != m_p);
  727. return m_p->szKey;
  728. }
  729. inline VsStringFileInfo::const_iterator::const_iterator(void const* p)
  730. : m_p(p)
  731. {}
  732. inline VsStringFileInfo::const_iterator::class_type& VsStringFileInfo::const_iterator::operator ++()
  733. {
  734. StringTable_hdr const* strtbl = static_cast<StringTable_hdr const*>(m_p);
  735. m_p = rounded_ptr(m_p, strtbl->wLength, 4);
  736. return *this;
  737. }
  738. inline VsStringFileInfo::const_iterator::class_type VsStringFileInfo::const_iterator::operator ++(int)
  739. {
  740. const_iterator ret(*this);
  741. operator ++();
  742. return ret;
  743. }
  744. inline VsStringTable VsStringFileInfo::const_iterator::operator *() const
  745. {
  746. StringTable_hdr const* strtbl = static_cast<StringTable_hdr const*>(m_p);
  747. return VsStringTable(strtbl);
  748. }
  749. inline ws_bool_t VsStringFileInfo::const_iterator::operator ==(class_type const& rhs) const
  750. {
  751. return m_p == rhs.m_p;
  752. }
  753. inline ws_bool_t VsStringFileInfo::const_iterator::operator !=(class_type const& rhs) const
  754. {
  755. return !operator ==(rhs);
  756. }
  757. inline VsStringFileInfo::const_iterator VsStringFileInfo::begin() const
  758. {
  759. return const_iterator(m_vars);
  760. }
  761. inline VsStringFileInfo::const_iterator VsStringFileInfo::end() const
  762. {
  763. return const_iterator(rounded_ptr(m_p, m_p->wLength, 4));
  764. }
  765. inline /* ss_explicit_k */ version_info::version_info(ws_char_a_t const* moduleName)
  766. : m_hdr(retrieve_module_info_block_(moduleName))
  767. , m_key(calc_key_(m_hdr))
  768. , m_ffi(calc_ffi_(m_key))
  769. , m_children(calc_children_(m_ffi))
  770. , m_sfi(NULL)
  771. , m_vfi(NULL)
  772. {
  773. init_();
  774. }
  775. inline /* ss_explicit_k */ version_info::version_info(ws_char_w_t const* moduleName)
  776. : m_hdr(retrieve_module_info_block_(moduleName))
  777. , m_key(calc_key_(m_hdr))
  778. , m_ffi(calc_ffi_(m_key))
  779. , m_children(calc_children_(m_ffi))
  780. , m_sfi(NULL)
  781. , m_vfi(NULL)
  782. {
  783. init_();
  784. }
  785. inline version_info::~version_info() stlsoft_throw_0()
  786. {
  787. allocator_type allocator;
  788. allocator.deallocate(const_cast<ws_byte_t*>(sap_cast<ws_byte_t const*>(m_hdr)));
  789. }
  790. inline ws_size_t version_info::Length() const
  791. {
  792. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  793. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  794. if(NULL == m_hdr)
  795. {
  796. return 0;
  797. }
  798. #else /* ? exceptions */
  799. WINSTL_ASSERT(NULL != m_hdr);
  800. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  801. return *(sap_cast<WORD const*>(m_hdr) + 0);
  802. }
  803. inline ws_size_t version_info::ValueLength() const
  804. {
  805. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  806. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  807. if(NULL == m_hdr)
  808. {
  809. return 0;
  810. }
  811. #else /* ? exceptions */
  812. WINSTL_ASSERT(NULL != m_hdr);
  813. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  814. return *(sap_cast<WORD const*>(m_hdr) + 1);
  815. }
  816. inline ws_size_t version_info::Type() const
  817. {
  818. WINSTL_ASSERT(NULL != m_hdr);
  819. return *(sap_cast<WORD const*>(m_hdr) + 2);
  820. }
  821. inline wchar_t const* version_info::Key() const
  822. {
  823. WINSTL_ASSERT(NULL != m_hdr);
  824. return m_key;
  825. }
  826. inline fixed_file_info version_info::FixedFileInfo() const
  827. {
  828. WINSTL_ASSERT(NULL != m_hdr);
  829. return fixed_file_info(m_ffi);
  830. }
  831. inline ws_bool_t version_info::HasVarFileInfo() const
  832. {
  833. return NULL != m_vfi;
  834. }
  835. inline VsVarFileInfo version_info::VarFileInfo() const
  836. {
  837. WINSTL_ASSERT(NULL != m_vfi);
  838. return VsVarFileInfo(m_vfi);
  839. }
  840. inline ws_bool_t version_info::HasStringFileInfo() const
  841. {
  842. return NULL != m_sfi;
  843. }
  844. inline VsStringFileInfo version_info::StringFileInfo() const
  845. {
  846. WINSTL_ASSERT(NULL != m_sfi);
  847. return VsStringFileInfo(m_sfi);
  848. }
  849. inline /* static */ VS_VERSIONINFO_hdr const* version_info::retrieve_module_info_block_(ws_char_a_t const* moduleName)
  850. {
  851. #ifdef WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER
  852. ws_char_a_t buffer[1 + WINSTL_CONST_MAX_PATH];
  853. #else /* ?WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  854. basic_file_path_buffer<ws_char_a_t> buffer;
  855. #endif /* WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  856. if( NULL == moduleName &&
  857. #ifdef WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER
  858. 0 != ::GetModuleFileNameA(NULL, &buffer[0], STLSOFT_NUM_ELEMENTS(buffer)))
  859. #else /* ?WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  860. 0 != ::GetModuleFileNameA(NULL, &buffer[0], DWORD(buffer.size())))
  861. #endif /* WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  862. {
  863. moduleName = stlsoft_ns_qual(c_str_ptr)(buffer);
  864. }
  865. else
  866. {
  867. // Must verify it can be loaded, i.e. is a 32-bit resource
  868. //
  869. // TODO: Work out how to support 16-bit versions
  870. HINSTANCE hinst = ::LoadLibraryExA(moduleName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  871. if(NULL == hinst)
  872. {
  873. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  874. STLSOFT_THROW_X(version_info_exception("Could not elicit version information from module", ::GetLastError()));
  875. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  876. return NULL;
  877. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  878. }
  879. else
  880. {
  881. ::FreeLibrary(hinst);
  882. }
  883. }
  884. allocator_type allocator;
  885. ws_dword_t cb = ::GetFileVersionInfoSizeA(const_cast<ws_char_a_t*>(moduleName), NULL);
  886. void *pv = (0 == cb) ? NULL : allocator.allocate(cb);
  887. #if !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  888. // If bad_alloc will not be thrown, then we need to check for NULL, but only act on it
  889. // if cb is non-zero
  890. if( 0 != cb &&
  891. pv == NULL)
  892. {
  893. ::GetLastError();
  894. return NULL;
  895. }
  896. #endif /* !STLSOFT_CF_THROW_BAD_ALLOC */
  897. WINSTL_ASSERT(0 == cb || pv != NULL);
  898. if( 0 == cb ||
  899. !::GetFileVersionInfoA(const_cast<ws_char_a_t*>(moduleName), 0, cb, pv))
  900. {
  901. allocator.deallocate(static_cast<ws_byte_t*>(pv), cb);
  902. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  903. STLSOFT_THROW_X(version_info_exception("Could not elicit version information from module", ::GetLastError()));
  904. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  905. return NULL;
  906. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  907. }
  908. WINSTL_ASSERT(pv != NULL);
  909. return static_cast<VS_VERSIONINFO_hdr*>(pv);
  910. }
  911. inline /* static */ VS_VERSIONINFO_hdr const* version_info::retrieve_module_info_block_(ws_char_w_t const* moduleName)
  912. {
  913. #ifdef WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER
  914. ws_char_w_t buffer[1 + WINSTL_CONST_MAX_PATH];
  915. #else /* ?WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  916. basic_file_path_buffer<ws_char_w_t> buffer;
  917. #endif /* WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  918. if( NULL == moduleName &&
  919. #ifdef WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER
  920. 0 != ::GetModuleFileNameW(NULL, &buffer[0], STLSOFT_NUM_ELEMENTS(buffer)))
  921. #else /* ?WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  922. 0 != ::GetModuleFileNameW(NULL, &buffer[0], DWORD(buffer.size())))
  923. #endif /* WINSTL_VERSION_INFO_NO_USE_FILE_PATH_BUFFER */
  924. {
  925. moduleName = stlsoft_ns_qual(c_str_ptr)(buffer);
  926. }
  927. else
  928. {
  929. // Must verify it can be loaded, i.e. is a 32-bit resource
  930. //
  931. // TODO: Work out how to support 16-bit versions
  932. HINSTANCE hinst = ::LoadLibraryExW(moduleName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  933. if(NULL == hinst)
  934. {
  935. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  936. STLSOFT_THROW_X(version_info_exception("Could not elicit version information from module", ::GetLastError()));
  937. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  938. return NULL;
  939. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  940. }
  941. else
  942. {
  943. ::FreeLibrary(hinst);
  944. }
  945. }
  946. allocator_type allocator;
  947. ws_dword_t cb = ::GetFileVersionInfoSizeW(const_cast<ws_char_w_t*>(moduleName), NULL);
  948. void *pv = (0 == cb) ? NULL : allocator.allocate(cb);
  949. #ifndef STLSOFT_CF_THROW_BAD_ALLOC
  950. if( 0 != cb &&
  951. pv == NULL)
  952. {
  953. return NULL;
  954. }
  955. #endif /* !STLSOFT_CF_THROW_BAD_ALLOC */
  956. if( 0 == cb ||
  957. !::GetFileVersionInfoW(const_cast<ws_char_w_t*>(moduleName), 0, cb, pv))
  958. {
  959. allocator.deallocate(static_cast<ws_byte_t*>(pv), cb);
  960. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  961. STLSOFT_THROW_X((version_info_exception("Could not elicit version information from module", ::GetLastError())));
  962. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  963. pv = NULL;
  964. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  965. }
  966. return static_cast<VS_VERSIONINFO_hdr*>(pv);
  967. }
  968. inline /* static */ wchar_t const* version_info::calc_key_(void const* pv)
  969. {
  970. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  971. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  972. if(NULL == pv)
  973. {
  974. return NULL;
  975. }
  976. #else /* ? exceptions */
  977. WINSTL_ASSERT(NULL != pv);
  978. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  979. #ifdef _DEBUG
  980. // Bit of 16-bit resource code here
  981. //
  982. // This is reasonably safe, because if it is unicode, then the n-limited string comparison
  983. // will simply return non-0, rather than potentially going off and crashing
  984. {
  985. char const* keyA = reinterpret_cast<char const*>(static_cast<WORD const*>(pv) + 2);
  986. if(0 == ::strncmp("VS_VERSION_INFO", keyA, 16))
  987. {
  988. keyA = NULL;
  989. }
  990. }
  991. #endif /* _DEBUG */
  992. wchar_t const* key = reinterpret_cast<wchar_t const*>(static_cast<WORD const*>(pv) + 3);
  993. WINSTL_ASSERT(0 == ::wcsncmp(L"VS_VERSION_INFO", key, 16));
  994. return key;
  995. }
  996. inline /* static */ VS_FIXEDFILEINFO const* version_info::calc_ffi_(wchar_t const* key)
  997. {
  998. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  999. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  1000. if(NULL == key)
  1001. {
  1002. return NULL;
  1003. }
  1004. #else /* ? exceptions */
  1005. WINSTL_ASSERT(NULL != key);
  1006. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  1007. return sap_cast<VS_FIXEDFILEINFO const*>(rounded_ptr(&key[1 + ::wcslen(key)], 4));
  1008. }
  1009. inline /* static */ WORD const* version_info::calc_children_(VS_FIXEDFILEINFO const* ffi)
  1010. {
  1011. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  1012. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  1013. if(NULL == ffi)
  1014. {
  1015. return NULL;
  1016. }
  1017. #else /* ? exceptions */
  1018. WINSTL_ASSERT(NULL != ffi);
  1019. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  1020. return sap_cast<WORD const*>(rounded_ptr(&ffi[1], 4));
  1021. }
  1022. inline void version_info::init_()
  1023. {
  1024. #if !defined(STLSOFT_CF_EXCEPTION_SUPPORT) || \
  1025. !defined(STLSOFT_CF_THROW_BAD_ALLOC)
  1026. if(NULL == m_hdr)
  1027. {
  1028. return;
  1029. }
  1030. #else /* ? exceptions */
  1031. WINSTL_ASSERT(NULL != m_hdr);
  1032. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT || !STLSOFT_CF_THROW_BAD_ALLOC */
  1033. #ifdef _DEBUG
  1034. // Check that ffi is the same as the pointer returned from VerQueryValue("\\");
  1035. VS_FIXEDFILEINFO *ffi = NULL;
  1036. UINT cchInfo = 0;
  1037. WINSTL_ASSERT(::VerQueryValueA(const_cast<VS_VERSIONINFO_hdr*>(m_hdr), "\\", reinterpret_cast<void**>(&ffi), &cchInfo));
  1038. WINSTL_ASSERT(ffi == m_ffi);
  1039. #endif /* _DEBUG */
  1040. // Now we must parse the children.
  1041. void const * pv = m_children;
  1042. void const *const end = rounded_ptr(m_hdr, m_hdr->wLength, 4);
  1043. WINSTL_ASSERT(ptr_byte_diff(end, pv) >= 0);
  1044. for(; pv != end; )
  1045. {
  1046. union
  1047. {
  1048. void const *pv_;
  1049. StringFileInfo_hdr const *psfi;
  1050. VarFileInfo_hdr const *pvfi;
  1051. } u;
  1052. u.pv_ = pv;
  1053. WINSTL_ASSERT(ptr_byte_diff(pv, m_hdr) < m_hdr->wLength);
  1054. if(0 == ::wcsncmp(u.psfi->szKey, L"StringFileInfo", 15))
  1055. {
  1056. WINSTL_ASSERT(NULL == m_sfi);
  1057. m_sfi = u.psfi;
  1058. pv = rounded_ptr(pv, u.psfi->wLength, 4);
  1059. }
  1060. else if(0 == ::wcsncmp(u.psfi->szKey, L"VarFileInfo", 12))
  1061. {
  1062. WINSTL_ASSERT(NULL == m_vfi);
  1063. m_vfi = u.pvfi;
  1064. pv = rounded_ptr(pv, u.pvfi->wLength, 4);
  1065. }
  1066. else
  1067. {
  1068. #ifdef STLSOFT_UNITTEST
  1069. ::wprintf(L"Unexpected contents of VS_VERSIONINFO children. pv: 0x%08x; Key: %.*s\n", pv, 20, u.psfi->szKey);
  1070. #endif /* STLSOFT_UNITTEST */
  1071. WINSTL_MESSAGE_ASSERT("Unexpected contents of VS_VERSIONINFO children", NULL == m_vfi);
  1072. break;
  1073. }
  1074. WINSTL_ASSERT(ptr_byte_diff(pv, end) <= 0);
  1075. }
  1076. WINSTL_ASSERT(ptr_byte_diff(pv, m_hdr) == m_hdr->wLength);
  1077. #ifdef _DEBUG
  1078. fixed_file_info fixedInfo = FixedFileInfo();
  1079. ws_uint16_t j = fixedInfo.FileVerMajor();
  1080. ws_uint16_t n = fixedInfo.FileVerMinor();
  1081. ws_uint16_t r = fixedInfo.FileVerRevision();
  1082. ws_uint16_t b = fixedInfo.FileVerBuild();
  1083. STLSOFT_SUPPRESS_UNUSED(j);
  1084. STLSOFT_SUPPRESS_UNUSED(n);
  1085. STLSOFT_SUPPRESS_UNUSED(r);
  1086. STLSOFT_SUPPRESS_UNUSED(b);
  1087. #endif /* _DEBUG */
  1088. }
  1089. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1090. /* ////////////////////////////////////////////////////////////////////// */
  1091. #ifndef _WINSTL_NO_NAMESPACE
  1092. # if defined(_STLSOFT_NO_NAMESPACE) || \
  1093. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1094. } // namespace winstl
  1095. # else
  1096. } // namespace winstl_project
  1097. } // namespace stlsoft
  1098. # endif /* _STLSOFT_NO_NAMESPACE */
  1099. #endif /* !_WINSTL_NO_NAMESPACE */
  1100. /* ////////////////////////////////////////////////////////////////////// */
  1101. #endif /* WINSTL_INCL_WINSTL_SYSTEM_HPP_VERSION_INFO */
  1102. /* ///////////////////////////// end of file //////////////////////////// */