/****************************************************************** * WDML_ServerConvProc * * */ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) { WDML_INSTANCE* pInstance; WDML_CONV* pConv; WDML_XACT* pXAct = NULL; if (iMsg == WM_DESTROY) { EnterCriticalSection(&WDML_CritSect); pConv = WDML_GetConvFromWnd(hwndServer); if (pConv && !(pConv->wStatus & ST_TERMINATED)) { WDML_ServerHandleTerminate(pConv, NULL); } LeaveCriticalSection(&WDML_CritSect); } if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST) { return DefWindowProcA(hwndServer, iMsg, wParam, lParam); } EnterCriticalSection(&WDML_CritSect); pInstance = WDML_GetInstanceFromWnd(hwndServer); pConv = WDML_GetConvFromWnd(hwndServer); if (!pConv) { ERR("Got a message (%u) on a not known conversation, dropping request\n", iMsg); goto theError; } if (pConv->hwndClient != WIN_GetFullHandle( (HWND)wParam ) || pConv->hwndServer != hwndServer) { ERR("mismatch between C/S windows and converstation\n"); goto theError; } if (pConv->instance != pInstance || pConv->instance == NULL) { ERR("mismatch in instances\n"); goto theError; } switch (iMsg) { case WM_DDE_INITIATE: FIXME("WM_DDE_INITIATE message received!\n"); break; case WM_DDE_REQUEST: pXAct = WDML_ServerQueueRequest(pConv, lParam); break; case WM_DDE_ADVISE: pXAct = WDML_ServerQueueAdvise(pConv, lParam); break; case WM_DDE_UNADVISE: pXAct = WDML_ServerQueueUnadvise(pConv, lParam); break; case WM_DDE_EXECUTE: pXAct = WDML_ServerQueueExecute(pConv, lParam); break; case WM_DDE_POKE: pXAct = WDML_ServerQueuePoke(pConv, lParam); break; case WM_DDE_TERMINATE: pXAct = WDML_ServerQueueTerminate(pConv, lParam); break; case WM_DDE_ACK: WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); break; default: FIXME("Unsupported message %d\n", iMsg); } if (pXAct) { pXAct->lParam = lParam; if (WDML_ServerHandle(pConv, pXAct) == WDML_QS_BLOCK) { WDML_QueueTransaction(pConv, pXAct); } else { WDML_FreeTransaction(pInstance, pXAct, TRUE); } } theError: LeaveCriticalSection(&WDML_CritSect); return 0; }
/****************************************************************** * WDML_ServerConvProc * * */ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) { WDML_INSTANCE* pInstance; WDML_CONV* pConv; WDML_XACT* pXAct = NULL; TRACE("%p %04x %08lx %08lx\n", hwndServer, iMsg, wParam, lParam); if (iMsg == WM_DESTROY) { pConv = WDML_GetConvFromWnd(hwndServer); if (pConv && !(pConv->wStatus & ST_TERMINATED)) { WDML_ServerHandleTerminate(pConv, NULL); } } if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST) { return IsWindowUnicode(hwndServer) ? DefWindowProcW(hwndServer, iMsg, wParam, lParam) : DefWindowProcA(hwndServer, iMsg, wParam, lParam); } pInstance = WDML_GetInstanceFromWnd(hwndServer); pConv = WDML_GetConvFromWnd(hwndServer); if (!pConv) { ERR("Got a message (%x) on a not known conversation, dropping request\n", iMsg); return 0; } if (pConv->hwndClient != WIN_GetFullHandle( (HWND)wParam ) || pConv->hwndServer != hwndServer) { ERR("mismatch between C/S windows and conversation\n"); return 0; } if (pConv->instance != pInstance || pConv->instance == NULL) { ERR("mismatch in instances\n"); return 0; } switch (iMsg) { case WM_DDE_INITIATE: FIXME("WM_DDE_INITIATE message received!\n"); break; case WM_DDE_REQUEST: pXAct = WDML_ServerQueueRequest(pConv, lParam); break; case WM_DDE_ADVISE: pXAct = WDML_ServerQueueAdvise(pConv, lParam); break; case WM_DDE_UNADVISE: pXAct = WDML_ServerQueueUnadvise(pConv, lParam); break; case WM_DDE_EXECUTE: pXAct = WDML_ServerQueueExecute(pConv, lParam); break; case WM_DDE_POKE: pXAct = WDML_ServerQueuePoke(pConv, lParam); break; case WM_DDE_TERMINATE: pXAct = WDML_ServerQueueTerminate(pConv, lParam); break; case WM_DDE_ACK: WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); break; default: FIXME("Unsupported message %x\n", iMsg); break; } if (pXAct) { pXAct->lParam = lParam; if ((pConv->wStatus & ST_BLOCKED) || WDML_ServerHandle(pConv, pXAct) == WDML_QS_BLOCK) { TRACE("Transactions are blocked, add to the queue and exit\n"); WDML_QueueTransaction(pConv, pXAct); } else { WDML_FreeTransaction(pInstance, pXAct, TRUE); } } else pConv->instance->lastError = DMLERR_MEMORY_ERROR; return 0; }
/****************************************************************** * WDML_ServerNameProc * * */ static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) { HWND hwndClient; HSZ hszApp, hszTop; HDDEDATA hDdeData = 0; WDML_INSTANCE* pInstance; UINT uiLo, uiHi; switch (iMsg) { case WM_DDE_INITIATE: /* wParam -- sending window handle LOWORD(lParam) -- application atom HIWORD(lParam) -- topic atom */ TRACE("WM_DDE_INITIATE message received!\n"); hwndClient = (HWND)wParam; pInstance = WDML_GetInstanceFromWnd(hwndServer); TRACE("idInst=%ld, threadID=0x%lx\n", pInstance->instanceID, GetCurrentThreadId()); if (!pInstance) return 0; /* don't free DDEParams, since this is a broadcast */ UnpackDDElParam(WM_DDE_INITIATE, lParam, &uiLo, &uiHi); hszApp = WDML_MakeHszFromAtom(pInstance, uiLo); hszTop = WDML_MakeHszFromAtom(pInstance, uiHi); if (!(pInstance->CBFflags & CBF_FAIL_CONNECTIONS)) { BOOL self = FALSE; CONVCONTEXT cc; CONVCONTEXT* pcc = NULL; WDML_CONV* pConv; char buf[256]; if (GetWindowThreadProcessId(hwndClient, NULL) == GetWindowThreadProcessId(hwndServer, NULL) && WDML_GetInstanceFromWnd(hwndClient) == WDML_GetInstanceFromWnd(hwndServer)) { self = TRUE; } /* FIXME: so far, we don't grab distant convcontext, so only check if remote is * handled under DDEML, and if so build a default context */ if ((GetClassNameA(hwndClient, buf, sizeof(buf)) && strcmp(buf, WDML_szClientConvClassA) == 0) || (GetClassNameW(hwndClient, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) && lstrcmpW((LPWSTR)buf, WDML_szClientConvClassW) == 0)) { pcc = &cc; memset(pcc, 0, sizeof(*pcc)); pcc->cb = sizeof(*pcc); pcc->iCodePage = IsWindowUnicode(hwndClient) ? CP_WINUNICODE : CP_WINANSI; } if ((pInstance->CBFflags & CBF_FAIL_SELFCONNECTIONS) && self) { TRACE("Don't do self connection as requested\n"); } else if (hszApp && hszTop) { WDML_SERVER* pServer = (WDML_SERVER*)GetWindowLongA(hwndServer, GWL_WDML_SERVER); /* check filters for name service */ if (!pServer->filterOn || DdeCmpStringHandles(pServer->hszService, hszApp) == 0) { /* pass on to the callback */ hDdeData = WDML_InvokeCallback(pInstance, XTYP_CONNECT, 0, 0, hszTop, hszApp, 0, (DWORD)pcc, self); if ((UINT)hDdeData) { pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, hszApp, hszTop); if (pConv && pcc) pConv->wStatus |= ST_ISLOCAL; } } } else if (pInstance->servers) { /* pass on to the callback */ hDdeData = WDML_InvokeCallback(pInstance, XTYP_WILDCONNECT, 0, 0, hszTop, hszApp, 0, (DWORD)pcc, self); if (hDdeData == (HDDEDATA)CBR_BLOCK) { /* MS doc is not consistent here */ FIXME("CBR_BLOCK returned for WILDCONNECT\n"); } else if ((UINT)hDdeData != 0) { HSZPAIR* hszp; hszp = (HSZPAIR*)DdeAccessData(hDdeData, NULL); if (hszp) { int i; for (i = 0; hszp[i].hszSvc && hszp[i].hszTopic; i++) { pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, hszp[i].hszSvc, hszp[i].hszTopic); if (pConv && pcc) pConv->wStatus |= ST_ISLOCAL; } DdeUnaccessData(hDdeData); } if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); } } } return 0; case WM_DDE_REQUEST: FIXME("WM_DDE_REQUEST message received!\n"); return 0; case WM_DDE_ADVISE: FIXME("WM_DDE_ADVISE message received!\n"); return 0; case WM_DDE_UNADVISE: FIXME("WM_DDE_UNADVISE message received!\n"); return 0; case WM_DDE_EXECUTE: FIXME("WM_DDE_EXECUTE message received!\n"); return 0; case WM_DDE_POKE: FIXME("WM_DDE_POKE message received!\n"); return 0; case WM_DDE_TERMINATE: FIXME("WM_DDE_TERMINATE message received!\n"); return 0; } return DefWindowProcA(hwndServer, iMsg, wParam, lParam); }
/****************************************************************** * WDML_ClientProc * * Window Proc created on client side for each conversation */ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { UINT uiLo, uiHi; WDML_CONV* pConv = NULL; HSZ hszSrv, hszTpc; TRACE("%p %04x %08lx %08lx\n", hwnd, iMsg, wParam , lParam); if (iMsg == WM_DDE_ACK && /* in the initial WM_INITIATE sendmessage */ ((pConv = WDML_GetConvFromWnd(hwnd)) == NULL || pConv->wStatus == XST_INIT1)) { /* In response to WM_DDE_INITIATE, save server window */ char buf[256]; WDML_INSTANCE* pInstance; /* note: sent messages do not need packing */ uiLo = LOWORD(lParam); uiHi = HIWORD(lParam); /* FIXME: convlist should be handled here */ if (pConv) { /* we already have started the conv with a server, drop other replies */ GlobalDeleteAtom(uiLo); GlobalDeleteAtom(uiHi); PostMessageW((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, 0); return 0; } pInstance = WDML_GetInstanceFromWnd(hwnd); hszSrv = WDML_MakeHszFromAtom(pInstance, uiLo); hszTpc = WDML_MakeHszFromAtom(pInstance, uiHi); pConv = WDML_AddConv(pInstance, WDML_CLIENT_SIDE, hszSrv, hszTpc, hwnd, (HWND)wParam); SetWindowLongPtrW(hwnd, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv); pConv->wStatus |= ST_CONNECTED; pConv->wConvst = XST_INIT1; /* check if server is handled by DDEML */ if ((GetClassNameA((HWND)wParam, buf, sizeof(buf)) && lstrcmpiA(buf, WDML_szServerConvClassA) == 0) || (GetClassNameW((HWND)wParam, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) && lstrcmpiW((LPWSTR)buf, WDML_szServerConvClassW) == 0)) { pConv->wStatus |= ST_ISLOCAL; } GlobalDeleteAtom(uiLo); GlobalDeleteAtom(uiHi); /* accept conversation */ return 1; } if (iMsg >= WM_DDE_FIRST && iMsg <= WM_DDE_LAST) { pConv = WDML_GetConvFromWnd(hwnd); if (pConv) { MSG msg; HDDEDATA hdd; msg.hwnd = hwnd; msg.message = iMsg; msg.wParam = wParam; msg.lParam = lParam; WDML_HandleReply(pConv, &msg, &hdd, NULL); } return 0; } return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, iMsg, wParam, lParam) : DefWindowProcA(hwnd, iMsg, wParam, lParam); }