コード例 #1
0
ファイル: ddemlcli.c プロジェクト: conioh/os-design
/***************************************************************************\
* DdeNameService (DDEML API)
*
* Description:
* Registers, and Unregisters service names and sets the Initiate filter
* state for an instance.
*
* History:
* 11-1-91 sanfords Created.
\***************************************************************************/
HDDEDATA DdeNameService(
DWORD idInst,
HSZ hsz1, // service name
HSZ hsz2, // reserved for future enhancements
UINT afCmd) // DNS_ flags.
{
    BOOL fRet = TRUE;
    LATOM *plaNameService;
    PCL_INSTANCE_INFO pcii;

    EnterDDECrit;

    pcii = ValidateInstance((HANDLE)LongToHandle( idInst ));
    if (pcii == NULL) {
        BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
        fRet = FALSE;
        goto Exit;
    }

    if ((hsz1 && ValidateHSZ(hsz1) == HSZT_INVALID) || hsz2 != 0) {
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        fRet = FALSE;
        goto Exit;
    }

    if (afCmd & DNS_FILTERON && !(pcii->afCmd & APPCMD_FILTERINITS)) {
        pcii->afCmd |= APPCMD_FILTERINITS;
        NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd);
    }
    if (afCmd & DNS_FILTEROFF && (pcii->afCmd & APPCMD_FILTERINITS)) {
        pcii->afCmd &= ~APPCMD_FILTERINITS;
        NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd);
    }

    if (afCmd & (DNS_REGISTER | DNS_UNREGISTER)) {
        GATOM ga;

        if (pcii->afCmd & APPCMD_CLIENTONLY) {
            SetLastDDEMLError(pcii, DMLERR_DLL_USAGE);
            fRet = FALSE;
            goto Exit;
        }

        if (hsz1 == 0) {
            if (afCmd & DNS_REGISTER) {

                /*
                 * registering NULL is not allowed!
                 */
                SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
                fRet = FALSE;
                goto Exit;
            }

            /*
             * unregistering NULL is just like unregistering each
             * registered name.
             *
             * 10/19/90 - made this a synchronous event so that hsz
             * can be freed by calling app after this call completes
             * without us having to keep a copy around forever.
             */
            plaNameService = pcii->plaNameService;
            while (*plaNameService != 0) {
                ga = LocalToGlobalAtom(*plaNameService);
                DeleteAtom(*plaNameService);
                LeaveDDECrit;
                RegisterService(FALSE, ga, pcii->hwndMother);
                EnterDDECrit;
                GlobalDeleteAtom(ga);
                plaNameService++;
            }
            pcii->cNameServiceAlloc = 1;
            *pcii->plaNameService = 0;
            goto Exit;
        }

        if (afCmd & DNS_REGISTER) {
            plaNameService = (LATOM *)DDEMLReAlloc(pcii->plaNameService,
                    sizeof(LATOM) * ++pcii->cNameServiceAlloc);
            if (plaNameService == NULL) {
                SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
                pcii->cNameServiceAlloc--;
                fRet = FALSE;
                goto Exit;
            } else {
                pcii->plaNameService = plaNameService;
            }
            IncLocalAtomCount(LATOM_FROM_HSZ(hsz1)); // NameService copy
            plaNameService[pcii->cNameServiceAlloc - 2] = LATOM_FROM_HSZ(hsz1);
            plaNameService[pcii->cNameServiceAlloc - 1] = 0;

        } else { // DNS_UNREGISTER
            plaNameService = pcii->plaNameService;
            while (*plaNameService != 0 && *plaNameService != LATOM_FROM_HSZ(hsz1)) {
                plaNameService++;
            }
            if (*plaNameService == 0) {
                goto Exit; // not found just exit
            }
            //
            // fill empty slot with last entry and fill last entry with 0
            //
            pcii->cNameServiceAlloc--;
            *plaNameService = pcii->plaNameService[pcii->cNameServiceAlloc - 1];
            pcii->plaNameService[pcii->cNameServiceAlloc - 1] = 0;
        }

        ga = LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1));
        LeaveDDECrit;
        RegisterService((afCmd & DNS_REGISTER) ? TRUE : FALSE, ga,
            pcii->hwndMother);
        EnterDDECrit;
        GlobalDeleteAtom(ga);
    }

