DDE.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:23k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /*
- * This module serves to demonstrate one way a sophisticated DDE server
- * that uses enumerable topics and items might be implemented. It takes
- * full advantage of appowned data handles (when fAppowned is set) to
- * minimize the need for repeated rendering of data when shared with
- * multiple clients.
- *
- * The server supports full system topic information plus help and non
- * system topic item enumeration for the benefit of browsing clients
- * that are wondering what's around.
- *
- * This server can be made secure by altering the conversation context
- * filter.
- *
- * This server can appear to support alternate codepages and languages
- * by altering the conversation context filter. On Windows this is
- * pretty much moot since there is not yet a clearly defined way of
- * doing international communication and because the atom manager restricts
- * what topic and item strings can be used on the system.
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <memory.h>
- #include "server.h"
- #include "huge.h"
- /*
- * This function verifies that the incomming conversation context fits the
- * server's context filter's requirements.
- */
- BOOL ValidateContext(
- PCONVCONTEXT pCC)
- {
- // make sure our CCFilter allows it...mock security, language support
- // old DDE app client case...pCC == NULL
- if (pCC == NULL &&
- CCFilter.dwSecurity == 0 && // were nonsecure
- CCFilter.iCodePage == CP_WINANSI && // were normal cp
- CCFilter.qos.ImpersonationLevel == SecurityImpersonation
- ) {
- return(TRUE);
- }
- if (pCC &&
- pCC->wFlags == CCFilter.wFlags && // no special flags needed
- pCC->iCodePage == CCFilter.iCodePage && // codepages match
- pCC->dwSecurity == CCFilter.dwSecurity && // security passes
- pCC->qos.ImpersonationLevel >= CCFilter.qos.ImpersonationLevel) {
- // dont care about language and country.
- return(TRUE);
- }
- return(FALSE); // disallow no match
- }
- /***************************** Public Function ****************************
- *
- * This function is called by the DDE manager DLL and passes control onto
- * the apropriate function pointed to by the global topic and item arrays.
- * It handles all DDE interaction generated by external events.
- *
- ***************************************************************************/
- HDDEDATA CALLBACK DdeCallback(
- UINT wType,
- UINT wFmt,
- HCONV hConv,
- HSZ hszTopic,
- HSZ hszItem,
- HDDEDATA hData,
- DWORD lData1,
- DWORD lData2)
- {
- WORD i, j;
- register ITEMLIST *pItemList;
- WORD cItems, iFmt;
- HDDEDATA hDataRet;
- /*
- * Block this callback if its blockable and we are supposed to.
- */
- if (fBlockNextCB && !(wType & XTYPF_NOBLOCK)) {
- fBlockNextCB = FALSE;
- fAllEnabled = FALSE;
- return(CBR_BLOCK);
- }
- /*
- * Block this callback if its associated with a conversation and we
- * are supposed to.
- */
- if (fTermNextCB && hConv) {
- fTermNextCB = FALSE;
- DdeDisconnect(hConv);
- wType = XTYP_DISCONNECT;
- }
- /*
- * Keep a count of connections
- */
- if (wType == XTYP_CONNECT_CONFIRM) {
- cServers++;
- InvalidateRect(hwndServer, &rcConnCount, TRUE);
- return(0);
- }
- if (wType == XTYP_DISCONNECT) {
- cServers--;
- InvalidateRect(hwndServer, &rcConnCount, TRUE);
- return(0);
- }
- /*
- * only allow transactions on the formats we support if they have a format.
- */
- if (wFmt) {
- for (iFmt = 0; iFmt < CFORMATS; iFmt++) {
- if ((ATOM)wFmt == aFormats[iFmt].atom)
- break;
- }
- if (iFmt == CFORMATS)
- return(0); // illegal format - ignore now.
- }
- /*
- * Executes are allowed only on the system topic. This is a general
- * convention, not a requirement.
- *
- * Any executes received result in the execute text being shown in
- * the server client area. No real action is taken.
- */
- if (wType == XTYP_EXECUTE) {
- if (hszTopic == topicList[0].hszTopic) { // must be on system topic
- // Format is assumed to be CF_TEXT.
- DdeGetData(hData, (LPBYTE)szExec, MAX_EXEC, 0);
- szExec[MAX_EXEC - 1] = TEXT(' ');
- InvalidateRect(hwndServer, &rcExec, TRUE);
- hDataRet = (HDDEDATA)TRUE;
- goto ReturnSpot;
- }
- pszComment = TEXT("Execute received on non-system topic - ignored");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- return(0);
- }
- /*
- * Process wild initiates here
- */
- if (wType == XTYP_WILDCONNECT) {
- HSZ ahsz[(CTOPICS + 1) * 2];
- /*
- * He wants a hsz list of all our available app/topic pairs
- * that conform to hszTopic and hszItem(App).
- */
- if (!ValidateContext((PCONVCONTEXT)lData1)) {
- return(FALSE);
- }
- if (hszItem != hszAppName && hszItem != 0) {
- // we only support the hszAppName service
- return(0);
- }
- // scan the topic table and create hsz pairs
- j = 0;
- for (i = 0; i < CTOPICS; i++) {
- if (hszTopic == 0 || hszTopic == topicList[i].hszTopic) {
- ahsz[j++] = hszAppName;
- ahsz[j++] = topicList[i].hszTopic;
- }
- }
- // cap off the list with 0s
- ahsz[j++] = ahsz[j++] = 0L;
- // send it back
- return(DdeCreateDataHandle(idInst, (LPBYTE)&ahsz[0], sizeof(HSZ) * j, 0L, 0, wFmt, 0));
- }
- /*
- * Check our hsz tables and send to the apropriate proc. to process.
- * We use DdeCmpStringHandles() which is the portable case-insensitive
- * method of comparing string handles. (this is a macro on windows so
- * there is no real speed hit.) On WINDOWS, HSZs are case-insensitive
- * anyway, but this may not be the case on other platforms.
- */
- for (i = 0; i < CTOPICS; i++) {
- if (DdeCmpStringHandles(topicList[i].hszTopic, hszTopic) == 0) {
- /*
- * connections must be on a topic we support.
- */
- if (wType == XTYP_CONNECT) {
- return((HDDEDATA)ValidateContext((PCONVCONTEXT)lData1));
- }
- pItemList = topicList[i].pItemList;
- cItems = topicList[i].cItems;
- for (j = 0; j < cItems; j++) {
- if (DdeCmpStringHandles(pItemList[j].hszItem, hszItem) == 0) {
- XFERINFO xi;
- /*
- * If Win32s - security isn't supported
- */
- if(GetVersion() & 0x80000000) {
- /*
- * Make call to worker function here...
- */
- xi.wType = wType;
- xi.wFmt = wFmt;
- xi.hConv = hConv;
- xi.hszTopic = hszTopic;
- xi.hszItem = hszItem;
- xi.hData = hData;
- xi.lData1 = lData1;
- xi.lData2 = lData2;
- hDataRet = (*pItemList[j].npfnCallback)(&xi, iFmt);
- } else {
- /*
- * Windows NT - impersonate client here
- */
- if (DdeImpersonateClient(hConv)) {
- /*
- * Make call to worker function here...
- */
- xi.wType = wType;
- xi.wFmt = wFmt;
- xi.hConv = hConv;
- xi.hszTopic = hszTopic;
- xi.hszItem = hszItem;
- xi.hData = hData;
- xi.lData1 = lData1;
- xi.lData2 = lData2;
- hDataRet = (*pItemList[j].npfnCallback)(&xi, iFmt);
- RevertToSelf();
- } else {
- pszComment = TEXT("Impersonation failed.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- hDataRet = 0;
- }
- }
- ReturnSpot:
- /*
- * The table functions return a boolean or data.
- * It gets translated here.
- */
- switch (wType & XCLASS_MASK) {
- case XCLASS_DATA:
- return(hDataRet);
- break;
- case XCLASS_FLAGS:
- return(HDDEDATA)(hDataRet ? DDE_FACK : DDE_FNOTPROCESSED);
- break;
- case XCLASS_BOOL:
- return((HDDEDATA)TRUE);
- default: // XCLASS_NOTIFICATION
- return(0);
- break;
- }
- break;
- }
- }
- break;
- }
- }
- /*
- * anything else fails - DDEML is designed so that a 0 return is ALWAYS ok.
- */
- return(0);
- }
- /***************************** Private Function ****************************
- * This passes out a standard tab-delimited list of topic names for this
- * application.
- *
- * This support is required for other apps to be able to
- * find out about us. This kind of support should be in every DDE
- * application.
- *
- ***************************************************************************/
- HDDEDATA TopicListXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- WORD cbAlloc, i;
- LPTSTR pszTopicList;
- HDDEDATA hData;
- if (pXferInfo->wType == XTYP_ADVSTART)
- return((HDDEDATA)TRUE);
- if (pXferInfo->wType != XTYP_REQUEST &&
- pXferInfo->wType != XTYP_ADVREQ)
- return(0);
- /*
- * construct the list of topics we have
- */
- cbAlloc = 0;
- for (i = 0; i < CTOPICS; i++)
- cbAlloc += (_tcslen(topicList[i].pszTopic) + 1) * sizeof(TCHAR); // 1 for tab
- // allocate a data handle big enough for the list.
- hData = DdeCreateDataHandle(idInst, NULL, 0, cbAlloc, pXferInfo->hszItem,
- pXferInfo->wFmt, 0);
- pszTopicList = (LPTSTR)DdeAccessData(hData, NULL);
- if (pszTopicList) {
- for (i = 0; i < CTOPICS; i++) {
- _tcscpy(pszTopicList, topicList[i].pszTopic);
- pszTopicList += _tcslen(topicList[i].pszTopic);
- *pszTopicList++ = TEXT('t');
- }
- *--pszTopicList = TEXT(' ');
- DdeUnaccessData(hData);
- return(hData);
- }
- return(0);
- }
- /***************************** Private Function ****************************
- * This passes out a standard tab-delimited list of item names for the
- * specified topic.
- *
- * This support is required for other apps to be able to
- * find out about us. This kind of support should be in every DDE
- * application.
- *
- ***************************************************************************/
- HDDEDATA ItemListXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- WORD cbAlloc, i, iItem, cItems;
- ITEMLIST *pItemList = 0;
- LPTSTR pszItemList;
- HDDEDATA hData;
- if (pXferInfo->wType == XTYP_ADVSTART)
- return((HDDEDATA)TRUE);
- if (pXferInfo->wType != XTYP_REQUEST &&
- pXferInfo->wType != XTYP_ADVREQ)
- return(0);
- /*
- * construct the list of items we support for this topic - this supports
- * more than the minimum standard which would support SysItems only on
- * the system topic.
- */
- // locate the requested topic item table
- for (i = 0; i < CTOPICS; i++) {
- if (pXferInfo->hszTopic == topicList[i].hszTopic) {
- pItemList = topicList[i].pItemList;
- cItems = topicList[i].cItems;
- break;
- }
- }
- if (!pItemList)
- return(0); // item not found
- cbAlloc = 0;
- for (iItem = 0; iItem < cItems; iItem++)
- cbAlloc += (_tcslen(pItemList[iItem].pszItem) + 1) * sizeof(TCHAR); // 1 for tab
- // allocate a data handle big enough for the list.
- hData = DdeCreateDataHandle(idInst, NULL, 0, cbAlloc, pXferInfo->hszItem,
- pXferInfo->wFmt, 0);
- pszItemList = (LPTSTR)DdeAccessData(hData, NULL);
- if (pszItemList) {
- for (i = 0; i < cItems; i++) {
- _tcscpy(pszItemList, pItemList[i].pszItem);
- pszItemList += _tcslen(pItemList[i].pszItem);
- *pszItemList++ = TEXT('t');
- }
- *--pszItemList = TEXT(' ');
- DdeUnaccessData(hData);
- return(hData);
- }
- return(0);
- }
- /***************************** Private Function ****************************
- * Gives out a 0 terminated array of dde format numbers supported by this app.
- *
- * This support is required for other apps to be able to
- * find out about us. This kind of support should be in every DDE
- * application.
- *
- ***************************************************************************/
- HDDEDATA sysFormatsXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- INT i, cb;
- LPTSTR psz, pszT;
- HDDEDATA hData;
- if (pXferInfo->wType == XTYP_ADVSTART)
- return((HDDEDATA)TRUE);
- if (pXferInfo->wType != XTYP_REQUEST &&
- pXferInfo->wType != XTYP_ADVREQ)
- return(0);
- for (i = 0, cb = 0; i < CFORMATS; i++)
- cb += (_tcslen(aFormats[i].sz) + 1) * sizeof(TCHAR);
- hData = DdeCreateDataHandle(idInst, NULL, (DWORD)cb,
- 0L, pXferInfo->hszItem, pXferInfo->wFmt, 0);
- psz = pszT = (LPTSTR)DdeAccessData(hData, NULL);
- for (i = 0; i < CFORMATS; i++) {
- _tcscpy(pszT, aFormats[i].sz);
- pszT += _tcslen(pszT);
- *pszT++ = TEXT('t');
- }
- *(--pszT) = TEXT(' ');
- DdeUnaccessData(hData);
- return(hData);
- }
- /*
- * This is a runaway item. Each time it is requested, it changes.
- * pokes just make it change again.
- */
- HDDEDATA TestRandomXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- TCHAR szT[10]; // SS==DS!
- LPTSTR pszData;
- HDDEDATA hData;
- WORD i;
- switch (pXferInfo->wType) {
- case XTYP_POKE:
- // we expect an ascii number to replace the current seed.
- pszComment = TEXT("Rand poke received.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- InvalidateRect(hwndServer, &rcRand, TRUE);
- if (DdeGetData(pXferInfo->hData, (PBYTE)szT, 10, 0)) {
- szT[9] = TEXT(' '); // just incase we overran.
- _stscanf(szT, TEXT("%d"), &seed);
- for (i = 0; i < CFORMATS; i++) {
- if (hDataRand[i])
- DdeFreeDataHandle(hDataRand[i]);
- hDataRand[i] = 0;
- }
- DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
- return((HDDEDATA)1);
- }
- break;
- case XTYP_REQUEST:
- pszComment = TEXT("Rand data requested.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- case XTYP_ADVREQ:
- Delay(RenderDelay, FALSE);
- if (!hDataRand[iFmt]) {
- hDataRand[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10,
- pXferInfo->hszItem, (UINT)pXferInfo->wFmt,
- fAppowned ? HDATA_APPOWNED : 0);
- if (pszData = (LPTSTR)DdeAccessData(hDataRand[iFmt], NULL)) {
- wsprintf(pszData, TEXT("%d"), seed);
- DdeUnaccessData(hDataRand[iFmt]);
- }
- }
- hData = hDataRand[iFmt];
- if (!fAppowned)
- hDataRand[iFmt] = 0;
- return(hData);
- break;
- case XTYP_ADVSTART:
- return((HDDEDATA)1);
- }
- return(0);
- }
- /*
- * This is a runaway item. Each time it is requested, it changes.
- * pokes just make it change again.
- */
- HDDEDATA TestCountXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- TCHAR szT[16]; // SS==DS!
- LPTSTR pszData;
- HDDEDATA hData;
- WORD i;
- switch (pXferInfo->wType) {
- case XTYP_POKE:
- // we expect an ascii number to replace the current count.
- pszComment = TEXT("Count poke received");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- InvalidateRect(hwndServer, &rcCount, TRUE);
- if (DdeGetData(pXferInfo->hData, (PBYTE)szT, 10, 0)) {
- szT[9] = TEXT(' '); // just incase we overran.
- _stscanf(szT, TEXT("%ld"), &count);
- for (i = 0; i < CFORMATS; i++) {
- if (hDataCount[i])
- DdeFreeDataHandle(hDataCount[i]);
- hDataCount[i] = 0;
- }
- DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
- return((HDDEDATA)1);
- }
- break;
- case XTYP_REQUEST:
- pszComment = TEXT("Count data requested.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- case XTYP_ADVREQ:
- Delay(RenderDelay, FALSE);
- if (!hDataCount[iFmt]) {
- hDataCount[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10, pXferInfo->hszItem,
- pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
- if (pszData = (LPTSTR)DdeAccessData(hDataCount[iFmt], NULL)) {
- wsprintf(pszData, TEXT("%ld"), count);
- DdeUnaccessData(hDataCount[iFmt]);
- }
- }
- hData = hDataCount[iFmt];
- if (!fAppowned)
- hDataCount[iFmt] = 0;
- return(hData);
- break;
- case XTYP_ADVSTART:
- return((HDDEDATA)1);
- }
- return(0);
- }
- /*
- * This is not a runaway item. Only Pokes make it change.
- */
- HDDEDATA TestHugeXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- BOOL fSuccess;
- DWORD ulcb;
- LPBYTE lpData;
- WORD i;
- HDDEDATA hData;
- switch (pXferInfo->wType) {
- case XTYP_POKE:
- ulcb = DdeGetData(pXferInfo->hData, NULL, 0, 0);
- fSuccess = CheckHugeData(pXferInfo->hData);
- if (fSuccess) {
- pszComment = TEXT("Huge poke data successfully received.");
- } else {
- wsprintf(szComment, TEXT("%ld bytes of invalid Huge data received."), ulcb);
- pszComment = szComment;
- }
- InvalidateRect(hwndServer, &rcComment, TRUE);
- InvalidateRect(hwndServer, &rcHugeSize, TRUE);
- if (fSuccess) {
- for (i = 0; i < CFORMATS; i++) {
- if (hDataHuge[i]) {
- DdeFreeDataHandle(hDataHuge[i]);
- hDataHuge[i] = 0;
- }
- }
- /*
- * Since callback data handles are only good for the duration of
- * the callback, we must copy the data to our own data handle.
- */
- lpData = DdeAccessData(pXferInfo->hData, &cbHuge);
- hDataHuge[iFmt] = DdeCreateDataHandle(idInst, lpData, cbHuge, 0,
- pXferInfo->hszItem, pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
- DdeUnaccessData(pXferInfo->hData);
- DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
- }
- return((HDDEDATA)fSuccess);
- break;
- case XTYP_REQUEST:
- pszComment = TEXT("Huge data requested.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- case XTYP_ADVREQ:
- Delay(RenderDelay, FALSE);
- if (!hDataHuge[iFmt]) {
- cbHuge = (DWORD)rand() * 64L + 0x10000L;
- wsprintf(szComment, TEXT("Generating huge data - length=%ld..."), cbHuge);
- pszComment = szComment;
- InvalidateRect(hwndServer, &rcComment, TRUE);
- UpdateWindow(hwndServer);
- hDataHuge[iFmt] = CreateHugeDataHandle((LONG)cbHuge, 4325, 345, 5,
- pXferInfo->hszItem,
- pXferInfo->wFmt, (WORD)(fAppowned ? HDATA_APPOWNED : 0));
- pszComment = TEXT("");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- InvalidateRect(hwndServer, &rcHugeSize, TRUE);
- }
- hData = hDataHuge[iFmt];
- if (!fAppowned)
- hDataHuge[iFmt] = 0;
- return(hData);
- break;
- case XTYP_ADVSTART:
- return((HDDEDATA)1);
- }
- return(0);
- }
- HDDEDATA HelpXfer(
- PXFERINFO pXferInfo,
- WORD iFmt)
- {
- HDDEDATA hData;
- switch (pXferInfo->wType) {
- case XTYP_REQUEST:
- pszComment = TEXT("Help text requested.");
- InvalidateRect(hwndServer, &rcComment, TRUE);
- case XTYP_ADVREQ:
- if (!hDataHelp[iFmt]) {
- hDataHelp[iFmt] = DdeCreateDataHandle(idInst,
- (PBYTE)szDdeHelp,
- (_tcslen(szDdeHelp) + 1) * sizeof(TCHAR),
- 0, pXferInfo->hszItem, pXferInfo->wFmt,
- fAppowned ? HDATA_APPOWNED : 0);
- }
- hData = hDataHelp[iFmt];
- if (!fAppowned)
- hDataHelp[iFmt] = 0;
- return(hData);
- break;
- case XTYP_ADVSTART:
- return((HDDEDATA)1);
- }
- return(0);
- }
- /***************************** Private Function ****************************
- * This creates often used global hszs from standard global strings.
- * It also fills the hsz fields of the topic and item tables.
- *
- ***************************************************************************/
- VOID Hszize()
- {
- register ITEMLIST *pItemList;
- int iTopic, iItem;
- hszAppName = DdeCreateStringHandle(idInst, szServer, 0);
- for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
- topicList[iTopic].hszTopic =
- DdeCreateStringHandle(idInst, topicList[iTopic].pszTopic, 0);
- pItemList = topicList[iTopic].pItemList;
- for (iItem = 0; iItem < (int)topicList[iTopic].cItems; iItem++) {
- pItemList[iItem].hszItem =
- DdeCreateStringHandle(idInst, pItemList[iItem].pszItem, 0);
- }
- }
- }
- /***************************** Private Function ****************************
- * This destroys often used global hszs from standard global strings.
- *
- ***************************************************************************/
- VOID UnHszize()
- {
- register ITEMLIST *pItemList;
- int iTopic, iItem;
- DdeFreeStringHandle(idInst, hszAppName);
- for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
- DdeFreeStringHandle(idInst, topicList[iTopic].hszTopic);
- pItemList = topicList[iTopic].pItemList;
- for (iItem = 0; iItem < (int)topicList[iTopic].cItems; iItem++) {
- DdeFreeStringHandle(idInst, pItemList[iItem].hszItem);
- }
- }
- }