Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 66a90de

Browse files
committed
Bug 1942424 - [4/5] Rewrite nsDataObj::GetText() r=win-reviewers,gstoll
Again, convert C-style explicit allocations to use RAII. No functional changes -- not even to fix questionable return values. Differential Revision: https://phabricator.services.mozilla.com/D236080
1 parent 6138b77 commit 66a90de

File tree

1 file changed

+57
-49
lines changed

1 file changed

+57
-49
lines changed

widget/windows/nsDataObj.cpp

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,96 +1480,104 @@ HRESULT nsDataObj::GetPreferredDropEffect(FORMATETC& aFE, STGMEDIUM& aSTG) {
14801480
//-----------------------------------------------------
14811481
HRESULT nsDataObj::GetText(const nsACString& aDataFlavor, FORMATETC& aFE,
14821482
STGMEDIUM& aSTG) {
1483-
void* data = nullptr;
1483+
// assignDataToStg
1484+
//
1485+
// Helper function to fill the STG with a block of data.
1486+
auto const assignDataToStg = [&aSTG](void* data, size_t extent) -> HRESULT {
1487+
aSTG.tymed = TYMED_HGLOBAL;
1488+
aSTG.pUnkForRelease = nullptr;
1489+
1490+
ScopedOLEMemory<char[]> hGlobalMemory(extent);
1491+
if (hGlobalMemory) {
1492+
auto dest = hGlobalMemory.lock();
1493+
memcpy(dest.get(), data, extent);
1494+
}
1495+
1496+
aSTG.hGlobal = hGlobalMemory.forget();
1497+
1498+
return S_OK;
1499+
};
14841500

14851501
const nsPromiseFlatCString& flavorStr = PromiseFlatCString(aDataFlavor);
14861502

1487-
// NOTE: CreateDataFromPrimitive creates new memory, that needs to be deleted
14881503
nsCOMPtr<nsISupports> genericDataWrapper;
14891504
nsresult rv = mTransferable->GetTransferData(
14901505
flavorStr.get(), getter_AddRefs(genericDataWrapper));
14911506
if (NS_FAILED(rv) || !genericDataWrapper) {
14921507
return E_FAIL;
14931508
}
14941509

1495-
uint32_t len;
1496-
nsPrimitiveHelpers::CreateDataFromPrimitive(
1497-
nsDependentCString(flavorStr.get()), genericDataWrapper, &data, &len);
1510+
// data is a possibly-wide NUL-terminated string. len is its strlen() -- not
1511+
// its allocation length!
1512+
auto const [data, len] = [&]() {
1513+
void* data = nullptr;
1514+
uint32_t len;
1515+
nsPrimitiveHelpers::CreateDataFromPrimitive(
1516+
nsDependentCString(flavorStr.get()), genericDataWrapper, &data, &len);
1517+
return std::tuple{data, size_t(len)};
1518+
}();
14981519
if (!data) return E_FAIL;
14991520

1500-
HGLOBAL hGlobalMemory = nullptr;
1501-
1502-
aSTG.tymed = TYMED_HGLOBAL;
1503-
aSTG.pUnkForRelease = nullptr;
1521+
// CreateDataFromPrimitive allocates memory; free it on exit.
1522+
auto const _release_data =
1523+
mozilla::MakeScopeExit([data = data]() { ::free(data); });
15041524

1505-
// We play games under the hood and advertise flavors that we know we
1506-
// can support, only they require a bit of conversion or munging of the data.
1507-
// Do that here.
1525+
// We play games under the hood and advertise flavors that we know we can
1526+
// support, only they require a bit of conversion or munging of the data. Do
1527+
// that here.
15081528
//
15091529
// The transferable gives us data that is null-terminated, but this isn't
1510-
// reflected in the |len| parameter. Windoze apps expect this null to be there
1530+
// reflected in the |len| parameter. Windows apps expect this null to be there
15111531
// so bump our data buffer by the appropriate size to account for the null
15121532
// (one char for CF_TEXT, one char16_t for CF_UNICODETEXT).
1513-
DWORD allocLen = (DWORD)len;
1533+
15141534
if (aFE.cfFormat == CF_TEXT) {
15151535
// Someone is asking for text/plain; convert the unicode (assuming it's
15161536
// present) to text with the correct platform encoding.
15171537
size_t bufferSize = sizeof(char) * (len + 2);
15181538
char* plainTextData = static_cast<char*>(moz_xmalloc(bufferSize));
1539+
auto const _release =
1540+
mozilla::MakeScopeExit([plainTextData]() { ::free(plainTextData); });
1541+
15191542
char16_t* castedUnicode = reinterpret_cast<char16_t*>(data);
15201543
int32_t plainTextLen =
15211544
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)castedUnicode, len / 2 + 1,
15221545
plainTextData, bufferSize, NULL, NULL);
1523-
// replace the unicode data with our plaintext data. Recall that
1524-
// |plainTextLen| doesn't include the null in the length.
1525-
free(data);
1546+
15261547
if (plainTextLen) {
1527-
data = plainTextData;
1528-
allocLen = plainTextLen;
1529-
} else {
1530-
free(plainTextData);
1531-
NS_WARNING("Oh no, couldn't convert unicode to plain text");
1532-
return S_OK;
1548+
return assignDataToStg(plainTextData, plainTextLen);
15331549
}
1534-
} else if (aFE.cfFormat == nsClipboard::GetHtmlClipboardFormat()) {
1550+
1551+
NS_WARNING("Oh no, couldn't convert unicode to plain text");
1552+
return S_OK;
1553+
}
1554+
1555+
if (aFE.cfFormat == nsClipboard::GetHtmlClipboardFormat()) {
15351556
// Someone is asking for win32's HTML flavor. Convert our html fragment
15361557
// from unicode to UTF-8 then put it into a format specified by msft.
15371558
NS_ConvertUTF16toUTF8 converter(reinterpret_cast<char16_t*>(data));
15381559
char* utf8HTML = nullptr;
15391560
nsresult rv =
15401561
BuildPlatformHTML(converter.get(), &utf8HTML); // null terminates
1562+
auto const _release =
1563+
mozilla::MakeScopeExit([utf8HTML]() { ::free(utf8HTML); });
15411564

1542-
free(data);
15431565
if (NS_SUCCEEDED(rv) && utf8HTML) {
1544-
// replace the unicode data with our HTML data. Don't forget the null.
1545-
data = utf8HTML;
1546-
allocLen = strlen(utf8HTML) + sizeof(char);
1547-
} else {
1548-
NS_WARNING("Oh no, couldn't convert to HTML");
1549-
return S_OK;
1566+
// return our HTML data. Don't forget the null.
1567+
return assignDataToStg(utf8HTML, strlen(utf8HTML) + sizeof(char));
15501568
}
1551-
} else if (aFE.cfFormat != nsClipboard::GetCustomClipboardFormat()) {
1552-
// we assume that any data that isn't caught above is unicode. This may
1553-
// be an erroneous assumption, but is true so far.
1554-
allocLen += sizeof(char16_t);
1555-
}
15561569