Exit:
    LeaveDDECrit;
    return ((HDDEDATA)IntToPtr( fRet ));
}
コード例 #2
0
ファイル: callback.c プロジェクト: Gaikokujin/WinNT4
/***************************************************************************\
* DoCallback
*
* Description:
* Performs a synchronous callback to the given instance's callback proc.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
HDDEDATA DoCallback(
PCL_INSTANCE_INFO pcii,
WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hData,
DWORD dw1,
DWORD dw2)
{
    HDDEDATA hDataRet;
    PCLIENTINFO pci;

    CheckDDECritIn;


    /*
     * Zombie conversations don't generate callbacks!
     */
    if (hConv && TypeFromHandle(hConv) == HTYPE_ZOMBIE_CONVERSATION) {
        return(0);
    }

    pci = GetClientInfo();
    pci->cInDDEMLCallback++;

    pcii->cInDDEMLCallback++;
    pci->hDdemlCallbackInst = pcii->hInstClient;
    LeaveDDECrit;
    CheckDDECritOut;

    hDataRet = (*pcii->pfnCallback)((UINT)wType, (UINT)wFmt, hConv, hsz1, hsz2,
            hData, dw1, dw2);

    EnterDDECrit;
    pcii->cInDDEMLCallback--;
    pci->cInDDEMLCallback--;

    if (!(pcii->afCmd & APPCLASS_MONITOR) && pcii->MonitorFlags & MF_CALLBACKS) {
        PEVENT_PACKET pep;

        pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) +
                sizeof(MONCBSTRUCT));
        if (pep != NULL) {

            pep->EventType =    MF_CALLBACKS;
            pep->fSense =       TRUE;
            pep->cbEventData =  sizeof(MONCBSTRUCT);

#define pcbs ((MONCBSTRUCT *)&pep->Data)
            pcbs->cb =      sizeof(MONCBSTRUCT);
            pcbs->dwTime =  NtGetTickCount();
            pcbs->hTask =   (HANDLE)pcii->tid;
            pcbs->dwRet =   (DWORD)hDataRet;
            pcbs->wType =   wType;
            pcbs->wFmt =    wFmt;
            pcbs->hConv =   hConv;
            pcbs->hsz1 =    (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1));
            pcbs->hsz2 =    (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz2));
            pcbs->hData =   hData;
            pcbs->dwData1 = dw1;
            pcbs->dwData2 = dw2;
            if (((wType == XTYP_CONNECT) || (wType == XTYP_WILDCONNECT)) && dw1) {
                RtlCopyMemory(&pcbs->cc, (PVOID)dw1, sizeof(CONVCONTEXT));
            }

            LeaveDDECrit;

                if (wType & XCLASS_DATA) {
                    if (hDataRet && hDataRet != CBR_BLOCK) {
                        pcbs->cbData = DdeGetData(hDataRet, (LPBYTE)pcbs->Data, 32, 0);
                    }
                } else if (hData) {
                    pcbs->cbData = DdeGetData(hData, (LPBYTE)pcbs->Data, 32, 0);
                }

                Event(pep);

            EnterDDECrit;

            GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz1));
            GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz2));
            DDEMLFree(pep);
#undef pcbs
        }
    }
    return (hDataRet);
}
コード例 #3
0
ファイル: connect.c プロジェクト: Gaikokujin/WinNT4
/***************************************************************************\
* DdeReconnect (DDEML API)
*
* Description:
* Attempts to reconnect an externally (from the server) terminated
* client side conversation.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
HCONV DdeReconnect(
    HCONV hConv)
{
    PCL_INSTANCE_INFO pcii;
    PCL_CONV_INFO pci, pciNew;
    HCONV hConvRet = 0;
    CONVCONTEXT cc;

    EnterDDECrit;

    pcii = PciiFromHandle((HANDLE)hConv);
    if (pcii == NULL) {
        BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
        goto Exit;
    }
    pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConv,
            HTYPE_CLIENT_CONVERSATION, HINST_ANY);
    if (pci == NULL) {
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    if (pci->ci.state & ST_CONNECTED) {
        goto Exit;
    }

    GetConvContext(pci->ci.hwndConv, (LONG *)&cc);
    pciNew = ConnectConv(pcii, pci->ci.laService, pci->ci.laTopic,
            pci->hwndReconnect, 0, &cc, 0, CLST_SINGLE_INITIALIZING);
    if (pciNew == NULL) {
        SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
        goto Exit;
    } else {
        hConvRet = pciNew->ci.hConv;
        if (pci->ci.cLinks) {
            PXACT_INFO pxi;
            int iLink;
            PADVISE_LINK paLink;

            /*
             * reestablish advise links
             */

            for (paLink = pci->ci.aLinks, iLink = pci->ci.cLinks;
                    iLink; paLink++, iLink--) {

                pxi = (PXACT_INFO)DDEMLAlloc(sizeof(XACT_INFO));
                if (pxi == NULL) {
                    break;              // abort relinking
                }
                pxi->pcoi = (PCONV_INFO)pciNew;
                pxi->gaItem = LocalToGlobalAtom(paLink->laItem); // pxi copy
                pxi->wFmt = paLink->wFmt;
                pxi->wType = (WORD)((paLink->wType >> 12) | XTYP_ADVSTART);
                if (ClStartAdvise(pxi)) {
                    pxi->flags |= XIF_ABANDONED;
                } else {
                    GlobalDeleteAtom(pxi->gaItem);
                    DDEMLFree(pxi);
                }
            }
        }
    }
