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

📄 dde.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:

    if (side == WDML_SERVER_SIDE)
    {
	from = pConv->hwndServer;
	to   = pConv->hwndClient;
    }
    else
    {
	to   = pConv->hwndServer;
	from = pConv->hwndClient;
    }

    ddeAck.bAppReturnCode = appRetCode;
    ddeAck.reserved       = 0;
    ddeAck.fBusy          = fBusy;
    ddeAck.fAck           = fAck;

    TRACE("Posting a %s ack\n", ddeAck.fAck ? "positive" : "negative");

    lParam = (lParam) ? ReuseDDElParam(lParam, oldMsg, WM_DDE_ACK, *(WORD*)&ddeAck, pmt) :
        PackDDElParam(WM_DDE_ACK, *(WORD*)&ddeAck, pmt);
    if (!PostMessageW(to, WM_DDE_ACK, (WPARAM)from, lParam))
    {
	pConv->wStatus &= ~ST_CONNECTED;
        FreeDDElParam(WM_DDE_ACK, lParam);
        return FALSE;
    }
    return TRUE;
}

/*****************************************************************
 *            DdeSetUserHandle (USER32.@)
 */
BOOL WINAPI DdeSetUserHandle(HCONV hConv, DWORD id, DWORD hUser)
{
    WDML_CONV*	pConv;
    BOOL	ret = TRUE;

    TRACE("(%p,%lx,%lx)\n", hConv, id, hUser);

    EnterCriticalSection(&WDML_CritSect);

    pConv = WDML_GetConv(hConv, FALSE);
    if (pConv == NULL)
    {
	ret = FALSE;
	goto theError;
    }
    if (id == QID_SYNC)
    {
	pConv->hUser = hUser;
    }
    else
    {
	WDML_XACT*	pXAct;

	pXAct = WDML_FindTransaction(pConv, id);
	if (pXAct)
	{
	    pXAct->hUser = hUser;
	}
	else
	{
	    pConv->instance->lastError = DMLERR_UNFOUND_QUEUE_ID;
	    ret = FALSE;
	}
    }
 theError:
    LeaveCriticalSection(&WDML_CritSect);
    return ret;
}

/******************************************************************
 *		WDML_GetLocalConvInfo
 *
 *
 */
static	BOOL	WDML_GetLocalConvInfo(WDML_CONV* pConv, CONVINFO* ci, DWORD id)
{
    BOOL 	ret = TRUE;
    WDML_LINK*	pLink;
    WDML_SIDE	side;

    ci->hConvPartner = (pConv->wStatus & ST_ISLOCAL) ? (HCONV)((ULONG_PTR)pConv | 1) : 0;
    ci->hszSvcPartner = pConv->hszService;
    ci->hszServiceReq = pConv->hszService; /* FIXME: they shouldn't be the same, should they ? */
    ci->hszTopic = pConv->hszTopic;
    ci->wStatus = pConv->wStatus;

    side = (pConv->wStatus & ST_CLIENT) ? WDML_CLIENT_SIDE : WDML_SERVER_SIDE;

    for (pLink = pConv->instance->links[side]; pLink != NULL; pLink = pLink->next)
    {
	if (pLink->hConv == (HCONV)pConv)
	{
	    ci->wStatus |= ST_ADVISE;
	    break;
	}
    }

    /* FIXME: non handled status flags:
       ST_BLOCKED
       ST_BLOCKNEXT
       ST_INLIST
    */

    ci->wConvst = pConv->wConvst; /* FIXME */

    ci->wLastError = 0; /* FIXME: note it's not the instance last error */
    ci->hConvList = 0;
    ci->ConvCtxt = pConv->convContext;
    if (ci->wStatus & ST_CLIENT)
    {
	ci->hwnd = pConv->hwndClient;
	ci->hwndPartner = pConv->hwndServer;
    }
    else
    {
	ci->hwnd = pConv->hwndServer;
	ci->hwndPartner = pConv->hwndClient;
    }
    if (id == QID_SYNC)
    {
	ci->hUser = pConv->hUser;
	ci->hszItem = 0;
	ci->wFmt = 0;
	ci->wType = 0;
    }
    else
    {
	WDML_XACT*	pXAct;

	pXAct = WDML_FindTransaction(pConv, id);
	if (pXAct)
	{
	    ci->hUser = pXAct->hUser;
	    ci->hszItem = pXAct->hszItem;
	    ci->wFmt = pXAct->wFmt;
	    ci->wType = pXAct->wType;
	}
	else
	{
	    ret = 0;
	    pConv->instance->lastError = DMLERR_UNFOUND_QUEUE_ID;
	}
    }
    return ret;
}

