📄 client.c
字号:
pXAct->hDdeData = (HDDEDATA)1; } return WDML_QS_HANDLED;}/****************************************************************** * WDML_ClientQueueRequest * * */static WDML_XACT* WDML_ClientQueueRequest(WDML_CONV* pConv, UINT wFmt, HSZ hszItem){ WDML_XACT* pXAct; ATOM atom; TRACE("XTYP_REQUEST transaction\n"); atom = WDML_MakeAtomFromHsz(hszItem); if (!atom) return NULL; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_REQUEST, wFmt, hszItem); if (!pXAct) { GlobalDeleteAtom(atom); return NULL; } pXAct->lParam = PackDDElParam(WM_DDE_REQUEST, wFmt, atom); return pXAct;}/****************************************************************** * WDML_HandleRequestReply * * */static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct){ DDEACK ddeAck; WINE_DDEHEAD wdh; UINT_PTR uiLo, uiHi; HSZ hsz; if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer) return WDML_QS_PASS; switch (msg->message) { case WM_DDE_ACK: UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi); FreeDDElParam(WM_DDE_ACK, msg->lParam); GlobalDeleteAtom(uiHi); WDML_ExtractAck(uiLo, &ddeAck); pXAct->hDdeData = 0; if (ddeAck.fAck) ERR("Positive answer should appear in NACK for a request, assuming negative\n"); TRACE("Negative answer...\n"); break; case WM_DDE_DATA: UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi); TRACE("Got the result (%08x)\n", uiLo); hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi); if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0) return WDML_QS_PASS; pXAct->hDdeData = WDML_Global2DataHandle((HGLOBAL)uiLo, &wdh); if (wdh.fRelease) { GlobalFree((HGLOBAL)uiLo); } if (wdh.fAckReq) { WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA); } else { GlobalDeleteAtom(uiHi); FreeDDElParam(WM_DDE_ACK, msg->lParam); } break; default: FreeDDElParam(msg->message, msg->lParam); return WDML_QS_PASS; } return WDML_QS_HANDLED;}/****************************************************************** * WDML_BuildExecuteCommand * * Creates a DDE block suitable for sending in WM_DDE_COMMAND * It also takes care of string conversion between the two window procedures */static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV* pConv, LPCVOID pData, DWORD cbData){ HGLOBAL hMem; BOOL clientUnicode, serverUnicode; DWORD memSize; clientUnicode = IsWindowUnicode(pConv->hwndClient); serverUnicode = IsWindowUnicode(pConv->hwndServer); if (clientUnicode == serverUnicode) { memSize = cbData; } else { if (clientUnicode) { memSize = WideCharToMultiByte( CP_ACP, 0, pData, cbData, NULL, 0, NULL, NULL); } else { memSize = MultiByteToWideChar( CP_ACP, 0, pData, cbData, NULL, 0); } } hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, memSize); if (hMem) { LPBYTE pDst; pDst = GlobalLock(hMem); if (pDst) { if (clientUnicode == serverUnicode) { memcpy(pDst, pData, cbData); } else { if (clientUnicode) { WideCharToMultiByte( CP_ACP, 0, pData, cbData, pDst, memSize, NULL, NULL); } else { MultiByteToWideChar( CP_ACP, 0, pData, cbData, (LPWSTR)pDst, memSize); } } GlobalUnlock(hMem); } else { GlobalFree(hMem); hMem = 0; } } return hMem;}/****************************************************************** * WDML_ClientQueueExecute * * */static WDML_XACT* WDML_ClientQueueExecute(WDML_CONV* pConv, LPCVOID pData, DWORD cbData){ WDML_XACT* pXAct; TRACE("XTYP_EXECUTE transaction\n"); pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_EXECUTE, 0, 0); if (!pXAct) return NULL; if (cbData == (DWORD)-1) { HDDEDATA hDdeData = (HDDEDATA)pData; pData = DdeAccessData(hDdeData, &cbData); if (pData) { pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData); DdeUnaccessData(hDdeData); } } else { pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData); } pXAct->lParam = (LPARAM)pXAct->hMem; return pXAct;}/****************************************************************** * WDML_HandleExecuteReply * * */static WDML_QUEUE_STATE WDML_HandleExecuteReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct){ DDEACK ddeAck; UINT_PTR uiLo, uiHi; if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer) { return WDML_QS_PASS; } UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi); FreeDDElParam(WM_DDE_ACK, msg->lParam); if ((HANDLE)uiHi != pXAct->hMem) { return WDML_QS_PASS; } WDML_ExtractAck(uiLo, &ddeAck); pXAct->hDdeData = (HDDEDATA)(UINT_PTR)ddeAck.fAck; return WDML_QS_HANDLED;}/****************************************************************** * WDML_ClientQueuePoke * * */static WDML_XACT* WDML_ClientQueuePoke(WDML_CONV* pConv, LPCVOID pData, DWORD cbData, UINT wFmt, HSZ hszItem){ WDML_XACT* pXAct; ATOM atom; TRACE("XTYP_POKE transaction\n"); atom = WDML_MakeAtomFromHsz(hszItem); if (!atom) return NULL; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_POKE, wFmt, hszItem); if (!pXAct) { GlobalDeleteAtom(atom); return NULL; } if (cbData == (DWORD)-1) { pXAct->hMem = (HDDEDATA)pData; } else { DDEPOKE* ddePoke; pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(DDEPOKE) + cbData); ddePoke = GlobalLock(pXAct->hMem); if (ddePoke) { memcpy(ddePoke->Value, pData, cbData); ddePoke->fRelease = FALSE; /* FIXME: app owned ? */ ddePoke->cfFormat = wFmt; GlobalUnlock(pXAct->hMem); } } pXAct->lParam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)pXAct->hMem, atom); return pXAct;}/****************************************************************** * WDML_HandlePokeReply * * */static WDML_QUEUE_STATE WDML_HandlePokeReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct){ DDEACK ddeAck; UINT_PTR uiLo, uiHi; HSZ hsz; if (msg->message != WM_DDE_ACK && WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer) { return WDML_QS_PASS; } UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi); hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi); if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0) { return WDML_QS_PASS; } FreeDDElParam(WM_DDE_ACK, msg->lParam); GlobalDeleteAtom(uiHi); WDML_ExtractAck(uiLo, &ddeAck); GlobalFree(pXAct->hMem); pXAct->hDdeData = (HDDEDATA)TRUE; return TRUE;}/****************************************************************** * WDML_ClientQueueTerminate * * Creates and queue an WM_DDE_TERMINATE transaction */static WDML_XACT* WDML_ClientQueueTerminate(WDML_CONV* pConv){ WDML_XACT* pXAct; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_TERMINATE, 0, 0); if (!pXAct) return NULL; pXAct->lParam = 0; pConv->wStatus &= ~ST_CONNECTED; return pXAct;}/****************************************************************** * WDML_HandleTerminateReply * * handles the reply to a terminate request */static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct){ if (msg->message != WM_DDE_TERMINATE) { /* FIXME: should delete data passed here */ return WDML_QS_SWALLOWED; } if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer) { FIXME("hmmm shouldn't happen\n"); return WDML_QS_PASS; } if (!pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS) { WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv, 0, 0, 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0); } WDML_RemoveConv(pConv, WDML_CLIENT_SIDE); return WDML_QS_HANDLED;}/****************************************************************** * WDML_HandleReplyData * * */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((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 ? TRUE : FALSE, 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_HandleIncomingTerminate * * */static WDML_QUEUE_STATE WDML_HandleIncomingTerminate(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd){ if (pConv->hwndServer != WIN_GetFullHandle((HWND)msg->wParam)) return WDML_QS_PASS; pConv->wStatus |= ST_TERMINATED; if (!pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS) { WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv, 0, 0, 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0); } if (pConv->wStatus & ST_CONNECTED) { /* don't care about result code (if server exists or not) */ PostMessageA(pConv->hwndServer, WM_DDE_TERMINATE, (WPARAM)pConv->hwndClient, 0L); pConv->wStatus &= ~ST_CONNECTED; } /* have to keep connection around to allow reconnection */ return WDML_QS_HANDLED;}/****************************************************************** * WDML_HandleReply * * handles any incoming reply, and try to match to an already sent request */static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd){ WDML_XACT* pXAct = pConv->transactions; WDML_QUEUE_STATE qs; if (pConv->transactions) { /* first check message against a pending transaction, if any */ switch (pXAct->ddeMsg) { case WM_DDE_ADVISE: qs = WDML_HandleAdviseReply(pConv, msg, pXAct); break; case WM_DDE_UNADVISE: qs = WDML_HandleUnadviseReply(pConv, msg, pXAct); break; case WM_DDE_EXECUTE: qs = WDML_HandleExecuteReply(pConv, msg, pXAct); break; case WM_DDE_REQUEST: qs = WDML_HandleRequestReply(pConv, msg, pXAct); break; case WM_DDE_POKE: qs = WDML_HandlePokeReply(pConv, msg, pXAct); break; case WM_DDE_TERMINATE: qs = WDML_HandleTerminateReply(pConv, msg, pXAct); break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -