00032 {
00033     MSG 
msg, msgKey;
00034     
DWORD result = 0;
00035     
BOOL fDrag = 
TRUE;
00036     LPDROPSTRUCT lpds;
00037     
PWND pwndDragging = 
NULL;
00038     
PWND pwndTop;
00039     
PCURSOR pcurOld, pcurT;
00040     
PWND pwndT;
00041     
TL tlpwndT;
00042     
TL tlpwndTop;
00043     
TL tlpwndDragging;
00044     
TL tlPool;
00045     
PTHREADINFO pti = 
PtiCurrent();
00046 
00047     
CheckLock(pwndParent);
00048     
CheckLock(pwndFrom);
00049     
CheckLock(pcur);
00050     UserAssert(
IsWinEventNotifyDeferredOK());
00051 
00052     lpds = (LPDROPSTRUCT)UserAllocPoolWithQuota(2 * 
sizeof(DROPSTRUCT), TAG_DRAGDROP);
00053     
if (lpds == 
NULL)
00054         
return 0;
00055 
00056     
ThreadLockPool(pti, lpds, &tlPool);
00057     lpds->hwndSource = 
HW(pwndFrom);
00058     lpds->wFmt = wFmt;
00059     lpds->dwData = dwData;
00060 
00061     
if (pcur != 
NULL) {
00062         
00063 
00064 
00065         pcurOld = 
zzzSetCursor(pcur);
00066     } 
else {
00067         pcurOld = pti->
pq->
spcurCurrent;
00068     }
00069 
00070     
if (pwndFrom) {
00071         
for (pwndTop = pwndFrom; 
TestwndChild(pwndTop);
00072                 pwndTop = pwndTop->
spwndParent) ;
00073 
00074         
ThreadLockWithPti(pti, pwndTop, &tlpwndTop);
00075         
xxxUpdateWindow(pwndTop);
00076         
ThreadUnlock(&tlpwndTop);
00077     }
00078 
00079     
if (
FWINABLE()) {
00080         
xxxWindowEvent(EVENT_SYSTEM_DRAGDROPSTART, pwndFrom, OBJID_WINDOW, INDEXID_CONTAINER, 0);
00081     }
00082 
00083     
xxxSetCapture(pwndFrom);
00084     
zzzShowCursor(TRUE);
00085 
00086     
ThreadLockWithPti(pti, pwndDragging, &tlpwndDragging);
00087 
00088     
while (fDrag && pti->
pq->
spwndCapture == pwndFrom) {
00089         
while (!(
xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
00090                  
xxxPeekMessage(&msg, NULL, WM_QUEUESYNC, WM_QUEUESYNC, PM_REMOVE) ||
00091                  
xxxPeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))) {
00092             
if (!
xxxSleepThread(QS_MOUSE | QS_KEY, 0, TRUE)) {
00093                 
ThreadUnlock(&tlpwndDragging);
00094                 
ThreadUnlockAndFreePool(pti, &tlPool);
00095                 
return 0;
00096             }
00097         }
00098 
00099         
00100 
00101 
00102 
00103 
00104         
while (
xxxPeekMessage(&msgKey, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
00105            ;
00106 
00107         
if  ( (pti->
pq->
spwndCapture != pwndFrom) ||
00108               (
msg.message == WM_KEYDOWN && 
msg.wParam == VK_ESCAPE) )
00109         {
00110             
if (pcurT = 
SYSCUR(NO))
00111                 
zzzSetCursor(pcurT);
00112             
break;
00113         }
00114 
00115         RtlCopyMemory(lpds + 1, lpds, 
sizeof(DROPSTRUCT));
00116 
00117         
00118 
00119 
00120         lpds->ptDrop = 
msg.pt;
00121 
00122         pcurT = 
xxxQueryDropObject(pwndParent, lpds);
00123 
00124         
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132         
if (pcurT == (
PCURSOR)
FALSE) {
00133             pcurT = 
SYSCUR(NO);
00134             lpds->hwndSink = 
NULL;
00135         } 
else if (pcurT == (
PCURSOR)
TRUE) {
00136             pcurT = pcur;
00137         }
00138 
00139         
if (pcurT != 
NULL)
00140             
zzzSetCursor(pcurT);
00141 
00142         
00143 
00144 
00145 
00146         
if (pwndFrom) {
00147             
xxxSendMessage(pwndFrom, WM_DRAGLOOP, (pcurT != 
SYSCUR(NO)),
00148                     (LPARAM)lpds);
00149         }
00150 
00151         
00152 
00153 
00154         
if (pwndDragging != 
RevalidateHwnd(lpds->hwndSink)) {
00155             
if (pwndDragging != 
NULL) {
00156                 
xxxSendMessage(pwndDragging, WM_DRAGSELECT, FALSE,
00157                         (LPARAM)(lpds + 1));
00158             }
00159             pwndDragging = 
RevalidateHwnd(lpds->hwndSink);
00160             
ThreadUnlock(&tlpwndDragging);
00161             
ThreadLockWithPti(pti, pwndDragging, &tlpwndDragging);
00162 
00163             
if (pwndDragging != 
NULL) {
00164                 
xxxSendMessage(pwndDragging, WM_DRAGSELECT, TRUE, (LPARAM)lpds);
00165             }
00166         } 
else {
00167             
if (pwndDragging != 
NULL) {
00168                 
xxxSendMessage(pwndDragging, WM_DRAGMOVE, 0, (LPARAM)lpds);
00169             }
00170         }
00171 
00172         
switch (
msg.message) {
00173         
case WM_LBUTTONUP:
00174         
case WM_NCLBUTTONUP:
00175             fDrag = 
FALSE;
00176             
break;
00177         }
00178     }
00179 
00180     
ThreadUnlock(&tlpwndDragging);
00181 
00182     
00183 
00184 
00185     
if (fDrag)
00186         pcurT = 
SYSCUR(NO);
00187 
00188     
00189 
00190 
00191 
00192     
xxxReleaseCapture();
00193     
zzzShowCursor(FALSE);
00194 
00195     
zzzSetCursor(pcurOld);
00196 
00197     
00198 
00199 
00200     
if (pcurT != 
SYSCUR(NO)) {
00201 
00202         
00203 
00204 
00205         pwndT = 
ValidateHwnd(lpds->hwndSink);
00206         
if (pwndT != 
NULL) {
00207 
00208             
ThreadLockAlwaysWithPti(pti, pwndT, &tlpwndT);
00209 
00210             
00211 
00212 
00213             
GETPTI(pwndT)->TIF_flags |= 
TIF_ALLOWFOREGROUNDACTIVATE;
00214             TAGMSG1(DBGTAG_FOREGROUND, 
"xxxDragObject set TIF %#p", 
GETPTI(pwndT));
00215             result = (
DWORD)
xxxSendMessage(pwndT, WM_DROPOBJECT,
00216                     (WPARAM)
HW(pwndFrom), (LPARAM)lpds);
00217 
00218             
ThreadUnlock(&tlpwndT);
00219         }
00220     }
00221 
00222     
if (
FWINABLE()) {
00223         
xxxWindowEvent(EVENT_SYSTEM_DRAGDROPEND, pwndFrom, OBJID_WINDOW, INDEXID_CONTAINER, 0);
00224     }
00225 
00226     
ThreadUnlockAndFreePool(pti, &tlPool);
00227     
return result;
00228 }