1557-
hGlobalMemory = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, allocLen);
1558-
1559-
// Copy text to Global Memory Area
1560-
if (hGlobalMemory) {
1561-
char* dest = reinterpret_cast<char*>(GlobalLock(hGlobalMemory));
1562-
char* source = reinterpret_cast<char*>(data);
1563-
memcpy(dest, source, allocLen); // copies the null as well
1564-
GlobalUnlock(hGlobalMemory);
1570+
NS_WARNING("Oh no, couldn't convert to HTML");
1571+
return S_OK;
15651572
}
1566-
aSTG.hGlobal = hGlobalMemory;
15671573

1568-
// Now, delete the memory that was created by CreateDataFromPrimitive (or our
1569-
// text/plain data)
1570-
free(data);
1574+
// We assume that any data-format that isn't caught above can be satisfied by
1575+
// Unicode text. (This may be an erroneous assumption, but seems to have been
1576+
// true so far.)
1577+
bool const excludeNull =
1578+
aFE.cfFormat == nsClipboard::GetCustomClipboardFormat();
15711579

1572-
return S_OK;
1580+
return assignDataToStg(data, len + (excludeNull ? 0 : sizeof(char16_t)));
15731581
}
15741582

15751583
//-----------------------------------------------------

0 commit comments

Comments
 (0)