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.

138 lines
3.5 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 000
  5. *
  6. * File: guidhelp.inl
  7. *
  8. * Contents:
  9. *
  10. * History: 13-Apr-2000 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #pragma once
  14. #include "xmlbase.h" // for CXMLBinary
  15. /*+-------------------------------------------------------------------------*
  16. * ExtractString
  17. *
  18. * Gets string data representing the given clipboard format from the data
  19. * object. StringType must be a type that can accept assignment from
  20. * LPCTSTR (WTL::CString, CStr, tstring, etc.)
  21. *
  22. * Many (many!) implementations of IDataObject::GetDataHere incorrectly call
  23. * CreateStreamOnHGlobal using the HGLOBAL we get them (calling it is
  24. * incorrect because GetDataHere is specifically forbidden from reallocating
  25. * the medium that is given to it, which the IStream implementation returned
  26. * from CreateStreamOnHGlobal will do if it needs more room).
  27. *
  28. * We would be more robust if we used TYMED_STREAM in preference to
  29. * TYMED_HGLOBAL, if the snap-in supported it.
  30. *--------------------------------------------------------------------------*/
  31. template<class StringType>
  32. HRESULT ExtractString (
  33. IDataObject* piDataObject,
  34. CLIPFORMAT cfClipFormat,
  35. StringType& str)
  36. {
  37. DECLARE_SC (sc, _T("ExtractString"));
  38. sc = ScCheckPointers (piDataObject);
  39. if (sc)
  40. return (sc.ToHr());
  41. /*
  42. * clear out the output
  43. */
  44. str = _T("");
  45. FORMATETC formatetc = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  46. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL};
  47. CXMLBinary xmlBin;
  48. /*
  49. * 1024 isn't a random number. It must be (at least) this large to
  50. * maintain compatibility with buggy snap-ins.
  51. */
  52. const int cchGrow = 1024;
  53. int cchBuffer = 0;
  54. /*
  55. * to enter the loop the first time
  56. */
  57. sc = STG_E_MEDIUMFULL;
  58. while (sc == STG_E_MEDIUMFULL)
  59. {
  60. /*
  61. * increase the buffer size
  62. */
  63. cchBuffer += cchGrow;
  64. const int cbBuffer = cchBuffer * sizeof(WCHAR);
  65. /*
  66. * Allocate a buffer for the string. In the reallocation case,
  67. * it is safe to store the return value from GlobalReAlloc in
  68. * stgmedium.hGlobal because the original handle is also held
  69. * in autoGlobal
  70. */
  71. if (cchBuffer == cchGrow)
  72. sc = xmlBin.ScAlloc (cbBuffer, true /* fZeroInit */);
  73. else
  74. sc = xmlBin.ScRealloc (cbBuffer, true /* fZeroInit */);
  75. if (sc)
  76. return (sc.ToHr());
  77. /*
  78. * get the HGLOBAL out of the CXMLBinary
  79. */
  80. stgmedium.hGlobal = xmlBin.GetHandle();
  81. sc = ScCheckPointers (stgmedium.hGlobal, E_UNEXPECTED);
  82. if (sc)
  83. return (sc.ToHr());
  84. /*
  85. * get the string from the data object
  86. */
  87. sc = piDataObject->GetDataHere (&formatetc, &stgmedium);
  88. // don't check for error here, it'll be checked at the top of the loop
  89. }
  90. /*
  91. * this will handle all non-STG_E_MEDIUMFULL errors from
  92. * IDataObject::GetDataHere
  93. */
  94. if (sc)
  95. {
  96. // don't trace these errors
  97. SC scTemp = sc;
  98. sc.Clear();
  99. return scTemp.ToHr();
  100. }
  101. /*
  102. * lock down the returned data in preparation for copying
  103. */
  104. CXMLBinaryLock lock (xmlBin);
  105. LPWSTR pchBuffer = NULL;
  106. sc = lock.ScLock (&pchBuffer);
  107. if (sc)
  108. return (sc.ToHr());
  109. /*
  110. * Copy the string. The termination isn't unjustified paranoia.
  111. * Many implementations of IDataObject::GetDataHere don't terminate
  112. * their strings.
  113. */
  114. USES_CONVERSION;
  115. pchBuffer[cchBuffer-1] = 0;
  116. str = W2CT (pchBuffer);
  117. return (sc.ToHr());
  118. }