Beispiel #1
0
/***************************************************************************\
* DdeFreeStringHandle (DDEML API)
*
* Description:
* Decrement the use count of an HSZ.
*
* History:
* 11-1-91 sanfords Created.
\***************************************************************************/
BOOL DdeFreeStringHandle(
DWORD idInst,
HSZ hsz)
{
    PCL_INSTANCE_INFO pcii;
    BOOL fRet = FALSE;

    EnterDDECrit;

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

    if (ValidateHSZ(hsz) == HSZT_INVALID) {
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    MONHSZ(pcii, hsz, MH_DELETE);
    fRet = TRUE;
    if (LATOM_FROM_HSZ(hsz) != 0) {
        if (DeleteAtom(LATOM_FROM_HSZ(hsz))) {
            SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
            fRet = FALSE;
        }
    }

Exit:
    LeaveDDECrit;
    return (fRet);
}
Beispiel #2
0
/***************************************************************************\
* DdeKeepStringHandle (DDEML API)
*
* Description:
* Increments the use count of an HSZ.
*
* History:
* 11-1-91 sanfords Created.
\***************************************************************************/
BOOL DdeKeepStringHandle(
DWORD idInst,
HSZ hsz)
{
    PCL_INSTANCE_INFO pcii;
    BOOL fRet = FALSE;

    EnterDDECrit;

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

    if (ValidateHSZ(hsz) == HSZT_INVALID) {
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    if (LATOM_FROM_HSZ(hsz) == 0) {
        fRet = TRUE;
        goto Exit;
    }
    MONHSZ(pcii, hsz, MH_KEEP);
    fRet = IncLocalAtomCount(LATOM_FROM_HSZ(hsz)) ? TRUE : FALSE;

Exit:
    LeaveDDECrit;
    return (fRet);
}
Beispiel #3
0
/***************************************************************************\
* DdeConnect (DDEML API)
*
* Description:
* Initiates a DDE conversation.
*
* History:
* 11-1-91 sanfords Created.
\***************************************************************************/
HCONV DdeConnect(
    DWORD idInst,
    HSZ hszService,
    HSZ hszTopic,
    PCONVCONTEXT pCC)
{
    PCL_INSTANCE_INFO pcii;
    PCL_CONV_INFO pci;
    HCONV hConvRet = 0;
    HWND hwndTarget = 0;
    LATOM aNormalSvcName = 0;

    EnterDDECrit;

    if (!ValidateConnectParameters((HANDLE)idInst, &pcii, &hszService, hszTopic,
            &aNormalSvcName, &pCC, &hwndTarget, 0)) {
        goto Exit;
    }
    pci = ConnectConv(pcii, LATOM_FROM_HSZ(hszService), LATOM_FROM_HSZ(hszTopic),
            hwndTarget,
            (pcii->afCmd & CBF_FAIL_SELFCONNECTIONS) ? pcii->hwndMother : 0,
            pCC, 0, CLST_SINGLE_INITIALIZING);
    if (pci == NULL) {
        SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
        goto Exit;
    } else {
        hConvRet = pci->ci.hConv;
    }

Exit:
    if (aNormalSvcName) {
        GlobalDeleteAtom(aNormalSvcName);
    }
    LeaveDDECrit;
    return (hConvRet);
}
Beispiel #4
0
/***************************************************************************\
* 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 ));
}
Beispiel #5
0
DWORD InternalDdeQueryString(
DWORD idInst,
HSZ hsz,
PVOID psz,
DWORD cbMax,
INT iCodePage)
{
    PCL_INSTANCE_INFO pcii;
    DWORD dwRet = 0;
    WCHAR szw[256];
// BOOL fDefUsed; // LATER

    EnterDDECrit;

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

    if (ValidateHSZ(hsz) == HSZT_INVALID) {
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    if (LATOM_FROM_HSZ(hsz) == 0) {
        if (iCodePage == CP_WINUNICODE) {
            if (psz != NULL) {
                *(LPWSTR)psz = L'\0';
            }
            dwRet = sizeof(WCHAR);
            goto Exit;
        } else {
            if (psz != NULL) {
                *(LPSTR)psz = '\0';
            }
            dwRet = sizeof(CHAR);
            goto Exit;
        }
    }

    if (psz == NULL) {
        cbMax = sizeof(szw);
        psz = (PVOID)szw;
    }

    switch (iCodePage) {
    case CP_WINANSI:
        dwRet = GetAtomNameA(LATOM_FROM_HSZ(hsz), psz, cbMax);
        break;

    default:
        dwRet = GetAtomNameW(LATOM_FROM_HSZ(hsz), (LPWSTR)psz, cbMax / sizeof(WCHAR));
        if (iCodePage != CP_WINUNICODE) {

            /*
             * convert psz to the appropriate codepage and count the
             * characters(ie BYTES for DBCS!) to alter dwRet.
             */
#ifdef LATER
            // Does this routine work in place? (i.e. input and output buffer the same).
            WideCharToMultiByte((UINT)iCodePage, 0, szw,
                    sizeof(szw) /  sizeof(WCHAR),
                    (LPSTR)psz, cbMax, NULL, &fDefUsed);
#endif
            dwRet = cbMax + 1;
        }
        break;
    }

