static LRESULT DdeMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { UINT_PTR hSzItem; switch(msg) { case WM_DDE_ACK: ddeAcked = 1; hwndDde = (HWND)wParam; break; case WM_DDE_DATA: UnpackDDElParam(msg, lParam, (PUINT_PTR)&hGlobalDdeData, (PUINT_PTR)&hSzItem); ddeData = 1; if (hGlobalDdeData) { DDEDATA* data = (DDEDATA*)GlobalLock(hGlobalDdeData); if (data->fAckReq) { DDEACK ack = {0}; PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)hwndDlg, PackDDElParam(WM_DDE_ACK, *(PUINT)&ack, hSzItem)); } else GlobalDeleteAtom((ATOM)hSzItem); GlobalUnlock(hGlobalDdeData); } else GlobalDeleteAtom((ATOM)hSzItem); break; } return 0; }
/****************************************************************** * WDML_ClientQueueAdvise * * Creates and queue an WM_DDE_ADVISE transaction */ static WDML_XACT* WDML_ClientQueueAdvise(WDML_CONV* pConv, UINT wType, UINT wFmt, HSZ hszItem) { DDEADVISE* pDdeAdvise; WDML_XACT* pXAct; ATOM atom; TRACE("XTYP_ADVSTART (with%s data) transaction\n", (wType & XTYPF_NODATA) ? "out" : ""); atom = WDML_MakeAtomFromHsz(hszItem); if (!atom) return NULL; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, wFmt, hszItem); if (!pXAct) { GlobalDeleteAtom(atom); return NULL; } pXAct->wType = wType & ~0x0F; pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(DDEADVISE)); /* FIXME: hMem is unfreed for now... should be deleted in server */ /* pack DdeAdvise */ pDdeAdvise = GlobalLock(pXAct->hMem); pDdeAdvise->fAckReq = (wType & XTYPF_ACKREQ) != 0; pDdeAdvise->fDeferUpd = (wType & XTYPF_NODATA) != 0; pDdeAdvise->cfFormat = wFmt; GlobalUnlock(pXAct->hMem); pXAct->lParam = PackDDElParam(WM_DDE_ADVISE, (UINT_PTR)pXAct->hMem, atom); return pXAct; }
/****************************************************************** * WDML_ClientQueuePoke * * */ static WDML_XACT* WDML_ClientQueuePoke(WDML_CONV* pConv, LPVOID pData, DWORD cbData, UINT wFmt, HSZ hszItem) { DDE_DATAHANDLE_HEAD *dh; WDML_XACT *pXAct; DDEPOKE *ddePoke; HGLOBAL hglobal; 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) { hglobal = pData; dh = GlobalLock(hglobal); cbData = GlobalSize(hglobal) - sizeof(DDE_DATAHANDLE_HEAD); pData = dh + 1; GlobalUnlock(hglobal); } pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, FIELD_OFFSET(DDEPOKE, Value[cbData])); ddePoke = GlobalLock(pXAct->hMem); if (!ddePoke) { pConv->instance->lastError = DMLERR_MEMORY_ERROR; return NULL; } ddePoke->unused = 0; ddePoke->fRelease = TRUE; ddePoke->cfFormat = wFmt; memcpy(ddePoke->Value, pData, cbData); GlobalUnlock(pXAct->hMem); pXAct->lParam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)pXAct->hMem, atom); return pXAct; }
/****************************************************************** * 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_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_ClientQueueUnadvise * * queues an unadvise transaction */ static WDML_XACT* WDML_ClientQueueUnadvise(WDML_CONV* pConv, UINT wFmt, HSZ hszItem) { WDML_XACT* pXAct; ATOM atom; TRACE("XTYP_ADVSTOP transaction\n"); atom = WDML_MakeAtomFromHsz(hszItem); if (!atom) return NULL; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_UNADVISE, wFmt, hszItem); if (!pXAct) { GlobalDeleteAtom(atom); return NULL; } /* end advise loop: post WM_DDE_UNADVISE to server to terminate link * on the specified item. */ pXAct->lParam = PackDDElParam(WM_DDE_UNADVISE, wFmt, atom); return pXAct; }
static bool DoDdePoke(HWND hwndServerDDE, HWND hwndClientDDE, LPCSTR szItem, LPCSTR szValue) { HANDLE hPokeData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DDEPOKE) + strlen(szValue) + 2); if (!hPokeData) return false; DDEPOKE* lpPokeData = (DDEPOKE*)GlobalLock(hPokeData); if (lpPokeData) { lpPokeData->fRelease = true; lpPokeData->cfFormat = CF_TEXT; strcpy(LPSTR(lpPokeData->Value), szValue); // Each line of CF_TEXT data is terminated by CR/LF. strcat(LPSTR(lpPokeData->Value), "\r\n"); GlobalUnlock(hPokeData); ATOM atomItem = GlobalAddAtom(szItem); if (atomItem) { if (PostMessage(hwndServerDDE, WM_DDE_POKE, (WPARAM) hwndClientDDE, PackDDElParam(WM_DDE_POKE, UINT(hPokeData), atomItem))) return true; GlobalDeleteAtom(atomItem); } } GlobalFree(hPokeData); return false; }
/****************************************************************************** * DdePostAdvise [USER32.@] Send transaction to DDE callback function. * * PARAMS * idInst [I] Instance identifier * hszTopic [I] Handle to topic name string * hszItem [I] Handle to item name string * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem) { WDML_INSTANCE* pInstance = NULL; WDML_LINK* pLink = NULL; HDDEDATA hDdeData = 0; HGLOBAL hItemData = 0; WDML_CONV* pConv = NULL; ATOM atom = 0; UINT count; TRACE("(%ld,0x%x,0x%x)\n", idInst, hszTopic, hszItem); EnterCriticalSection(&WDML_CritSect); pInstance = WDML_GetInstance(idInst); if (pInstance == NULL || pInstance->links == NULL) { goto theError; } atom = WDML_MakeAtomFromHsz(hszItem); if (!atom) goto theError; /* first compute the number of links which will trigger a message */ count = 0; for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) { if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) { count++; } } if (count >= CADV_LATEACK) { FIXME("too high value for count\n"); count &= 0xFFFF; } for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) { if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) { hDdeData = WDML_InvokeCallback(pInstance, XTYP_ADVREQ, pLink->uFmt, pLink->hConv, hszTopic, hszItem, 0, count--, 0); if (hDdeData == (HDDEDATA)CBR_BLOCK) { /* MS doc is not consistent here */ FIXME("CBR_BLOCK returned for ADVREQ\n"); continue; } if (hDdeData) { if (pLink->transactionType & XTYPF_NODATA) { TRACE("no data\n"); hItemData = 0; } else { TRACE("with data\n"); hItemData = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE); } pConv = WDML_GetConv(pLink->hConv, TRUE); if (pConv == NULL) { if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); goto theError; } if (!PostMessageA(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, PackDDElParam(WM_DDE_DATA, (UINT)hItemData, atom))) { ERR("post message failed\n"); pConv->wStatus &= ~ST_CONNECTED; if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); GlobalFree(hItemData); goto theError; } if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); } } } LeaveCriticalSection(&WDML_CritSect); return TRUE; theError: LeaveCriticalSection(&WDML_CritSect); if (atom) GlobalDeleteAtom(atom); return FALSE; }
/* The callback routine for the main window. PA: The WM_CREATE message registers the main window as a clipboard viewer. The WM_DESTROY message unregisters the main window. */ static LRESULT CALLBACK MainWindowProcedure (HWND hWin, UINT uMess, WPARAM wPara, LPARAM lPara) { switch (uMess) { case WM_NCPAINT: break; /* WM_ENTERIDLE message is used to let Clean evaluate the initialisation action of a modal dialog by sending the CcWmIDLEDIALOG message. */ case WM_ENTERIDLE: { HWND hwndModalDialog; hwndModalDialog = (HWND)lPara; if (wPara == MSGF_DIALOGBOX && hwndModalDialog != ghwndLastModalDialog) { SendMessage1ToClean (CcWmIDLEDIALOG,(int)hwndModalDialog); ghwndLastModalDialog = hwndModalDialog; } else { SendMessage0ToClean (CcWmIDLETIMER); } return 0; } break; case WM_TIMER: { SendMessage2ToClean (CcWmTIMER, wPara, GetMessageTime ()); } break; case WM_ENABLE: { HWND hwin; char title[64]; hwin = GetWindow (ghMainWindow, GW_HWNDFIRST); while (hwin != NULL) { GetWindowText (hwin, title, 63); if (GetWindow (hwin, GW_OWNER) == ghMainWindow) { RECT r; GetWindowRect (hwin, &r); if (r.top != -1 || r.left != -1 || r.right != 0 || r.bottom != 0) { EnableWindow (hwin, (BOOL) wPara); } } hwin = GetWindow (hwin, GW_HWNDNEXT); } } break; /* PM_SOCKET_EVENT and PM_DNS_EVENT are intercepted by MainWindowProcedure. If ghTCPWindow != NULL, then these messages are passed on to ghTCPWindow. */ case PM_SOCKET_EVENT: case PM_DNS_EVENT: { if (ghTCPWindow != NULL) SendMessage (ghTCPWindow, uMess, wPara, lPara); return 0; } break; case WM_DDE_INITIATE: { static char apptext[256], topictext[256]; ATOM aApp, aTopic; /* RWS ... */ BOOL handleTopic; /* ... RWS */ GlobalGetAtomName (HIWORD (lPara), topictext, 256); if (lstrcmp (topictext, "CLEANOPEN") == 0) /* RWS: compare application name */ { GlobalGetAtomName (LOWORD (lPara), apptext, 256); handleTopic = CompareStringA (LOCALE_USER_DEFAULT, NORM_IGNORECASE, apptext, lstrlen (apptext), gAppName, lstrlen (gAppName)) == 2; /* 2 means they are equal */ } else handleTopic = FALSE; if (handleTopic) { /* ... RWS */ aApp = GlobalAddAtom (apptext); aTopic = GlobalAddAtom (topictext); SendMessage ((HWND) wPara, WM_DDE_ACK, (WPARAM) hWin, MAKELONG (aApp, aTopic)); GlobalDeleteAtom (aApp); GlobalDeleteAtom (aTopic); } else { return DefWindowProc (hWin, uMess, wPara, lPara); } } break; case WM_DDE_EXECUTE: { char *commandstring; char *pcommand; int len; union { DDEACK ddeack; WORD w; } da; pcommand = GlobalLock ((HANDLE) lPara); len = lstrlen (pcommand) + 1; commandstring = rmalloc (len); /* this pointer is passed to and freed in the Clean code. */ lstrcpyn (commandstring, pcommand, len); GlobalUnlock ((HANDLE) lPara); SendMessage1ToClean (CcWmDDEEXECUTE, commandstring); da.ddeack.bAppReturnCode = 0; da.ddeack.fBusy = 0; da.ddeack.fAck = 1; PostMessage ((HWND) wPara, WM_DDE_ACK, (WPARAM) hWin, PackDDElParam (WM_DDE_ACK, (UINT) da.w, lPara)); return 0; } break; case WM_DDE_TERMINATE: { PostMessage ((HWND) wPara, WM_DDE_TERMINATE, (WPARAM) hWin, 0); } return 0; default: return DefWindowProc (hWin, uMess, wPara, lPara); break; } return 0; } /* MainWindowProcedure */
static long ProcessShellDDE(HWND w, UINT msg, WPARAM wp, LPARAM lp) { char *command; ATOM app,top,a; WPARAM hi,lo; unsigned short ack; char buffer[256]; switch (msg) { case WM_DDE_INITIATE: /* * Initiate DDE command */ a = (ATOM)LOWORD(lp); if (a == NULL) return 0; ::GlobalGetAtomName(a,buffer,sizeof(buffer)); if (::strcmp(_GDDEAppName,buffer)) return 0; a = (ATOM)HIWORD(lp); if (a != NULL) { ::GlobalGetAtomName(a,buffer,sizeof(buffer)); if (::strcmp(_GDDETopicName,buffer)) return 0; } /* * Respond with ACK of only conversation I do */ app = ::GlobalAddAtom(_GDDEAppName); top = ::GlobalAddAtom(_GDDETopicName); ::SendMessage((HWND)wp,WM_DDE_ACK,(WPARAM)w,MAKELPARAM(app,top)); ::GlobalDeleteAtom(app); ::GlobalDeleteAtom(top); return 0; case WM_DDE_TERMINATE: /* * Terminate DDE connection */ ::PostMessage((HWND)wp,WM_DDE_TERMINATE,(WPARAM)w,0); return 0; case WM_DDE_EXECUTE: /* * Extract command string */ command = (char *)GlobalLock((HANDLE)lp); ExecuteDDE(command); ::GlobalUnlock((HANDLE)lp); ack = 1; lo = *(WPARAM *)&ack; lp = PackDDElParam(WM_DDE_ACK,lo,lp); PostMessage((HWND)wp,WM_DDE_ACK,(LPARAM)w,lp); return 0; case WM_DDE_UNADVISE: case WM_DDE_ADVISE: case WM_DDE_DATA: case WM_DDE_POKE: case WM_DDE_REQUEST: /* * Don't do 'em, don't ack 'em! */ UnpackDDElParam(msg,lp,&lo,&hi); if ((msg == WM_DDE_ADVISE) || (msg == WM_DDE_DATA) || (msg == WM_DDE_POKE)) { ::GlobalFree((HANDLE)lo); } ack = 0; lo = *(WPARAM *)(&ack); ReuseDDElParam(lp,msg,WM_DDE_ACK,lo,hi); PostMessage((HWND)wp,WM_DDE_ACK,(WPARAM)w,lp); return 0; default: return -1; } }