ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ddeserver.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.