コード例 #4
0
ファイル: connect.c プロジェクト: Gaikokujin/WinNT4
/***************************************************************************\
* ConnectConv
*
* Description:
* Work function for all Connect cases.
*
* Method:
*
* To reduce the number of windows we use and to simplify how client
* windows handle multiple WM_DDE_ACK messages during initiation, a
* single client window can handle many conversations, each with
* a different server window.
*
* The client window is created and set to a initiation state via the
* GWL_CONVSTATE window word. Initiates are then sent to enumerated server
* window candidates.
* The GWL_CONVSTATE value is used by the DDEML mother windows
* to determine if only one or several ACKs are desired to minimize
* unnessary message traffic.
*
* The client window GWL_CONVCONTEXT? window words are also used by
* Event Windows to pass context information.
*
* Note that all client and server windows are children of the mother
* window. This reduces the number of top level windows that
* WM_DDE_INITIATES need to hit.
*
* Each WM_DDE_ACK that is received by a client window while in the
* initiation state causes it to create a CL_CONV_INFO structure,
* partially initialize it, and link it into its list of CL_CONV_INFO
* structures. The head of the list is pointed to by the GWL_PCI
* client window word.
*
* After each WM_DDE_INITIALIZE is sent, the GWL_PCI value is checked
* to see if it exists and needs initialization to be completed. If
* this is the case the init code knows that at least one ACK was
* received in response to the WM_DDE_INITIALIZE send. The
* initialization of each CL_CONV_INFO struct that needs it is then completed.
*
* Once the broadcasting of WM_DDE_INITIALIZE is done, the init code
* then sets the GWL_CONVSTATE value in the client window to indicate that
* initialization is complete.
*
* Returns:
* The head pci to the client window or NULL if no connections made it.
*
* History:
* 11-1-91 sanfords Created.
\***************************************************************************/
PCL_CONV_INFO ConnectConv(
    PCL_INSTANCE_INFO pcii,
    LATOM laService,
    LATOM laTopic,
    HWND hwndTarget, // 0 implies broadcast
    HWND hwndSkip, // 0 implies no skips - avoids self-connections.
    PCONVCONTEXT pCC,
    HCONVLIST hConvList,
    DWORD clst)
{
    INIT_ENUM ie;
    PCL_CONV_INFO pci;
    PCONV_INFO pcoi;
    GATOM gaService, gaTopic;

    CheckDDECritIn;

    if (hwndTarget && hwndTarget == hwndSkip) {
        return(NULL);
    }

    LeaveDDECrit;
    CheckDDECritOut;

    if (pcii->flags & IIF_UNICODE) {
        ie.hwndClient = CreateWindowW((LPWSTR)(gpsi->atomSysClass[ICLS_DDEMLCLIENTW]),
                                     L"",
                                     WS_CHILD,
                                     0, 0, 0, 0,
                                     pcii->hwndMother,
                                     (HMENU)0,
                                     (HANDLE)0,
                                     (LPVOID)NULL);
    } else {
        ie.hwndClient = CreateWindowA((LPSTR)(gpsi->atomSysClass[ICLS_DDEMLCLIENTA]),
                                     "",
                                     WS_CHILD,
                                     0, 0, 0, 0,
                                     pcii->hwndMother,
                                     (HMENU)0,
                                     (HANDLE)0,
                                     (LPVOID)NULL);
    }

    EnterDDECrit;

    if (ie.hwndClient == 0) {
        return (NULL);
    }

    if (pCC != NULL) {
        if (!NtUserDdeSetQualityOfService(ie.hwndClient, &(pCC->qos), NULL)) {
            SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
            goto Error;
        }
    }
    /*
     * Note that a pci will be created and allocated for each ACK recieved.
     */
    SetConvContext(ie.hwndClient, (LONG *)pCC);
    SetWindowLong(ie.hwndClient, GWL_CONVSTATE, clst);
    SetWindowLong(ie.hwndClient, GWL_SHINST, (LONG)pcii->hInstServer);
    SetWindowLong(ie.hwndClient, GWL_CHINST, (LONG)pcii->hInstClient);

    gaService = LocalToGlobalAtom(laService);
    gaTopic = LocalToGlobalAtom(laTopic);
    ie.lParam = MAKELONG(gaService, gaTopic);
    if (!hwndTarget) {
        ie.hwndSkip = hwndSkip;
        ie.laServiceRequested = laService;
        ie.laTopic = laTopic;
        ie.hConvList = hConvList;
        ie.clst = clst;
    }

    LeaveDDECrit;

    if (hwndTarget) {
        SendMessage(hwndTarget, WM_DDE_INITIATE, (DWORD)ie.hwndClient,
                ie.lParam);
    } else {
        /*
         * Send this message to the nddeagnt app first so it can start
         * the netdde services BEFORE we do an enumeration of windows.
         * This lets things work the first time.  NetDDEAgent caches
         * service status so this is the fastest way to do this.
         */
        HWND hwndAgent = FindWindowW(SZ_NDDEAGNT_CLASS, SZ_NDDEAGNT_TITLE);
        if (hwndAgent) {
            SendMessage(hwndAgent,
                WM_DDE_INITIATE, (WPARAM)ie.hwndClient, ie.lParam);
        }
        EnumWindows((WNDENUMPROC)InitiateEnumerationProc, (LONG)&ie);
    }

    EnterDDECrit;
    /*
     * hConvList may have been destroyed during the enumeration but we are
     * done with it now so no need to revalidate.
     */

#ifdef DEBUG
    {
        WCHAR sz[10];

        if (gaService && GlobalGetAtomName(gaService, sz, 10) == 0) {
            RIPMSG1(RIP_ERROR, "Bad Service Atom after Initiate phase: %lX", (DWORD)gaService);
        }
        if (gaTopic && GlobalGetAtomName(gaTopic, sz, 10) == 0) {
            RIPMSG1(RIP_ERROR, "Bad Topic Atom after Initiate phase: %lX", (DWORD)gaTopic);
        }
    }
#endif // DEBUG

    GlobalDeleteAtom(gaService);
    GlobalDeleteAtom(gaTopic);

    //
    // Get the first pci allocated when a WM_DDE_ACK was recieved.
    //
    pci = (PCL_CONV_INFO)GetWindowLong(ie.hwndClient, GWL_PCI);
    if (pci == NULL) {
Error:
        LeaveDDECrit;
        NtUserDestroyWindow(ie.hwndClient);
        EnterDDECrit;
        return (NULL);
    }

    SetWindowLong(ie.hwndClient, GWL_CONVSTATE, CLST_CONNECTED);
    if (hwndTarget) {
        /*
         * If hwndTarget was NULL, the enumeration proc took care of this.
         */
        pci->hwndReconnect = hwndTarget;
        UserAssert(pci->ci.next == NULL);
        pci->ci.laServiceRequested = laService;
        IncLocalAtomCount(laService); // pci copy
    }

    if (pcii->MonitorFlags & MF_CONV) {
        for (pcoi = (PCONV_INFO)pci; pcoi; pcoi = pcoi->next) {
            MONCONV(pcoi, TRUE);
        }
    }
    return (pci);
}
コード例 #5
0
ファイル: connect.c プロジェクト: Gaikokujin/WinNT4
/***************************************************************************\
* FreeConversationResources
*
* Description:
* Used when: Client window is disconnected by app, Server window is
* disconnected by either side, or when a conversation is disconnected
* at Uninitialize time.
*
* This function releases all resources held by the pcoi and unlinks it
* from its host window pcoi chian. pcoi is freed once this return s.
*
* History:
* 12-21-91 sanfords Created.
\***************************************************************************/
VOID FreeConversationResources(
    PCONV_INFO pcoi)
{
    PADVISE_LINK paLink;
    PDDE_MESSAGE_QUEUE pdmq;
    PXACT_INFO pxi;

    CheckDDECritIn;

    /*
     * Don't free resources on locked conversations.
     */
    if (pcoi->cLocks > 0) {
        pcoi->state |= ST_FREE_CONV_RES_NOW;
        return;
    }

    /*
     * Don't free resources if a synchronous transaction is in effect!
     */
    pxi = pcoi->pxiOut;
    while (pxi != NULL) {
        if (pxi->flags & XIF_SYNCHRONOUS) {
            /*
             * This conversation is in a synchronous transaction.
             * Shutdown the modal loop FIRST, then call this when
             * the loop exits.
             */
            PostMessage(pcoi->hwndConv, WM_TIMER, TID_TIMEOUT, 0);
            pcoi->state |= ST_FREE_CONV_RES_NOW;
            return;
        }
        pxi = pxi->next;
    }

    /*
     * If this is an Intra-Process conversation that hasn't yet received
     * a terminate message, make it a zombie.  We will call this routine
     * again once the terminate arrives or when WaitForZombieTerminate() has
     * timed out waiting.
     */
    if (pcoi->state & ST_INTRA_PROCESS && !(pcoi->state & ST_TERMINATE_RECEIVED)) {
        DestroyHandle((HANDLE)pcoi->hConv);
        pcoi->hConv = (HCONV)CreateHandle((DWORD)pcoi, HTYPE_ZOMBIE_CONVERSATION,
                InstFromHandle(pcoi->hConv));
        UnlinkConvFromOthers(pcoi, TRUE);
        return;
    }

    /*
     * remove any transactions left in progress
     */
    while (pcoi->pxiOut != NULL) {
        (pcoi->pxiOut->pfnResponse)(pcoi->pxiOut, 0, 0);
    }

    /*
     * Throw away any incomming queued DDE messages.
     */
    while (pcoi->dmqOut != NULL) {

        pdmq = pcoi->dmqOut;
        DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), pdmq->msg, pdmq->lParam);
        pcoi->dmqOut = pcoi->dmqOut->next;
        if (pcoi->dmqOut == NULL) {
            pcoi->dmqIn = NULL;
        }
        DDEMLFree(pdmq);
    }

    //
    // Remove all link info
    //
    paLink = pcoi->aLinks;
    while (pcoi->cLinks) {
        if (pcoi->state & ST_CLIENT) {
            MONLINK(pcoi->pcii, FALSE, paLink->wType & XTYPF_NODATA,
                    pcoi->laService, pcoi->laTopic,
                    LocalToGlobalAtom(paLink->laItem),
                    paLink->wFmt, FALSE,
                    (HCONV)pcoi->hwndPartner, (HCONV)pcoi->hwndConv);
        } else {
            MONLINK(pcoi->pcii, FALSE, paLink->wType & XTYPF_NODATA,
                    pcoi->laService, pcoi->laTopic,
                    LocalToGlobalAtom(paLink->laItem),
                    paLink->wFmt, TRUE,
                    (HCONV)pcoi->hwndConv, (HCONV)pcoi->hwndPartner);
        }
        if (!(pcoi->state & ST_CLIENT)) {
            DeleteLinkCount(pcoi->pcii, paLink->pLinkCount);
        }
        DeleteAtom(paLink->laItem); // link structure copy
        paLink++;
        pcoi->cLinks--;
    }
    if (pcoi->aLinks) {
        DDEMLFree(pcoi->aLinks);
    }

    //
    // free atoms associated with this conv
    //
    DeleteAtom(pcoi->laService);
    DeleteAtom(pcoi->laTopic);
    if (pcoi->laServiceRequested) {
        DeleteAtom(pcoi->laServiceRequested);
    }

    UnlinkConvFromOthers(pcoi, FALSE);

    /*
     * invalidate app's conversation handle
     */
    DestroyHandle((HANDLE)pcoi->hConv);

    DDEMLFree(pcoi);
}