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

📄 dde.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
						0, 0, 0, 0);

	SetWindowLongPtrW(pInstance->hwndEvent, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance);

	TRACE("New application instance processing finished OK\n");
    }
    else
    {
	/* Reinitialisation situation   --- FIX  */
	TRACE("reinitialisation of (%p,%p,0x%lx,%ld): stub\n", pidInst, pfnCallback, afCmd, ulRes);

	EnterCriticalSection(&WDML_CritSect);

	if (WDML_InstanceList == NULL)
	{
	    ret = DMLERR_INVALIDPARAMETER;
	    goto theError;
	}
	HeapFree(GetProcessHeap(), 0, pInstance); /* finished - release heap space used as work store */
	/* can't reinitialise if we have initialised nothing !! */
	reference_inst = WDML_InstanceList;
	/* must first check if we have been given a valid instance to re-initialise !!  how do we do that ? */
	/*
	 *	MS allows initialisation without specifying a callback, should we allow addition of the
	 *	callback by a later call to initialise ? - if so this lot will have to change
	 */
	while (reference_inst->next != NULL)
	{
	    if (*pidInst == reference_inst->instanceID && pfnCallback == reference_inst->callback)
	    {
		/* Check 1 - cannot change client-only mode if set via APPCMD_CLIENTONLY */

		if (reference_inst->clientOnly)
		{
		    if  ((reference_inst->CBFflags & CBF_FAIL_ALLSVRXACTIONS) != CBF_FAIL_ALLSVRXACTIONS)
		    {
			/* i.e. Was set to Client-only and through APPCMD_CLIENTONLY */

			if (!(afCmd & APPCMD_CLIENTONLY))
			{
			    ret = DMLERR_INVALIDPARAMETER;
			    goto theError;
			}
		    }
		}
		/* Check 2 - cannot change monitor modes */

		if (pInstance->monitor != reference_inst->monitor)
		{
		    ret = DMLERR_INVALIDPARAMETER;
		    goto theError;
		}

		/* Check 3 - trying to set Client-only via APPCMD when not set so previously */

		if ((afCmd&APPCMD_CLIENTONLY) && !reference_inst->clientOnly)
		{
		    ret = DMLERR_INVALIDPARAMETER;
		    goto theError;
		}
		break;
	    }
	    reference_inst = reference_inst->next;
	}
	if (reference_inst->next == NULL)
	{
	    ret = DMLERR_INVALIDPARAMETER;
	    goto theError;
	}
	/* All checked - change relevant flags */

	reference_inst->CBFflags = pInstance->CBFflags;
	reference_inst->clientOnly = pInstance->clientOnly;
	reference_inst->monitorFlags = pInstance->monitorFlags;
	LeaveCriticalSection(&WDML_CritSect);
    }

    return DMLERR_NO_ERROR;
 theError:
    HeapFree(GetProcessHeap(), 0, pInstance);
    LeaveCriticalSection(&WDML_CritSect);
    return ret;
}

/******************************************************************************
 *            DdeInitializeA   (USER32.@)
 *
 * See DdeInitializeW.
 */
UINT WINAPI DdeInitializeA(LPDWORD pidInst, PFNCALLBACK pfnCallback,
			   DWORD afCmd, DWORD ulRes)
{
    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, FALSE, FALSE);
}

/******************************************************************************
 * DdeInitializeW [USER32.@]
 * Registers an application with the DDEML
 *
 * PARAMS
 *    pidInst     [I] Pointer to instance identifier
 *    pfnCallback [I] Pointer to callback function
 *    afCmd       [I] Set of command and filter flags
 *    ulRes       [I] Reserved
 *
 * RETURNS
 *    Success: DMLERR_NO_ERROR
 *    Failure: DMLERR_DLL_USAGE, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
 */
UINT WINAPI DdeInitializeW(LPDWORD pidInst, PFNCALLBACK pfnCallback,
			   DWORD afCmd, DWORD ulRes)
{
    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, TRUE, FALSE);
}

/*****************************************************************
 * DdeUninitialize [USER32.@]  Frees DDEML resources
 *
 * PARAMS
 *    idInst [I] Instance identifier
 *
 * RETURNS
 *    Success: TRUE
 *    Failure: FALSE
 */