/******************************************************************
 *		DdeQueryConvInfo (USER32.@)
 *
 * FIXME: Set last DDE error on failure.
 */
UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, PCONVINFO lpConvInfo)
{
    UINT	ret = lpConvInfo->cb;
    CONVINFO	ci;
    WDML_CONV*	pConv;

    TRACE("(%p,%lx,%p)\n", hConv, id, lpConvInfo);

    if (!hConv)
    {
        FIXME("hConv is NULL\n");
        return 0;
    }

    EnterCriticalSection(&WDML_CritSect);

    pConv = WDML_GetConv(hConv, FALSE);
    if (pConv != NULL)
    {
        if (!WDML_GetLocalConvInfo(pConv, &ci, id))
            ret = 0;
    }
    else
    {
        if ((ULONG_PTR)hConv & 1)
        {
            pConv = WDML_GetConv((HCONV)((ULONG_PTR)hConv & ~1), FALSE);
            if (pConv != NULL)
                FIXME("Request on remote conversation information is not implemented yet\n");
        }
        ret = 0;
    }
    LeaveCriticalSection(&WDML_CritSect);
    if (ret != 0)
	memcpy(lpConvInfo, &ci, min((size_t)lpConvInfo->cb, sizeof(ci)));
    return ret;
}

/* ================================================================
 *
 * 			Link (hot & warm) management
 *
 * ================================================================ */

/******************************************************************
 *		WDML_AddLink
 *
 *
 */
void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
		  UINT wType, HSZ hszItem, UINT wFmt)
{
    WDML_LINK*	pLink;

    pLink = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_LINK));
    if (pLink == NULL)
    {
	ERR("OOM\n");
	return;
    }

    pLink->hConv = hConv;
    pLink->transactionType = wType;
    WDML_IncHSZ(pInstance, pLink->hszItem = hszItem);
    pLink->uFmt = wFmt;
    pLink->next = pInstance->links[side];
    pInstance->links[side] = pLink;
}

/******************************************************************
 *		WDML_RemoveLink
 *
 *
 */
void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
		     HSZ hszItem, UINT uFmt)
{
    WDML_LINK* pPrev = NULL;
    WDML_LINK* pCurrent = NULL;

    pCurrent = pInstance->links[side];

    while (pCurrent != NULL)
    {
	if (pCurrent->hConv == hConv &&
	    DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 &&
	    pCurrent->uFmt == uFmt)
	{
	    if (pCurrent == pInstance->links[side])
	    {
		pInstance->links[side] = pCurrent->next;
	    }
	    else
	    {
		pPrev->next = pCurrent->next;
	    }

	    WDML_DecHSZ(pInstance, pCurrent->hszItem);
	    HeapFree(GetProcessHeap(), 0, pCurrent);
	    break;
	}

	pPrev = pCurrent;
	pCurrent = pCurrent->next;
    }
}

/* this function is called to remove all links related to the conv.
   It should be called from both client and server when terminating
   the conversation.
*/
/******************************************************************
 *		WDML_RemoveAllLinks
 *
 *
 */
void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE side)
{
    WDML_LINK* pPrev = NULL;
    WDML_LINK* pCurrent = NULL;
    WDML_LINK* pNext = NULL;

    pCurrent = pInstance->links[side];

    while (pCurrent != NULL)
    {
	if (pCurrent->hConv == (HCONV)pConv)
	{
	    if (pCurrent == pInstance->links[side])
	    {
		pInstance->links[side] = pCurrent->next;
		pNext = pCurrent->next;
	    }
	    else
	    {
		pPrev->next = pCurrent->next;
		pNext = pCurrent->next;
	    }

	    WDML_DecHSZ(pInstance, pCurrent->hszItem);

	    HeapFree(GetProcessHeap(), 0, pCurrent);
	    pCurrent = NULL;
	}

	if (pCurrent)
	{
	    pPrev = pCurrent;
	    pCurrent = pCurrent->next;
	}
	else
	{
	    pCurrent = pNext;
	}
    }
}

/******************************************************************
 *		WDML_FindLink
 *
 *
 */
