Leaked source code of windows server 2003
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.

345 lines
7.0 KiB

  1. #include "precomp.h"
  2. #include <pshpack1.h>
  3. #include "buffer.h"
  4. #include <corex.h>
  5. #include <poppack.h>
  6. #define DWORD_ALIGNED(x) (((x) + 3) & ~3)
  7. #define QWORD_ALIGNED(x) (((x) + 7) & ~7)
  8. #ifdef _WIN64
  9. #define DEF_ALIGNED QWORD_ALIGNED
  10. #else
  11. #define DEF_ALIGNED DWORD_ALIGNED
  12. #endif
  13. #ifdef _ASSERT
  14. #undef _ASSERT
  15. #endif
  16. #ifdef DBG
  17. #define _ASSERT(X) { if (!(X)) { DebugBreak(); } }
  18. #else
  19. #define _ASSERT(X)
  20. #endif
  21. CBuffer::CBuffer(LPCVOID pBuffer, DWORD_PTR dwSize, ALIGN_TYPE type) :
  22. m_bAllocated(FALSE),
  23. m_pBuffer(NULL),
  24. m_pCurrent(NULL)
  25. {
  26. LPBYTE pRealBuffer = NULL;
  27. // Align the buffer if necessary.
  28. if (type == ALIGN_NONE)
  29. pRealBuffer = (LPBYTE) pBuffer;
  30. else if (type == ALIGN_DWORD)
  31. pRealBuffer = (LPBYTE) DWORD_ALIGNED((DWORD_PTR) pBuffer);
  32. else if (type == ALIGN_QWORD)
  33. pRealBuffer = (LPBYTE) QWORD_ALIGNED((DWORD_PTR) pBuffer);
  34. else if (type == ALIGN_DWORD_PTR)
  35. pRealBuffer = (LPBYTE) DEF_ALIGNED((DWORD_PTR) pBuffer);
  36. else
  37. // Caller passed an invalid type.
  38. _ASSERT(FALSE);
  39. dwSize -= pRealBuffer - (LPBYTE) pBuffer;
  40. Reset(pRealBuffer, dwSize);
  41. }
  42. CBuffer::CBuffer(DWORD_PTR dwSize) :
  43. m_bAllocated(FALSE),
  44. m_pBuffer(NULL)
  45. {
  46. Reset(NULL, dwSize);
  47. }
  48. CBuffer::CBuffer(const CBuffer &other) :
  49. m_bAllocated(FALSE),
  50. m_pBuffer(NULL)
  51. {
  52. *this = other;
  53. }
  54. void CBuffer::Reset(LPCVOID pBuffer, DWORD_PTR dwSize)
  55. {
  56. Free();
  57. if (!pBuffer)
  58. {
  59. pBuffer = malloc(dwSize);
  60. if (!pBuffer)
  61. throw CX_MemoryException();
  62. m_bAllocated = TRUE;
  63. }
  64. else
  65. m_bAllocated = FALSE;
  66. m_pCurrent = m_pBuffer = (LPBYTE) pBuffer;
  67. m_dwSize = dwSize;
  68. }
  69. CBuffer::~CBuffer()
  70. {
  71. Free();
  72. }
  73. void CBuffer::Free()
  74. {
  75. if (m_bAllocated && m_pBuffer)
  76. {
  77. free(m_pBuffer);
  78. m_pBuffer = NULL;
  79. }
  80. }
  81. BOOL CBuffer::Write(LPCSTR szVal)
  82. {
  83. return Write(szVal, lstrlenA(szVal) + 1);
  84. }
  85. BOOL CBuffer::Write(LPCWSTR szVal)
  86. {
  87. return Write(szVal, (wcslen(szVal) + 1) * sizeof(WCHAR));
  88. }
  89. BOOL CBuffer::Resize(DWORD_PTR dwNewSize)
  90. {
  91. if ( dwNewSize < m_dwSize )
  92. return TRUE;
  93. if (m_pBuffer)
  94. {
  95. DWORD_PTR dwUsedSize = GetUsedSize();
  96. _ASSERT( dwUsedSize <= dwNewSize );
  97. LPBYTE pNewBuffer;
  98. if (m_bAllocated)
  99. {
  100. pNewBuffer = (LPBYTE) realloc(m_pBuffer, dwNewSize);
  101. if (!pNewBuffer)
  102. {
  103. pNewBuffer = (LPBYTE) malloc(dwNewSize);
  104. if (!pNewBuffer)
  105. throw CX_MemoryException();
  106. memcpy(pNewBuffer, m_pBuffer, dwUsedSize);
  107. free(m_pBuffer);
  108. }
  109. }
  110. else
  111. {
  112. pNewBuffer = (LPBYTE) malloc(dwNewSize);
  113. if (!pNewBuffer)
  114. throw CX_MemoryException();
  115. memcpy(pNewBuffer, m_pBuffer, dwUsedSize);
  116. m_bAllocated = TRUE;
  117. // Free not needed because we didn't allocate the original memory.
  118. }
  119. m_pBuffer = pNewBuffer;
  120. m_pCurrent = pNewBuffer + dwUsedSize;
  121. m_dwSize = dwNewSize;
  122. // Inform the buffer that we reallocated.
  123. OnResize();
  124. }
  125. else
  126. Reset(dwNewSize);
  127. return TRUE;
  128. }
  129. BOOL CBuffer::WriteAlignedLenString(LPCWSTR szVal)
  130. {
  131. DWORD dwLen = (wcslen(szVal) + 1) * sizeof(WCHAR),
  132. dwLenAligned = DWORD_ALIGNED(dwLen);
  133. BOOL bRet;
  134. bRet = Write(dwLen);
  135. if (bRet)
  136. {
  137. bRet = Write(szVal, dwLen);
  138. if (bRet)
  139. // Move current to make up for the padding, if needed.
  140. MoveCurrent(dwLenAligned - dwLen);
  141. }
  142. return bRet;
  143. }
  144. #define DEF_GROW_BY 256
  145. void CBuffer::AssureSizeRemains(DWORD_PTR dwSize)
  146. {
  147. DWORD_PTR dwUnusedSize = GetUnusedSize();
  148. if (dwSize > dwUnusedSize)
  149. {
  150. Grow(max(dwSize - dwUnusedSize, DEF_GROW_BY));
  151. }
  152. }
  153. BOOL CBuffer::Write(DWORD dwVal)
  154. {
  155. AssureSizeRemains(sizeof(dwVal));
  156. *((DWORD *) m_pCurrent) = dwVal;
  157. m_pCurrent += sizeof(dwVal);
  158. return TRUE;
  159. }
  160. BOOL CBuffer::Write(DWORD64 dwVal)
  161. {
  162. AssureSizeRemains(sizeof(dwVal));
  163. *((DWORD64 *) m_pCurrent) = dwVal;
  164. m_pCurrent += sizeof(dwVal);
  165. return TRUE;
  166. }
  167. BOOL CBuffer::Write(BYTE cVal)
  168. {
  169. AssureSizeRemains(sizeof(cVal));
  170. *((BYTE *) m_pCurrent) = cVal;
  171. m_pCurrent += sizeof(cVal);
  172. return TRUE;
  173. }
  174. BOOL CBuffer::Write(WORD wVal)
  175. {
  176. AssureSizeRemains(sizeof(wVal));
  177. *((WORD *) m_pCurrent) = wVal;
  178. m_pCurrent += sizeof(WORD);
  179. return TRUE;
  180. }
  181. DWORD CBuffer::ReadDWORD()
  182. {
  183. if ( GetUnusedSize() < sizeof(DWORD) )
  184. throw CX_MemoryException();
  185. #ifndef _WIN32_WCE
  186. DWORD dwVal = *((DWORD *) m_pCurrent);
  187. #else
  188. DWORD dwVal = 0;
  189. memcpy(&dwVal, m_pCurrent, sizeof(DWORD));
  190. #endif
  191. m_pCurrent += sizeof(dwVal);
  192. return dwVal;
  193. }
  194. BYTE CBuffer::ReadBYTE()
  195. {
  196. if ( GetUnusedSize() < 1 )
  197. throw CX_MemoryException();
  198. BYTE cVal = *((BYTE *) m_pCurrent);
  199. m_pCurrent += sizeof(cVal);
  200. return cVal;
  201. }
  202. WORD CBuffer::ReadWORD()
  203. {
  204. if ( GetUnusedSize() < 2 )
  205. throw CX_MemoryException();
  206. #ifndef _WIN32_WCE
  207. WORD wVal = *((WORD *) m_pCurrent);
  208. #else
  209. WORD wVal;
  210. memcpy(&wVal, m_pCurrent, sizeof(WORD));
  211. #endif
  212. m_pCurrent += sizeof(wVal);
  213. return wVal;
  214. }
  215. BOOL CBuffer::Read(LPVOID pBuffer, DWORD dwToRead)
  216. {
  217. if ( GetUnusedSize() < dwToRead )
  218. throw CX_MemoryException();
  219. memcpy(pBuffer, m_pCurrent, dwToRead);
  220. m_pCurrent += dwToRead;
  221. return TRUE;
  222. }
  223. BOOL CBuffer::Write(LPCVOID pBuffer, DWORD dwSize)
  224. {
  225. AssureSizeRemains(dwSize);
  226. memcpy(m_pCurrent, pBuffer, dwSize);
  227. m_pCurrent += dwSize;
  228. return TRUE;
  229. }
  230. BOOL CBuffer::operator ==(const CBuffer &other)
  231. {
  232. if (!m_pBuffer && !other.m_pBuffer)
  233. return TRUE;
  234. // See if the sizes aren't the same, or if either buffer is NULL,
  235. // return FALSE.
  236. if (m_dwSize != other.m_dwSize || !m_pBuffer || !other.m_pBuffer)
  237. return FALSE;
  238. // Compare the buffers.
  239. return !memcmp(m_pBuffer, other.m_pBuffer, m_dwSize);
  240. }
  241. const CBuffer& CBuffer::operator =(const CBuffer &other)
  242. {
  243. // NULL so we allocate our own buffer.
  244. Reset(NULL, other.m_dwSize);
  245. // Copy the bits.
  246. memcpy(m_pBuffer, other.m_pBuffer, other.m_dwSize);
  247. return *this;
  248. }
  249. LPWSTR CBuffer::ReadAlignedLenString(DWORD *pdwBytes)
  250. {
  251. LPWSTR szRet = (LPWSTR) (m_pCurrent + sizeof(DWORD));
  252. if ( GetUnusedSize() < sizeof(DWORD) )
  253. throw CX_MemoryException();
  254. *pdwBytes = *(DWORD*) m_pCurrent;
  255. if ( GetUnusedSize() < DWORD_ALIGNED(*pdwBytes) + sizeof(DWORD) )
  256. throw CX_MemoryException();
  257. m_pCurrent += DWORD_ALIGNED(*pdwBytes) + sizeof(DWORD);
  258. return szRet;
  259. }