VersionInfoImpl.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. #ifndef __VersionInfoImpl_h__
  2. #define __VersionInfoImpl_h__
  3. #if _MSC_VER > 1000
  4. #pragma once
  5. #endif // _MSC_VER > 1000
  6. /////////////////////////////////////////////////////////////////////////////
  7. // VersionInfoImpl.h: Declaration of the TCVersionInfoImpl class.template.
  8. //
  9. #include "..\TCLib\ObjectLock.h"
  10. #include "..\TCLib\AutoHandle.h"
  11. /////////////////////////////////////////////////////////////////////////////
  12. // Interface Map Macro
  13. //
  14. // Classes derived from TCVersionInfoImpl should include this macro in their
  15. // interface maps.
  16. //
  17. #define COM_INTERFACE_ENTRIES_TCVersionInfoImpl() \
  18. COM_INTERFACE_ENTRY(IDispatch) \
  19. COM_INTERFACE_ENTRY(ISupportErrorInfo) \
  20. COM_INTERFACE_ENTRY(IPersistStreamInit) \
  21. COM_INTERFACE_ENTRY2(IPersistStream, IPersistStreamInit) \
  22. COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) \
  23. COM_INTERFACE_ENTRY(IMarshal)
  24. /////////////////////////////////////////////////////////////////////////////
  25. // Macros to make implementation less tedious
  26. #define TCVersionInfoImpl_Flag(flagName) \
  27. STDMETHODIMP get_Is##flagName(VARIANT_BOOL* pFlag) \
  28. { \
  29. XLock lock(static_cast<T*>(this)); \
  30. RETURN_FAILED(VerifyInit(pFlag)); \
  31. *pFlag = VARBOOL(m_vi.Is##flagName()); \
  32. return S_OK; \
  33. }
  34. #define TCVersionInfoImpl_CommonValue(valueName) \
  35. STDMETHODIMP get_##valueName(BSTR* pbstrValue) \
  36. { \
  37. XLock lock(static_cast<T*>(this)); \
  38. RETURN_FAILED(VerifyInit(pbstrValue)); \
  39. USES_CONVERSION; \
  40. ZString strValue(m_vi.Get##valueName()); \
  41. HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); \
  42. *pbstrValue = CComBSTR(strValue).Detach(); \
  43. return hr; \
  44. }
  45. /////////////////////////////////////////////////////////////////////////////
  46. // TCVersionInfoImpl
  47. //
  48. template <class T, class I, const GUID* pTLB>
  49. class TCVersionInfoImpl :
  50. public IDispatchImpl<I, &__uuidof(I), pTLB>,
  51. public ISupportErrorInfo,
  52. public IPersistStreamInit,
  53. public IMarshal,
  54. public CComObjectRootEx<CComMultiThreadModel>
  55. {
  56. // Types
  57. protected:
  58. typedef TCObjectLock<T> XLock;
  59. // Construction / Destruction
  60. public:
  61. TCVersionInfoImpl() :
  62. m_vi(false),
  63. m_bDirty(false)
  64. {
  65. }
  66. // Implementation
  67. protected:
  68. HRESULT VerifyInit()
  69. {
  70. // Verify that we have been initialized
  71. XLock lock(static_cast<T*>(this));
  72. return m_vi.GetFixed() ? S_OK :
  73. T::Error(L"Version object has not been initialized.", __uuidof(I));
  74. }
  75. HRESULT VerifyInit(VARIANT_BOOL* pb)
  76. {
  77. CLEAROUT(pb, VARIANT_FALSE);
  78. return VerifyInit();
  79. }
  80. HRESULT VerifyInit(BSTR* pbstr)
  81. {
  82. CLEAROUT(pbstr, (BSTR)NULL);
  83. return VerifyInit();
  84. }
  85. HRESULT VerifyInit(WORD* pw)
  86. {
  87. CLEAROUT(pw, (WORD)0);
  88. return VerifyInit();
  89. }
  90. // ISupportErrorInfo Interface Methods
  91. public:
  92. STDMETHODIMP InterfaceSupportsErrorInfo(REFIID riid)
  93. {
  94. return (__uuidof(I) == riid) ? S_OK : S_FALSE;
  95. }
  96. // IPersist Interface Methods
  97. public:
  98. STDMETHODIMP GetClassID(CLSID* pClassID)
  99. {
  100. __try
  101. {
  102. *pClassID = T::GetObjectCLSID();
  103. }
  104. __except(1)
  105. {
  106. return E_POINTER;
  107. }
  108. return S_OK;
  109. }
  110. // IPersistStreamInit Interface Methods
  111. public:
  112. STDMETHODIMP IsDirty()
  113. {
  114. // Return dirty flag
  115. XLock lock(static_cast<T*>(this));
  116. return m_bDirty ? S_OK : S_FALSE;
  117. }
  118. STDMETHODIMP Load(LPSTREAM pStm)
  119. {
  120. // Initialize the object
  121. XLock lock(static_cast<T*>(this));
  122. RETURN_FAILED(InitNew());
  123. // Read the number of bytes of version data
  124. UINT cbVerInfo = 0;
  125. RETURN_FAILED(pStm->Read(&cbVerInfo, sizeof(cbVerInfo), NULL));
  126. if (!cbVerInfo)
  127. return S_OK;
  128. // Allocate the memory
  129. TCArrayPtr<void*> spvVerInfo = new BYTE[cbVerInfo];
  130. if (spvVerInfo.IsNull())
  131. return E_OUTOFMEMORY;
  132. // Read the version info from the stream
  133. RETURN_FAILED(pStm->Read(spvVerInfo, cbVerInfo, NULL));
  134. // Initialize the ZVersionInfo object
  135. m_vi.Load(spvVerInfo, cbVerInfo);
  136. // Read the module filename
  137. m_bstrFileName.Empty();
  138. RETURN_FAILED(m_bstrFileName.ReadFromStream(pStm));
  139. // Indicate success
  140. return S_OK;
  141. }
  142. STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty)
  143. {
  144. // Write the number of bytes of version data
  145. XLock lock(static_cast<T*>(this));
  146. UINT cbVerInfo = m_vi.GetVerInfoSize();
  147. RETURN_FAILED(pStm->Write(&cbVerInfo, sizeof(cbVerInfo), NULL));
  148. // Write the version data
  149. if (cbVerInfo)
  150. RETURN_FAILED(pStm->Write(m_vi.GetVerInfo(), cbVerInfo, NULL));
  151. // Write the module filename
  152. RETURN_FAILED(m_bstrFileName.WriteToStream(pStm));
  153. // Clear the dirty flag, if specified
  154. if (fClearDirty)
  155. m_bDirty = false;
  156. // Indicate success
  157. return S_OK;
  158. }
  159. STDMETHODIMP GetSizeMax(ULARGE_INTEGER* pCbSize)
  160. {
  161. XLock lock(static_cast<T*>(this));
  162. return TCGetPersistStreamSize(static_cast<T*>(this)->GetUnknown(), pCbSize);
  163. }
  164. STDMETHODIMP InitNew(void)
  165. {
  166. // Set the dirty flag
  167. XLock lock(static_cast<T*>(this));
  168. m_bDirty = true;
  169. // Unload the ZVersionInfo object
  170. m_vi.Unload();
  171. // Reset the filename
  172. m_bstrFileName.Empty();
  173. // Indicate success
  174. return S_OK;
  175. }
  176. // IMarshal Interface Methods
  177. public:
  178. STDMETHODIMP GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
  179. void* pvDestContext, DWORD mshlflags, CLSID* pCid)
  180. {
  181. UNUSED(riid);
  182. UNUSED(pv);
  183. UNUSED(dwDestContext);
  184. UNUSED(pvDestContext);
  185. UNUSED(mshlflags);
  186. // Delegate to IPersistStream::GetClassID
  187. return GetClassID(pCid);
  188. }
  189. STDMETHODIMP GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
  190. void* pvDestContext, DWORD mshlflags, DWORD* pSize)
  191. {
  192. UNUSED(riid);
  193. UNUSED(pv);
  194. UNUSED(dwDestContext);
  195. UNUSED(pvDestContext);
  196. UNUSED(mshlflags);
  197. // Initialize the [out] parameter
  198. *pSize = 0;
  199. // Delegate to IPersistStream::GetSizeMax
  200. ULARGE_INTEGER uli;
  201. HRESULT hr = hr = GetSizeMax(&uli);
  202. if (SUCCEEDED(hr))
  203. {
  204. // Include the size of an endian indicator DWORD value
  205. *pSize = uli.LowPart + sizeof(m_dwEndian);
  206. }
  207. // Return the last HRESULT
  208. return hr;
  209. }
  210. STDMETHODIMP MarshalInterface(IStream* pStm, REFIID riid, void* pv,
  211. DWORD dwDestContext, void* pvDestContext, DWORD mshlflags)
  212. {
  213. UNUSED(riid);
  214. UNUSED(pv);
  215. UNUSED(dwDestContext);
  216. UNUSED(pvDestContext);
  217. UNUSED(mshlflags);
  218. // Write an endian indicator DWORD value to the stream
  219. DWORD dwEndian = m_dwEndianOriginal;
  220. HRESULT hr = pStm->Write(&dwEndian, sizeof(dwEndian), NULL);
  221. // Delegate to IPersistStream::Save
  222. if (SUCCEEDED(hr))
  223. hr = Save(pStm, FALSE);
  224. // Return the last HRESULT
  225. return hr;
  226. }
  227. STDMETHODIMP UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv)
  228. {
  229. // Read the endian indicator DWORD value from the stream
  230. XLock lock(static_cast<T*>(this));
  231. HRESULT hr = pStm->Read(&m_dwEndian, sizeof(m_dwEndian), NULL);
  232. if (SUCCEEDED(hr))
  233. {
  234. // Delegate to IPersistStream::Load
  235. if (SUCCEEDED(hr = Load(pStm)))
  236. hr = static_cast<T*>(this)->QueryInterface(riid, ppv);
  237. }
  238. // Return the last HRESULT
  239. return hr;
  240. }
  241. STDMETHODIMP ReleaseMarshalData(IStream* pStm)
  242. {
  243. // Marshaling by value does not cause us to acquire any resources
  244. return S_OK;
  245. }
  246. STDMETHODIMP DisconnectObject(DWORD dwReserved)
  247. {
  248. // Marshaling by value has no notion of connected-ness
  249. return S_OK;
  250. }
  251. // <I> Interface Methods
  252. public:
  253. // Initialization
  254. STDMETHODIMP put_FileName(BSTR bstrFileName)
  255. {
  256. // Use the current module, if an empty string was specified
  257. LPTSTR pszFileName = NULL;
  258. if (!BSTRLen(bstrFileName))
  259. {
  260. DWORD cch = _MAX_PATH * sizeof(TCHAR);
  261. pszFileName = (LPTSTR)_alloca(cch);
  262. GetModuleFileName(NULL, pszFileName, cch);
  263. }
  264. else
  265. {
  266. USES_CONVERSION;
  267. pszFileName = OLE2T(bstrFileName);
  268. }
  269. // Set the dirty flag
  270. XLock lock(static_cast<T*>(this));
  271. m_bDirty = true;
  272. // Load the version information resource
  273. if (!m_vi.Load(pszFileName))
  274. return HRESULT_FROM_WIN32(GetLastError());
  275. // Save the specified file name
  276. m_bstrFileName = pszFileName;
  277. // Indicate success
  278. return S_OK;
  279. }
  280. STDMETHODIMP get_FileName(BSTR* pbstrFileName)
  281. {
  282. CLEAROUT(pbstrFileName, (BSTR)NULL);
  283. *pbstrFileName = m_bstrFileName.Copy();
  284. return S_OK;
  285. }
  286. // File Version
  287. STDMETHODIMP get_FileVersionString(BSTR* pbstrString)
  288. {
  289. XLock lock(static_cast<T*>(this));
  290. RETURN_FAILED(VerifyInit(pbstrString));
  291. CComBSTR bstrFmt(m_vi.GetFileVersionString());
  292. *pbstrString = bstrFmt.Detach();
  293. return S_OK;
  294. }
  295. STDMETHODIMP get_FileVersionMSHigh(WORD* pwMSHigh)
  296. {
  297. XLock lock(static_cast<T*>(this));
  298. RETURN_FAILED(VerifyInit(pwMSHigh));
  299. *pwMSHigh = m_vi.GetFileVersionMSHigh();
  300. return S_OK;
  301. }
  302. STDMETHODIMP get_FileVersionMSLow(WORD* pwMSLow)
  303. {
  304. XLock lock(static_cast<T*>(this));
  305. RETURN_FAILED(VerifyInit(pwMSLow));
  306. *pwMSLow = m_vi.GetFileVersionMSLow();
  307. return S_OK;
  308. }
  309. STDMETHODIMP get_FileVersionLSHigh(WORD* pwLSHigh)
  310. {
  311. XLock lock(static_cast<T*>(this));
  312. RETURN_FAILED(VerifyInit(pwLSHigh));
  313. *pwLSHigh = m_vi.GetFileVersionLSHigh();
  314. return S_OK;
  315. }
  316. STDMETHODIMP get_FileVersionLSLow(WORD* pwLSLow)
  317. {
  318. XLock lock(static_cast<T*>(this));
  319. RETURN_FAILED(VerifyInit(pwLSLow));
  320. *pwLSLow = m_vi.GetFileVersionLSLow();
  321. return S_OK;
  322. }
  323. STDMETHODIMP get_FileBuildNumber(WORD* pwBuildNumber)
  324. {
  325. XLock lock(static_cast<T*>(this));
  326. RETURN_FAILED(VerifyInit(pwBuildNumber));
  327. *pwBuildNumber = m_vi.GetFileBuildNumber();
  328. return S_OK;
  329. }
  330. // Product Version
  331. STDMETHODIMP get_ProductVersionString(BSTR* pbstrString)
  332. {
  333. XLock lock(static_cast<T*>(this));
  334. RETURN_FAILED(VerifyInit(pbstrString));
  335. CComBSTR bstrFmt(m_vi.GetProductVersionString());
  336. *pbstrString = bstrFmt.Detach();
  337. return S_OK;
  338. }
  339. STDMETHODIMP get_ProductVersionMSHigh(WORD* pwMSHigh)
  340. {
  341. XLock lock(static_cast<T*>(this));
  342. RETURN_FAILED(VerifyInit(pwMSHigh));
  343. *pwMSHigh = m_vi.GetProductVersionMSHigh();
  344. return S_OK;
  345. }
  346. STDMETHODIMP get_ProductVersionMSLow(WORD* pwMSLow)
  347. {
  348. XLock lock(static_cast<T*>(this));
  349. RETURN_FAILED(VerifyInit(pwMSLow));
  350. *pwMSLow = m_vi.GetProductVersionMSLow();
  351. return S_OK;
  352. }
  353. STDMETHODIMP get_ProductVersionLSHigh(WORD* pwLSHigh)
  354. {
  355. XLock lock(static_cast<T*>(this));
  356. RETURN_FAILED(VerifyInit(pwLSHigh));
  357. *pwLSHigh = m_vi.GetProductVersionLSHigh();
  358. return S_OK;
  359. }
  360. STDMETHODIMP get_ProductVersionLSLow(WORD* pwLSLow)
  361. {
  362. XLock lock(static_cast<T*>(this));
  363. RETURN_FAILED(VerifyInit(pwLSLow));
  364. *pwLSLow = m_vi.GetProductVersionLSLow();
  365. return S_OK;
  366. }
  367. STDMETHODIMP get_ProductBuildNumber(WORD* pwBuildNumber)
  368. {
  369. XLock lock(static_cast<T*>(this));
  370. RETURN_FAILED(VerifyInit(pwBuildNumber));
  371. *pwBuildNumber = m_vi.GetProductBuildNumber();
  372. return S_OK;
  373. }
  374. // File Flags
  375. TCVersionInfoImpl_Flag(Debug )
  376. TCVersionInfoImpl_Flag(InfoInferred)
  377. TCVersionInfoImpl_Flag(Patched )
  378. TCVersionInfoImpl_Flag(PreRelease )
  379. TCVersionInfoImpl_Flag(PrivateBuild)
  380. TCVersionInfoImpl_Flag(SpecialBuild)
  381. // Target Operating Systems
  382. TCVersionInfoImpl_Flag(TargetUnknown )
  383. TCVersionInfoImpl_Flag(TargetDOS )
  384. TCVersionInfoImpl_Flag(TargetOS216 )
  385. TCVersionInfoImpl_Flag(TargetOS232 )
  386. TCVersionInfoImpl_Flag(TargetNT )
  387. TCVersionInfoImpl_Flag(TargetBase )
  388. TCVersionInfoImpl_Flag(TargetWin16 )
  389. TCVersionInfoImpl_Flag(TargetPM16 )
  390. TCVersionInfoImpl_Flag(TargetPM32 )
  391. TCVersionInfoImpl_Flag(TargetWin32 )
  392. TCVersionInfoImpl_Flag(TargetDOSWin16 )
  393. TCVersionInfoImpl_Flag(TargetDOSWin32 )
  394. TCVersionInfoImpl_Flag(TargetOS216PM16)
  395. TCVersionInfoImpl_Flag(TargetOS232PM32)
  396. TCVersionInfoImpl_Flag(TargetNTWin32 )
  397. // File Types
  398. TCVersionInfoImpl_Flag(App )
  399. TCVersionInfoImpl_Flag(Dll )
  400. TCVersionInfoImpl_Flag(Driver )
  401. TCVersionInfoImpl_Flag(Font )
  402. TCVersionInfoImpl_Flag(Vxd )
  403. TCVersionInfoImpl_Flag(StaticLib)
  404. // Driver Types
  405. TCVersionInfoImpl_Flag(DriverUnknown )
  406. TCVersionInfoImpl_Flag(DriverPrinter )
  407. TCVersionInfoImpl_Flag(DriverKeyboard )
  408. TCVersionInfoImpl_Flag(DriverLanguage )
  409. TCVersionInfoImpl_Flag(DriverDisplay )
  410. TCVersionInfoImpl_Flag(DriverMouse )
  411. TCVersionInfoImpl_Flag(DriverNetwork )
  412. TCVersionInfoImpl_Flag(DriverSystem )
  413. TCVersionInfoImpl_Flag(DriverInstallable)
  414. TCVersionInfoImpl_Flag(DriverSound )
  415. TCVersionInfoImpl_Flag(DriverComm )
  416. TCVersionInfoImpl_Flag(DriverInputMethod)
  417. // Font Types
  418. TCVersionInfoImpl_Flag(FontRaster )
  419. TCVersionInfoImpl_Flag(FontVector )
  420. TCVersionInfoImpl_Flag(FontTrueType)
  421. // String Values
  422. STDMETHODIMP put_LanguageID(WORD wLangID)
  423. {
  424. XLock lock(static_cast<T*>(this));
  425. if (wLangID != m_vi.GetLanguageID())
  426. {
  427. m_vi.SetLanguageID(wLangID);
  428. m_bDirty = true;
  429. }
  430. return S_OK;
  431. }
  432. STDMETHODIMP get_LanguageID(WORD* pwLangID)
  433. {
  434. XLock lock(static_cast<T*>(this));
  435. CLEAROUT(pwLangID, (WORD)m_vi.GetLanguageID());
  436. return S_OK;
  437. }
  438. STDMETHODIMP put_CodePage(WORD wCodePage)
  439. {
  440. XLock lock(static_cast<T*>(this));
  441. if (wCodePage != m_vi.GetCodePage())
  442. {
  443. m_vi.SetCodePage(wCodePage);
  444. m_bDirty = true;
  445. }
  446. return S_OK;
  447. }
  448. STDMETHODIMP get_CodePage(WORD* pwCodePage)
  449. {
  450. XLock lock(static_cast<T*>(this));
  451. CLEAROUT(pwCodePage, (WORD)m_vi.GetCodePage());
  452. return S_OK;
  453. }
  454. STDMETHODIMP get_Exists(BSTR bstrKey, VARIANT_BOOL* pbExists)
  455. {
  456. XLock lock(static_cast<T*>(this));
  457. RETURN_FAILED(VerifyInit(pbExists));
  458. bool bExists;
  459. USES_CONVERSION;
  460. m_vi.GetStringValue(bstrKey ? OLE2CT(bstrKey) : "", &bExists);
  461. *pbExists = VARBOOL(bExists);
  462. return HRESULT_FROM_WIN32(GetLastError());
  463. }
  464. STDMETHODIMP get_Value(BSTR bstrKey, BSTR* pbstrValue)
  465. {
  466. XLock lock(static_cast<T*>(this));
  467. RETURN_FAILED(VerifyInit(pbstrValue));
  468. USES_CONVERSION;
  469. ZString strValue(m_vi.GetStringValue(bstrKey ? OLE2CT(bstrKey) : ""));
  470. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  471. *pbstrValue = CComBSTR(strValue).Detach();
  472. return hr;
  473. }
  474. // Common String Values
  475. TCVersionInfoImpl_CommonValue(CompanyName )
  476. TCVersionInfoImpl_CommonValue(FileDescription )
  477. TCVersionInfoImpl_CommonValue(FileVersion )
  478. TCVersionInfoImpl_CommonValue(InternalName )
  479. TCVersionInfoImpl_CommonValue(LegalCopyright )
  480. TCVersionInfoImpl_CommonValue(OriginalFilename)
  481. TCVersionInfoImpl_CommonValue(ProductName )
  482. TCVersionInfoImpl_CommonValue(ProductVersion )
  483. TCVersionInfoImpl_CommonValue(SpecialBuild )
  484. TCVersionInfoImpl_CommonValue(OLESelfRegister )
  485. // Data Members
  486. protected:
  487. CComBSTR m_bstrFileName;
  488. ZVersionInfo m_vi;
  489. bool m_bDirty:1;
  490. DWORD m_dwEndian;
  491. static const DWORD m_dwEndianOriginal, m_dwEndianInverted;
  492. };
  493. /////////////////////////////////////////////////////////////////////////////
  494. // Static Initialization
  495. template <class T, class I, const GUID* pTLB>
  496. const DWORD TCVersionInfoImpl<T, I, pTLB>::m_dwEndianOriginal = 0xFF669900;
  497. template <class T, class I, const GUID* pTLB>
  498. const DWORD TCVersionInfoImpl<T, I, pTLB>::m_dwEndianInverted = 0x009966FF;
  499. /////////////////////////////////////////////////////////////////////////////
  500. #endif // !__VersionInfoImpl_h__