Lars Erdmann
2010-12-30 19:28:18 UTC
Found the below in "gui/kernel/qmime_pm.cpp".
Did you test this with a target that asks for source rendering ?
My understanding is that the source as well as the target call
DrgFreeDragtransfer (that's why it needs to be called twice).
If you call DrgFreeDragtransfer twice in the source this might
lead to an access problem in the target.
/*! \internal
According to my tests, DrgFreeDragtransfer() appears to be bogus: when the
drag source attempts to free the DRAGTRANSFER structure passed to it in
DM_RENDERPREPARE/DM_RENDER by another process, the shared memory object is not
actually released until DrgFreeDragtransfer() is called for the second time.
This method tries to fix this problem.
\note The problem (and the solution) was not tested on platforms other than
eCS!
*/
void qt_DrgFreeDragtransfer(DRAGTRANSFER *xfer)
{
Q_ASSERT(xfer);
if (xfer) {
BOOL ok = DrgFreeDragtransfer(xfer);
Q_ASSERT(ok);
if (ok) {
ULONG size = ~0, flags = 0;
APIRET rc = DosQueryMem(xfer, &size, &flags);
Q_ASSERT(rc == 0);
if (rc == 0 && !(flags & PAG_FREE)) {
PID pid;
TID tid;
ok = WinQueryWindowProcess(xfer->hwndClient, &pid, &tid);
Q_ASSERT(ok);
if (ok) {
PPIB ppib = 0;
DosGetInfoBlocks(0, &ppib);
if (ppib->pib_ulpid != pid) {
DEBUG(() << "qt_DrgFreeDragtransfer: Will free xfer"
<< xfer << "TWICE (other process)!");
DrgFreeDragtransfer(xfer);
}
}
}
}
}
}
Did you test this with a target that asks for source rendering ?
My understanding is that the source as well as the target call
DrgFreeDragtransfer (that's why it needs to be called twice).
If you call DrgFreeDragtransfer twice in the source this might
lead to an access problem in the target.
/*! \internal
According to my tests, DrgFreeDragtransfer() appears to be bogus: when the
drag source attempts to free the DRAGTRANSFER structure passed to it in
DM_RENDERPREPARE/DM_RENDER by another process, the shared memory object is not
actually released until DrgFreeDragtransfer() is called for the second time.
This method tries to fix this problem.
\note The problem (and the solution) was not tested on platforms other than
eCS!
*/
void qt_DrgFreeDragtransfer(DRAGTRANSFER *xfer)
{
Q_ASSERT(xfer);
if (xfer) {
BOOL ok = DrgFreeDragtransfer(xfer);
Q_ASSERT(ok);
if (ok) {
ULONG size = ~0, flags = 0;
APIRET rc = DosQueryMem(xfer, &size, &flags);
Q_ASSERT(rc == 0);
if (rc == 0 && !(flags & PAG_FREE)) {
PID pid;
TID tid;
ok = WinQueryWindowProcess(xfer->hwndClient, &pid, &tid);
Q_ASSERT(ok);
if (ok) {
PPIB ppib = 0;
DosGetInfoBlocks(0, &ppib);
if (ppib->pib_ulpid != pid) {
DEBUG(() << "qt_DrgFreeDragtransfer: Will free xfer"
<< xfer << "TWICE (other process)!");
DrgFreeDragtransfer(xfer);
}
}
}
}
}
}