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.

504 lines
15 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/shell/memory/functions.h
  3. *
  4. * Purpose: Shell memory functions.
  5. *
  6. * Created: 2nd March 1996
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1996-2009, 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/shell/memory/functions.h
  40. *
  41. * \brief [C, C++] Shell memory functions
  42. * (\ref group__library__memory "Memory" Library).
  43. */
  44. #ifndef WINSTL_INCL_WINSTL_SHELL_MEMORY_H_FUNCTIONS
  45. #define WINSTL_INCL_WINSTL_SHELL_MEMORY_H_FUNCTIONS
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define WINSTL_VER_WINSTL_SHELL_MEMORY_H_FUNCTIONS_MAJOR 6
  48. # define WINSTL_VER_WINSTL_SHELL_MEMORY_H_FUNCTIONS_MINOR 0
  49. # define WINSTL_VER_WINSTL_SHELL_MEMORY_H_FUNCTIONS_REVISION 3
  50. # define WINSTL_VER_WINSTL_SHELL_MEMORY_H_FUNCTIONS_EDIT 53
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Compatibility
  54. */
  55. /*
  56. [DocumentationStatus:Ready]
  57. */
  58. /* /////////////////////////////////////////////////////////////////////////
  59. * Includes
  60. */
  61. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  62. # include <winstl/winstl.h>
  63. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  64. #ifndef STLSOFT_INCL_H_SHLOBJ
  65. # define STLSOFT_INCL_H_SHLOBJ
  66. # include <shlobj.h>
  67. #endif /* !STLSOFT_INCL_H_SHLOBJ */
  68. /* /////////////////////////////////////////////////////////////////////////
  69. * Namespace
  70. */
  71. #if !defined(_WINSTL_NO_NAMESPACE) && \
  72. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  73. # if defined(_STLSOFT_NO_NAMESPACE)
  74. /* There is no stlsoft namespace, so must define ::winstl */
  75. namespace winstl
  76. {
  77. # else
  78. /* Define stlsoft::winstl_project */
  79. namespace stlsoft
  80. {
  81. namespace winstl_project
  82. {
  83. # endif /* _STLSOFT_NO_NAMESPACE */
  84. #endif /* !_WINSTL_NO_NAMESPACE */
  85. /* /////////////////////////////////////////////////////////////////////////
  86. * C functions
  87. */
  88. /** \brief [C only] Allocates a block of shell memory.
  89. *
  90. * \ingroup group__library__memory
  91. *
  92. * This function uses the shell allocator to allocate a memory block.
  93. *
  94. * \param cb The size, in bytes, of the memory block to be allocated.
  95. * \return Pointer to the allocated memory block, or NULL if the request
  96. * failed.
  97. *
  98. * \remarks On failure, the function will set the thread error information,
  99. * which may be retrieved by the Win32 API function
  100. * <code>GetLastError()</code>
  101. *
  102. * \note [C++] This function is wrapped by the winstl::SHMemAlloc()
  103. * function.
  104. */
  105. STLSOFT_INLINE void *winstl__SHMemAlloc(ws_size_t cb)
  106. {
  107. LPMALLOC lpmalloc;
  108. void *pv;
  109. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(&lpmalloc);
  110. if(SUCCEEDED(hr))
  111. {
  112. pv = WINSTL_ITF_CALL(lpmalloc)->Alloc(WINSTL_ITF_THIS(lpmalloc) cb);
  113. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  114. if(NULL == pv)
  115. {
  116. STLSOFT_NS_GLOBAL(SetLastError)(ERROR_NOT_ENOUGH_MEMORY);
  117. }
  118. }
  119. else
  120. {
  121. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  122. pv = NULL;
  123. }
  124. return pv;
  125. }
  126. /** \brief [C only] Deallocates a block of shell memory previously allocated
  127. * by a call to winstl__SHMemAlloc(), winstl__SHMemRealloc() or through
  128. * the <code>IMalloc::Alloc()</code> or <code>IMalloc::Realloc()</code>
  129. * methods on the shell allocator (obtained via <code>SHGetMalloc()</code>).
  130. *
  131. * \ingroup group__library__memory
  132. *
  133. * This function uses the shell allocator to allocate a memory block.
  134. *
  135. * \param pv Pointer to the memory block to be deallocated
  136. *
  137. * \remarks On failure, the function will set the thread error information,
  138. * which may be retrieved by the Win32 API function
  139. * <code>GetLastError()</code>
  140. *
  141. * \note [C++] This function is wrapped by the winstl::SHMemFree()
  142. * function.
  143. */
  144. STLSOFT_INLINE void winstl__SHMemFree(void *pv)
  145. {
  146. LPMALLOC lpmalloc;
  147. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(&lpmalloc);
  148. if(SUCCEEDED(hr))
  149. {
  150. WINSTL_ITF_CALL(lpmalloc)->Free(WINSTL_ITF_THIS(lpmalloc) pv);
  151. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  152. }
  153. else
  154. {
  155. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  156. }
  157. }
  158. #if defined(STLSOFT_COMPILER_IS_GCC) && \
  159. __GNUC__ < 4 && \
  160. __GNUC_MINOR__ < 3
  161. /* GCC pre 3.3 contains an invalid definition of IMalloc, where
  162. * the Realloc() method is called ReAlloc().
  163. *
  164. * We use a bit of casting to get round it here.
  165. */
  166. # undef INTERFACE
  167. # define INTERFACE IMallocGcc32
  168. DECLARE_INTERFACE_(IMallocGcc32,IUnknown)
  169. {
  170. STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
  171. STDMETHOD_(ULONG,AddRef)(THIS) PURE;
  172. STDMETHOD_(ULONG,Release)(THIS) PURE;
  173. STDMETHOD_(void*,Alloc)(THIS_ ULONG) PURE;
  174. STDMETHOD_(void*,Realloc)(THIS_ void*,ULONG) PURE;
  175. STDMETHOD_(void,Free)(THIS_ void*) PURE;
  176. STDMETHOD_(ULONG,GetSize)(THIS_ void*) PURE;
  177. STDMETHOD_(int,DidAlloc)(THIS_ void*) PURE;
  178. STDMETHOD_(void,HeapMinimize)(THIS) PURE;
  179. };
  180. #endif /* compiler */
  181. /** \brief [C only] Rellocates a block of shell memory.
  182. *
  183. * \ingroup group__library__memory
  184. *
  185. * This function uses the shell allocator to allocate a memory block.
  186. *
  187. * \param pv Pointer to the memory block to be reallocated. Can be NULL, in
  188. * which case the function acts like SHMemAlloc()
  189. * \param cb The size, in bytes, of the memory block to be reallocated. Can
  190. * be 0, in which case the function acts like SHMemFree() (if pv is not
  191. * NULL), or like SHMemAlloc() (if pv is NULL).
  192. * \return Pointer to the allocated memory block, or NULL if the request
  193. * failed or cb is 0 and pv is not NULL.
  194. *
  195. * \remarks On failure, the function will set the thread error information,
  196. * which may be retrieved by the Win32 API function
  197. * <code>GetLastError()</code>
  198. *
  199. * \note [C++] This function is wrapped by the winstl::SHMemRealloc()
  200. * function.
  201. */
  202. STLSOFT_INLINE void *winstl__SHMemRealloc(void *pv, ws_size_t cb)
  203. {
  204. #if defined(STLSOFT_COMPILER_IS_GCC) && \
  205. __GNUC__ < 4 && \
  206. __GNUC_MINOR__ < 3
  207. IMallocGcc32 *lpmalloc;
  208. #else /* ? compiler */
  209. LPMALLOC lpmalloc;
  210. #endif /* compiler */
  211. void *pvNew;
  212. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(stlsoft_reinterpret_cast(LPMALLOC*, &lpmalloc));
  213. if(SUCCEEDED(hr))
  214. {
  215. pvNew = WINSTL_ITF_CALL(lpmalloc)->Realloc(WINSTL_ITF_THIS(lpmalloc) pv, cb);
  216. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  217. if( NULL == pvNew &&
  218. 0 != cb &&
  219. NULL != pv)
  220. {
  221. STLSOFT_NS_GLOBAL(SetLastError)(ERROR_NOT_ENOUGH_MEMORY);
  222. }
  223. }
  224. else
  225. {
  226. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  227. pvNew = NULL;
  228. }
  229. return pvNew;
  230. }
  231. /** \brief [C only] Gives the size of a memory block
  232. *
  233. * \ingroup group__library__memory
  234. *
  235. * This function returns the size of a memory block relative to the COM task
  236. * alloctor, as per <code>IMalloc::GetSize()</code>
  237. *
  238. * \param pv Pointer to the memory block
  239. * \return The size of the memory block (in bytes)
  240. *
  241. * \note [C++] This function is wrapped by the winstl::SHMemGetSize()
  242. * function.
  243. */
  244. STLSOFT_INLINE ws_size_t winstl__SHMemGetSize(void *pv)
  245. {
  246. LPMALLOC lpmalloc;
  247. ws_size_t ulRet;
  248. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(&lpmalloc);
  249. if(SUCCEEDED(hr))
  250. {
  251. ulRet = WINSTL_ITF_CALL(lpmalloc)->GetSize(WINSTL_ITF_THIS(lpmalloc) pv);
  252. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  253. }
  254. else
  255. {
  256. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  257. ulRet = 0;
  258. }
  259. return ulRet;
  260. }
  261. /** \brief [C only] Determines allocation ownership of a memory block
  262. *
  263. * \ingroup group__library__memory
  264. *
  265. * This function returns a value indicating whether a memory block was allocated
  266. * by the COM task allocator, as per <code>IMalloc::DidAlloc()</code>
  267. *
  268. * \param pv Pointer to the memory block
  269. * \return Result indicating ownership
  270. * \retval 1 The memory block was allocated by the task allocator
  271. * \retval 0 The memory block was <i>not</i> allocated by the task allocator
  272. * \retval -1 SHMemDidAlloc() cannot determine whether the memory block was allocated by the task allocator
  273. *
  274. * \note [C++] This function is wrapped by the winstl::SHMemDidAlloc()
  275. * function.
  276. */
  277. STLSOFT_INLINE ws_sint_t winstl__SHMemDidAlloc(void *pv)
  278. {
  279. LPMALLOC lpmalloc;
  280. ws_sint_t iRet;
  281. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(&lpmalloc);
  282. if(SUCCEEDED(hr))
  283. {
  284. iRet = WINSTL_ITF_CALL(lpmalloc)->DidAlloc(WINSTL_ITF_THIS(lpmalloc) pv);
  285. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  286. }
  287. else
  288. {
  289. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  290. iRet = -1;
  291. }
  292. return iRet;
  293. }
  294. /** \brief [C only] Minimises the heap
  295. *
  296. * \ingroup group__library__memory
  297. *
  298. * This function minimises the heap as much as possible by releasing unused
  299. * memory to the operating system, coalescing adjacent free blocks and
  300. * committing free pages, as as per <code>IMalloc::HeapMinimize()</code>.
  301. *
  302. * \note [C++] This function is wrapped by the winstl::SHMemHeapMinimise()
  303. * function.
  304. */
  305. STLSOFT_INLINE void winstl__SHMemHeapMinimise(void)
  306. {
  307. LPMALLOC lpmalloc;
  308. HRESULT hr = STLSOFT_NS_GLOBAL(SHGetMalloc)(&lpmalloc);
  309. if(SUCCEEDED(hr))
  310. {
  311. WINSTL_ITF_CALL(lpmalloc)->HeapMinimize(WINSTL_ITF_THIS0(lpmalloc));
  312. WINSTL_ITF_CALL(lpmalloc)->Release(WINSTL_ITF_THIS0(lpmalloc));
  313. }
  314. else
  315. {
  316. STLSOFT_NS_GLOBAL(SetLastError)(stlsoft_static_cast(DWORD, hr));
  317. }
  318. }
  319. /* /////////////////////////////////////////////////////////////////////////
  320. * Namespace
  321. */
  322. #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
  323. namespace winstl
  324. {
  325. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  326. /* /////////////////////////////////////////////////////////////////////////
  327. * C++ functions
  328. */
  329. #ifdef __cplusplus
  330. /** \brief Allocates a block of shell memory.
  331. *
  332. * \ingroup group__library__memory
  333. *
  334. * This function is a wrapper for winstl__SHMemAlloc().
  335. *
  336. * \param cb The size, in bytes, of the memory block to be allocated.
  337. * \return Pointer to the allocated memory block, or NULL if the request
  338. * failed.
  339. */
  340. inline void *SHMemAlloc(ws_size_t cb)
  341. {
  342. return winstl__SHMemAlloc(cb);
  343. }
  344. /** \brief Deallocates a block of shell memory.
  345. *
  346. * \ingroup group__library__memory
  347. *
  348. * This function is a wrapper for winstl__SHMemFree().
  349. *
  350. * \param pv Pointer to the memory block to be deallocated
  351. */
  352. inline void SHMemFree(void *pv)
  353. {
  354. winstl__SHMemFree(pv);
  355. }
  356. /** \brief Changes the size of a previously allocated block of shell memory.
  357. *
  358. * \ingroup group__library__memory
  359. *
  360. * This function is a wrapper for winstl__SHMemRelloc().
  361. *
  362. * \param pv Pointer to the memory block to be reallocated. Can be NULL, in
  363. * which case the function acts like SHMemAlloc()
  364. * \param cb The size, in bytes, of the memory block to be reallocated. Can
  365. * be 0, in which case the function acts like SHMemFree() (if pv is not
  366. * NULL), or like SHMemAlloc() (if pv is NULL).
  367. * \return Pointer to the allocated memory block, or NULL if the request
  368. * failed or cb is 0 and pv is not NULL.
  369. */
  370. inline void *SHMemRealloc(void *pv, ws_size_t cb)
  371. {
  372. return winstl__SHMemRealloc(pv, cb);
  373. }
  374. /** \brief Gives the size of a memory block
  375. *
  376. * \ingroup group__library__memory
  377. *
  378. * This function is a wrapper for winstl__SHMemGetSize().
  379. *
  380. * \param pv Pointer to the memory block
  381. * \return The size of the memory block (in bytes)
  382. */
  383. inline ws_size_t SHMemGetSize(void *pv)
  384. {
  385. return winstl__SHMemGetSize(pv);
  386. }
  387. /** \brief Determines allocation ownership of a memory block
  388. *
  389. * \ingroup group__library__memory
  390. *
  391. * This function is a wrapper for winstl__SHMemDidAlloc().
  392. *
  393. * \param pv Pointer to the memory block
  394. * \return Result indicating ownership
  395. * \retval 1 The memory block was allocated by the task allocator
  396. * \retval 0 The memory block was <i>not</i> allocated by the task allocator
  397. * \retval -1 SHMemDidAlloc() cannot determine whether the memory block was allocated by the task allocator
  398. */
  399. inline ws_sint_t SHMemDidAlloc(void *pv)
  400. {
  401. return winstl__SHMemDidAlloc(pv);
  402. }
  403. /** \brief Minimises the heap
  404. *
  405. * \ingroup group__library__memory
  406. *
  407. * This function is a wrapper for winstl__SHMemHeapMinimise().
  408. */
  409. inline void SHMemHeapMinimise()
  410. {
  411. winstl__SHMemHeapMinimise();
  412. }
  413. /** \brief Minimises the heap
  414. *
  415. * \ingroup group__library__memory
  416. *
  417. * This function is a wrapper for winstl__SHMemHeapMinimise().
  418. */
  419. inline void SHMemHeapMinimize()
  420. {
  421. winstl__SHMemHeapMinimise();
  422. }
  423. #endif /* __cplusplus */
  424. /* /////////////////////////////////////////////////////////////////////////
  425. * Unit-testing
  426. */
  427. #ifdef STLSOFT_UNITTEST
  428. # include "./unittest/functions_unittest_.h"
  429. #endif /* STLSOFT_UNITTEST */
  430. /* ////////////////////////////////////////////////////////////////////// */
  431. #ifndef _WINSTL_NO_NAMESPACE
  432. # if defined(_STLSOFT_NO_NAMESPACE) || \
  433. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  434. } /* namespace winstl */
  435. # else
  436. } /* namespace stlsoft::winstl_project */
  437. } /* namespace stlsoft */
  438. # endif /* _STLSOFT_NO_NAMESPACE */
  439. #endif /* !_WINSTL_NO_NAMESPACE */
  440. /* ////////////////////////////////////////////////////////////////////// */
  441. #endif /* !WINSTL_INCL_WINSTL_SHELL_MEMORY_H_FUNCTIONS */
  442. /* ///////////////////////////// end of file //////////////////////////// */