/***************************************************************************\ * AddInstance * * Description: * Adds a server side instance handle to the instance handle array. * The array index becomes the client-side unique instance index used for * identifying other client side handles. * * Returns: * client side instance handle or 0 on error. * * History: * 11-1-91 sanfords Created. \***************************************************************************/ DWORD AddInstance( HANDLE hInstServer) { int i, iNextFree; PHANDLE ph; if (iFirstFreeInst >= cInstAllocated) { if (cInstAllocated == 0) { aInstance = (PHANDLE)DDEMLAlloc(sizeof(HANDLE) * INST_GROW_COUNT); } else { aInstance = (PHANDLE)DDEMLReAlloc((PVOID)aInstance, sizeof(HANDLE) * (cInstAllocated + INST_GROW_COUNT)); } if (aInstance == 0) { return (0); } ph = &aInstance[cInstAllocated]; i = cInstAllocated + 1; while (i <= cInstAllocated + INST_GROW_COUNT) { *ph++ = (HANDLE)i++; } cInstAllocated += INST_GROW_COUNT; } iNextFree = (int)aInstance[iFirstFreeInst]; if (iNextFree > MAX_INST) { /* * Instance limit for this process exceeded! */ return(0); } aInstance[iFirstFreeInst] = hInstServer; i = iFirstFreeInst; iFirstFreeInst = iNextFree; return ((DWORD)CreateHandle(0, HTYPE_INSTANCE, i)); }
/***************************************************************************\ * 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 )); }
/***************************************************************************\ * 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); }