⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
	    qs = WDML_QS_ERROR;	    FIXME("oooch\n");	}    }    else    {	qs = WDML_QS_PASS;    }    /* now check the results */    switch (qs)    {    case WDML_QS_ERROR:    case WDML_QS_SWALLOWED:	*hdd = 0;	break;    case WDML_QS_HANDLED:	/* ok, we have resolved a pending transaction	 * notify callback if asynchronous, and remove it in any case	 */	WDML_UnQueueTransaction(pConv, pXAct);	if (pXAct->dwTimeout == TIMEOUT_ASYNC && pXAct->ddeMsg != WM_DDE_TERMINATE)	{	    WDML_InvokeCallback(pConv->instance, XTYP_XACT_COMPLETE, pXAct->wFmt,				(HCONV)pConv, pConv->hszTopic, pXAct->hszItem,				pXAct->hDdeData, MAKELONG(0, pXAct->xActID), 0 /* FIXME */);	    qs = WDML_QS_PASS;	}	else	{	    *hdd = pXAct->hDdeData;	}	WDML_FreeTransaction(pConv->instance, pXAct, TRUE);	break;    case WDML_QS_PASS:	/* no pending transaction found, try a warm/hot link or a termination request */	switch (msg->message)	{	case WM_DDE_DATA:	    qs = WDML_HandleIncomingData(pConv, msg, hdd);	    break;	case WM_DDE_TERMINATE:	    qs = WDML_HandleIncomingTerminate(pConv, msg, hdd);	    break;	}	break;    case WDML_QS_BLOCK:	FIXME("shouldn't be used on client side\n");	break;    }    return qs;}/****************************************************************** *		WDML_SyncWaitTransactionReply * * waits until an answer for a sent request is received * time out is also handled. only used for synchronous transactions */static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, WDML_XACT* pXAct){    DWORD	dwTime;    DWORD	err;    WDML_CONV*	pConv;    TRACE("Starting wait for a timeout of %ld ms\n", dwTimeout);    /* FIXME: time 32 bit wrap around */    dwTimeout += GetCurrentTime();    while ((dwTime = GetCurrentTime()) < dwTimeout)    {	/* we cannot be in the crit sect all the time because when client and server run in a	 * single process they need to share the access to the internal data	 */	if (MsgWaitForMultipleObjects(0, NULL, FALSE,				      dwTimeout - dwTime, QS_POSTMESSAGE) == WAIT_OBJECT_0)	{	    BOOL	ret = FALSE;	    MSG		msg;	    WDML_CONV*	pConv;	    HDDEDATA	hdd;	    EnterCriticalSection(&WDML_CritSect);	    pConv = WDML_GetConv(hConv, FALSE);	    if (pConv == NULL)	    {		LeaveCriticalSection(&WDML_CritSect);		/* conversation no longer available... return failure */		break;	    }	    while (PeekMessageA(&msg, pConv->hwndClient, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))	    {		/* check that either pXAct has been processed or no more xActions are pending */		ret = (pConv->transactions == pXAct);		ret = WDML_HandleReply(pConv, &msg, &hdd) == WDML_QS_HANDLED &&		    (pConv->transactions == NULL || ret);		if (ret) break;	    }	    LeaveCriticalSection(&WDML_CritSect);	    if (ret)	    {		return hdd;	    }	}    }    TRACE("Timeout !!\n");    EnterCriticalSection(&WDML_CritSect);    pConv = WDML_GetConv(hConv, FALSE);    if (pConv != NULL)    {	if (pConv->transactions)	{	    switch (pConv->transactions->ddeMsg)	    {	    case WM_DDE_ADVISE:		err = DMLERR_ADVACKTIMEOUT;	break;	    case WM_DDE_REQUEST:	err = DMLERR_DATAACKTIMEOUT; 	break;	    case WM_DDE_EXECUTE:	err = DMLERR_EXECACKTIMEOUT;	break;	    case WM_DDE_POKE:		err = DMLERR_POKEACKTIMEOUT;	break;	    case WM_DDE_UNADVISE:	err = DMLERR_UNADVACKTIMEOUT;	break;	    default:			err = DMLERR_INVALIDPARAMETER;	break;	    }	    pConv->instance->lastError = err;	}    }    LeaveCriticalSection(&WDML_CritSect);    return 0;}/***************************************************************** *            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)    {	ERR("Invalid conversation handle\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:	if (hszItem != 0 || wFmt != 0)	{	    pConv->instance->lastError = DMLERR_INVALIDPARAMETER;	    goto theError;	}	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 (!PostMessageA(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;	if (pdwResult)	{	    *pdwResult = 0L;	}	count = WDML_CritSect.RecursionCount;	for (i = 0; i < count; i++)	    LeaveCriticalSection(&WDML_CritSect);	hDdeData = WDML_SyncWaitTransactionReply((HCONV)pConv, dwTimeout, pXAct);	for (i = 0; i < count; i++)	    EnterCriticalSection(&WDML_CritSect);    }    LeaveCriticalSection(&WDML_CritSect);    return hDdeData; theError:    LeaveCriticalSection(&WDML_CritSect);    return 0;}/***************************************************************** *            DdeAbandonTransaction (USER32.@) */BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction){    WDML_INSTANCE*	pInstance;    WDML_CONV*		pConv;    WDML_XACT*          pXAct;    TRACE("(%08lx,%p,%08ld);\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;}/****************************************************************** *		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;    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);            PostMessageA((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);	SetWindowLongA(hwnd, GWL_WDML_CONVERSATION, (DWORD)pConv);	pConv->wStatus |= ST_CONNECTED;	pConv->wConvst = XST_INIT1;	/* check if server is handled by DDEML */	if ((GetClassNameA((HWND)wParam, buf, sizeof(buf)) &&	     strcmp(buf, WDML_szServerConvClassA) == 0) ||	    (GetClassNameW((HWND)wParam, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) &&	     lstrcmpW((LPWSTR)buf, WDML_szServerConvClassW) == 0))	{	    pConv->wStatus |= ST_ISLOCAL;	}	WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_CONNECT_CONFIRM, (WPARAM)hwnd, wParam);	GlobalDeleteAtom(uiLo);	GlobalDeleteAtom(uiHi);	/* accept conversation */	return 1;    }    if (iMsg >= WM_DDE_FIRST && iMsg <= WM_DDE_LAST)    {	EnterCriticalSection(&WDML_CritSect);	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);	}	LeaveCriticalSection(&WDML_CritSect);	return 0;    }    return (IsWindowUnicode(hwnd)) ?	DefWindowProcA(hwnd, iMsg, wParam, lParam) : DefWindowProcW(hwnd, iMsg, wParam, lParam);}/***************************************************************** *            DdeDisconnect   (USER32.@) */BOOL WINAPI DdeDisconnect(HCONV hConv){    WDML_CONV*	pConv = NULL;    WDML_XACT*	pXAct;    DWORD	count, i;    BOOL	ret = FALSE;    TRACE("(%p)\n", hConv);    if (hConv == 0)    {	ERR("DdeDisconnect(): hConv = 0\n");	return FALSE;    }    EnterCriticalSection(&WDML_CritSect);    pConv = WDML_GetConv(hConv, TRUE);    if (pConv != NULL)    {        if (pConv->wStatus & ST_CLIENT)        {            /* FIXME: should abandon all pending transactions */            pXAct = WDML_ClientQueueTerminate(pConv);            if (pXAct != NULL)            {                count = WDML_CritSect.RecursionCount;                for (i = 0; i < count; i++)                    LeaveCriticalSection(&WDML_CritSect);                if (PostMessageA(pConv->hwndServer, pXAct->ddeMsg,                                 (WPARAM)pConv->hwndClient, pXAct->lParam))                    WDML_SyncWaitTransactionReply(hConv, 10000, pXAct);                for (i = 0; i < count; i++)                    EnterCriticalSection(&WDML_CritSect);                ret = TRUE;                WDML_FreeTransaction(pConv->instance, pXAct, TRUE);                /* still have to destroy data assosiated with conversation */                WDML_RemoveConv(pConv, WDML_CLIENT_SIDE);            }            else            {                FIXME("Not implemented yet for a server side conversation\n");            }        }    }    LeaveCriticalSection(&WDML_CritSect);    return ret;}/***************************************************************** *            DdeImpersonateClient (USER32.@) */BOOL WINAPI DdeImpersonateClient(HCONV hConv){    WDML_CONV*	pConv;    BOOL	ret = FALSE;    TRACE("(%p)\n", hConv);    EnterCriticalSection(&WDML_CritSect);    pConv = WDML_GetConv(hConv, TRUE);    if (pConv)    {	ret = ImpersonateDdeClientWindow(pConv->hwndClient, pConv->hwndServer);    }    LeaveCriticalSection(&WDML_CritSect);    return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -