/****************************************************************************** * DdeNameService [USER32.@] {Un}registers service name of DDE server * * PARAMS * idInst [I] Instance identifier * hsz1 [I] Handle to service name string * hsz2 [I] Reserved * afCmd [I] Service name flags * * RETURNS * Success: Non-zero * Failure: 0 */ HDDEDATA WINAPI DdeNameService(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT afCmd) { WDML_SERVER* pServer; WDML_INSTANCE* pInstance; HDDEDATA hDdeData; HWND hwndServer; WNDCLASSEXA wndclass; hDdeData = (HDDEDATA)NULL; TRACE("(%ld,0x%x,0x%x,%d)\n", idInst, hsz1, hsz2, afCmd); EnterCriticalSection(&WDML_CritSect); /* First check instance */ pInstance = WDML_GetInstance(idInst); if (pInstance == NULL) { TRACE("Instance not found as initialised\n"); /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */ goto theError; } if (hsz2 != 0L) { /* Illegal, reserved parameter */ pInstance->lastError = DMLERR_INVALIDPARAMETER; WARN("Reserved parameter no-zero !!\n"); goto theError; } if (hsz1 == 0 && afCmd != DNS_UNREGISTER) { /* don't know if we should check this but it makes sense * why supply REGISTER or filter flags if de-registering all */ TRACE("General unregister unexpected flags\n"); pInstance->lastError = DMLERR_INVALIDPARAMETER; goto theError; } switch (afCmd) { case DNS_REGISTER: pServer = WDML_FindServer(pInstance, hsz1, 0); if (pServer) { ERR("Trying to register already registered service!\n"); pInstance->lastError = DMLERR_DLL_USAGE; goto theError; } TRACE("Adding service name\n"); WDML_IncHSZ(pInstance, hsz1); pServer = WDML_AddServer(pInstance, hsz1, 0); WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_REGISTER, pServer->atomService, pServer->atomServiceSpec); wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = WDML_ServerNameProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 2 * sizeof(DWORD); wndclass.hInstance = 0; wndclass.hIcon = 0; wndclass.hCursor = 0; wndclass.hbrBackground = 0; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szServerNameClassA; wndclass.hIconSm = 0; RegisterClassExA(&wndclass); LeaveCriticalSection(&WDML_CritSect); hwndServer = CreateWindowA(szServerNameClassA, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); EnterCriticalSection(&WDML_CritSect); SetWindowLongA(hwndServer, GWL_WDML_INSTANCE, (DWORD)pInstance); SetWindowLongA(hwndServer, GWL_WDML_SERVER, (DWORD)pServer); TRACE("Created nameServer=%04x for instance=%08lx\n", hwndServer, idInst); pServer->hwndServer = hwndServer; break; case DNS_UNREGISTER: if (hsz1 == 0L) { /* General unregister situation * terminate all server side pending conversations */ while (pInstance->servers) WDML_RemoveServer(pInstance, pInstance->servers->hszService, 0); pInstance->servers = NULL; TRACE("General de-register - finished\n"); } else { WDML_RemoveServer(pInstance, hsz1, 0L); } break; case DNS_FILTERON: case DNS_FILTEROFF: /* Set filter flags on to hold notifications of connection */ pServer = WDML_FindServer(pInstance, hsz1, 0); if (!pServer) { /* trying to filter where no service names !! */ pInstance->lastError = DMLERR_DLL_USAGE; goto theError; } else { pServer->filterOn = (afCmd == DNS_FILTERON); } break; } LeaveCriticalSection(&WDML_CritSect); return (HDDEDATA)TRUE; theError: LeaveCriticalSection(&WDML_CritSect); return FALSE; }
/****************************************************************** * 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; TRACE("%p %04x %08x %08lx\n", hwnd, iMsg, wParam , lParam); 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); PostMessageW((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); SetWindowLongPtrW(hwnd, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv); pConv->wStatus |= ST_CONNECTED; pConv->wConvst = XST_INIT1; /* check if server is handled by DDEML */ if ((GetClassNameA((HWND)wParam, buf, sizeof(buf)) && lstrcmpiA(buf, WDML_szServerConvClassA) == 0) || (GetClassNameW((HWND)wParam, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) && lstrcmpiW((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, NULL); } LeaveCriticalSection(&WDML_CritSect); return 0; } return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, iMsg, wParam, lParam) : DefWindowProcA(hwnd, iMsg, wParam, lParam); }