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.

721 lines
16 KiB

  1. #include "stdafx.h"
  2. #include "wsb.h"
  3. #include "wsbpstrg.h"
  4. // {C03D4861-70D7-11d1-994F-0060976A546D}
  5. static const GUID StringPtrGuid =
  6. { 0xc03d4861, 0x70d7, 0x11d1, { 0x99, 0x4f, 0x0, 0x60, 0x97, 0x6a, 0x54, 0x6d } };
  7. CComPtr<IMalloc> CWsbStringPtr::m_pMalloc = 0;
  8. CWsbStringPtr::CWsbStringPtr()
  9. {
  10. HRESULT hr = S_OK;
  11. try {
  12. m_pString = 0;
  13. m_givenSize = 0;
  14. if (m_pMalloc == 0) {
  15. WsbAssertHr(CoGetMalloc(1, &m_pMalloc));
  16. }
  17. WSB_OBJECT_ADD(StringPtrGuid, this);
  18. } WsbCatch(hr);
  19. }
  20. CWsbStringPtr::CWsbStringPtr(const CHAR* pChar)
  21. {
  22. HRESULT hr = S_OK;
  23. try {
  24. m_pString = 0;
  25. m_givenSize = 0;
  26. if (m_pMalloc == 0) {
  27. WsbAssertHr(CoGetMalloc(1, &m_pMalloc));
  28. }
  29. WSB_OBJECT_ADD(StringPtrGuid, this);
  30. *this = pChar;
  31. } WsbCatch(hr);
  32. }
  33. CWsbStringPtr::CWsbStringPtr(const WCHAR* pWchar)
  34. {
  35. HRESULT hr = S_OK;
  36. try {
  37. m_pString = 0;
  38. m_givenSize = 0;
  39. if (m_pMalloc == 0) {
  40. WsbAssertHr(CoGetMalloc(1, &m_pMalloc));
  41. }
  42. WSB_OBJECT_ADD(StringPtrGuid, this);
  43. *this = pWchar;
  44. } WsbCatch(hr);
  45. }
  46. CWsbStringPtr::CWsbStringPtr(REFGUID rguid)
  47. {
  48. HRESULT hr = S_OK;
  49. try {
  50. m_pString = 0;
  51. m_givenSize = 0;
  52. if (m_pMalloc == 0) {
  53. WsbAssertHr(CoGetMalloc(1, &m_pMalloc));
  54. }
  55. WSB_OBJECT_ADD(StringPtrGuid, this);
  56. *this = rguid;
  57. } WsbCatch(hr);
  58. }
  59. CWsbStringPtr::CWsbStringPtr(const CWsbStringPtr& pString)
  60. {
  61. HRESULT hr = S_OK;
  62. try {
  63. m_pString = 0;
  64. m_givenSize = 0;
  65. if (m_pMalloc == 0) {
  66. WsbAssertHr(CoGetMalloc(1, &m_pMalloc));
  67. }
  68. WSB_OBJECT_ADD(StringPtrGuid, this);
  69. *this = pString;
  70. } WsbCatch(hr);
  71. }
  72. CWsbStringPtr::~CWsbStringPtr()
  73. {
  74. WSB_OBJECT_SUB(StringPtrGuid, this);
  75. Free();
  76. }
  77. CWsbStringPtr::operator WCHAR*()
  78. {
  79. return(m_pString);
  80. }
  81. WCHAR& CWsbStringPtr::operator *()
  82. {
  83. _ASSERTE(0 != m_pString);
  84. return(*m_pString);
  85. }
  86. WCHAR** CWsbStringPtr::operator &()
  87. {
  88. return(&m_pString);
  89. }
  90. WCHAR& CWsbStringPtr::operator [](const int i)
  91. {
  92. _ASSERTE(0 != m_pString);
  93. return(m_pString[i]);
  94. }
  95. CWsbStringPtr& CWsbStringPtr::operator =(const CHAR* pChar)
  96. {
  97. HRESULT hr = S_OK;
  98. ULONG length;
  99. int count;
  100. try {
  101. // Are they setting it to something?
  102. if (0 != pChar) {
  103. // Otherwise, see if our current buffer is big enough.
  104. //
  105. // NOTE: With multibyte characters, we may be getting a bigger
  106. // buffer than we need, but the call to return the accurate
  107. // size is not ANSI.
  108. length = strlen(pChar);
  109. WsbAffirmHr(Realloc(length));
  110. WsbAffirm(0 != m_pString, E_OUTOFMEMORY);
  111. // Copy the data (and convert to wide characters)
  112. count = mbstowcs(m_pString, pChar, length + 1);
  113. WsbAffirm((count != -1), E_FAIL);
  114. }
  115. else {
  116. Free();
  117. }
  118. } WsbCatch(hr);
  119. return(*this);
  120. }
  121. CWsbStringPtr& CWsbStringPtr::operator =(const WCHAR* pWchar)
  122. {
  123. HRESULT hr = S_OK;
  124. ULONG length;
  125. try {
  126. // Are they setting it to something?
  127. if (0 != pWchar) {
  128. // Otherwise, see if our current buffer is big enough.
  129. length = wcslen(pWchar);
  130. WsbAffirmHr(Realloc(length));
  131. // Copy the data (and convert to wide characters)
  132. wcscpy(m_pString, pWchar);
  133. }
  134. else {
  135. Free();
  136. }
  137. } WsbCatch(hr);
  138. return(*this);
  139. }
  140. CWsbStringPtr& CWsbStringPtr::operator =(REFGUID rguid)
  141. {
  142. HRESULT hr = S_OK;
  143. OLECHAR* tmpString = 0;
  144. try {
  145. // See if our current buffer is big enough.
  146. WsbAffirmHr(Realloc(WSB_GUID_STRING_SIZE));
  147. // Fill with the GUID in string format
  148. WsbAffirmHr(WsbStringFromGuid(rguid, m_pString));
  149. } WsbCatch(hr);
  150. return(*this);
  151. }
  152. CWsbStringPtr& CWsbStringPtr::operator =(const CWsbStringPtr& pString)
  153. {
  154. *this = pString.m_pString;
  155. return(*this);
  156. }
  157. BOOL CWsbStringPtr::operator !()
  158. {
  159. return((0 == m_pString) ? TRUE : FALSE);
  160. }
  161. HRESULT CWsbStringPtr::Alloc(ULONG size)
  162. {
  163. HRESULT hr = S_OK;
  164. try {
  165. WsbAssert(0 == m_pString, E_UNEXPECTED);
  166. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  167. m_pString = (WCHAR*)WsbAlloc((size + 1) * sizeof(WCHAR));
  168. WsbAffirm(0 != m_pString, E_OUTOFMEMORY);
  169. // Make sure we always have a valid string so bad things don't happen.
  170. *m_pString = 0;
  171. } WsbCatch(hr);
  172. return(hr);
  173. }
  174. HRESULT CWsbStringPtr::Append(const CHAR* pChar)
  175. {
  176. HRESULT hr = S_OK;
  177. CWsbStringPtr tmpString = pChar;
  178. hr = Append(tmpString);
  179. return(hr);
  180. }
  181. HRESULT CWsbStringPtr::Append(const WCHAR* pWchar)
  182. {
  183. HRESULT hr = S_OK;
  184. ULONG length = 0;
  185. ULONG appendLength;
  186. try {
  187. // If they passed us a null pointer, then we don't need to do anything.
  188. WsbAffirm(pWchar != 0, S_OK);
  189. // If they passed us an empty string, then we don't need to do anything.
  190. appendLength = wcslen(pWchar);
  191. if (0 != appendLength) {
  192. // Make sure the buffer is big enough.
  193. if (0 != m_pString) {
  194. length = wcslen(m_pString);
  195. }
  196. WsbAffirmHr(Realloc(length + appendLength));
  197. // Append the string.
  198. wcscat(m_pString, pWchar);
  199. }
  200. } WsbCatch(hr);
  201. return(hr);
  202. }
  203. HRESULT CWsbStringPtr::Append(const CWsbStringPtr& pString) {
  204. HRESULT hr = S_OK;
  205. hr = Append(pString.m_pString);
  206. return(hr);
  207. }
  208. HRESULT CWsbStringPtr::CopyTo(CHAR** ppChar)
  209. {
  210. HRESULT hr = S_OK;
  211. hr = CopyTo(ppChar, 0);
  212. return(hr);
  213. }
  214. HRESULT CWsbStringPtr::CopyTo(CHAR** ppChar, ULONG bufferSize)
  215. {
  216. HRESULT hr = S_OK;
  217. ULONG length = 0;
  218. CHAR* tmpString = 0;
  219. try {
  220. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  221. // Allocate a buffer big enough to hold their string.
  222. //
  223. // NOTE: With multibyte characters, we may be getting a bigger
  224. // buffer than we need, but the call to return the accurate
  225. // size is not ANSI.
  226. if (m_pString != 0) {
  227. length = wcstombs(0, m_pString, 0);
  228. }
  229. if (bufferSize == 0) {
  230. tmpString = (CHAR*) WsbRealloc(*ppChar, (length + 1) * sizeof(CHAR));
  231. } else {
  232. WsbAssert(bufferSize >= length, E_FAIL);
  233. if (*ppChar == 0) {
  234. tmpString = (CHAR*)WsbAlloc((bufferSize + 1) * sizeof(CHAR));
  235. } else {
  236. tmpString = *ppChar;
  237. }
  238. }
  239. WsbAffirm(0 != tmpString, E_OUTOFMEMORY);
  240. *ppChar = tmpString;
  241. // Copy and return the string;
  242. if (m_pString != 0) {
  243. WsbAffirm (-1 != wcstombs(*ppChar, m_pString, length + 1), E_FAIL);
  244. } else {
  245. **ppChar = 0;
  246. }
  247. } WsbCatch(hr);
  248. return(hr);
  249. }
  250. HRESULT CWsbStringPtr::CopyTo(WCHAR** ppWchar)
  251. {
  252. HRESULT hr = S_OK;
  253. hr = CopyTo(ppWchar, 0);
  254. return(hr);
  255. }
  256. HRESULT CWsbStringPtr::CopyTo(WCHAR** ppWchar, ULONG bufferSize)
  257. {
  258. HRESULT hr = S_OK;
  259. ULONG length = 0;
  260. WCHAR* tmpString = 0;
  261. try {
  262. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  263. // Allocate a buffer big enough to hold their string.
  264. if (m_pString != 0) {
  265. length = wcslen(m_pString);
  266. }
  267. if (bufferSize == 0) {
  268. tmpString = (WCHAR*) WsbRealloc(*ppWchar, (length + 1) * sizeof(WCHAR));
  269. } else {
  270. WsbAssert(bufferSize >= length, E_FAIL);
  271. if (*ppWchar == 0) {
  272. tmpString = (WCHAR*) WsbRealloc(*ppWchar, (bufferSize + 1) * sizeof(WCHAR));
  273. }
  274. }
  275. WsbAffirm(0 != tmpString, E_OUTOFMEMORY);
  276. *ppWchar = tmpString;
  277. // Copy and return the string;
  278. if (m_pString != 0) {
  279. wcscpy(*ppWchar, m_pString);
  280. } else {
  281. **ppWchar = 0;
  282. }
  283. } WsbCatch(hr);
  284. return(hr);
  285. }
  286. HRESULT CWsbStringPtr::CopyTo(GUID * pguid)
  287. {
  288. HRESULT hr = S_OK;
  289. hr = WsbGuidFromString(m_pString, pguid);
  290. return(hr);
  291. }
  292. HRESULT CWsbStringPtr::CopyToBstr(BSTR* pBstr)
  293. {
  294. HRESULT hr = S_OK;
  295. hr = CopyToBstr(pBstr, 0);
  296. return(hr);
  297. }
  298. HRESULT CWsbStringPtr::CopyToBstr(BSTR* pBstr, ULONG bufferSize)
  299. {
  300. HRESULT hr = S_OK;
  301. ULONG length = 0;
  302. try {
  303. // Allocate a buffer big enough to hold their string.
  304. if (m_pString != 0) {
  305. length = wcslen(m_pString);
  306. }
  307. if (bufferSize == 0) {
  308. if (0 == *pBstr) {
  309. *pBstr = WsbAllocString(m_pString);
  310. } else {
  311. WsbAffirm(WsbReallocString(pBstr, m_pString), E_OUTOFMEMORY);
  312. }
  313. } else {
  314. WsbAssert(bufferSize >= length, E_FAIL);
  315. if (0 == pBstr) {
  316. *pBstr = WsbAllocStringLen(m_pString, bufferSize);
  317. } else {
  318. WsbAffirm(WsbReallocStringLen(pBstr, m_pString, bufferSize), E_OUTOFMEMORY);
  319. }
  320. }
  321. WsbAffirm(0 != pBstr, E_OUTOFMEMORY);
  322. } WsbCatch(hr);
  323. return(hr);
  324. }
  325. HRESULT CWsbStringPtr::FindInRsc(ULONG startId, ULONG idsToCheck, ULONG* pMatchId)
  326. {
  327. HRESULT hr = S_FALSE;
  328. CWsbStringPtr dest;
  329. try {
  330. WsbAssert(0 != pMatchId, E_POINTER);
  331. // Initialize the return value.
  332. *pMatchId = 0;
  333. // Check each resource string mention and see if it is the same as
  334. // the string provided.
  335. for (ULONG testId = startId; (testId < (startId + idsToCheck)) && (*pMatchId == 0); testId++) {
  336. WsbAffirmHr(dest.LoadFromRsc(_Module.m_hInst, testId));
  337. if (wcscmp(dest, m_pString) == 0) {
  338. *pMatchId = testId;
  339. hr = S_OK;
  340. }
  341. }
  342. } WsbCatch(hr);
  343. return(hr);
  344. }
  345. HRESULT CWsbStringPtr::Free(void)
  346. {
  347. HRESULT hr = S_OK;
  348. try {
  349. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  350. if ((0 != m_pString) && (0 == m_givenSize)) {
  351. WsbFree(m_pString);
  352. m_pString = 0;
  353. }
  354. } WsbCatch(hr);
  355. return(hr);
  356. }
  357. HRESULT CWsbStringPtr::GetSize(ULONG* pSize)
  358. {
  359. HRESULT hr = S_OK;
  360. try {
  361. WsbAssert(0 != pSize, E_POINTER);
  362. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  363. if (0 == m_pString) {
  364. *pSize = 0;
  365. } else if (0 != m_givenSize) {
  366. *pSize = m_givenSize;
  367. } else {
  368. *pSize = (ULONG)(m_pMalloc->GetSize(m_pString) / sizeof(WCHAR) - 1);
  369. }
  370. } WsbCatch(hr);
  371. return(hr);
  372. }
  373. HRESULT CWsbStringPtr::GiveTo(WCHAR** ppWchar)
  374. {
  375. HRESULT hr = S_OK;
  376. try {
  377. WsbAssert(0 != ppWchar, E_POINTER);
  378. // Given them our string buffer, and forget about it.
  379. *ppWchar = m_pString;
  380. m_pString = 0;
  381. m_givenSize = 0;
  382. } WsbCatch(hr);
  383. return(hr);
  384. }
  385. HRESULT CWsbStringPtr::LoadFromRsc(HINSTANCE instance, ULONG id)
  386. {
  387. HRESULT hr = S_OK;
  388. HRSRC resource;
  389. ULONG stringSize;
  390. try {
  391. // Find the resource requested. This requires converting the resource
  392. // identifier into a string.
  393. //
  394. // NOTE: Strings are not number individually, but in groups of 16!! This throws
  395. // off the latter size calculation, and some other strategy might be better
  396. // here (e.g. load to a fixed size and then allocate again if too small).
  397. resource = FindResource(instance, MAKEINTRESOURCE((id/16) + 1), RT_STRING);
  398. WsbAffirm(resource != 0, E_FAIL);
  399. // How big is the string?
  400. stringSize = SizeofResource(instance, resource);
  401. WsbAffirm(0 != stringSize, E_FAIL);
  402. // Get the right sized buffer.
  403. WsbAffirmHr(Realloc(stringSize / sizeof(WCHAR)));
  404. // Load the string into the buffer.
  405. WsbAffirm(LoadString(instance, id, m_pString, (stringSize / sizeof(WCHAR)) + 1) != 0, E_FAIL);
  406. } WsbCatch(hr);
  407. return(hr);
  408. }
  409. HRESULT CWsbStringPtr::Prepend(const CHAR* pChar) {
  410. HRESULT hr = S_OK;
  411. CWsbStringPtr tmpString = pChar;
  412. hr = Prepend(tmpString);
  413. return(hr);
  414. }
  415. HRESULT CWsbStringPtr::Prepend(const WCHAR* pWchar) {
  416. HRESULT hr = S_OK;
  417. ULONG length;
  418. ULONG prependLength;
  419. ULONG i, j;
  420. try {
  421. // If they passed us a null pointer, then we don't need to do anything.
  422. WsbAffirm(pWchar != 0, S_OK);
  423. // If they passed us an empty string, then we don't need to do anything.
  424. prependLength = wcslen(pWchar);
  425. WsbAffirm(0 != prependLength, S_OK);
  426. if (0 != m_pString) {
  427. length = wcslen(m_pString);
  428. } else {
  429. // Prepend code will work as long as we have a null string and not a null pointer...
  430. // Next Realloc statement will make it happen...
  431. length = 0;
  432. }
  433. WsbAffirmHr(Realloc(length + prependLength));
  434. // First move the existing string down in the buffer.
  435. for (i = length + 1, j = length + prependLength; i > 0; i--, j--) {
  436. m_pString[j] = m_pString[i - 1];
  437. }
  438. // Now prepend the string (except for the null)
  439. for (i = 0; i < prependLength; i++) {
  440. m_pString[i] = pWchar[i];
  441. }
  442. } WsbCatch(hr);
  443. return(hr);
  444. }
  445. HRESULT CWsbStringPtr::Prepend(const CWsbStringPtr& pString) {
  446. HRESULT hr = S_OK;
  447. hr = Prepend(pString.m_pString);
  448. return(hr);
  449. }
  450. HRESULT CWsbStringPtr::Realloc(ULONG size)
  451. {
  452. HRESULT hr = S_OK;
  453. WCHAR* tmpString;
  454. ULONG currentSize;
  455. BOOL bigEnough = FALSE;
  456. try {
  457. // We want to try to get a buffer of the size indicated.
  458. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  459. // If the buffer is already bigger than the size needed, then
  460. // don't do anything.
  461. if (0 != m_pString) {
  462. WsbAffirmHr(GetSize(&currentSize));
  463. if (currentSize >= size) {
  464. bigEnough = TRUE;
  465. }
  466. }
  467. // Reallocate the buffer if we need a bigger one.
  468. if (!bigEnough) {
  469. // If we were given this buffer, then we can't reallocate it.
  470. WsbAssert(0 == m_givenSize, E_UNEXPECTED);
  471. // If we have never allocated a buffer, then allocate it normally.
  472. if (0 == m_pString) {
  473. WsbAffirmHr(Alloc(size));
  474. } else {
  475. WsbAssert(m_pMalloc != 0, E_UNEXPECTED);
  476. tmpString = (WCHAR*) WsbRealloc(m_pString, (size + 1) * sizeof(WCHAR));
  477. WsbAffirm(0 != tmpString, E_OUTOFMEMORY);
  478. m_pString = tmpString;
  479. }
  480. }
  481. } WsbCatch(hr);
  482. return(hr);
  483. }
  484. HRESULT CWsbStringPtr::TakeFrom(WCHAR* pWchar, ULONG bufferSize)
  485. {
  486. HRESULT hr = S_OK;
  487. try {
  488. // Clear out any previously "taken" string.
  489. if (0 != m_givenSize) {
  490. m_pString = 0;
  491. m_givenSize = 0;
  492. }
  493. // If the given buffer is null, then we are responsible for allocating it.
  494. if (0 == pWchar) {
  495. if (0 != bufferSize) {
  496. WsbAffirmHr(Realloc(bufferSize));
  497. }
  498. }
  499. // Otherwise, we need to get rid of any buffer we had and use the one indicated.
  500. else {
  501. if (0 != m_pString) {
  502. WsbAffirmHr(Free());
  503. }
  504. m_pString = pWchar;
  505. if (0 != bufferSize) {
  506. m_givenSize = bufferSize;
  507. }
  508. }
  509. } WsbCatch(hr);
  510. return(hr);
  511. }
  512. HRESULT CWsbStringPtr::VPrintf(const WCHAR* fmtString, va_list vaList)
  513. {
  514. HRESULT hr = S_OK;
  515. try {
  516. Realloc(WSB_TRACE_BUFF_SIZE);
  517. vswprintf (m_pString, fmtString, vaList);
  518. } WsbCatch(hr);
  519. return(hr);
  520. }