/***************************************************************************\ * DdeImpersonateClient() * * Description: * Does security impersonation for DDEML server apps. * This API should only be called with server side hConvs; * * History: * 5-4-92 sanfords Created. \***************************************************************************/ BOOL DdeImpersonateClient( HCONV hConv) { PCONV_INFO pcoi; PCL_INSTANCE_INFO pcii; BOOL fRet = FALSE; EnterDDECrit; pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, HTYPE_SERVER_CONVERSATION, HINST_ANY); if (pcoi == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } pcii = PciiFromHandle((HANDLE)hConv); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } fRet = NtUserImpersonateDdeClientWindow(pcoi->hwndPartner, pcoi->hwndConv); Exit: LeaveDDECrit; return (fRet); }
/***************************************************************************\ * DdeDisconnect (DDEML API) * * Description: * Terminates a conversation. * * History: * 11-12-91 sanfords Created. \***************************************************************************/ BOOL DdeDisconnect( HCONV hConv) { BOOL fRet = FALSE; PCONV_INFO pcoi; PCL_INSTANCE_INFO pcii; CheckDDECritOut; EnterDDECrit; pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, HTYPE_CLIENT_CONVERSATION, HINST_ANY); if (pcoi == NULL) { pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, HTYPE_SERVER_CONVERSATION, HINST_ANY); } if (pcoi == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } pcii = PciiFromHandle((HANDLE)hConv); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } if (pcoi->state & ST_CONNECTED) { ShutdownConversation(pcoi, FALSE); } fRet = TRUE; Exit: LeaveDDECrit; return (fRet); }
/***************************************************************************\ * 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); }
/***************************************************************************\ * 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); }
/***************************************************************************\ * DdeDisconnectList (DDEML API) * * Description: * Terminates all conversations in a conversation list and frees the list. * * History: * 11-12-91 sanfords Created. \***************************************************************************/ BOOL DdeDisconnectList( HCONVLIST hConvList) { BOOL fRet = FALSE; PCL_INSTANCE_INFO pcii; PCONVLIST pcl; PCONV_INFO pcoi, pcoiNext; int i; CheckDDECritOut; EnterDDECrit; pcl = (PCONVLIST)ValidateCHandle((HANDLE)hConvList, HTYPE_CONVERSATION_LIST, HINST_ANY); if (pcl == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } ValidateConvList(hConvList); pcii = PciiFromHandle((HANDLE)hConvList); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } for(i = pcl->chwnd - 1; i >= 0; i--) { pcoi = (PCONV_INFO)GetWindowLong(pcl->ahwnd[i], GWL_PCI); while (pcoi != NULL && pcoi->state & ST_CONNECTED) { pcoiNext = pcoi->next; ShutdownConversation(pcoi, FALSE); // may unlink pcoi! pcoi = pcoiNext; } } DestroyHandle((HANDLE)hConvList); DDEMLFree(pcl); fRet = TRUE; Exit: LeaveDDECrit; return (fRet); }
HSZ InternalDdeCreateStringHandle( DWORD idInst, PVOID psz, int iCodePage) { PCL_INSTANCE_INFO pcii; HSZ hszRet = 0; int cb; WCHAR szw[256]; EnterDDECrit; pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } switch (iCodePage) { case CP_WINANSI: if (*(LPSTR)psz == '\0') { goto Exit; } hszRet = NORMAL_HSZ_FROM_LATOM(AddAtomA((LPSTR)psz)); break; default: /* * Convert psz to unicode and fall through. */ cb = sizeof(szw) / sizeof(WCHAR); #ifdef LATER MultiByteToWideChar((UINT)iCodePage, MB_PRECOMPOSED, (LPSTR)psz, -1, szw, cb); #endif psz = &szw[0]; case CP_WINUNICODE: if (*(LPWSTR)psz == L'\0') { goto Exit; } hszRet = NORMAL_HSZ_FROM_LATOM(AddAtomW((LPWSTR)psz)); break; } MONHSZ(pcii, hszRet, MH_CREATE); Exit: LeaveDDECrit; return (hszRet); }
/***************************************************************************\ * 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 )); }
/***************************************************************************\ * DdeUninitialize (DDEML API) * * Description: * Shuts down a DDEML instance and frees all associated resources. * * History: * 11-12-91 sanfords Created. \***************************************************************************/ BOOL DdeUninitialize( DWORD idInst) { PCL_INSTANCE_INFO pcii, pciiPrev; BOOL fRet = FALSE; CheckDDECritOut; EnterDDECrit; pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } /* * If this thread is in the middle of a synchronous transaction or * a callback, we need to back out of those first. */ if ((pcii->flags & IIF_IN_SYNC_XACT) || pcii->cInDDEMLCallback) { pcii->afCmd |= APPCMD_UNINIT_ASAP; fRet = TRUE; goto Exit; } ApplyFunctionToObjects(HTYPE_CONVERSATION_LIST, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnectList); ApplyFunctionToObjects(HTYPE_CLIENT_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnect); ApplyFunctionToObjects(HTYPE_SERVER_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnect); ApplyFunctionToObjects(HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)WaitForZombieTerminate); ApplyFunctionToObjects(HTYPE_DATA_HANDLE, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)ApplyFreeDataHandle); LeaveDDECrit; NtUserCallOneParam((ULONG_PTR)pcii->hInstServer, SFI__CSDDEUNINITIALIZE); NtUserDestroyWindow(pcii->hwndMother); EnterDDECrit; DDEMLFree(pcii->plaNameService); DestroyInstance(pcii->hInstClient); // unlink pcii from pciiList if (pciiList == pcii) { pciiList = pciiList->next; } else { for (pciiPrev = pciiList; pciiPrev != NULL && pciiPrev->next != pcii; pciiPrev = pciiPrev->next) { ; } if (pciiPrev != NULL) { pciiPrev->next = pcii->next; } } DDEMLFree(pcii); fRet = TRUE; Exit: LeaveDDECrit; return (fRet); }
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); }
/***************************************************************************\ * 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); }
/***************************************************************************\ * 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); }
/***************************************************************************\ * 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); } } } }