BOOL WINAPI DdeUninitialize(DWORD idInst)
{
    /*  Stage one - check if we have a handle for this instance
     */
    WDML_INSTANCE*		pInstance;
    WDML_CONV*			pConv;
    WDML_CONV*			pConvNext;

    TRACE("(%ld)\n", idInst);

    EnterCriticalSection(&WDML_CritSect);

    /*  First check instance
     */
    pInstance = WDML_GetInstance(idInst);
    if (pInstance == NULL)
    {
	LeaveCriticalSection(&WDML_CritSect);
	/*
	 *	Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
	 */
	return FALSE;
    }

    /* first terminate all conversations client side
     * this shall close existing links...
     */
    for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv != NULL; pConv = pConvNext)
    {
	pConvNext = pConv->next;
	DdeDisconnect((HCONV)pConv);
    }
    if (pInstance->convs[WDML_CLIENT_SIDE])
	FIXME("still pending conversations\n");

    /* then unregister all known service names */
    DdeNameService(idInst, 0, 0, DNS_UNREGISTER);

    /* Free the nodes that were not freed by this instance
     * and remove the nodes from the list of HSZ nodes.
     */
    WDML_FreeAllHSZ(pInstance);

    DestroyWindow(pInstance->hwndEvent);

    /* OK now delete the instance handle itself */

    if (WDML_InstanceList == pInstance)
    {
	/* special case - the first/only entry */
	WDML_InstanceList = pInstance->next;
    }
    else
    {
	/* general case, remove entry */
	WDML_INSTANCE*	inst;

	for (inst = WDML_InstanceList; inst->next != pInstance; inst = inst->next);
	inst->next = pInstance->next;
    }
    /* leave crit sect and release the heap entry
     */
    HeapFree(GetProcessHeap(), 0, pInstance);
    LeaveCriticalSection(&WDML_CritSect);
    return TRUE;
}

/******************************************************************
 *		WDML_NotifyThreadExit
 *
 *
 */
void WDML_NotifyThreadDetach(void)
{
    WDML_INSTANCE*	pInstance;
    WDML_INSTANCE*	next;
    DWORD		tid = GetCurrentThreadId();

    EnterCriticalSection(&WDML_CritSect);
    for (pInstance = WDML_InstanceList; pInstance != NULL; pInstance = next)
    {
	next = pInstance->next;
	if (pInstance->threadID == tid)
	{
	    DdeUninitialize(pInstance->instanceID);
	}
    }
    LeaveCriticalSection(&WDML_CritSect);
}

/******************************************************************
 *		WDML_InvokeCallback
 *
 *
 */
HDDEDATA 	WDML_InvokeCallback(WDML_INSTANCE* pInstance, UINT uType, UINT uFmt, HCONV hConv,
				    HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
				    ULONG_PTR dwData1, ULONG_PTR dwData2)
{
    HDDEDATA	ret;

    if (pInstance == NULL)
	return NULL;
    TRACE("invoking CB%d[%p] (%x %x %p %p %p %p %lx %lx)\n",
	  pInstance->win16 ? 16 : 32, pInstance->callback, uType, uFmt,
	  hConv, hsz1, hsz2, hdata, dwData1, dwData2);
    ret = pInstance->callback(uType, uFmt, hConv, hsz1, hsz2, hdata, dwData1, dwData2);
    TRACE("done => %p\n", ret);
    return ret;
}

/*****************************************************************************
 *	WDML_GetInstance
 *
 *	generic routine to return a pointer to the relevant DDE_HANDLE_ENTRY
 *	for an instance Id, or NULL if the entry does not exist
 *
 */
WDML_INSTANCE*	WDML_GetInstance(DWORD instId)
{
    WDML_INSTANCE*	pInstance;

    for (pInstance = WDML_InstanceList; pInstance != NULL; pInstance = pInstance->next)
    {
	if (pInstance->instanceID == instId)
	{
	    if (GetCurrentThreadId() != pInstance->threadID)
	    {
		FIXME("Tried to get instance from wrong thread\n");
		continue;
	    }
	    return pInstance;
	}
    }
    TRACE("Instance entry missing\n");
    return NULL;
}

/******************************************************************
 *		WDML_GetInstanceFromWnd
 *
 *
 */
WDML_INSTANCE*	WDML_GetInstanceFromWnd(HWND hWnd)
{
    return (WDML_INSTANCE*)GetWindowLongPtrW(hWnd, GWL_WDML_INSTANCE);
}

/******************************************************************************
 * DdeGetLastError [USER32.@]  Gets most recent error code
 *
 * PARAMS
 *    idInst [I] Instance identifier
 *
 * RETURNS
 *    Last error code
 */
UINT WINAPI DdeGetLastError(DWORD idInst)
{
    DWORD		error_code;
    WDML_INSTANCE*	pInstance;

    EnterCriticalSection(&WDML_CritSect);

    /*  First check instance
     */
    pInstance = WDML_GetInstance(idInst);
    if  (pInstance == NULL)
    {
	error_code = DMLERR_INVALIDPARAMETER;
    }
    else
    {
	error_code = pInstance->lastError;
	pInstance->lastError = 0;
    }

    LeaveCriticalSection(&WDML_CritSect);
    return error_code;
}

/* ================================================================
 *
 * 			String management
 *
 * ================================================================ */


/******************************************************************
 *		WDML_FindNode
 *
 *
 */
static HSZNode*	WDML_FindNode(WDML_INSTANCE* pInstance, HSZ hsz)
{
    HSZNode*	pNode;

    if (pInstance == NULL) return NULL;

    for (pNode = pInstance->nodeList; pNode != NULL; pNode = pNode->next)
    {
	if (pNode->hsz == hsz) break;
    }
    if (!pNode) WARN("HSZ %p not found\n", hsz);
    return pNode;
}

