/***************************************************************** * DdeClientTransaction (USER32.@) */ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt, UINT wType, DWORD dwTimeout, LPDWORD pdwResult) { WDML_CONV* pConv; WDML_XACT* pXAct; HDDEDATA hDdeData; TRACE("(%p,%d,%p,%p,%x,%x,%d,%p)\n", pData, cbData, hConv, hszItem, wFmt, wType, dwTimeout, pdwResult); if (hConv == 0) { WARN("Invalid conversation handle NULL\n"); return 0; } pConv = WDML_GetConv(hConv, TRUE); if (pConv == NULL) { /* cannot set error... cannot get back to DDE instance */ return 0; } switch (wType) { case XTYP_EXECUTE: /* Windows simply ignores hszItem and wFmt in this case */ pXAct = WDML_ClientQueueExecute(pConv, pData, cbData); if (pXAct == NULL) return 0; break; case XTYP_POKE: if (!hszItem) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; return 0; } pXAct = WDML_ClientQueuePoke(pConv, pData, cbData, wFmt, hszItem); break; case XTYP_ADVSTART|XTYPF_NODATA: case XTYP_ADVSTART|XTYPF_NODATA|XTYPF_ACKREQ: case XTYP_ADVSTART: case XTYP_ADVSTART|XTYPF_ACKREQ: if (pData) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; return 0; } pXAct = WDML_ClientQueueAdvise(pConv, wType, wFmt, hszItem); break; case XTYP_ADVSTOP: if (pData) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; return 0; } pXAct = WDML_ClientQueueUnadvise(pConv, wFmt, hszItem); break; case XTYP_REQUEST: if (pData || !hszItem) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; return 0; } pXAct = WDML_ClientQueueRequest(pConv, wFmt, hszItem); break; default: FIXME("Unknown transaction type %04x\n", wType); /* unknown transaction type */ pConv->instance->lastError = DMLERR_INVALIDPARAMETER; return 0; } if (pXAct == NULL) { pConv->instance->lastError = DMLERR_MEMORY_ERROR; return 0; } WDML_QueueTransaction(pConv, pXAct); TRACE("pConv->wStatus %04x\n", pConv->wStatus); if (pConv->wStatus & ST_BLOCKED) { TRACE("Transactions are blocked, add to the queue and exit\n"); return (HDDEDATA)1; } hDdeData = WDML_ClientHandle(pConv, pXAct, dwTimeout, pdwResult); if (dwTimeout != TIMEOUT_ASYNC) { WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pConv->instance, pXAct, TRUE); } return hDdeData; }
/***************************************************************** * DdeClientTransaction (USER32.@) */ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt, UINT wType, DWORD dwTimeout, LPDWORD pdwResult) { WDML_CONV* pConv; WDML_XACT* pXAct; HDDEDATA hDdeData = 0; TRACE("(%p,%ld,%p,%p,%x,%x,%ld,%p)\n", pData, cbData, hConv, hszItem, wFmt, wType, dwTimeout, pdwResult); if (hConv == 0) { WARN("Invalid conversation handle NULL\n"); return 0; } EnterCriticalSection(&WDML_CritSect); pConv = WDML_GetConv(hConv, TRUE); if (pConv == NULL) { /* cannot set error... cannot get back to DDE instance */ goto theError; } switch (wType) { case XTYP_EXECUTE: /* Windows simply ignores hszItem and wFmt in this case */ pXAct = WDML_ClientQueueExecute(pConv, pData, cbData); break; case XTYP_POKE: pXAct = WDML_ClientQueuePoke(pConv, pData, cbData, wFmt, hszItem); break; case XTYP_ADVSTART|XTYPF_NODATA: case XTYP_ADVSTART|XTYPF_NODATA|XTYPF_ACKREQ: case XTYP_ADVSTART: case XTYP_ADVSTART|XTYPF_ACKREQ: if (pData) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } pXAct = WDML_ClientQueueAdvise(pConv, wType, wFmt, hszItem); break; case XTYP_ADVSTOP: if (pData) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } pXAct = WDML_ClientQueueUnadvise(pConv, wFmt, hszItem); break; case XTYP_REQUEST: if (pData) { pConv->instance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } pXAct = WDML_ClientQueueRequest(pConv, wFmt, hszItem); break; default: FIXME("Unknown transation\n"); /* unknown transaction type */ pConv->instance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } if (pXAct == NULL) { pConv->instance->lastError = DMLERR_MEMORY_ERROR; goto theError; } WDML_QueueTransaction(pConv, pXAct); if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam)) { WARN("Failed posting message %x to %p (error=0x%lx)\n", pXAct->ddeMsg, pConv->hwndServer, GetLastError()); pConv->wStatus &= ~ST_CONNECTED; WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pConv->instance, pXAct, TRUE); goto theError; } pXAct->dwTimeout = dwTimeout; /* FIXME: should set the app bits on *pdwResult */ if (dwTimeout == TIMEOUT_ASYNC) { if (pdwResult) { *pdwResult = MAKELONG(0, pXAct->xActID); } hDdeData = (HDDEDATA)1; } else { DWORD count, i; count = WDML_CritSect.RecursionCount; for (i = 0; i < count; i++) LeaveCriticalSection(&WDML_CritSect); hDdeData = WDML_SyncWaitTransactionReply((HCONV)pConv, dwTimeout, pXAct, pdwResult); for (i = 0; i < count; i++) EnterCriticalSection(&WDML_CritSect); } LeaveCriticalSection(&WDML_CritSect); return hDdeData; theError: LeaveCriticalSection(&WDML_CritSect); return 0; }