WDML_LINK* 	WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
			      HSZ hszItem, BOOL use_fmt, UINT uFmt)
{
    WDML_LINK*	pCurrent = NULL;

    for (pCurrent = pInstance->links[side]; pCurrent != NULL; pCurrent = pCurrent->next)
    {
	/* we don't need to check for transaction type as it can be altered */

	if (pCurrent->hConv == hConv &&
	    DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 &&
	    (!use_fmt || pCurrent->uFmt == uFmt))
	{
	    break;
	}

    }

    return pCurrent;
}

/* ================================================================
 *
 * 			Transaction management
 *
 * ================================================================ */

/******************************************************************
 *		WDML_AllocTransaction
 *
 * Alloc a transaction structure for handling the message ddeMsg
 */
WDML_XACT*	WDML_AllocTransaction(WDML_INSTANCE* pInstance, UINT ddeMsg,
				      UINT wFmt, HSZ hszItem)
{
    WDML_XACT*		pXAct;
    static WORD		tid = 1;	/* FIXME: wrap around */

    pXAct = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_XACT));
    if (!pXAct)
    {
	pInstance->lastError = DMLERR_MEMORY_ERROR;
	return NULL;
    }

    pXAct->xActID = tid++;
    pXAct->ddeMsg = ddeMsg;
    pXAct->hDdeData = 0;
    pXAct->hUser = 0;
    pXAct->next = NULL;
    pXAct->wType = 0;
    pXAct->wFmt = wFmt;
    if ((pXAct->hszItem = hszItem)) WDML_IncHSZ(pInstance, pXAct->hszItem);
    pXAct->atom = 0;
    pXAct->hMem = 0;
    pXAct->lParam = 0;

    return pXAct;
}

/******************************************************************
 *		WDML_QueueTransaction
 *
 * Adds a transaction to the list of transaction
 */
void	WDML_QueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct)
{
    WDML_XACT**	pt;

    /* advance to last in queue */
    for (pt = &pConv->transactions; *pt != NULL; pt = &(*pt)->next);
    *pt = pXAct;
}

/******************************************************************
 *		WDML_UnQueueTransaction
 *
 *
 */
BOOL	WDML_UnQueueTransaction(WDML_CONV* pConv, WDML_XACT*  pXAct)
{
    WDML_XACT**	pt;

    for (pt = &pConv->transactions; *pt; pt = &(*pt)->next)
    {
	if (*pt == pXAct)
	{
	    *pt = pXAct->next;
	    return TRUE;
	}
    }
    return FALSE;
}

/******************************************************************
 *		WDML_FreeTransaction
 *
 *
 */
void	WDML_FreeTransaction(WDML_INSTANCE* pInstance, WDML_XACT* pXAct, BOOL doFreePmt)
{
    /* free pmt(s) in pXAct too. check against one for not deleting TRUE return values */
    if (doFreePmt && (ULONG_PTR)pXAct->hMem > 1)
    {
	GlobalFree(pXAct->hMem);
    }
    if (pXAct->hszItem) WDML_DecHSZ(pInstance, pXAct->hszItem);

    HeapFree(GetProcessHeap(), 0, pXAct);
}

/******************************************************************
 *		WDML_FindTransaction
 *
 *
 */
WDML_XACT*	WDML_FindTransaction(WDML_CONV* pConv, DWORD tid)
{
    WDML_XACT* pXAct;

    tid = HIWORD(tid);
    for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next)
    {
	if (pXAct->xActID == tid)
	    break;
    }
    return pXAct;
}

/* ================================================================
 *
 * 	   Information broadcast across DDEML implementations
 *
 * ================================================================ */

struct tagWDML_BroadcastPmt
{
    LPCWSTR	clsName;
    UINT	uMsg;
    WPARAM	wParam;
    LPARAM	lParam;
};

/******************************************************************
 *		WDML_BroadcastEnumProc
 *
 *
 */
static	BOOL CALLBACK WDML_BroadcastEnumProc(HWND hWnd, LPARAM lParam)
{
    struct tagWDML_BroadcastPmt*	s = (struct tagWDML_BroadcastPmt*)lParam;
    WCHAR				buffer[128];

    if (GetClassNameW(hWnd, buffer, 128) > 0 &&
	lstrcmpiW(buffer, s->clsName) == 0)
    {
	PostMessageW(hWnd, s->uMsg, s->wParam, s->lParam);
    }
    return TRUE;
}

/******************************************************************
 *		WDML_BroadcastDDEWindows

⌨️ 快捷键说明

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