Exit:
    LeaveDDECrit;
    return (dwRet);
}
Beispiel #6
0
/***************************************************************************\
* DdeEnableCallback (DDEML API)
*
* Description:
* Turns on and off asynchronous callbacks (BLOCKABLE).
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
BOOL DdeEnableCallback(
DWORD idInst,
HCONV hConv,
UINT wCmd)
{
    BOOL fRet = FALSE;
    PCL_INSTANCE_INFO pcii;
    PCONV_INFO pcoi;
    ENABLE_ENUM_STRUCT ees;

    EnterDDECrit;

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

    switch (wCmd) {
    case EC_QUERYWAITING:
    case EC_DISABLE:
    case EC_ENABLEONE:
    case EC_ENABLEALL:
        break;

    default:
        SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    if (hConv) {
        pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
                HTYPE_CLIENT_CONVERSATION, InstFromHandle(idInst));
        if (pcoi == NULL) {
            pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
                    HTYPE_SERVER_CONVERSATION, InstFromHandle(idInst));
        }
        if (pcoi == NULL) {
            SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
            goto Exit;
        }
        pcoi->cLocks++;
        fRet = SetEnableState(pcoi, wCmd);
        switch (wCmd) {
        case EC_ENABLEALL:
        case EC_ENABLEONE:
            CheckForQueuedMessages(pcoi);
        }
        pcoi->cLocks--;
        if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
            FreeConversationResources(pcoi);
        }
    } else {
        if (wCmd == EC_ENABLEONE) {
            wCmd = EC_ENABLEONEOFALL;
        }
        switch (wCmd) {
        case EC_ENABLEONEOFALL:
            pcii->ConvStartupState = ST_BLOCKNEXT | ST_BLOCKALLNEXT;
            break;

        case EC_DISABLE:
            pcii->ConvStartupState = ST_BLOCKED;
            break;

        case EC_ENABLEALL:
            pcii->ConvStartupState = 0;
            break;
        }
        ees.pfRet = &fRet;
        ees.wCmd = wCmd;
        switch (wCmd) {
        case EC_ENABLEALL:
            ees.wCmd2 = EC_CHECKQUEUE;
            break;

        case EC_ENABLEONEOFALL:
            ees.wCmd2 = EC_CHECKQUEUEONCE;
            break;

        default:
            ees.wCmd2 = 0;
        }
        EnumChildWindows(pcii->hwndMother, (WNDENUMPROC)EnableEnumProc,
                (LONG)&ees);
    }

Exit:
    LeaveDDECrit;
    return (fRet);
}
Beispiel #7
0
/***************************************************************************\
* DdeQueryNextServer (DDEML API)
*
* Description:
* Enumerates conversations within a list.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
HCONV DdeQueryNextServer(
    HCONVLIST hConvList,
    HCONV hConvPrev)
{
    HCONV hConvRet = 0;
    PCONVLIST pcl;
    HWND *phwnd;
    int i;
    PCL_CONV_INFO pci;
    PCL_INSTANCE_INFO pcii;

    EnterDDECrit;

    pcl = (PCONVLIST)ValidateCHandle((HANDLE)hConvList,
            HTYPE_CONVERSATION_LIST, HINST_ANY);
    if (pcl == NULL) {
        BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
        goto Exit;
    }
    if (!pcl->chwnd) {      // empty list
        goto Exit;
    }
    pcii = PciiFromHandle((HANDLE)hConvList);
    if (pcii == NULL) {
        BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
        goto Exit;
    }

    pcii->LastError = DMLERR_NO_ERROR;

    do {

        hConvRet = 0;

        if (hConvPrev == 0) {
            pci = (PCL_CONV_INFO)GetWindowLong(pcl->ahwnd[0], GWL_PCI);
            if (pci == NULL) {
                goto Exit;  // Must have all conversations zombied.
            }
            hConvPrev = hConvRet = pci->ci.hConv;
            continue;
        }

        pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConvPrev,
                HTYPE_CLIENT_CONVERSATION, InstFromHandle(hConvList));
        if (pci == NULL) {
            pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConvPrev,
                    HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(hConvList));
            if (pci == NULL) {
                SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
                break;
            } else {
                goto ZombieSkip;
            }
        }

        if (pci->hConvList != hConvList) {
            SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
            break;
        }

ZombieSkip:

        if (pci->ci.next == NULL) {

            /*
             * end of list for this window, go to next window
             */
            for (phwnd = pcl->ahwnd, i = 0; (i + 1) < pcl->chwnd; i++) {
                if (phwnd[i] == pci->ci.hwndConv) {
                    pci = (PCL_CONV_INFO)GetWindowLong(phwnd[i + 1], GWL_PCI);
                    if (pci == NULL) {
                        break;
                    }
                    hConvPrev = hConvRet = pci->ci.hConv;
                    break;
                }
            }
        } else {

            hConvPrev = hConvRet = pci->ci.next->hConv; // next conv for this window.
        }

    } while (hConvRet && TypeFromHandle(hConvRet) == HTYPE_ZOMBIE_CONVERSATION);
