Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenddeserver.c
Go to the documentation of this file.
00001 /* 00002 * DDEML library 00003 * 00004 * Copyright 1997 Alexandre Julliard 00005 * Copyright 1997 Len White 00006 * Copyright 1999 Keith Matthews 00007 * Copyright 2000 Corel 00008 * Copyright 2001 Eric Pouech 00009 * Copyright 2003, 2004, 2005 Dmitry Timoshkov 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2.1 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this library; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00024 */ 00025 00026 #include <user32.h> 00027 00028 #include <wine/debug.h> 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(ddeml); 00031 00032 static const WCHAR szServerNameClass[] = {'D','d','e','S','e','r','v','e','r','N','a','m','e',0}; 00033 const char WDML_szServerConvClassA[] = "DdeServerConvAnsi"; 00034 const WCHAR WDML_szServerConvClassW[] = {'D','d','e','S','e','r','v','e','r','C','o','n','v','U','n','i','c','o','d','e',0}; 00035 00036 static LRESULT CALLBACK WDML_ServerNameProc(HWND, UINT, WPARAM, LPARAM); 00037 static LRESULT CALLBACK WDML_ServerConvProc(HWND, UINT, WPARAM, LPARAM); 00038 00039 /****************************************************************************** 00040 * DdePostAdvise [USER32.@] Send transaction to DDE callback function. 00041 * 00042 * PARAMS 00043 * idInst [I] Instance identifier 00044 * hszTopic [I] Handle to topic name string 00045 * hszItem [I] Handle to item name string 00046 * 00047 * RETURNS 00048 * Success: TRUE 00049 * Failure: FALSE 00050 */ 00051 BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem) 00052 { 00053 WDML_INSTANCE* pInstance = NULL; 00054 WDML_LINK* pLink = NULL; 00055 HDDEDATA hDdeData = 0; 00056 HGLOBAL hItemData = 0; 00057 WDML_CONV* pConv = NULL; 00058 ATOM atom = 0; 00059 UINT count; 00060 00061 TRACE("(%d,%p,%p)\n", idInst, hszTopic, hszItem); 00062 00063 pInstance = WDML_GetInstance(idInst); 00064 00065 if (pInstance == NULL || pInstance->links == NULL) 00066 return FALSE; 00067 00068 atom = WDML_MakeAtomFromHsz(hszItem); 00069 if (!atom) return FALSE; 00070 00071 /* first compute the number of links which will trigger a message */ 00072 count = 0; 00073 for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) 00074 { 00075 if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) 00076 { 00077 count++; 00078 } 00079 } 00080 if (count >= CADV_LATEACK) 00081 { 00082 FIXME("too high value for count\n"); 00083 count &= 0xFFFF; 00084 } 00085 00086 for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) 00087 { 00088 if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) 00089 { 00090 hDdeData = WDML_InvokeCallback(pInstance, XTYP_ADVREQ, pLink->uFmt, pLink->hConv, 00091 hszTopic, hszItem, 0, --count, 0); 00092 00093 if (hDdeData == CBR_BLOCK) 00094 { 00095 /* MS doc is not consistent here */ 00096 FIXME("CBR_BLOCK returned for ADVREQ\n"); 00097 continue; 00098 } 00099 if (hDdeData) 00100 { 00101 if (pLink->transactionType & XTYPF_NODATA) 00102 { 00103 TRACE("no data\n"); 00104 hItemData = 0; 00105 } 00106 else 00107 { 00108 TRACE("with data\n"); 00109 00110 hItemData = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE); 00111 } 00112 00113 pConv = WDML_GetConv(pLink->hConv, TRUE); 00114 00115 if (pConv == NULL) 00116 { 00117 if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); 00118 goto theError; 00119 } 00120 00121 if (!PostMessageW(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, 00122 PackDDElParam(WM_DDE_DATA, (UINT_PTR)hItemData, atom))) 00123 { 00124 ERR("post message failed\n"); 00125 pConv->wStatus &= ~ST_CONNECTED; 00126 pConv->instance->lastError = DMLERR_POSTMSG_FAILED; 00127 if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); 00128 GlobalFree(hItemData); 00129 goto theError; 00130 } 00131 if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); 00132 } 00133 } 00134 } 00135 return TRUE; 00136 00137 theError: 00138 if (atom) GlobalDeleteAtom(atom); 00139 return FALSE; 00140 } 00141 00142 00143 /****************************************************************************** 00144 * DdeNameService [USER32.@] {Un}registers service name of DDE server 00145 * 00146 * PARAMS 00147 * idInst [I] Instance identifier 00148 * hsz1 [I] Handle to service name string 00149 * hsz2 [I] Reserved 00150 * afCmd [I] Service name flags 00151 * 00152 * RETURNS 00153 * Success: Non-zero 00154 * Failure: 0 00155 */ 00156 HDDEDATA WINAPI DdeNameService(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT afCmd) 00157 { 00158 WDML_SERVER* pServer; 00159 WDML_INSTANCE* pInstance; 00160 HWND hwndServer; 00161 WNDCLASSEXW wndclass; 00162 00163 TRACE("(%d,%p,%p,%x)\n", idInst, hsz1, hsz2, afCmd); 00164 00165 /* First check instance 00166 */ 00167 pInstance = WDML_GetInstance(idInst); 00168 if (pInstance == NULL) 00169 { 00170 TRACE("Instance not found as initialised\n"); 00171 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */ 00172 return NULL; 00173 } 00174 00175 if (hsz2 != 0L) 00176 { 00177 /* Illegal, reserved parameter 00178 */ 00179 pInstance->lastError = DMLERR_INVALIDPARAMETER; 00180 WARN("Reserved parameter no-zero !!\n"); 00181 return NULL; 00182 } 00183 if (hsz1 == 0 && !(afCmd & DNS_UNREGISTER)) 00184 { 00185 /* don't know if we should check this but it makes sense 00186 * why supply REGISTER or filter flags if de-registering all 00187 */ 00188 TRACE("General unregister unexpected flags\n"); 00189 pInstance->lastError = DMLERR_INVALIDPARAMETER; 00190 return NULL; 00191 } 00192 00193 switch (afCmd & (DNS_REGISTER | DNS_UNREGISTER)) 00194 { 00195 case DNS_REGISTER: 00196 pServer = WDML_FindServer(pInstance, hsz1, 0); 00197 if (pServer) 00198 { 00199 ERR("Trying to register already registered service!\n"); 00200 pInstance->lastError = DMLERR_DLL_USAGE; 00201 return NULL; 00202 } 00203 00204 TRACE("Adding service name\n"); 00205 00206 WDML_IncHSZ(pInstance, hsz1); 00207 00208 pServer = WDML_AddServer(pInstance, hsz1, 0); 00209 00210 WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_REGISTER, 00211 pServer->atomService, pServer->atomServiceSpec); 00212 00213 wndclass.cbSize = sizeof(wndclass); 00214 wndclass.style = 0; 00215 wndclass.lpfnWndProc = WDML_ServerNameProc; 00216 wndclass.cbClsExtra = 0; 00217 wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR); 00218 wndclass.hInstance = 0; 00219 wndclass.hIcon = 0; 00220 wndclass.hCursor = 0; 00221 wndclass.hbrBackground = 0; 00222 wndclass.lpszMenuName = NULL; 00223 wndclass.lpszClassName = szServerNameClass; 00224 wndclass.hIconSm = 0; 00225 00226 RegisterClassExW(&wndclass); 00227 00228 hwndServer = CreateWindowW(szServerNameClass, NULL, 00229 WS_POPUP, 0, 0, 0, 0, 00230 0, 0, 0, 0); 00231 00232 SetWindowLongPtrW(hwndServer, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance); 00233 SetWindowLongPtrW(hwndServer, GWL_WDML_SERVER, (ULONG_PTR)pServer); 00234 TRACE("Created nameServer=%p for instance=%08x\n", hwndServer, idInst); 00235 00236 pServer->hwndServer = hwndServer; 00237 break; 00238 00239 case DNS_UNREGISTER: 00240 if (hsz1 == 0L) 00241 { 00242 /* General unregister situation 00243 * terminate all server side pending conversations 00244 */ 00245 while (pInstance->servers) 00246 WDML_RemoveServer(pInstance, pInstance->servers->hszService, 0); 00247 pInstance->servers = NULL; 00248 TRACE("General de-register - finished\n"); 00249 } 00250 else 00251 { 00252 WDML_RemoveServer(pInstance, hsz1, 0L); 00253 } 00254 break; 00255 } 00256 00257 if (afCmd & (DNS_FILTERON | DNS_FILTEROFF)) 00258 { 00259 /* Set filter flags on to hold notifications of connection 00260 */ 00261 pServer = WDML_FindServer(pInstance, hsz1, 0); 00262 if (!pServer) 00263 { 00264 /* trying to filter where no service names !! 00265 */ 00266 pInstance->lastError = DMLERR_DLL_USAGE; 00267 return NULL; 00268 } 00269 else 00270 { 00271 pServer->filterOn = (afCmd & DNS_FILTERON) != 0; 00272 } 00273 } 00274 return (HDDEDATA)TRUE; 00275 } 00276 00277 /****************************************************************** 00278 * WDML_CreateServerConv 00279 * 00280 * 00281 */ 00282 static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClient, 00283 HWND hwndServerName, HSZ hszApp, HSZ hszTopic) 00284 { 00285 HWND hwndServerConv; 00286 WDML_CONV* pConv; 00287 00288 if (pInstance->unicode) 00289 { 00290 WNDCLASSEXW wndclass; 00291 00292 wndclass.cbSize = sizeof(wndclass); 00293 wndclass.style = 0; 00294 wndclass.lpfnWndProc = WDML_ServerConvProc; 00295 wndclass.cbClsExtra = 0; 00296 wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR); 00297 wndclass.hInstance = 0; 00298 wndclass.hIcon = 0; 00299 wndclass.hCursor = 0; 00300 wndclass.hbrBackground = 0; 00301 wndclass.lpszMenuName = NULL; 00302 wndclass.lpszClassName = WDML_szServerConvClassW; 00303 wndclass.hIconSm = 0; 00304 00305 RegisterClassExW(&wndclass); 00306 00307 hwndServerConv = CreateWindowW(WDML_szServerConvClassW, 0, 00308 WS_CHILD, 0, 0, 0, 0, 00309 hwndServerName, 0, 0, 0); 00310 } 00311 else 00312 { 00313 WNDCLASSEXA wndclass; 00314 00315 wndclass.cbSize = sizeof(wndclass); 00316 wndclass.style = 0; 00317 wndclass.lpfnWndProc = WDML_ServerConvProc; 00318 wndclass.cbClsExtra = 0; 00319 wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR); 00320 wndclass.hInstance = 0; 00321 wndclass.hIcon = 0; 00322 wndclass.hCursor = 0; 00323 wndclass.hbrBackground = 0; 00324 wndclass.lpszMenuName = NULL; 00325 wndclass.lpszClassName = WDML_szServerConvClassA; 00326 wndclass.hIconSm = 0; 00327 00328 RegisterClassExA(&wndclass); 00329 00330 hwndServerConv = CreateWindowA(WDML_szServerConvClassA, 0, 00331 WS_CHILD, 0, 0, 0, 0, 00332 hwndServerName, 0, 0, 0); 00333 } 00334 00335 TRACE("Created convServer=%p (nameServer=%p) for instance=%08x unicode=%d\n", 00336 hwndServerConv, hwndServerName, pInstance->instanceID, pInstance->unicode); 00337 00338 pConv = WDML_AddConv(pInstance, WDML_SERVER_SIDE, hszApp, hszTopic, 00339 hwndClient, hwndServerConv); 00340 if (pConv) 00341 { 00342 SetWindowLongPtrW(hwndServerConv, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance); 00343 SetWindowLongPtrW(hwndServerConv, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv); 00344 00345 /* this should be the only place using SendMessage for WM_DDE_ACK */ 00346 /* note: sent messages shall not use packing */ 00347 SendMessageW(hwndClient, WM_DDE_ACK, (WPARAM)hwndServerConv, 00348 MAKELPARAM(WDML_MakeAtomFromHsz(hszApp), WDML_MakeAtomFromHsz(hszTopic))); 00349 /* we assume we're connected since we've sent an answer... 00350 * I'm not sure what we can do... it doesn't look like the return value 00351 * of SendMessage is used... sigh... 00352 */ 00353 pConv->wStatus |= ST_CONNECTED; 00354 } 00355 else 00356 { 00357 DestroyWindow(hwndServerConv); 00358 } 00359 return pConv; 00360 } 00361 00362 /****************************************************************** 00363 * WDML_ServerNameProc 00364 * 00365 * 00366 */ 00367 static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) 00368 { 00369 HWND hwndClient; 00370 HSZ hszApp, hszTop; 00371 HDDEDATA hDdeData = 0; 00372 WDML_INSTANCE* pInstance; 00373 UINT_PTR uiLo, uiHi; 00374 00375 switch (iMsg) 00376 { 00377 case WM_DDE_INITIATE: 00378 00379 /* wParam -- sending window handle 00380 LOWORD(lParam) -- application atom 00381 HIWORD(lParam) -- topic atom */ 00382 00383 TRACE("WM_DDE_INITIATE message received!\n"); 00384 hwndClient = (HWND)wParam; 00385 00386 pInstance = WDML_GetInstanceFromWnd(hwndServer); 00387 TRACE("idInst=%d, threadID=0x%x\n", pInstance->instanceID, GetCurrentThreadId()); 00388 if (!pInstance) return 0; 00389 00390 /* don't free DDEParams, since this is a broadcast */ 00391 UnpackDDElParam(WM_DDE_INITIATE, lParam, &uiLo, &uiHi); 00392 00393 hszApp = WDML_MakeHszFromAtom(pInstance, uiLo); 00394 hszTop = WDML_MakeHszFromAtom(pInstance, uiHi); 00395 00396 if (!(pInstance->CBFflags & CBF_FAIL_CONNECTIONS)) 00397 { 00398 BOOL self = FALSE; 00399 CONVCONTEXT cc; 00400 CONVCONTEXT* pcc = NULL; 00401 WDML_CONV* pConv; 00402 char buf[256]; 00403 00404 if (GetWindowThreadProcessId(hwndClient, NULL) == GetWindowThreadProcessId(hwndServer, NULL) && 00405 WDML_GetInstanceFromWnd(hwndClient) == WDML_GetInstanceFromWnd(hwndServer)) 00406 { 00407 self = TRUE; 00408 } 00409 /* FIXME: so far, we don't grab distant convcontext, so only check if remote is 00410 * handled under DDEML, and if so build a default context 00411 */ 00412 if ((GetClassNameA(hwndClient, buf, sizeof(buf)) && 00413 lstrcmpiA(buf, WDML_szClientConvClassA) == 0) || 00414 (GetClassNameW(hwndClient, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) && 00415 lstrcmpiW((LPWSTR)buf, WDML_szClientConvClassW) == 0)) 00416 { 00417 pcc = &cc; 00418 memset(pcc, 0, sizeof(*pcc)); 00419 pcc->cb = sizeof(*pcc); 00420 pcc->iCodePage = IsWindowUnicode(hwndClient) ? CP_WINUNICODE : CP_WINANSI; 00421 } 00422 if ((pInstance->CBFflags & CBF_FAIL_SELFCONNECTIONS) && self) 00423 { 00424 TRACE("Don't do self connection as requested\n"); 00425 } 00426 else if (hszApp && hszTop) 00427 { 00428 WDML_SERVER* pServer = (WDML_SERVER*)GetWindowLongPtrW(hwndServer, GWL_WDML_SERVER); 00429 00430 /* check filters for name service */ 00431 if (!pServer->filterOn || DdeCmpStringHandles(pServer->hszService, hszApp) == 0) 00432 { 00433 /* pass on to the callback */ 00434 hDdeData = WDML_InvokeCallback(pInstance, XTYP_CONNECT, 00435 0, 0, hszTop, hszApp, 0, (ULONG_PTR)pcc, self); 00436 if ((ULONG_PTR)hDdeData) 00437 { 00438 pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, 00439 hszApp, hszTop); 00440 if (pConv) 00441 { 00442 if (pcc) pConv->wStatus |= ST_ISLOCAL; 00443 WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv, 00444 hszTop, hszApp, 0, (ULONG_PTR)pcc, self); 00445 } 00446 } 00447 } 00448 } 00449 else if (pInstance->servers) 00450 { 00451 /* pass on to the callback */ 00452 hDdeData = WDML_InvokeCallback(pInstance, XTYP_WILDCONNECT, 00453 0, 0, hszTop, hszApp, 0, (ULONG_PTR)pcc, self); 00454 00455 if (hDdeData == CBR_BLOCK) 00456 { 00457 /* MS doc is not consistent here */ 00458 FIXME("CBR_BLOCK returned for WILDCONNECT\n"); 00459 } 00460 else if ((ULONG_PTR)hDdeData != 0) 00461 { 00462 HSZPAIR* hszp; 00463 00464 hszp = (HSZPAIR*)DdeAccessData(hDdeData, NULL); 00465 if (hszp) 00466 { 00467 int i; 00468 for (i = 0; hszp[i].hszSvc && hszp[i].hszTopic; i++) 00469 { 00470 pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, 00471 hszp[i].hszSvc, hszp[i].hszTopic); 00472 if (pConv) 00473 { 00474 if (pcc) pConv->wStatus |= ST_ISLOCAL; 00475 WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv, 00476 hszp[i].hszTopic, hszp[i].hszSvc, 0, (ULONG_PTR)pcc, self); 00477 } 00478 } 00479 DdeUnaccessData(hDdeData); 00480 } 00481 if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); 00482 } 00483 } 00484 } 00485 00486 return 0; 00487 00488 case WM_DDE_REQUEST: 00489 FIXME("WM_DDE_REQUEST message received!\n"); 00490 return 0; 00491 case WM_DDE_ADVISE: 00492 FIXME("WM_DDE_ADVISE message received!\n"); 00493 return 0; 00494 case WM_DDE_UNADVISE: 00495 FIXME("WM_DDE_UNADVISE message received!\n"); 00496 return 0; 00497 case WM_DDE_EXECUTE: 00498 FIXME("WM_DDE_EXECUTE message received!\n"); 00499 return 0; 00500 case WM_DDE_POKE: 00501 FIXME("WM_DDE_POKE message received!\n"); 00502 return 0; 00503 case WM_DDE_TERMINATE: 00504 FIXME("WM_DDE_TERMINATE message received!\n"); 00505 return 0; 00506 default: 00507 break; 00508 } 00509 00510 return DefWindowProcW(hwndServer, iMsg, wParam, lParam); 00511 } 00512 00513 /****************************************************************** 00514 * WDML_ServerQueueRequest 00515 * 00516 * 00517 */ 00518 static WDML_XACT* WDML_ServerQueueRequest(WDML_CONV* pConv, LPARAM lParam) 00519 { 00520 UINT_PTR uiLo, uiHi; 00521 WDML_XACT* pXAct; 00522 00523 UnpackDDElParam(WM_DDE_REQUEST, lParam, &uiLo, &uiHi); 00524 00525 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_REQUEST, 00526 uiLo, WDML_MakeHszFromAtom(pConv->instance, uiHi)); 00527 if (pXAct) pXAct->atom = uiHi; 00528 return pXAct; 00529 } 00530 00531 /****************************************************************** 00532 * WDML_ServerHandleRequest 00533 * 00534 * 00535 */ 00536 static WDML_QUEUE_STATE WDML_ServerHandleRequest(WDML_CONV* pConv, WDML_XACT* pXAct) 00537 { 00538 HDDEDATA hDdeData = 0; 00539 BOOL fAck = TRUE; 00540 00541 if (!(pConv->instance->CBFflags & CBF_FAIL_REQUESTS)) 00542 { 00543 00544 hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_REQUEST, pXAct->wFmt, (HCONV)pConv, 00545 pConv->hszTopic, pXAct->hszItem, 0, 0, 0); 00546 } 00547 00548 switch ((ULONG_PTR)hDdeData) 00549 { 00550 case 0: 00551 TRACE("No data returned from the Callback\n"); 00552 fAck = FALSE; 00553 break; 00554 00555 case (ULONG_PTR)CBR_BLOCK: 00556 return WDML_QS_BLOCK; 00557 00558 default: 00559 { 00560 HGLOBAL hMem = WDML_DataHandle2Global(hDdeData, TRUE, FALSE, FALSE, FALSE); 00561 if (!PostMessageW(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, 00562 ReuseDDElParam(pXAct->lParam, WM_DDE_REQUEST, WM_DDE_DATA, 00563 (UINT_PTR)hMem, (UINT_PTR)pXAct->atom))) 00564 { 00565 pConv->instance->lastError = DMLERR_POSTMSG_FAILED; 00566 DdeFreeDataHandle(hDdeData); 00567 GlobalFree(hMem); 00568 fAck = FALSE; 00569 } 00570 } 00571 break; 00572 } 00573 00574 WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_REQUEST); 00575 00576 WDML_DecHSZ(pConv->instance, pXAct->hszItem); 00577 00578 return WDML_QS_HANDLED; 00579 } 00580 00581 /****************************************************************** 00582 * WDML_ServerQueueAdvise 00583 * 00584 * 00585 */ 00586 static WDML_XACT* WDML_ServerQueueAdvise(WDML_CONV* pConv, LPARAM lParam) 00587 { 00588 UINT_PTR uiLo, uiHi; 00589 WDML_XACT* pXAct; 00590 00591 /* XTYP_ADVSTART transaction: 00592 establish link and save link info to InstanceInfoTable */ 00593 00594 if (!UnpackDDElParam(WM_DDE_ADVISE, lParam, &uiLo, &uiHi)) 00595 return NULL; 00596 00597 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, 00598 0, WDML_MakeHszFromAtom(pConv->instance, uiHi)); 00599 if (pXAct) 00600 { 00601 pXAct->hMem = (HGLOBAL)uiLo; 00602 pXAct->atom = uiHi; 00603 } 00604 return pXAct; 00605 } 00606 00607 /****************************************************************** 00608 * WDML_ServerHandleAdvise 00609 * 00610 * 00611 */ 00612 static WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXAct) 00613 { 00614 UINT uType; 00615 WDML_LINK* pLink; 00616 DDEADVISE* pDdeAdvise; 00617 HDDEDATA hDdeData = 0; 00618 BOOL fAck = TRUE; 00619 00620 pDdeAdvise = GlobalLock(pXAct->hMem); 00621 uType = XTYP_ADVSTART | 00622 (pDdeAdvise->fDeferUpd ? XTYPF_NODATA : 0) | 00623 (pDdeAdvise->fAckReq ? XTYPF_ACKREQ : 0); 00624 00625 if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) 00626 { 00627 hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_ADVSTART, pDdeAdvise->cfFormat, 00628 (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); 00629 } 00630 00631 switch ((ULONG_PTR)hDdeData) 00632 { 00633 case 0: 00634 TRACE("No data returned from the Callback\n"); 00635 fAck = FALSE; 00636 break; 00637 00638 case (ULONG_PTR)CBR_BLOCK: 00639 return WDML_QS_BLOCK; 00640 00641 default: 00642 /* billx: first to see if the link is already created. */ 00643 pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, 00644 pXAct->hszItem, TRUE, pDdeAdvise->cfFormat); 00645 00646 if (pLink != NULL) 00647 { 00648 /* we found a link, and only need to modify it in case it changes */ 00649 pLink->transactionType = uType; 00650 } 00651 else 00652 { 00653 TRACE("Adding Link with hConv %p\n", pConv); 00654 WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, 00655 uType, pXAct->hszItem, pDdeAdvise->cfFormat); 00656 } 00657 break; 00658 } 00659 00660 GlobalUnlock(pXAct->hMem); 00661 if (fAck) 00662 { 00663 GlobalFree(pXAct->hMem); 00664 } 00665 pXAct->hMem = 0; 00666 00667 WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_ADVISE); 00668 00669 WDML_DecHSZ(pConv->instance, pXAct->hszItem); 00670 00671 return WDML_QS_HANDLED; 00672 } 00673 00674 /****************************************************************** 00675 * WDML_ServerQueueUnadvise 00676 * 00677 * 00678 */ 00679 static WDML_XACT* WDML_ServerQueueUnadvise(WDML_CONV* pConv, LPARAM lParam) 00680 { 00681 UINT_PTR uiLo, uiHi; 00682 WDML_XACT* pXAct; 00683 00684 UnpackDDElParam(WM_DDE_UNADVISE, lParam, &uiLo, &uiHi); 00685 00686 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_UNADVISE, 00687 uiLo, WDML_MakeHszFromAtom(pConv->instance, uiHi)); 00688 if (pXAct) pXAct->atom = uiHi; 00689 return pXAct; 00690 } 00691 00692 /****************************************************************** 00693 * WDML_ServerHandleUnadvise 00694 * 00695 * 00696 */ 00697 static WDML_QUEUE_STATE WDML_ServerHandleUnadvise(WDML_CONV* pConv, WDML_XACT* pXAct) 00698 { 00699 WDML_LINK* pLink; 00700 00701 if (pXAct->hszItem == NULL || pXAct->wFmt == 0) 00702 { 00703 ERR("Unsupported yet options (null item or clipboard format)\n"); 00704 return WDML_QS_ERROR; 00705 } 00706 00707 pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, 00708 pXAct->hszItem, TRUE, pXAct->wFmt); 00709 if (pLink == NULL) 00710 { 00711 ERR("Couln'd find link for %p, dropping request\n", pXAct->hszItem); 00712 FreeDDElParam(WM_DDE_UNADVISE, pXAct->lParam); 00713 return WDML_QS_ERROR; 00714 } 00715 00716 if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) 00717 { 00718 WDML_InvokeCallback(pConv->instance, XTYP_ADVSTOP, pXAct->wFmt, (HCONV)pConv, 00719 pConv->hszTopic, pXAct->hszItem, 0, 0, 0); 00720 } 00721 00722 WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, 00723 pXAct->hszItem, pXAct->wFmt); 00724 00725 /* send back ack */ 00726 WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, TRUE, pXAct->atom, 00727 pXAct->lParam, WM_DDE_UNADVISE); 00728 00729 WDML_DecHSZ(pConv->instance, pXAct->hszItem); 00730 00731 return WDML_QS_HANDLED; 00732 } 00733 00734 /****************************************************************** 00735 * WDML_QueueExecute 00736 * 00737 * 00738 */ 00739 static WDML_XACT* WDML_ServerQueueExecute(WDML_CONV* pConv, LPARAM lParam) 00740 { 00741 WDML_XACT* pXAct; 00742 00743 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_EXECUTE, 0, 0); 00744 if (pXAct) 00745 { 00746 pXAct->hMem = (HGLOBAL)lParam; 00747 } 00748 return pXAct; 00749 } 00750 00751 /****************************************************************** 00752 * WDML_ServerHandleExecute 00753 * 00754 * 00755 */ 00756 static WDML_QUEUE_STATE WDML_ServerHandleExecute(WDML_CONV* pConv, WDML_XACT* pXAct) 00757 { 00758 HDDEDATA hDdeData = DDE_FNOTPROCESSED; 00759 BOOL fAck = FALSE, fBusy = FALSE; 00760 00761 if (!(pConv->instance->CBFflags & CBF_FAIL_EXECUTES)) 00762 { 00763 LPVOID ptr = GlobalLock(pXAct->hMem); 00764 00765 if (ptr) 00766 { 00767 hDdeData = DdeCreateDataHandle(pConv->instance->instanceID, ptr, GlobalSize(pXAct->hMem), 00768 0, 0, CF_TEXT, 0); 00769 GlobalUnlock(pXAct->hMem); 00770 } 00771 hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_EXECUTE, 0, (HCONV)pConv, 00772 pConv->hszTopic, 0, hDdeData, 0L, 0L); 00773 } 00774 00775 switch ((ULONG_PTR)hDdeData) 00776 { 00777 case (ULONG_PTR)CBR_BLOCK: 00778 return WDML_QS_BLOCK; 00779 00780 case DDE_FACK: 00781 fAck = TRUE; 00782 break; 00783 case DDE_FBUSY: 00784 fBusy = TRUE; 00785 break; 00786 default: 00787 FIXME("Unsupported returned value %p\n", hDdeData); 00788 /* fall through */ 00789 case DDE_FNOTPROCESSED: 00790 break; 00791 } 00792 WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, fBusy, fAck, (UINT_PTR)pXAct->hMem, 0, 0); 00793 00794 return WDML_QS_HANDLED; 00795 } 00796 00797 /****************************************************************** 00798 * WDML_ServerQueuePoke 00799 * 00800 * 00801 */ 00802 static WDML_XACT* WDML_ServerQueuePoke(WDML_CONV* pConv, LPARAM lParam) 00803 { 00804 UINT_PTR uiLo, uiHi; 00805 WDML_XACT* pXAct; 00806 00807 UnpackDDElParam(WM_DDE_POKE, lParam, &uiLo, &uiHi); 00808 00809 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_POKE, 00810 0, WDML_MakeHszFromAtom(pConv->instance, uiHi)); 00811 if (pXAct) 00812 { 00813 pXAct->atom = uiHi; 00814 pXAct->hMem = (HGLOBAL)uiLo; 00815 } 00816 return pXAct; 00817 } 00818 00819 /****************************************************************** 00820 * WDML_ServerHandlePoke 00821 * 00822 * 00823 */ 00824 static WDML_QUEUE_STATE WDML_ServerHandlePoke(WDML_CONV* pConv, WDML_XACT* pXAct) 00825 { 00826 DDEPOKE* pDdePoke; 00827 HDDEDATA hDdeData; 00828 BOOL fBusy = FALSE, fAck = FALSE; 00829 00830 pDdePoke = GlobalLock(pXAct->hMem); 00831 if (!pDdePoke) 00832 { 00833 return WDML_QS_ERROR; 00834 } 00835 00836 if (!(pConv->instance->CBFflags & CBF_FAIL_POKES)) 00837 { 00838 hDdeData = DdeCreateDataHandle(pConv->instance->instanceID, pDdePoke->Value, 00839 GlobalSize(pXAct->hMem) - FIELD_OFFSET(DDEPOKE, Value), 00840 0, 0, pDdePoke->cfFormat, 0); 00841 if (hDdeData) 00842 { 00843 HDDEDATA hDdeDataOut; 00844 00845 hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_POKE, pDdePoke->cfFormat, 00846 (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 00847 hDdeData, 0, 0); 00848 switch ((ULONG_PTR)hDdeDataOut) 00849 { 00850 case DDE_FACK: 00851 fAck = TRUE; 00852 break; 00853 case DDE_FBUSY: 00854 fBusy = TRUE; 00855 break; 00856 default: 00857 FIXME("Unsupported returned value %p\n", hDdeDataOut); 00858 /* fal through */ 00859 case DDE_FNOTPROCESSED: 00860 break; 00861 } 00862 DdeFreeDataHandle(hDdeData); 00863 } 00864 } 00865 GlobalUnlock(pXAct->hMem); 00866 00867 if (!fAck) 00868 { 00869 GlobalFree(pXAct->hMem); 00870 } 00871 WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, fBusy, fAck, pXAct->atom, pXAct->lParam, WM_DDE_POKE); 00872 00873 WDML_DecHSZ(pConv->instance, pXAct->hszItem); 00874 00875 return WDML_QS_HANDLED; 00876 } 00877 00878 /****************************************************************** 00879 * WDML_ServerQueueTerminate 00880 * 00881 * 00882 */ 00883 static WDML_XACT* WDML_ServerQueueTerminate(WDML_CONV* pConv, LPARAM lParam) 00884 { 00885 WDML_XACT* pXAct; 00886 00887 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_TERMINATE, 0, 0); 00888 return pXAct; 00889 } 00890 00891 /****************************************************************** 00892 * WDML_ServerHandleTerminate 00893 * 00894 * 00895 */ 00896 static WDML_QUEUE_STATE WDML_ServerHandleTerminate(WDML_CONV* pConv, WDML_XACT* pXAct) 00897 { 00898 /* billx: two things to remove: the conv, and associated links. 00899 * Respond with another WM_DDE_TERMINATE iMsg. 00900 */ 00901 if (!(pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS)) 00902 { 00903 WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv, 0, 0, 00904 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0); 00905 } 00906 PostMessageW(pConv->hwndClient, WM_DDE_TERMINATE, (WPARAM)pConv->hwndServer, 0); 00907 WDML_RemoveConv(pConv, WDML_SERVER_SIDE); 00908 00909 return WDML_QS_HANDLED; 00910 } 00911 00912 /****************************************************************** 00913 * WDML_ServerHandle 00914 * 00915 * 00916 */ 00917 WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV* pConv, WDML_XACT* pXAct) 00918 { 00919 WDML_QUEUE_STATE qs = WDML_QS_ERROR; 00920 00921 switch (pXAct->ddeMsg) 00922 { 00923 case WM_DDE_INITIATE: 00924 FIXME("WM_DDE_INITIATE shouldn't be there!\n"); 00925 break; 00926 case WM_DDE_REQUEST: 00927 qs = WDML_ServerHandleRequest(pConv, pXAct); 00928 break; 00929 00930 case WM_DDE_ADVISE: 00931 qs = WDML_ServerHandleAdvise(pConv, pXAct); 00932 break; 00933 00934 case WM_DDE_UNADVISE: 00935 qs = WDML_ServerHandleUnadvise(pConv, pXAct); 00936 break; 00937 00938 case WM_DDE_EXECUTE: 00939 qs = WDML_ServerHandleExecute(pConv, pXAct); 00940 break; 00941 00942 case WM_DDE_POKE: 00943 qs = WDML_ServerHandlePoke(pConv, pXAct); 00944 break; 00945 00946 case WM_DDE_TERMINATE: 00947 qs = WDML_ServerHandleTerminate(pConv, pXAct); 00948 break; 00949 00950 case WM_DDE_ACK: 00951 WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); 00952 break; 00953 00954 default: 00955 FIXME("Unsupported message %d\n", pXAct->ddeMsg); 00956 } 00957 return qs; 00958 } 00959 00960 /****************************************************************** 00961 * WDML_ServerConvProc 00962 * 00963 * 00964 */ 00965 static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) 00966 { 00967 WDML_INSTANCE* pInstance; 00968 WDML_CONV* pConv; 00969 WDML_XACT* pXAct = NULL; 00970 00971 TRACE("%p %04x %08lx %08lx\n", hwndServer, iMsg, wParam, lParam); 00972 00973 if (iMsg == WM_DESTROY) 00974 { 00975 pConv = WDML_GetConvFromWnd(hwndServer); 00976 if (pConv && !(pConv->wStatus & ST_TERMINATED)) 00977 { 00978 WDML_ServerHandleTerminate(pConv, NULL); 00979 } 00980 } 00981 if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST) 00982 { 00983 return IsWindowUnicode(hwndServer) ? DefWindowProcW(hwndServer, iMsg, wParam, lParam) : 00984 DefWindowProcA(hwndServer, iMsg, wParam, lParam); 00985 } 00986 00987 pInstance = WDML_GetInstanceFromWnd(hwndServer); 00988 pConv = WDML_GetConvFromWnd(hwndServer); 00989 00990 if (!pConv) 00991 { 00992 ERR("Got a message (%x) on a not known conversation, dropping request\n", iMsg); 00993 return 0; 00994 } 00995 if (pConv->hwndClient != WIN_GetFullHandle( (HWND)wParam ) || pConv->hwndServer != hwndServer) 00996 { 00997 ERR("mismatch between C/S windows and conversation\n"); 00998 return 0; 00999 } 01000 if (pConv->instance != pInstance || pConv->instance == NULL) 01001 { 01002 ERR("mismatch in instances\n"); 01003 return 0; 01004 } 01005 01006 switch (iMsg) 01007 { 01008 case WM_DDE_INITIATE: 01009 FIXME("WM_DDE_INITIATE message received!\n"); 01010 break; 01011 01012 case WM_DDE_REQUEST: 01013 pXAct = WDML_ServerQueueRequest(pConv, lParam); 01014 break; 01015 01016 case WM_DDE_ADVISE: 01017 pXAct = WDML_ServerQueueAdvise(pConv, lParam); 01018 break; 01019 01020 case WM_DDE_UNADVISE: 01021 pXAct = WDML_ServerQueueUnadvise(pConv, lParam); 01022 break; 01023 01024 case WM_DDE_EXECUTE: 01025 pXAct = WDML_ServerQueueExecute(pConv, lParam); 01026 break; 01027 01028 case WM_DDE_POKE: 01029 pXAct = WDML_ServerQueuePoke(pConv, lParam); 01030 break; 01031 01032 case WM_DDE_TERMINATE: 01033 pXAct = WDML_ServerQueueTerminate(pConv, lParam); 01034 break; 01035 01036 case WM_DDE_ACK: 01037 WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); 01038 break; 01039 01040 default: 01041 FIXME("Unsupported message %x\n", iMsg); 01042 break; 01043 } 01044 01045 if (pXAct) 01046 { 01047 pXAct->lParam = lParam; 01048 01049 if ((pConv->wStatus & ST_BLOCKED) || WDML_ServerHandle(pConv, pXAct) == WDML_QS_BLOCK) 01050 { 01051 TRACE("Transactions are blocked, add to the queue and exit\n"); 01052 WDML_QueueTransaction(pConv, pXAct); 01053 } 01054 else 01055 { 01056 WDML_FreeTransaction(pInstance, pXAct, TRUE); 01057 } 01058 } 01059 else 01060 pConv->instance->lastError = DMLERR_MEMORY_ERROR; 01061 01062 return 0; 01063 } Generated on Sat May 26 2012 04:37:31 for ReactOS by
1.7.6.1
|