/****************************************************************** * WDML_HandleIncomingData * * */ static WDML_QUEUE_STATE WDML_HandleIncomingData(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd) { UINT_PTR uiLo, uiHi; HDDEDATA hDdeDataIn, hDdeDataOut; WDML_LINK* pLink; WINE_DDEHEAD wdh; HSZ hsz; TRACE("WM_DDE_DATA message received in the Client Proc!\n"); /* wParam -- sending window handle */ /* lParam -- hDdeData & item HSZ */ UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi); hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi); hDdeDataIn = WDML_Global2DataHandle(pConv, (HGLOBAL)uiLo, &wdh); /* billx: * For hot link, data should be passed to its callback with * XTYP_ADVDATA and callback should return the proper status. */ pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, hsz, uiLo != 0, wdh.cfFormat); if (!pLink) { WDML_DecHSZ(pConv->instance, hsz); DdeFreeDataHandle(hDdeDataIn); return WDML_QS_PASS; } if (hDdeDataIn != 0 && wdh.fAckReq) { WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA); if (msg->lParam) msg->lParam = 0; } else { GlobalDeleteAtom(uiHi); } hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_ADVDATA, pLink->uFmt, pLink->hConv, pConv->hszTopic, pLink->hszItem, hDdeDataIn, 0, 0); if (hDdeDataOut != (HDDEDATA)DDE_FACK || wdh.fRelease) { if (uiLo) GlobalFree((HANDLE)uiLo); } DdeFreeDataHandle(hDdeDataIn); WDML_DecHSZ(pConv->instance, hsz); if (msg->lParam) FreeDDElParam(WM_DDE_DATA, msg->lParam); return WDML_QS_HANDLED; }
/****************************************************************** * WDML_ServerHandlePoke * * */ static WDML_QUEUE_STATE WDML_ServerHandlePoke(WDML_CONV* pConv, WDML_XACT* pXAct) { DDEPOKE* pDdePoke; HDDEDATA hDdeData; BOOL fBusy = FALSE, fAck = FALSE; pDdePoke = (DDEPOKE*)GlobalLock(pXAct->hMem); if (!pDdePoke) { return WDML_QS_ERROR; } if (!(pConv->instance->CBFflags & CBF_FAIL_POKES)) { hDdeData = DdeCreateDataHandle(pConv->instance->instanceID, pDdePoke->Value, GlobalSize(pXAct->hMem) - sizeof(DDEPOKE) + 1, 0, 0, pDdePoke->cfFormat, 0); if (hDdeData) { HDDEDATA hDdeDataOut; hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_POKE, pDdePoke->cfFormat, (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, hDdeData, 0, 0); switch ((UINT)hDdeDataOut) { case DDE_FACK: fAck = TRUE; break; case DDE_FBUSY: fBusy = TRUE; break; default: FIXME("Unsupported returned value %08lx\n", (DWORD)hDdeDataOut); /* fal through */ case DDE_FNOTPROCESSED: break; } DdeFreeDataHandle(hDdeData); } } GlobalUnlock(pXAct->hMem); if (!fAck) { GlobalFree(pXAct->hMem); } WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, fBusy, fAck, pXAct->atom, pXAct->lParam, WM_DDE_POKE); WDML_DecHSZ(pConv->instance, pXAct->hszItem); return WDML_QS_HANDLED; }
/****************************************************************** * WDML_ServerHandleRequest * * */ static WDML_QUEUE_STATE WDML_ServerHandleRequest(WDML_CONV* pConv, WDML_XACT* pXAct) { HDDEDATA hDdeData = 0; BOOL fAck = TRUE; if (!(pConv->instance->CBFflags & CBF_FAIL_REQUESTS)) { hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_REQUEST, pXAct->wFmt, (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); } switch ((ULONG_PTR)hDdeData) { case 0: TRACE("No data returned from the Callback\n"); fAck = FALSE; break; case (ULONG_PTR)CBR_BLOCK: return WDML_QS_BLOCK; default: { HGLOBAL hMem = WDML_DataHandle2Global(hDdeData, TRUE, FALSE, FALSE, FALSE); if (!PostMessageW(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, ReuseDDElParam(pXAct->lParam, WM_DDE_REQUEST, WM_DDE_DATA, (UINT_PTR)hMem, (UINT_PTR)pXAct->atom))) { pConv->instance->lastError = DMLERR_POSTMSG_FAILED; DdeFreeDataHandle(hDdeData); GlobalFree(hMem); fAck = FALSE; } } break; } WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_REQUEST); WDML_DecHSZ(pConv->instance, pXAct->hszItem); return WDML_QS_HANDLED; }
/****************************************************************** * WDML_ServerHandleRequest * * */ static WDML_QUEUE_STATE WDML_ServerHandleRequest(WDML_CONV* pConv, WDML_XACT* pXAct) { HDDEDATA hDdeData = 0; WDML_QUEUE_STATE ret = WDML_QS_HANDLED; if (!(pConv->instance->CBFflags & CBF_FAIL_REQUESTS)) { hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_REQUEST, pXAct->wFmt, (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); } switch ((DWORD)hDdeData) { case 0: WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, FALSE, pXAct->atom, pXAct->lParam, WM_DDE_REQUEST); break; case CBR_BLOCK: ret = WDML_QS_BLOCK; break; default: { HGLOBAL hMem = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE); if (!PostMessageA(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, ReuseDDElParam(pXAct->lParam, WM_DDE_REQUEST, WM_DDE_DATA, (UINT)hMem, (UINT)pXAct->atom))) { DdeFreeDataHandle(hDdeData); GlobalFree(hMem); } } break; } WDML_DecHSZ(pConv->instance, pXAct->hszItem); return ret; }
/****************************************************************** * WDML_ServerHandleUnadvise * * */ static WDML_QUEUE_STATE WDML_ServerHandleUnadvise(WDML_CONV* pConv, WDML_XACT* pXAct) { WDML_LINK* pLink; if (pXAct->hszItem == (HSZ)0 || pXAct->wFmt == 0) { ERR("Unsupported yet options (null item or clipboard format)\n"); return WDML_QS_ERROR; } pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, pXAct->hszItem, TRUE, pXAct->wFmt); if (pLink == NULL) { ERR("Couln'd find link for %08lx, dropping request\n", (DWORD)pXAct->hszItem); FreeDDElParam(WM_DDE_UNADVISE, pXAct->lParam); return WDML_QS_ERROR; } if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) { WDML_InvokeCallback(pConv->instance, XTYP_ADVSTOP, pXAct->wFmt, (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); } WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, pXAct->hszItem, pXAct->wFmt); /* send back ack */ WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, TRUE, pXAct->atom, pXAct->lParam, WM_DDE_UNADVISE); WDML_DecHSZ(pConv->instance, pXAct->hszItem); return WDML_QS_HANDLED; }
/****************************************************************** * WDML_ServerHandleAdvise * * */ static WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXAct) { UINT uType; WDML_LINK* pLink; DDEADVISE* pDdeAdvise; HDDEDATA hDdeData; BOOL fAck; pDdeAdvise = (DDEADVISE*)GlobalLock(pXAct->hMem); uType = XTYP_ADVSTART | (pDdeAdvise->fDeferUpd ? XTYPF_NODATA : 0) | (pDdeAdvise->fAckReq ? XTYPF_ACKREQ : 0); if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) { hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_ADVSTART, pDdeAdvise->cfFormat, (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); } else { hDdeData = 0; } if ((UINT)hDdeData) { fAck = TRUE; /* billx: first to see if the link is already created. */ pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, pXAct->hszItem, TRUE, pDdeAdvise->cfFormat); if (pLink != NULL) { /* we found a link, and only need to modify it in case it changes */ pLink->transactionType = uType; } else { TRACE("Adding Link with hConv=0x%lx\n", (DWORD)pConv); WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, uType, pXAct->hszItem, pDdeAdvise->cfFormat); } } else { TRACE("No data returned from the Callback\n"); fAck = FALSE; } GlobalUnlock(pXAct->hMem); if (fAck) { GlobalFree(pXAct->hMem); } pXAct->hMem = 0; WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_ADVISE); WDML_DecHSZ(pConv->instance, pXAct->hszItem); return WDML_QS_HANDLED; }