Exit:
    LeaveDDECrit;
    return (hConvRet);
}
Beispiel #8
0
/***************************************************************************\
* 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);
}
Beispiel #9
0
/***************************************************************************\
* ValidateConnectParameters
*
* Description:
* worker function to handle common validation code.
*
* Note that paNormalSvcName is set to the atom value created upon extracting
* a normal HSZ from an InstanceSpecific HSZ.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
BOOL ValidateConnectParameters(
    HANDLE hInst,
    PCL_INSTANCE_INFO *ppcii, // set if valid hInst
    HSZ *phszService, // altered if InstSpecific HSZ
    HSZ hszTopic,
    LATOM *plaNormalSvcName, // set to atom that needs freeing when done
    PCONVCONTEXT *ppCC, // set to point to DefConvContext if NULL
    HWND *phwndTarget, // set if hszService is InstSpecific
    HCONVLIST hConvList)
{
    DWORD hszType;
    BOOL fError = FALSE;

    *ppcii = ValidateInstance(hInst);
    if (*ppcii == NULL) {
        return (FALSE);
    }
    hszType = ValidateHSZ(*phszService);
    if (hszType == HSZT_INVALID || ValidateHSZ(hszTopic) == HSZT_INVALID) {
        SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
        return (FALSE);
    }
    if (hszType == HSZT_INST_SPECIFIC) {
        *phwndTarget = ParseInstSpecificAtom(LATOM_FROM_HSZ(*phszService),
            plaNormalSvcName);
        if (*plaNormalSvcName == 0) {
            SetLastDDEMLError(*ppcii, DMLERR_SYS_ERROR);
            return (FALSE);
        }
        *phszService = NORMAL_HSZ_FROM_LATOM(*plaNormalSvcName);
    }
    if (*ppCC == NULL) {
        *ppCC = &DefConvContext;
        if ((*ppcii)->flags & IIF_UNICODE) {
            (*ppCC)->iCodePage = CP_WINUNICODE;
        } else {
            (*ppCC)->iCodePage = CP_WINANSI;
        }
    } else try {
        if ((*ppCC)->cb > sizeof(CONVCONTEXT)) {
            SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
            fError = TRUE;
        } else if ((*ppCC)->cb < sizeof(CONVCONTEXT)) {
            TempConvContext = DefConvContext;
            /*
             * we can use this static temp because we are synchronized.
             */
            RtlCopyMemory(&TempConvContext, *ppCC, (*ppCC)->cb);
            *ppCC = &TempConvContext;
        }
    } except(EXCEPTION_EXECUTE_HANDLER) {
        SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
        fError = TRUE;
    }
    if (fError) {
        return(FALSE);
    }
    if (hConvList != 0 &&
            !ValidateCHandle((HANDLE)hConvList, HTYPE_CONVERSATION_LIST,
            (DWORD)InstFromHandle((*ppcii)->hInstClient))) {
        return (FALSE);
    }
    return (TRUE);
}
Beispiel #10
0
/***************************************************************************\
* 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);
                }
            }
        }
    }
Beispiel #11
0
/***************************************************************************\
* DdeConnectList (DDEML API)
*
* Description:
* Initiates DDE conversations with multiple servers or adds unique servers
* to an existing conversation list.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
HCONVLIST DdeConnectList(
    DWORD idInst,
    HSZ hszService,
    HSZ hszTopic,
    HCONVLIST hConvList,
    PCONVCONTEXT pCC)
{
    PCL_INSTANCE_INFO pcii;
    PCONV_INFO pcoi, pcoiNew, pcoiExisting, pcoiNext;
    HCONVLIST hConvListRet = 0;
    HWND hwndTarget = 0;
    LATOM aNormalSvcName = 0;
    PCONVLIST pcl = NULL;
    HCONVLIST hConvListOld;
    int i;

    CheckDDECritOut;

    EnterDDECrit;

    if (!ValidateConnectParameters((HANDLE)idInst, &pcii, &hszService, hszTopic,
            &aNormalSvcName, &pCC, &hwndTarget, hConvList)) {
        goto Exit;
    }

    ValidateConvList(hConvList);

    hConvListOld = hConvList;
    pcoi = (PCONV_INFO)ConnectConv(pcii,
            LATOM_FROM_HSZ(hszService),
            LATOM_FROM_HSZ(hszTopic),
            hwndTarget,
            (pcii->afCmd & (CBF_FAIL_SELFCONNECTIONS | CBF_FAIL_CONNECTIONS)) ?
                pcii->hwndMother : 0,
            pCC,
            hConvListOld,
            CLST_MULT_INITIALIZING);

    if (pcoi == NULL) {
        /*
         * no new connections made
         */
        SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
        hConvListRet = hConvListOld;
        goto Exit;
    }

    /*
     * allocate or reallocate the hConvList hwnd list for later addition
     * If we already have a valid list, reuse the handle so we don't have
     * to alter the preexisting pcoi->hConvList values.
     */
    if (hConvListOld == 0) {
        pcl = (PCONVLIST)DDEMLAlloc(sizeof(CONVLIST));
        if (pcl == NULL) {
            SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
            DisconnectConv(pcoi);
            goto Exit;
        }
        // pcl->chwnd = 0; LPTR zero inits.

        hConvList = (HCONVLIST)CreateHandle((DWORD)pcl,
                HTYPE_CONVERSATION_LIST, InstFromHandle(pcii->hInstClient));
        if (hConvList == 0) {
            DDEMLFree(pcl);
            SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
            DisconnectConv(pcoi);
            goto Exit;
        }
    } else {
        pcl = (PCONVLIST)GetHandleData((HANDLE)hConvList);
        pcl = DDEMLReAlloc(pcl, sizeof(CONVLIST) + sizeof(HWND) * pcl->chwnd);
        if (pcl == NULL) {
            SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
            hConvListRet = hConvListOld;
            DisconnectConv(pcoi);
            goto Exit;
        }
        SetHandleData((HANDLE)hConvList, (DWORD)pcl);
    }

    ValidateConvList(hConvListOld);

    if (hConvListOld) {
        /*
         * remove duplicates from new conversations
         *
         * Although we tried to prevent duplicates from happening
         * within the initiate enumeration code, wild initiates or
         * servers responding with different service names than
         * requested could cause duplicates.
         */

        /* For each client window... */

        for (i = 0; i < pcl->chwnd; i++) {

        /* For each existing conversation in that window... */

            for (pcoiExisting = (PCONV_INFO)
                        GetWindowLong(pcl->ahwnd[i], GWL_PCI);
                    pcoi != NULL && pcoiExisting != NULL;
                    pcoiExisting = pcoiExisting->next) {

                if (!(pcoiExisting->state & ST_CONNECTED))
                    continue;

        /* For each new conversation... */

                for (pcoiNew = pcoi; pcoiNew != NULL; pcoiNew = pcoiNext) {

                    pcoiNext = pcoiNew->next;

        /* see if the new conversation duplicates the existing one */

                    if (!(pcoiNew->state & ST_CONNECTED))
                        continue;

                    UserAssert(((PCL_CONV_INFO)pcoiExisting)->hwndReconnect);
                    UserAssert(((PCL_CONV_INFO)pcoiNew)->hwndReconnect);

                    if (((PCL_CONV_INFO)pcoiExisting)->hwndReconnect ==
                                ((PCL_CONV_INFO)pcoiNew)->hwndReconnect &&
                            pcoiExisting->laTopic == pcoiNew->laTopic &&
                            pcoiExisting->laService == pcoiNew->laService) {
                        /*
                         * duplicate conversation - disconnection causes an unlink
                         */
                        if (pcoiNew == pcoi) {
                            /*
                             * We are freeing up the head of the list,
                             * Reset the head to the next guy.
                             */
                            pcoi = pcoiNext;
                        }
                        ValidateConvList(hConvList);
                        ShutdownConversation(pcoiNew, FALSE);
                        ValidateConvList(hConvList);
                        break;
                    }
                }
            }
        }

        for (pcoiExisting = pcoi; pcoiExisting != NULL; pcoiExisting = pcoiExisting->next) {
            /*
             * if these are all zombies - we DONT want to link it in!
             * This is possible because ShutdownConversation() leaves the critical section
             * and could allow responding terminates to come through.
             */
            if (pcoiExisting->state & ST_CONNECTED) {
                goto FoundOne;
            }
        }
        pcoi = NULL;    // abandon this guy - he will clean up in time.
FoundOne:
        /*
         * add new pcoi (if any are left) hwnd to ConvList hwnd list.
         */
        if (pcoi != NULL) {
            UserAssert(pcoi->hwndConv);
            pcl->ahwnd[pcl->chwnd] = pcoi->hwndConv;
            pcl->chwnd++;
            hConvListRet = hConvList;
        } else {
            hConvListRet = hConvListOld;
            if (!hConvListOld) {
                DestroyHandle((HANDLE)hConvList);
            }
        }


    } else {    // no hConvListOld

        UserAssert(pcoi->hwndConv);
        pcl->ahwnd[0] = pcoi->hwndConv;
        pcl->chwnd = 1;
        hConvListRet = hConvList;
    }

    if (pcoi != NULL) {
        /*
         * set hConvList field for all remaining new conversations.
         */
        UserAssert(hConvListRet);
        for (pcoiNew = pcoi; pcoiNew != NULL; pcoiNew = pcoiNew->next) {
            if (pcoiNew->state & ST_CONNECTED) {
                ((PCL_CONV_INFO)pcoiNew)->hConvList = hConvListRet;
            }
        }
    }

Exit:
    if (aNormalSvcName) {
        DeleteAtom(aNormalSvcName);
    }
    ValidateConvList(hConvListRet);
    LeaveDDECrit;
    return (hConvListRet);
}