📄 misc.c
字号:
wndclass.hCursor = 0; wndclass.hbrBackground = 0; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = WDML_szEventClass; wndclass.hIconSm = 0; RegisterClassExA(&wndclass); pInstance->hwndEvent = CreateWindowA(WDML_szEventClass, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); SetWindowLongA(pInstance->hwndEvent, GWL_WDML_INSTANCE, (DWORD)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_DLL_USAGE; 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_DLL_USAGE; goto theError; } } } /* Check 2 - cannot change monitor modes */ if (pInstance->monitor != reference_inst->monitor) { ret = DMLERR_DLL_USAGE; 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_DLL_USAGE; goto theError; } break; } reference_inst = reference_inst->next; } if (reference_inst->next == NULL) { /* Crazy situation - trying to re-initialize something that has not beeen initialized !! * * Manual does not say what we do, cannot return DMLERR_NOT_INITIALIZED so what ? */ 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.@) */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, DWORD dwData1, DWORD 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); if (pInstance->win16) { ret = WDML_InvokeCallback16(pInstance->callback, uType, uFmt, hConv, hsz1, hsz2, hdata, dwData1, dwData2); } else { 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*)GetWindowLongA(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; FIXME("(%ld): error reporting is weakly implemented\n", idInst); EnterCriticalSection(&WDML_CritSect); /* First check instance */ pInstance = WDML_GetInstance(idInst); if (pInstance == NULL) { error_code = DMLERR_DLL_NOT_INITIALIZED; } 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -