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

Commit 8c4a6bc

Browse files
committed
Bug 1942424 - [5/5] Clean up nsDataObj::GetFile() helpers r=win-reviewers,gstoll
Factor out the essentially-identical fragments of the helper functions called by nsDataObj::GetFile() into a single less-messy auxiliary function. No functional changes, beyond better failure return value reporting. Differential Revision: https://phabricator.services.mozilla.com/D236081
1 parent 66a90de commit 8c4a6bc

File tree

1 file changed

+66
-110
lines changed

1 file changed

+66
-110
lines changed

widget/windows/nsDataObj.cpp

Lines changed: 66 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,69 @@ HRESULT nsDataObj::GetFile(FORMATETC& aFE, STGMEDIUM& aSTG) {
15991599
return E_FAIL;
16001600
}
16011601

1602+
static HRESULT AssignDropfile(STGMEDIUM& aSTG, nsAString const& aPath) {
1603+
// Struct describing the data in the OLE memory space. Marginally cleaner than
1604+
// completely-manual pointer manipulation.
1605+
struct DFWithPaths {
1606+
DROPFILES dropfiles;
1607+
// An epsilon-terminated list of NUL-terminated strings.
1608+
// See the CF_HDROP shell clipboard format for more info.
1609+
WCHAR paths[];
1610+
};
1611+
1612+
// C++ doesn't have a dependent-type system robust enough for ScopedOLEMemory
1613+
// to handle a struct-with-flexible array member well, so we eschew it here
1614+
// for the less-strongly-typed (and slightly more awkward) nsAutoGlobalMem.
1615+
size_t const allocSize =
1616+
// Size of the initial header block...
1617+
sizeof(DFWithPaths) +
1618+
// ... size of the first path...
1619+
((aPath.Length() + 1) * sizeof(WCHAR)) +
1620+
// ... and size of the terminating empty string.
1621+
sizeof(L"");
1622+
1623+
nsAutoGlobalMem hGlobalMemory(
1624+
nsHGLOBAL(::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, allocSize)));
1625+
1626+
if (!hGlobalMemory) {
1627+
return E_FAIL;
1628+
}
1629+
1630+
{
1631+
ScopedOLELock<DFWithPaths*> pDFWithPaths(hGlobalMemory.get());
1632+
1633+
// First, populate the dropfile structure...
1634+
DROPFILES* pDropFile = &pDFWithPaths->dropfiles;
1635+
pDropFile->pFiles =
1636+
offsetof(DFWithPaths, paths) - offsetof(DFWithPaths, dropfiles);
1637+
pDropFile->fNC = 0;
1638+
pDropFile->pt.x = 0;
1639+
pDropFile->pt.y = 0;
1640+
pDropFile->fWide = TRUE;
1641+
1642+
// ... then copy the filename into `paths`.
1643+
WCHAR* dest = pDFWithPaths->paths;
1644+
WCHAR* after_dest [[maybe_unused]] =
1645+
std::copy_n(aPath.BeginReading(), aPath.Length(), dest);
1646+
1647+
// Two NULs are needed after the file name; the GMEM_ZEROINIT above should
1648+
// provide them.
1649+
size_t const offset [[maybe_unused]] =
1650+
(char*)after_dest - (char*)pDFWithPaths.get();
1651+
MOZ_ASSERT(allocSize - offset == sizeof(WCHAR) * 2);
1652+
MOZ_ASSERT(after_dest[0] == L'\0');
1653+
MOZ_ASSERT(after_dest[1] == L'\0');
1654+
}
1655+
1656+
aSTG = {
1657+
.tymed = TYMED_HGLOBAL,
1658+
.hGlobal = hGlobalMemory.disown(),
1659+
.pUnkForRelease = nullptr,
1660+
};
1661+
1662+
return S_OK;
1663+
}
1664+
16021665
HRESULT nsDataObj::DropFile(FORMATETC& aFE, STGMEDIUM& aSTG) {
16031666
nsresult rv;
16041667
nsCOMPtr<nsISupports> genericDataWrapper;
@@ -1610,44 +1673,11 @@ HRESULT nsDataObj::DropFile(FORMATETC& aFE, STGMEDIUM& aSTG) {
16101673
nsCOMPtr<nsIFile> file(do_QueryInterface(genericDataWrapper));
16111674
if (!file) return E_FAIL;
16121675

1613-
aSTG.tymed = TYMED_HGLOBAL;
1614-
aSTG.pUnkForRelease = nullptr;
1615-
16161676
nsAutoString path;
16171677
rv = file->GetPath(path);
16181678
if (NS_FAILED(rv)) return E_FAIL;
16191679

1620-
uint32_t allocLen = path.Length() + 2;
1621-
HGLOBAL hGlobalMemory = nullptr;
1622-
char16_t* dest;
1623-
1624-
hGlobalMemory = GlobalAlloc(GMEM_MOVEABLE,
1625-
sizeof(DROPFILES) + allocLen * sizeof(char16_t));
1626-
if (!hGlobalMemory) return E_FAIL;
1627-
1628-
DROPFILES* pDropFile = (DROPFILES*)GlobalLock(hGlobalMemory);
1629-
1630-
// First, populate the drop file structure
1631-
pDropFile->pFiles = sizeof(DROPFILES); // Offset to start of file name string
1632-
pDropFile->fNC = 0;
1633-
pDropFile->pt.x = 0;
1634-
pDropFile->pt.y = 0;
1635-
pDropFile->fWide = TRUE;
1636-
1637-
// Copy the filename right after the DROPFILES structure
1638-
dest = (char16_t*)(((char*)pDropFile) + pDropFile->pFiles);
1639-
memcpy(dest, path.get(), (allocLen - 1) * sizeof(char16_t));
1640-
1641-
// Two null characters are needed at the end of the file name.
1642-
// Lookup the CF_HDROP shell clipboard format for more info.
1643-
// Add the second null character right after the first one.
1644-
dest[allocLen - 1] = L'\0';
1645-
1646-
GlobalUnlock(hGlobalMemory);
1647-
1648-
aSTG.hGlobal = hGlobalMemory;
1649-
1650-
return S_OK;
1680+
return AssignDropfile(aSTG, path);
16511681
}
16521682

16531683
HRESULT nsDataObj::DropImage(FORMATETC& /* aFE */, STGMEDIUM& aSTG) {
@@ -1750,44 +1780,7 @@ HRESULT nsDataObj::DropImage(FORMATETC& /* aFE */, STGMEDIUM& aSTG) {
17501780
rv = mCachedTempFile->GetPath(path);
17511781
if (NS_FAILED(rv)) return E_FAIL;
17521782

1753-
// Two null characters are needed to terminate the file name list.
1754-
HGLOBAL hGlobalMemory = nullptr;
1755-
1756-
uint32_t allocLen = path.Length() + 2;
1757-
1758-
aSTG.tymed = TYMED_HGLOBAL;
1759-
aSTG.pUnkForRelease = nullptr;
1760-
1761-
hGlobalMemory = GlobalAlloc(GMEM_MOVEABLE,
1762-
sizeof(DROPFILES) + allocLen * sizeof(char16_t));
1763-
if (!hGlobalMemory) return E_FAIL;
1764-
1765-
DROPFILES* pDropFile = (DROPFILES*)GlobalLock(hGlobalMemory);
1766-
1767-
// First, populate the drop file structure.
1768-
pDropFile->pFiles =
1769-
sizeof(DROPFILES); // Offset to start of file name char array.
1770-
pDropFile->fNC = 0;
1771-
pDropFile->pt.x = 0;
1772-
pDropFile->pt.y = 0;
1773-
pDropFile->fWide = TRUE;
1774-
1775-
// Copy the filename right after the DROPFILES structure.
1776-
char16_t* dest = (char16_t*)(((char*)pDropFile) + pDropFile->pFiles);
1777-
memcpy(dest, path.get(),
1778-
(allocLen - 1) *
1779-
sizeof(char16_t)); // Copies the null character in path as well.
1780-
1781-
// Two null characters are needed at the end of the file name.
1782-
// Lookup the CF_HDROP shell clipboard format for more info.
1783-
// Add the second null character right after the first one.
1784-
dest[allocLen - 1] = L'\0';
1785-
1786-
GlobalUnlock(hGlobalMemory);
1787-
1788-
aSTG.hGlobal = hGlobalMemory;
1789-
1790-
return S_OK;
1783+
return AssignDropfile(aSTG, path);
17911784
}
17921785

17931786
HRESULT nsDataObj::DropTempFile(FORMATETC& aFE, STGMEDIUM& aSTG) {
@@ -1844,44 +1837,7 @@ HRESULT nsDataObj::DropTempFile(FORMATETC& aFE, STGMEDIUM& aSTG) {
18441837
rv = mCachedTempFile->GetPath(path);
18451838
if (NS_FAILED(rv)) return E_FAIL;
18461839

1847-
uint32_t allocLen = path.Length() + 2;
1848-
1849-
// Two null characters are needed to terminate the file name list.
1850-
HGLOBAL hGlobalMemory = nullptr;
1851-
1852-
aSTG.tymed = TYMED_HGLOBAL;
1853-
aSTG.pUnkForRelease = nullptr;
1854-
1855-
hGlobalMemory = GlobalAlloc(GMEM_MOVEABLE,
1856-
sizeof(DROPFILES) + allocLen * sizeof(char16_t));
1857-
if (!hGlobalMemory) return E_FAIL;
1858-
1859-
DROPFILES* pDropFile = (DROPFILES*)GlobalLock(hGlobalMemory);
1860-
1861-
// First, populate the drop file structure.
1862-
pDropFile->pFiles =
1863-
sizeof(DROPFILES); // Offset to start of file name char array.
1864-
pDropFile->fNC = 0;
1865-
pDropFile->pt.x = 0;
1866-
pDropFile->pt.y = 0;
1867-
pDropFile->fWide = TRUE;
1868-
1869-
// Copy the filename right after the DROPFILES structure.
1870-
char16_t* dest = (char16_t*)(((char*)pDropFile) + pDropFile->pFiles);
1871-
memcpy(dest, path.get(),
1872-
(allocLen - 1) *
1873-
sizeof(char16_t)); // Copies the null character in path as well.
1874-
1875-
// Two null characters are needed at the end of the file name.
1876-
// Lookup the CF_HDROP shell clipboard format for more info.
1877-
// Add the second null character right after the first one.
1878-
dest[allocLen - 1] = L'\0';
1879-
1880-
GlobalUnlock(hGlobalMemory);
1881-
1882-
aSTG.hGlobal = hGlobalMemory;
1883-
1884-
return S_OK;
1840+
return AssignDropfile(aSTG, path);
18851841
}
18861842

18871843
//-----------------------------------------------------

0 commit comments

Comments
 (0)