/***************************************************************** * DdeAbandonTransaction (USER32.@) */ BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction) { WDML_INSTANCE* pInstance; WDML_CONV* pConv; WDML_XACT* pXAct; if ((pInstance = WDML_GetInstance(idInst))) { if (hConv) { if ((pConv = WDML_GetConv(hConv, TRUE)) && pConv->instance == pInstance) { pXAct = pConv->transactions; while (pXAct) { WDML_XACT *nextXAct = pXAct->next; if (pXAct->dwTimeout == TIMEOUT_ASYNC && (idTransaction == 0 || pXAct->xActID == idTransaction)) { WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pInstance, pXAct, TRUE); } pXAct = nextXAct; } } } else { for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv; pConv = pConv->next) { if (!(pConv->wStatus & ST_CONNECTED)) continue; pXAct = pConv->transactions; while (pXAct) { WDML_XACT *nextXAct = pXAct->next; if (pXAct->dwTimeout == TIMEOUT_ASYNC) { WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pInstance, pXAct, TRUE); } pXAct = nextXAct; } } } } return TRUE; }
/***************************************************************** * DdeAbandonTransaction (USER32.@) */ BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction) { WDML_INSTANCE* pInstance; WDML_CONV* pConv; WDML_XACT* pXAct; TRACE("(%08lx,%p,%08lx);\n", idInst, hConv, idTransaction); EnterCriticalSection(&WDML_CritSect); if ((pInstance = WDML_GetInstance(idInst))) { if (hConv) { if ((pConv = WDML_GetConv(hConv, TRUE)) && pConv->instance == pInstance) { for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next) { if (pXAct->dwTimeout == TIMEOUT_ASYNC && (idTransaction == 0 || pXAct->xActID == idTransaction)) { WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pInstance, pXAct, TRUE); } } } } else { for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv; pConv = pConv->next) { if (!(pConv->wStatus & ST_CONNECTED)) continue; for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next) { if (pXAct->dwTimeout == TIMEOUT_ASYNC) { WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pInstance, pXAct, TRUE); } } } } } LeaveCriticalSection(&WDML_CritSect); return TRUE; }
/****************************************************************************** * 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; }
/****************************************************************************** * DdeNameService [USER32.@] {Un}registers service name of DDE server * * PARAMS * idInst [I] Instance identifier * hsz1 [I] Handle to service name string * hsz2 [I] Reserved * afCmd [I] Service name flags * * RETURNS * Success: Non-zero * Failure: 0 */ HDDEDATA WINAPI DdeNameService(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT afCmd) { WDML_SERVER* pServer; WDML_INSTANCE* pInstance; HDDEDATA hDdeData; HWND hwndServer; WNDCLASSEXA wndclass; hDdeData = (HDDEDATA)NULL; TRACE("(%ld,0x%x,0x%x,%d)\n", idInst, hsz1, hsz2, afCmd); EnterCriticalSection(&WDML_CritSect); /* First check instance */ pInstance = WDML_GetInstance(idInst); if (pInstance == NULL) { TRACE("Instance not found as initialised\n"); /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */ goto theError; } if (hsz2 != 0L) { /* Illegal, reserved parameter */ pInstance->lastError = DMLERR_INVALIDPARAMETER; WARN("Reserved parameter no-zero !!\n"); goto theError; } if (hsz1 == 0 && afCmd != DNS_UNREGISTER) { /* don't know if we should check this but it makes sense * why supply REGISTER or filter flags if de-registering all */ TRACE("General unregister unexpected flags\n"); pInstance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } switch (afCmd) { case DNS_REGISTER: pServer = WDML_FindServer(pInstance, hsz1, 0); if (pServer) { ERR("Trying to register already registered service!\n"); pInstance->lastError = DMLERR_DLL_USAGE; goto theError; } TRACE("Adding service name\n"); WDML_IncHSZ(pInstance, hsz1); pServer = WDML_AddServer(pInstance, hsz1, 0); WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_REGISTER, pServer->atomService, pServer->atomServiceSpec); wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = WDML_ServerNameProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 2 * sizeof(DWORD); wndclass.hInstance = 0; wndclass.hIcon = 0; wndclass.hCursor = 0; wndclass.hbrBackground = 0; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szServerNameClassA; wndclass.hIconSm = 0; RegisterClassExA(&wndclass); LeaveCriticalSection(&WDML_CritSect); hwndServer = CreateWindowA(szServerNameClassA, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); EnterCriticalSection(&WDML_CritSect); SetWindowLongA(hwndServer, GWL_WDML_INSTANCE, (DWORD)pInstance); SetWindowLongA(hwndServer, GWL_WDML_SERVER, (DWORD)pServer); TRACE("Created nameServer=%04x for instance=%08lx\n", hwndServer, idInst); pServer->hwndServer = hwndServer; break; case DNS_UNREGISTER: if (hsz1 == 0L) { /* General unregister situation * terminate all server side pending conversations */ while (pInstance->servers) WDML_RemoveServer(pInstance, pInstance->servers->hszService, 0); pInstance->servers = NULL; TRACE("General de-register - finished\n"); } else { WDML_RemoveServer(pInstance, hsz1, 0L); } break; case DNS_FILTERON: case DNS_FILTEROFF: /* Set filter flags on to hold notifications of connection */ pServer = WDML_FindServer(pInstance, hsz1, 0); if (!pServer) { /* trying to filter where no service names !! */ pInstance->lastError = DMLERR_DLL_USAGE; goto theError; } else { pServer->filterOn = (afCmd == DNS_FILTERON); } break; } LeaveCriticalSection(&WDML_CritSect); return (HDDEDATA)TRUE; theError: LeaveCriticalSection(&WDML_CritSect); return FALSE; }
/***************************************************************** * DdeConnect (USER32.@) */ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic, PCONVCONTEXT pCC) { HWND hwndClient; WDML_INSTANCE* pInstance; WDML_CONV* pConv; ATOM aSrv = 0, aTpc = 0; TRACE("(0x%x,%p,%p,%p)\n", idInst, hszService, hszTopic, pCC); pInstance = WDML_GetInstance(idInst); if (!pInstance) return NULL; /* make sure this conv is never created */ pConv = WDML_FindConv(pInstance, WDML_CLIENT_SIDE, hszService, hszTopic); if (pConv != NULL) { ERR("This Conv already exists: (%p)\n", pConv); return NULL; } /* we need to establish a conversation with server, so create a window for it */ if (pInstance->unicode) { WNDCLASSEXW wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = WDML_ClientProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR); wndclass.hInstance = 0; wndclass.hIcon = 0; wndclass.hCursor = 0; wndclass.hbrBackground = 0; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = WDML_szClientConvClassW; wndclass.hIconSm = 0; RegisterClassExW(&wndclass); hwndClient = CreateWindowW(WDML_szClientConvClassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); } else { WNDCLASSEXA wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = WDML_ClientProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR); wndclass.hInstance = 0; wndclass.hIcon = 0; wndclass.hCursor = 0; wndclass.hbrBackground = 0; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = WDML_szClientConvClassA; wndclass.hIconSm = 0; RegisterClassExA(&wndclass); hwndClient = CreateWindowA(WDML_szClientConvClassA, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); } SetWindowLongPtrW(hwndClient, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance); if (hszService) { aSrv = WDML_MakeAtomFromHsz(hszService); if (!aSrv) goto theEnd; } if (hszTopic) { aTpc = WDML_MakeAtomFromHsz(hszTopic); if (!aTpc) goto theEnd; } /* note: sent messages shall not use packing */ SendMessageTimeoutW( HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hwndClient, MAKELPARAM(aSrv, aTpc), SMTO_ABORTIFHUNG, 0, NULL ); pInstance = WDML_GetInstance(idInst); if (!pInstance) { goto theEnd; } /* At this point, Client WM_DDE_ACK should have saved hwndServer for this instance id and hwndClient if server responds. So get HCONV and return it. And add it to conv list */ pConv = WDML_GetConvFromWnd(hwndClient); if (pConv == NULL || pConv->hwndServer == 0) { WARN("Done with INITIATE, but no Server window available\n"); pConv = NULL; pInstance->lastError = DMLERR_NO_CONV_ESTABLISHED; goto theEnd; } TRACE("Connected to Server window (%p)\n", pConv->hwndServer); pConv->wConvst = XST_CONNECTED; /* finish init of pConv */ if (pCC != NULL) { pConv->convContext = *pCC; } else { memset(&pConv->convContext, 0, sizeof(pConv->convContext)); pConv->convContext.cb = sizeof(pConv->convContext); pConv->convContext.iCodePage = (pInstance->unicode) ? CP_WINUNICODE : CP_WINANSI; } theEnd: if (aSrv) GlobalDeleteAtom(aSrv); if (aTpc) GlobalDeleteAtom(aTpc); return (HCONV)pConv; }