1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1997 Alexandre Julliard
7 * Copyright 1997 Len White
8 * Copyright 1999 Keith Matthews
10 * Copyright 2001 Eric Pouech
21 #include "debugtools.h"
22 #include "dde/dde_private.h"
24 DEFAULT_DEBUG_CHANNEL(ddeml);
26 static const char szServerNameClassA[] = "DdeServerNameAnsi";
27 static const char szServerConvClassA[] = "DdeServerConvAnsi";
29 static LRESULT CALLBACK WDML_ServerNameProc(HWND, UINT, WPARAM, LPARAM);
30 static LRESULT CALLBACK WDML_ServerConvProc(HWND, UINT, WPARAM, LPARAM);
32 /******************************************************************************
33 * DdePostAdvise [USER32.@] Send transaction to DDE callback function.
39 BOOL WINAPI DdePostAdvise(
40 DWORD idInst, /* [in] Instance identifier */
41 HSZ hszTopic, /* [in] Handle to topic name string */
42 HSZ hszItem) /* [in] Handle to item name string */
44 WDML_INSTANCE* thisInstance = NULL;
45 WDML_LINK* pLink = NULL;
46 HDDEDATA hDdeData = 0, hItemData = 0;
47 WDML_CONV* pConv = NULL;
48 CHAR pszTopic[MAX_BUFFER_LEN];
49 CHAR pszItem[MAX_BUFFER_LEN];
52 TRACE("(%ld,%ld,%ld)\n",idInst,(DWORD)hszTopic,(DWORD)hszItem);
59 thisInstance = WDML_FindInstance(idInst);
61 if (thisInstance == NULL || thisInstance->links == NULL)
66 GlobalGetAtomNameA(hszTopic, (LPSTR)pszTopic, MAX_BUFFER_LEN);
67 GlobalGetAtomNameA(hszItem, (LPSTR)pszItem, MAX_BUFFER_LEN);
69 for (pLink = thisInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next)
71 if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0)
74 if (thisInstance->callback != NULL /* && thisInstance->Process_id == GetCurrentProcessId()*/)
77 TRACE("Calling the callback, type=XTYP_ADVREQ, CB=0x%lx, hConv=0x%lx, Topic=%s, Item=%s\n",
78 (DWORD)thisInstance->callback, (DWORD)pLink->hConv, pszTopic, pszItem);
79 hDdeData = (thisInstance->callback)(XTYP_ADVREQ,
85 TRACE("Callback was called\n");
91 if (pLink->transactionType & XTYPF_NODATA)
100 hItemData = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE);
103 pConv = WDML_GetConv(pLink->hConv);
106 !PostMessageA(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer,
107 PackDDElParam(WM_DDE_DATA, (UINT)hItemData, (DWORD)hszItem)))
109 ERR("post message failed\n");
110 DdeFreeDataHandle(hDdeData);
121 /******************************************************************************
122 * DdeNameService [USER32.@] {Un}registers service name of DDE server
125 * idInst [I] Instance identifier
126 * hsz1 [I] Handle to service name string
128 * afCmd [I] Service name flags
134 HDDEDATA WINAPI DdeNameService(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT afCmd)
136 WDML_SERVER* pServer;
137 WDML_SERVER* pServerTmp;
138 WDML_INSTANCE* thisInstance;
142 WNDCLASSEXA wndclass;
144 hDdeData = (HDDEDATA)NULL;
146 TRACE("(%ld,%d,%d,%d): stub\n",idInst,hsz1,hsz2,afCmd);
148 if (WDML_MaxInstanceID == 0)
150 /* Nothing has been initialised - exit now !
151 * needs something for DdeGetLastError */
155 if (!WDML_WaitForMutex(handle_mutex))
157 /* FIXME: setError DMLERR_SYS_ERROR; */
161 /* First check instance
163 thisInstance = WDML_FindInstance(idInst);
164 if (thisInstance == NULL)
166 TRACE("Instance not found as initialised\n");
167 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
168 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
174 /* Illegal, reserved parameter
176 thisInstance->lastError = DMLERR_INVALIDPARAMETER;
177 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
178 FIXME("Reserved parameter no-zero !!\n");
184 * General unregister situation
186 if (afCmd != DNS_UNREGISTER)
188 /* don't know if we should check this but it makes sense
189 * why supply REGISTER or filter flags if de-registering all
191 TRACE("General unregister unexpected flags\n");
192 thisInstance->lastError = DMLERR_DLL_USAGE;
193 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
196 /* Loop to find all registered service and de-register them
198 if (thisInstance->servers == NULL)
200 /* None to unregister !!
202 TRACE("General de-register - nothing registered\n");
203 thisInstance->lastError = DMLERR_DLL_USAGE;
204 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
209 pServer = thisInstance->servers;
210 while (pServer != NULL)
212 TRACE("general deregister - iteration\n");
213 pServerTmp = pServer;
214 pServer = pServer->next;
215 WDML_ReleaseAtom(thisInstance, pServerTmp->hszService);
216 /* finished - release heap space used as work store */
217 HeapFree(GetProcessHeap(), 0, pServerTmp);
219 thisInstance->servers = NULL;
220 TRACE("General de-register - finished\n");
222 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
223 return (HDDEDATA)TRUE;
225 TRACE("Specific name action detected\n");
226 if (afCmd & DNS_REGISTER)
228 /* Register new service name
231 pServer = WDML_FindServer(thisInstance, hsz1, 0);
233 ERR("Trying to register already registered service!\n");
236 TRACE("Adding service name\n");
238 WDML_ReserveAtom(thisInstance, hsz1);
240 pServer = WDML_AddServer(thisInstance, hsz1, 0);
242 WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_REGISTER, hsz1, hsz2nd);
245 wndclass.cbSize = sizeof(wndclass);
247 wndclass.lpfnWndProc = WDML_ServerNameProc;
248 wndclass.cbClsExtra = 0;
249 wndclass.cbWndExtra = 2 * sizeof(DWORD);
250 wndclass.hInstance = 0;
252 wndclass.hCursor = 0;
253 wndclass.hbrBackground = 0;
254 wndclass.lpszMenuName = NULL;
255 wndclass.lpszClassName = szServerNameClassA;
256 wndclass.hIconSm = 0;
258 RegisterClassExA(&wndclass);
260 hwndServer = CreateWindowA(szServerNameClassA, NULL,
261 WS_POPUP, 0, 0, 0, 0,
264 SetWindowLongA(hwndServer, 0, (DWORD)thisInstance);
265 TRACE("Created nameServer=%04x for instance=%08lx\n", hwndServer, idInst);
267 pServer->hwndServer = hwndServer;
269 if (afCmd & DNS_UNREGISTER)
271 TRACE("Broadcasting WM_DDE_TERMINATE message\n");
272 SendMessageA(HWND_BROADCAST, WM_DDE_TERMINATE, (WPARAM)NULL,
273 PackDDElParam(WM_DDE_TERMINATE, (UINT)hsz1, (UINT)hsz2));
275 WDML_RemoveServer(thisInstance, hsz1, hsz2);
277 if (afCmd & DNS_FILTERON)
279 /* Set filter flags on to hold notifications of connection
281 * test coded this way as this is the default setting
283 pServer = WDML_FindServer(thisInstance, hsz1, 0);
286 /* trying to filter where no service names !!
288 thisInstance->lastError = DMLERR_DLL_USAGE;
289 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
294 pServer->filterOn = TRUE;
297 if (afCmd & DNS_FILTEROFF)
299 /* Set filter flags on to hold notifications of connection
301 pServer = WDML_FindServer(thisInstance, hsz1, 0);
304 /* trying to filter where no service names !!
306 thisInstance->lastError = DMLERR_DLL_USAGE;
307 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
312 pServer->filterOn = FALSE;
315 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);
316 return (HDDEDATA)TRUE;
319 /******************************************************************
320 * WDML_CreateServerConv
324 static BOOL WDML_CreateServerConv(WDML_INSTANCE* thisInstance, HWND hwndClient, HWND hwndServerName,
325 HSZ hszApp, HSZ hszTopic)
327 WNDCLASSEXA wndclass;
331 wndclass.cbSize = sizeof(wndclass);
333 wndclass.lpfnWndProc = WDML_ServerConvProc;
334 wndclass.cbClsExtra = 0;
335 wndclass.cbWndExtra = 2 * sizeof(DWORD);
336 wndclass.hInstance = 0;
338 wndclass.hCursor = 0;
339 wndclass.hbrBackground = 0;
340 wndclass.lpszMenuName = NULL;
341 wndclass.lpszClassName = szServerConvClassA;
342 wndclass.hIconSm = 0;
344 RegisterClassExA(&wndclass);
346 hwndServerConv = CreateWindowA(szServerConvClassA, 0,
347 WS_CHILD, 0, 0, 0, 0,
348 hwndServerName, 0, 0, 0);
349 TRACE("Created convServer=%04x (nameServer=%04x) for instance=%08lx\n",
350 hwndServerConv, hwndServerName, thisInstance->instanceID);
352 pConv = WDML_AddConv(thisInstance, WDML_SERVER_SIDE, hszApp, hszTopic, hwndClient, hwndServerConv);
354 SetWindowLongA(hwndServerConv, 0, (DWORD)thisInstance);
355 SetWindowLongA(hwndServerConv, 4, (DWORD)pConv);
357 /* this should be the only place using SendMessage for WM_DDE_ACK */
358 SendMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServerConv,
359 PackDDElParam(WM_DDE_ACK, (UINT)hszApp, (UINT)hszTopic));
362 if (thisInstance && thisInstance->callback != NULL /*&& thisInstance->Process_id == GetCurrentProcessId()*/)
364 /* confirm connection...
365 * FIXME: a better way would be to check for any incoming message if the conversation
366 * exists (and/or) has been confirmed...
367 * Anyway, always pretend we use a connection from a different instance...
369 (thisInstance->callback)(XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv, hszApp, hszTopic, 0, 0, 0);
376 /******************************************************************
377 * WDML_ServerNameProc
381 static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam)
385 HDDEDATA hDdeData = 0;
386 WDML_INSTANCE* thisInstance;
391 case WM_DDE_INITIATE:
393 /* wParam -- sending window handle
394 LOWORD(lParam) -- application atom
395 HIWORD(lParam) -- topic atom */
397 TRACE("WM_DDE_INITIATE message received in the Server Proc!\n");
398 hwndClient = (HWND)wParam;
400 /* don't free DDEParams, since this is a broadcast */
401 UnpackDDElParam(WM_DDE_INITIATE, lParam, &uiLow, &uiHi);
406 thisInstance = (WDML_INSTANCE*)GetWindowLongA(hwndServer, 0);
407 TRACE("idInst=%ld, ProcessID=0x%lx\n", thisInstance->instanceID, GetCurrentProcessId());
409 if (hszApp && hszTop)
411 /* pass on to the callback */
412 if (thisInstance && thisInstance->callback != NULL /*&& thisInstance->Process_id == GetCurrentProcessId()*/)
415 TRACE("calling the Callback, type = XTYP_CONNECT, CB=0x%lx\n",
416 (DWORD)thisInstance->callback);
417 hDdeData = (thisInstance->callback)(XTYP_CONNECT,
424 WDML_CreateServerConv(thisInstance, hwndClient, hwndServer, hszApp, hszTop);
430 /* pass on to the callback */
431 if (thisInstance && thisInstance->callback != NULL /*&& thisInstance->Process_id == GetCurrentProcessId()*/)
433 TRACE("calling the Callback, type=XTYP_WILDCONNECT, CB=0x%lx\n",
434 (DWORD)thisInstance->callback);
435 hDdeData = (thisInstance->callback)(XTYP_WILDCONNECT,
444 hszp = (HSZPAIR*)DdeAccessData(hDdeData, NULL);
448 for (i = 0; hszp[i].hszSvc && hszp[i].hszTopic; i++)
450 WDML_CreateServerConv(thisInstance, hwndClient, hwndServer,
451 hszp[i].hszSvc, hszp[i].hszTopic);
453 DdeUnaccessData(hDdeData);
460 billx: make a conv and add it to the server list -
461 this can be delayed when link is created for the conv. NO NEED !!!
468 FIXME("WM_DDE_REQUEST message received!\n");
471 FIXME("WM_DDE_ADVISE message received!\n");
473 case WM_DDE_UNADVISE:
474 FIXME("WM_DDE_UNADVISE message received!\n");
477 FIXME("WM_DDE_EXECUTE message received!\n");
480 FIXME("WM_DDE_POKE message received!\n");
482 case WM_DDE_TERMINATE:
483 FIXME("WM_DDE_TERMINATE message received!\n");
488 return DefWindowProcA(hwndServer, iMsg, wParam, lParam);
491 /******************************************************************
492 * WDML_ServerHandleRequest
496 static LRESULT WDML_ServerHandleRequest(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
497 HWND hwndServer, HWND hwndClient, LPARAM lParam)
503 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
505 UnpackDDElParam(WM_DDE_REQUEST, lParam, &uiLow, &uiHi);
510 if (thisInstance && thisInstance->callback != NULL /* && thisInstance->Process_id == GetCurrentProcessId() */)
513 TRACE("calling the Callback, idInst=%ld, CB=0x%lx, uType=0x%x\n",
514 thisInstance->instanceID, (DWORD)thisInstance->callback, XTYP_REQUEST);
515 hDdeData = (thisInstance->callback)(XTYP_REQUEST, uiLow, (HCONV)pConv,
516 pConv->hszTopic, hszItem, 0, 0, 0);
521 HGLOBAL hMem = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE);
522 if (!PostMessageA(hwndClient, WM_DDE_DATA, (WPARAM)hwndServer,
523 ReuseDDElParam(lParam, WM_DDE_REQUEST, WM_DDE_DATA, (UINT)hMem, (UINT)hszItem)))
525 DdeFreeDataHandle(hDdeData);
533 ddeAck.bAppReturnCode = 0;
535 ddeAck.fBusy = FALSE;
538 TRACE("Posting a %s ack\n", ddeAck.fAck ? "positive" : "negative");
539 PostMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
540 ReuseDDElParam(lParam, WM_DDE_REQUEST, WM_DDE_ACK, *((WORD*)&ddeAck), (UINT)hszItem));
546 /******************************************************************
547 * WDML_ServerHandleAdvise
551 static LRESULT WDML_ServerHandleAdvise(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
552 HWND hwndServer, HWND hwndClient, LPARAM lParam)
554 UINT uiLo, uiHi, uType;
558 DDEADVISE* pDdeAdvise;
562 /* XTYP_ADVSTART transaction:
563 establish link and save link info to InstanceInfoTable */
565 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
567 UnpackDDElParam(WM_DDE_ADVISE, lParam, &uiLo, &uiHi);
569 hDdeAdvise = (HGLOBAL)uiLo;
570 hszItem = (HSZ)uiHi; /* FIXME: it should be a global atom */
574 ERR("Got an advise on a not known conversation, dropping request\n");
575 FreeDDElParam(WM_DDE_ADVISE, lParam);
579 pDdeAdvise = (DDEADVISE*)GlobalLock(hDdeAdvise);
580 uType = XTYP_ADVSTART |
581 (pDdeAdvise->fDeferUpd ? XTYPF_NODATA : 0) |
582 (pDdeAdvise->fAckReq ? XTYPF_ACKREQ : 0);
585 if (thisInstance && thisInstance->callback != NULL /* && thisInstance->Process_id == GetCurrentProcessId() */)
587 TRACE("calling the Callback, idInst=%ld, CB=0x%lx, uType=0x%x, uFmt=%x\n",
588 thisInstance->instanceID, (DWORD)thisInstance->callback,
589 uType, pDdeAdvise->cfFormat);
590 hDdeData = (thisInstance->callback)(XTYP_ADVSTART, pDdeAdvise->cfFormat, (HCONV)pConv,
591 pConv->hszTopic, hszItem, 0, 0, 0);
594 ddeAck.bAppReturnCode = 0;
596 ddeAck.fBusy = FALSE;
598 if ((UINT)hDdeData || TRUE) /* FIXME (from Corel ?) some apps don't return this value */
602 /* billx: first to see if the link is already created. */
603 pLink = WDML_FindLink(thisInstance, (HCONV)pConv, WDML_SERVER_SIDE,
604 hszItem, pDdeAdvise->cfFormat);
608 /* we found a link, and only need to modify it in case it changes */
609 pLink->transactionType = uType;
613 TRACE("Adding Link with hConv=0x%lx\n", (DWORD)pConv);
615 WDML_AddLink(thisInstance, (HCONV)pConv, WDML_SERVER_SIDE,
616 uType, hszItem, pDdeAdvise->cfFormat);
621 TRACE("No data returned from the Callback\n");
626 GlobalUnlock(hDdeAdvise);
628 GlobalFree(hDdeAdvise);
630 TRACE("Posting a %s ack\n", ddeAck.fAck ? "positive" : "negative");
631 PostMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
632 ReuseDDElParam(lParam, WM_DDE_ADVISE, WM_DDE_ACK, *((WORD*)&ddeAck), (UINT)hszItem));
637 /******************************************************************
638 * WDML_ServerHandleUnadvise
642 static LRESULT WDML_ServerHandleUnadvise(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
643 HWND hwndServer, HWND hwndClient, LPARAM lParam)
650 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
652 /* billx: XTYP_ADVSTOP transaction */
653 UnpackDDElParam(WM_DDE_UNADVISE, lParam, &uiLo, &uiHi);
656 hszItem = (HSZ)uiHi; /* FIXME: it should be a global atom */
658 if (hszItem == (HSZ)0 || uiLo == 0)
660 ERR("Unsupported yet options (null item or clipboard format\n");
663 pLink = WDML_FindLink(thisInstance, (HCONV)pConv, WDML_SERVER_SIDE, hszItem, uiLo);
666 ERR("Couln'd find link for %08lx, dropping request\n", (DWORD)hszItem);
667 FreeDDElParam(WM_DDE_UNADVISE, lParam);
671 /* callback shouldn't be invoked if CBF_FAIL_ADVISES is on. */
672 if (thisInstance && thisInstance->callback != NULL &&
673 !(thisInstance->CBFflags & CBF_SKIP_DISCONNECTS) /* && thisInstance->Process_id == GetCurrentProcessId() */)
675 TRACE("calling the Callback, idInst=%ld, CB=0x%lx, uType=0x%x\n",
676 thisInstance->instanceID, (DWORD)thisInstance->callback, XTYP_ADVSTOP);
677 (thisInstance->callback)(XTYP_ADVSTOP, uiLo, (HCONV)pConv, pConv->hszTopic,
681 WDML_RemoveLink(thisInstance, (HCONV)pConv, WDML_SERVER_SIDE, hszItem, uiLo);
684 ddeAck.bAppReturnCode = 0;
686 ddeAck.fBusy = FALSE;
689 PostMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
690 ReuseDDElParam(lParam, WM_DDE_UNADVISE, WM_DDE_ACK, *((WORD*)&ddeAck), (UINT)hszItem));
695 /******************************************************************
696 * WDML_ServerHandleExecute
700 static LRESULT WDML_ServerHandleExecute(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
701 HWND hwndServer, HWND hwndClient, LPARAM lParam)
706 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
708 if (hwndClient != pConv->hwndClient)
709 WARN("hmmm source window (%04x)\n", hwndClient);
712 if (thisInstance && thisInstance->callback != NULL /* && thisInstance->Process_id == GetCurrentProcessId() */)
714 LPVOID ptr = GlobalLock((HGLOBAL)lParam);
718 hDdeData = DdeCreateDataHandle(0, ptr, GlobalSize((HGLOBAL)lParam),
720 GlobalUnlock((HGLOBAL)lParam);
722 TRACE("calling the Callback, idInst=%ld, CB=0x%lx, uType=0x%x\n",
723 thisInstance->instanceID, (DWORD)thisInstance->callback, XTYP_EXECUTE);
724 hDdeData = (thisInstance->callback)(XTYP_EXECUTE, 0, (HCONV)pConv, pConv->hszTopic, 0,
728 ddeAck.bAppReturnCode = 0;
730 ddeAck.fBusy = FALSE;
732 switch ((UINT)hDdeData)
741 WARN("Bad result code\n");
743 case DDE_FNOTPROCESSED:
746 PostMessageA(pConv->hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
747 PackDDElParam(WM_DDE_ACK, *((WORD*)&ddeAck), lParam));
752 /******************************************************************
753 * WDML_ServerHandlePoke
757 static LRESULT WDML_ServerHandlePoke(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
758 HWND hwndServer, HWND hwndClient, LPARAM lParam)
766 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
768 UnpackDDElParam(WM_DDE_UNADVISE, lParam, &uiLo, &uiHi);
771 pDdePoke = (DDEPOKE*)GlobalLock((HGLOBAL)uiLo);
777 ddeAck.bAppReturnCode = 0;
779 ddeAck.fBusy = FALSE;
781 if (thisInstance && thisInstance->callback != NULL)
783 hDdeData = DdeCreateDataHandle(thisInstance->instanceID, pDdePoke->Value,
784 GlobalSize((HGLOBAL)uiLo) - sizeof(DDEPOKE) + 1,
785 0, 0, pDdePoke->cfFormat, 0);
788 HDDEDATA hDdeDataOut;
790 TRACE("calling callback XTYP_POKE, idInst=%ld\n",
791 thisInstance->instanceID);
792 hDdeDataOut = (thisInstance->callback)(XTYP_POKE,
793 pDdePoke->cfFormat, (HCONV)pConv,
794 pConv->hszTopic, (HSZ)uiHi,
796 switch ((UINT)hDdeDataOut)
805 FIXME("Unsupported returned value %08lx\n", (DWORD)hDdeDataOut);
807 case DDE_FNOTPROCESSED:
810 DdeFreeDataHandle(hDdeData);
813 GlobalUnlock((HGLOBAL)uiLo);
816 GlobalFree((HGLOBAL)uiHi);
818 PostMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
819 ReuseDDElParam(lParam, WM_DDE_POKE, WM_DDE_ACK, *((WORD*)&ddeAck), (UINT)hszItem));
824 /******************************************************************
825 * WDML_ServerHandleTerminate
829 static LRESULT WDML_ServerHandleTerminate(WDML_INSTANCE* thisInstance, WDML_CONV* pConv,
830 HWND hwndServer, HWND hwndClient, LPARAM lParam)
835 TRACE("(%04x %04x %08lx)!\n", hwndServer, hwndClient, lParam);
837 TRACE("WM_DDE_TERMINATE!\n");
838 /* XTYP_DISCONNECT transaction */
839 /* billx: two things to remove: the conv, and associated links.
840 callback shouldn't be called if CBF_SKIP_DISCONNECTS is on.
841 Respond with another WM_DDE_TERMINATE iMsg.*/
843 /* don't free DDEParams, since this is a broadcast */
844 UnpackDDElParam(WM_DDE_TERMINATE, lParam, &uiLo, &uiHi);
849 WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_UNREGISTER, hszApp, hszTop);
851 /* PostMessageA(hwndClient, WM_DDE_TERMINATE, (WPARAM)hwndServer, (LPARAM)hConv); */
852 WDML_RemoveAllLinks(thisInstance, (HCONV)pConv, WDML_SERVER_SIDE);
853 WDML_RemoveConv(thisInstance, WDML_SERVER_SIDE, (HCONV)pConv);
854 /* DestroyWindow(hwnd); don't destroy it now, we may still need it. */
859 /******************************************************************
860 * WDML_ServerConvProc
864 static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam)
866 WDML_INSTANCE* thisInstance;
869 if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST)
871 return DefWindowProcA(hwndServer, iMsg, wParam, lParam);
874 TRACE("About to wait... \n");
876 if (!WDML_WaitForMutex(handle_mutex))
881 thisInstance = (WDML_INSTANCE*)GetWindowLongA(hwndServer, 0);
882 pConv = (WDML_CONV*)GetWindowLongA(hwndServer, 4);
886 case WM_DDE_INITIATE:
887 FIXME("WM_DDE_INITIATE message received in the ServerConv Proc!\n");
891 WDML_ServerHandleRequest(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
895 WDML_ServerHandleAdvise(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
898 case WM_DDE_UNADVISE:
899 WDML_ServerHandleUnadvise(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
903 WDML_ServerHandleExecute(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
907 WDML_ServerHandlePoke(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
910 case WM_DDE_TERMINATE:
911 WDML_ServerHandleTerminate(thisInstance, pConv, hwndServer, (HWND)wParam, lParam);
915 WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n");
919 FIXME("Unsupported message %d\n", iMsg);
922 WDML_ReleaseMutex(handle_mutex, "handle_mutex", FALSE);