/******************************************************************
 *		WDML_MakeAtomFromHsz
 *
 * Creates a global atom from an existing HSZ
 * Generally used before sending an HSZ as an atom to a remote app
 */
ATOM	WDML_MakeAtomFromHsz(HSZ hsz)
{
    WCHAR nameBuffer[MAX_BUFFER_LEN];

    if (GetAtomNameW(HSZ2ATOM(hsz), nameBuffer, MAX_BUFFER_LEN))
	return GlobalAddAtomW(nameBuffer);
    WARN("HSZ %p not found\n", hsz);
    return 0;
}

/******************************************************************
 *		WDML_MakeHszFromAtom
 *
 * Creates a HSZ from an existing global atom
 * Generally used while receiving a global atom and transforming it
 * into an HSZ
 */
HSZ	WDML_MakeHszFromAtom(WDML_INSTANCE* pInstance, ATOM atom)
{
    WCHAR nameBuffer[MAX_BUFFER_LEN];

    if (!atom) return NULL;

    if (GlobalGetAtomNameW(atom, nameBuffer, MAX_BUFFER_LEN))
    {
	TRACE("%x => %s\n", atom, debugstr_w(nameBuffer));
	return DdeCreateStringHandleW(pInstance->instanceID, nameBuffer, CP_WINUNICODE);
    }
    WARN("ATOM 0x%x not found\n", atom);
    return 0;
}

/******************************************************************
 *		WDML_IncHSZ
 *
 *
 */
BOOL WDML_IncHSZ(WDML_INSTANCE* pInstance, HSZ hsz)
{
    HSZNode*	pNode;

    pNode = WDML_FindNode(pInstance, hsz);
    if (!pNode) return FALSE;

    pNode->refCount++;
    return TRUE;
}

/******************************************************************************
 *           WDML_DecHSZ    (INTERNAL)
 *
 * Decrease the ref count of an HSZ. If it reaches 0, the node is removed from the list
 * of HSZ nodes
 * Returns -1 is the HSZ isn't found, otherwise it's the current (after --) of the ref count
 */
BOOL WDML_DecHSZ(WDML_INSTANCE* pInstance, HSZ hsz)
{
    HSZNode* 	pPrev = NULL;
    HSZNode* 	pCurrent;

    for (pCurrent = pInstance->nodeList; pCurrent != NULL; pCurrent = (pPrev = pCurrent)->next)
    {
	/* If we found the node we were looking for and its ref count is one,
	 * we can remove it
	 */
	if (pCurrent->hsz == hsz)
	{
	    if (--pCurrent->refCount == 0)
	    {
		if (pCurrent == pInstance->nodeList)
		{
		    pInstance->nodeList = pCurrent->next;
		}
		else
		{
		    pPrev->next = pCurrent->next;
		}
		HeapFree(GetProcessHeap(), 0, pCurrent);
		DeleteAtom(HSZ2ATOM(hsz));
	    }
	    return TRUE;
	}
    }
    WARN("HSZ %p not found\n", hsz);

    return FALSE;
}

/******************************************************************************
 *            WDML_FreeAllHSZ    (INTERNAL)
 *
 * Frees up all the strings still allocated in the list and
 * remove all the nodes from the list of HSZ nodes.
 */
void WDML_FreeAllHSZ(WDML_INSTANCE* pInstance)
{
    /* Free any strings created in this instance.
     */
    while (pInstance->nodeList != NULL)
    {
	DdeFreeStringHandle(pInstance->instanceID, pInstance->nodeList->hsz);
    }
}

/******************************************************************************
 *            InsertHSZNode    (INTERNAL)
 *
 * Insert a node to the head of the list.
 */
static void WDML_InsertHSZNode(WDML_INSTANCE* pInstance, HSZ hsz)
{
    if (hsz != 0)
    {
	HSZNode* pNew = NULL;
	/* Create a new node for this HSZ.
	 */
	pNew = (HSZNode*)HeapAlloc(GetProcessHeap(), 0, sizeof(HSZNode));
	if (pNew != NULL)
	{
	    pNew->hsz      = hsz;
	    pNew->next     = pInstance->nodeList;
	    pNew->refCount = 1;
	    pInstance->nodeList = pNew;
	}
	else
	{
	    ERR("Primary HSZ Node allocation failed - out of memory\n");
	}
    }
}

/******************************************************************
 *		WDML_QueryString
 *
 *
 */
static int	WDML_QueryString(WDML_INSTANCE* pInstance, HSZ hsz, LPVOID ptr, DWORD cchMax,
				 int codepage)
{
    WCHAR	pString[MAX_BUFFER_LEN];
    int		ret;
    /* If psz is null, we have to return only the length
     * of the string.
     */
    if (ptr == NULL)

⌨️ 快捷键说明

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