Annotation of mstools/samples/ddeml/server/dde.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This module serves to demonstrate one way a sophisticated DDE server
        !             3:  * that uses enumerable topics and items might be implemented.  It takes
        !             4:  * full advantage of appowned data handles (when fAppowned is set) to
        !             5:  * minimize the need for repeated rendering of data when shared with
        !             6:  * multiple clients.
        !             7:  *
        !             8:  * The server supports full system topic information plus help and non
        !             9:  * system topic item enumeration for the benefit of browsing clients
        !            10:  * that are wondering what's around.
        !            11:  *
        !            12:  * This server can be made secure by altering the conversation context
        !            13:  * filter.
        !            14:  *
        !            15:  * This server can appear to support alternate codepages and languages
        !            16:  * by altering the conversation context filter.   On Windows this is
        !            17:  * pretty much moot since there is not yet a clearly defined way of
        !            18:  * doing international communication and because the atom manager restricts
        !            19:  * what topic and item strings can be used on the system.
        !            20:  */
        !            21: 
        !            22: #include <string.h>
        !            23: #include <stdlib.h>
        !            24: #include <stdio.h>
        !            25: #include <memory.h>
        !            26: #include "server.h"
        !            27: #include "huge.h"
        !            28: 
        !            29: /*
        !            30:  * This function verifies that the incomming conversation context fits the
        !            31:  * server's context filter's requirements.
        !            32:  */
        !            33: BOOL ValidateContext(
        !            34: PCONVCONTEXT pCC)
        !            35: {
        !            36:     // make sure our CCFilter allows it...mock security, language support
        !            37:     // old DDE app client case...pCC == NULL
        !            38:     if (pCC == NULL &&
        !            39:             CCFilter.dwSecurity == 0 &&      // were nonsecure
        !            40:             CCFilter.iCodePage == CP_WINANSI // were normal cp
        !            41:             ) {
        !            42:         return(TRUE);
        !            43:     }
        !            44: 
        !            45:     if (pCC &&
        !            46:             pCC->wFlags == CCFilter.wFlags && // no special flags needed
        !            47:             pCC->iCodePage == CCFilter.iCodePage && // codepages match
        !            48:             pCC->dwSecurity == CCFilter.dwSecurity) { // security passes
        !            49:         // dont care about language and country.
        !            50:         return(TRUE);
        !            51:     }
        !            52:     return(FALSE);  // disallow no match
        !            53: }
        !            54: 
        !            55: 
        !            56: /***************************** Public  Function ****************************\
        !            57: *
        !            58: * This function is called by the DDE manager DLL and passes control onto
        !            59: * the apropriate function pointed to by the global topic and item arrays.
        !            60: * It handles all DDE interaction generated by external events.
        !            61: *
        !            62: \***************************************************************************/
        !            63: HDDEDATA CALLBACK DdeCallback(
        !            64: WORD wType,
        !            65: WORD wFmt,
        !            66: HCONV hConv,
        !            67: HSZ hszTopic,
        !            68: HSZ hszItem,
        !            69: HDDEDATA hData,
        !            70: DWORD lData1,
        !            71: DWORD lData2)
        !            72: {
        !            73:     WORD i, j;
        !            74:     register ITEMLIST *pItemList;
        !            75:     WORD cItems, iFmt;
        !            76:     HDDEDATA hDataRet;
        !            77: 
        !            78:     /*
        !            79:      * Block this callback if its blockable and we are supposed to.
        !            80:      */
        !            81:     if (fBlockNextCB && !(wType & XTYPF_NOBLOCK)) {
        !            82:         fBlockNextCB = FALSE;
        !            83:         fAllEnabled = FALSE;
        !            84:         return(CBR_BLOCK);
        !            85:     }
        !            86: 
        !            87:     /*
        !            88:      * Block this callback if its associated with a conversation and we
        !            89:      * are supposed to.
        !            90:      */
        !            91:     if (fTermNextCB && hConv) {
        !            92:         fTermNextCB = FALSE;
        !            93:         DdeDisconnect(hConv);
        !            94:         wType = XTYP_DISCONNECT;
        !            95:     }
        !            96: 
        !            97:     /*
        !            98:      * Keep a count of connections
        !            99:      */
        !           100:     if (wType == XTYP_CONNECT_CONFIRM) {
        !           101:         cServers++;
        !           102:         InvalidateRect(hwndServer, &rcConnCount, TRUE);
        !           103:         return(0);
        !           104:     }
        !           105:     if (wType == XTYP_DISCONNECT) {
        !           106:         cServers--;
        !           107:         InvalidateRect(hwndServer, &rcConnCount, TRUE);
        !           108:         return(0);
        !           109:     }
        !           110: 
        !           111: 
        !           112:     /*
        !           113:      * only allow transactions on the formats we support if they have a format.
        !           114:      */
        !           115:     if (wFmt) {
        !           116:         for (iFmt = 0; iFmt < CFORMATS; iFmt++) {
        !           117:             if (wFmt == aFormats[iFmt].atom)
        !           118:                 break;
        !           119:         }
        !           120:         if (iFmt == CFORMATS)
        !           121:             return(0);          // illegal format - ignore now.
        !           122:     }
        !           123: 
        !           124:     /*
        !           125:      * Executes are allowed only on the system topic.  This is a general
        !           126:      * convention, not a requirement.
        !           127:      *
        !           128:      * Any executes received result in the execute text being shown in
        !           129:      * the server client area.  No real action is taken.
        !           130:      */
        !           131:     if (wType == XTYP_EXECUTE) {
        !           132:         if (hszTopic == topicList[0].hszTopic) {    // must be on system topic
        !           133:             // Format is assumed to be CF_TEXT.
        !           134:             DdeGetData(hData, (LPBYTE)szExec, MAX_EXEC, 0);
        !           135:             szExec[MAX_EXEC - 1] = '\0';
        !           136:             InvalidateRect(hwndServer, &rcExec, TRUE);
        !           137:             hDataRet = TRUE;
        !           138:             goto ReturnSpot;
        !           139:         }
        !           140:         pszComment = "Execute received on non-system topic - ignored";
        !           141:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           142:         return(0);
        !           143:     }
        !           144: 
        !           145:     /*
        !           146:      * Process wild initiates here
        !           147:      */
        !           148:     if (wType == XTYP_WILDCONNECT) {
        !           149:         HSZ ahsz[(CTOPICS + 1) * 2];
        !           150:         /*
        !           151:          * He wants a hsz list of all our available app/topic pairs
        !           152:          * that conform to hszTopic and hszItem(App).
        !           153:          */
        !           154: 
        !           155:         if (!ValidateContext((PCONVCONTEXT)lData1)) {
        !           156:             return(FALSE);
        !           157:         }
        !           158: 
        !           159:         if (hszItem != hszAppName && hszItem != 0) {
        !           160:             // we only support the hszAppName service
        !           161:             return(0);
        !           162:         }
        !           163: 
        !           164:         // scan the topic table and create hsz pairs
        !           165:         j = 0;
        !           166:         for (i = 0; i < CTOPICS; i++) {
        !           167:             if (hszTopic == 0 || hszTopic == topicList[i].hszTopic) {
        !           168:                 ahsz[j++] = hszAppName;
        !           169:                 ahsz[j++] = topicList[i].hszTopic;
        !           170:             }
        !           171:         }
        !           172: 
        !           173:         // cap off the list with 0s
        !           174:         ahsz[j++] = ahsz[j++] = 0L;
        !           175: 
        !           176:         // send it back
        !           177:         return(DdeCreateDataHandle(idInst, (LPBYTE)&ahsz[0], sizeof(HSZ) * j, 0L, 0, wFmt, 0));
        !           178:     }
        !           179: 
        !           180:     /*
        !           181:      * Check our hsz tables and send to the apropriate proc. to process.
        !           182:      * We use DdeCmpStringHandles() which is the portable case-insensitive
        !           183:      * method of comparing string handles.  (this is a macro on windows so
        !           184:      * there is no real speed hit.)  On WINDOWS, HSZs are case-insensitive
        !           185:      * anyway, but this may not be the case on other platforms.
        !           186:      */
        !           187:     for (i = 0; i < CTOPICS; i++) {
        !           188:         if (DdeCmpStringHandles(topicList[i].hszTopic, hszTopic) == 0) {
        !           189: 
        !           190:             /*
        !           191:              * connections must be on a topic we support.
        !           192:              */
        !           193:             if (wType == XTYP_CONNECT) {
        !           194:                 return(ValidateContext((PCONVCONTEXT)lData1));
        !           195:             }
        !           196: 
        !           197:             pItemList = topicList[i].pItemList;
        !           198:             cItems = topicList[i].cItems;
        !           199:             for (j = 0; j < cItems; j++) {
        !           200:                 if (DdeCmpStringHandles(pItemList[j].hszItem, hszItem) == 0) {
        !           201:                     XFERINFO xi;
        !           202:                     /*
        !           203:                      * Make call to worker function here...
        !           204:                      */
        !           205:                     xi.wType = wType;
        !           206:                     xi.wFmt = wFmt;
        !           207:                     xi.hConv = hConv;
        !           208:                     xi.hszTopic = hszTopic;
        !           209:                     xi.hszItem = hszItem;
        !           210:                     xi.hData = hData;
        !           211:                     xi.lData1 = lData1;
        !           212:                     xi.lData2 = lData2;
        !           213:                     hDataRet = (*pItemList[j].npfnCallback)(&xi, iFmt);
        !           214: 
        !           215: ReturnSpot:
        !           216:                     /*
        !           217:                      * The table functions return a boolean or data.
        !           218:                      * It gets translated here.
        !           219:                      */
        !           220:                     switch (wType & XCLASS_MASK) {
        !           221:                     case XCLASS_DATA:
        !           222:                         return(hDataRet);
        !           223:                         break;
        !           224:                     case XCLASS_FLAGS:
        !           225:                         return(hDataRet ? DDE_FACK : DDE_FNOTPROCESSED);
        !           226:                         break;
        !           227:                     case XCLASS_BOOL:
        !           228:                         return(TRUE);
        !           229:                     default: // XCLASS_NOTIFICATION
        !           230:                         return(0);
        !           231:                         break;
        !           232:                     }
        !           233:                     break;
        !           234:                 }
        !           235:             }
        !           236:             break;
        !           237:         }
        !           238:     }
        !           239: 
        !           240:     /*
        !           241:      * anything else fails - DDEML is designed so that a 0 return is ALWAYS ok.
        !           242:      */
        !           243:     return(0);
        !           244: }
        !           245: 
        !           246: 
        !           247: 
        !           248: 
        !           249: 
        !           250: /***************************** Private Function ****************************\
        !           251: * This passes out a standard tab-delimited list of topic names for this
        !           252: * application.
        !           253: *
        !           254: * This support is required for other apps to be able to
        !           255: * find out about us.  This kind of support should be in every DDE
        !           256: * application.
        !           257: *
        !           258: \***************************************************************************/
        !           259: HDDEDATA TopicListXfer(
        !           260: PXFERINFO pXferInfo,
        !           261: WORD iFmt)
        !           262: {
        !           263:     WORD cbAlloc, i;
        !           264:     LPSTR pszTopicList;
        !           265:     HDDEDATA hData;
        !           266: 
        !           267:     if (pXferInfo->wType == XTYP_ADVSTART)
        !           268:         return(TRUE);
        !           269: 
        !           270:     if (pXferInfo->wType != XTYP_REQUEST &&
        !           271:             pXferInfo->wType != XTYP_ADVREQ)
        !           272:         return(0);
        !           273:     /*
        !           274:      * construct the list of topics we have
        !           275:      */
        !           276:     cbAlloc = 0;
        !           277:     for (i = 0; i < CTOPICS; i++)
        !           278:         cbAlloc += lstrlen(topicList[i].pszTopic) + 1;  // 1 for tab
        !           279: 
        !           280:     // allocate a data handle big enough for the list.
        !           281:     hData = DdeCreateDataHandle(idInst, NULL, 0, cbAlloc, pXferInfo->hszItem,
        !           282:             pXferInfo->wFmt, 0);
        !           283:     pszTopicList = (LPSTR)DdeAccessData(hData, NULL);
        !           284:     if (pszTopicList) {
        !           285:         for (i = 0; i < CTOPICS; i++) {
        !           286:             _fstrcpy(pszTopicList, topicList[i].pszTopic);
        !           287:             pszTopicList += strlen(topicList[i].pszTopic);
        !           288:             *pszTopicList++ = '\t';
        !           289:         }
        !           290:         *--pszTopicList = '\0';
        !           291:         DdeUnaccessData(hData);
        !           292:         return(hData);
        !           293:     }
        !           294:     return(0);
        !           295: }
        !           296: 
        !           297: 
        !           298: 
        !           299: 
        !           300: /***************************** Private Function ****************************\
        !           301: * This passes out a standard tab-delimited list of item names for the
        !           302: * specified topic.
        !           303: *
        !           304: * This support is required for other apps to be able to
        !           305: * find out about us.  This kind of support should be in every DDE
        !           306: * application.
        !           307: *
        !           308: \***************************************************************************/
        !           309: HDDEDATA ItemListXfer(
        !           310: PXFERINFO pXferInfo,
        !           311: WORD iFmt)
        !           312: {
        !           313:     WORD cbAlloc, i, iItem, cItems;
        !           314:     ITEMLIST *pItemList = 0;
        !           315:     LPSTR pszItemList;
        !           316:     HDDEDATA hData;
        !           317: 
        !           318:     if (pXferInfo->wType == XTYP_ADVSTART)
        !           319:         return(TRUE);
        !           320: 
        !           321:     if (pXferInfo->wType != XTYP_REQUEST &&
        !           322:                 pXferInfo->wType != XTYP_ADVREQ)
        !           323:         return(0);
        !           324:     /*
        !           325:      * construct the list of items we support for this topic - this supports
        !           326:      * more than the minimum standard which would support SysItems only on
        !           327:      * the system topic.
        !           328:      */
        !           329: 
        !           330:     // locate the requested topic item table
        !           331:     for (i = 0; i < CTOPICS; i++) {
        !           332:         if (pXferInfo->hszTopic == topicList[i].hszTopic) {
        !           333:             pItemList = topicList[i].pItemList;
        !           334:             cItems = topicList[i].cItems;
        !           335:             break;
        !           336:         }
        !           337:     }
        !           338: 
        !           339:     if (!pItemList)
        !           340:         return(0);  // item not found
        !           341: 
        !           342:     cbAlloc = 0;
        !           343:     for (iItem = 0; iItem < cItems; iItem++)
        !           344:         cbAlloc += lstrlen(pItemList[iItem].pszItem) + 1; // 1 for tab
        !           345: 
        !           346:     // allocate a data handle big enough for the list.
        !           347:     hData = DdeCreateDataHandle(idInst, NULL, 0, cbAlloc, pXferInfo->hszItem,
        !           348:             pXferInfo->wFmt, 0);
        !           349:     pszItemList = (LPSTR)DdeAccessData(hData, NULL);
        !           350:     if (pszItemList) {
        !           351:         for (i = 0; i < cItems; i++) {
        !           352:             _fstrcpy(pszItemList, pItemList[i].pszItem);
        !           353:             pszItemList += strlen(pItemList[i].pszItem);
        !           354:             *pszItemList++ = '\t';
        !           355:         }
        !           356:         *--pszItemList = '\0';
        !           357:         DdeUnaccessData(hData);
        !           358:         return(hData);
        !           359:     }
        !           360:     return(0);
        !           361: }
        !           362: 
        !           363: 
        !           364: 
        !           365: 
        !           366: 
        !           367: /***************************** Private Function ****************************\
        !           368: * Gives out a 0 terminated array of dde format numbers supported by this app.
        !           369: *
        !           370: * This support is required for other apps to be able to
        !           371: * find out about us.  This kind of support should be in every DDE
        !           372: * application.
        !           373: *
        !           374: \***************************************************************************/
        !           375: HDDEDATA sysFormatsXfer(
        !           376: PXFERINFO pXferInfo,
        !           377: WORD iFmt)
        !           378: {
        !           379:     INT i, cb;
        !           380:     LPSTR psz, pszT;
        !           381:     HDDEDATA hData;
        !           382: 
        !           383:     if (pXferInfo->wType == XTYP_ADVSTART)
        !           384:         return(TRUE);
        !           385: 
        !           386:     if (pXferInfo->wType != XTYP_REQUEST &&
        !           387:             pXferInfo->wType != XTYP_ADVREQ)
        !           388:         return(0);
        !           389: 
        !           390:     for (i = 0, cb = 0; i < CFORMATS; i++)
        !           391:         cb += strlen(aFormats[i].sz) + 1;
        !           392: 
        !           393:     hData = DdeCreateDataHandle(idInst, NULL, (DWORD)cb,
        !           394:             0L, pXferInfo->hszItem, pXferInfo->wFmt, 0);
        !           395:     psz = pszT = DdeAccessData(hData, NULL);
        !           396:     for (i = 0; i < CFORMATS; i++) {
        !           397:         _fstrcpy(pszT, aFormats[i].sz);
        !           398:         pszT += _fstrlen(pszT);
        !           399:         *pszT++ = '\t';
        !           400:     }
        !           401:     *(--pszT) = '\0';
        !           402:     DdeUnaccessData(hData);
        !           403:     return(hData);
        !           404: }
        !           405: 
        !           406: 
        !           407: 
        !           408: /*
        !           409:  * This is a runaway item.  Each time it is requested, it changes.
        !           410:  * pokes just make it change again.
        !           411:  */
        !           412: HDDEDATA TestRandomXfer(
        !           413: PXFERINFO pXferInfo,
        !           414: WORD iFmt)
        !           415: {
        !           416:     CHAR szT[10];   // SS==DS!
        !           417:     LPSTR pszData;
        !           418:     HDDEDATA hData;
        !           419:     WORD i;
        !           420: 
        !           421:     switch (pXferInfo->wType) {
        !           422:     case XTYP_POKE:
        !           423:         // we expect an ascii number to replace the current seed.
        !           424:         pszComment = "Rand poke received.";
        !           425:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           426:         InvalidateRect(hwndServer, &rcRand, TRUE);
        !           427:         if (DdeGetData(pXferInfo->hData, szT, 10, 0)) {
        !           428:             szT[9] = '\0';  // just incase we overran.
        !           429:             sscanf(szT, "%d", &seed);
        !           430:             for (i = 0; i < CFORMATS; i++) {
        !           431:                 if (hDataRand[i])
        !           432:                     DdeFreeDataHandle(hDataRand[i]);
        !           433:                 hDataRand[i] = 0;
        !           434:             }
        !           435:             DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
        !           436:             return(1);
        !           437:         }
        !           438:         break;
        !           439: 
        !           440:     case XTYP_REQUEST:
        !           441:         pszComment = "Rand data requested.";
        !           442:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           443:     case XTYP_ADVREQ:
        !           444:         Delay(RenderDelay, FALSE);
        !           445:         if (!hDataRand[iFmt]) {
        !           446:             hDataRand[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10, pXferInfo->hszItem,
        !           447:                 pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
        !           448:             if (pszData = DdeAccessData(hDataRand[iFmt], NULL)) {
        !           449:                 wsprintf(pszData, "%d", seed);
        !           450:                 DdeUnaccessData(hDataRand[iFmt]);
        !           451:             }
        !           452:         }
        !           453:         hData = hDataRand[iFmt];
        !           454:         if (!fAppowned)
        !           455:             hDataRand[iFmt] = 0;
        !           456:         return(hData);
        !           457:         break;
        !           458: 
        !           459:     case XTYP_ADVSTART:
        !           460:         return(1);
        !           461:     }
        !           462:     return(0);
        !           463: }
        !           464: 
        !           465: /*
        !           466:  * This is a runaway item.  Each time it is requested, it changes.
        !           467:  * pokes just make it change again.
        !           468:  */
        !           469: HDDEDATA TestCountXfer(
        !           470: PXFERINFO pXferInfo,
        !           471: WORD iFmt)
        !           472: {
        !           473:     CHAR szT[16];   // SS==DS!
        !           474:     LPSTR pszData;
        !           475:     HDDEDATA hData;
        !           476:     WORD i;
        !           477: 
        !           478:     switch (pXferInfo->wType) {
        !           479:     case XTYP_POKE:
        !           480:         // we expect an ascii number to replace the current count.
        !           481:         pszComment = "Count poke received";
        !           482:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           483:         InvalidateRect(hwndServer, &rcCount, TRUE);
        !           484:         if (DdeGetData(pXferInfo->hData, szT, 10, 0)) {
        !           485:             szT[9] = '\0';  // just incase we overran.
        !           486:             sscanf(szT, "%ld", &count);
        !           487:             for (i = 0; i < CFORMATS; i++) {
        !           488:                 if (hDataCount[i])
        !           489:                     DdeFreeDataHandle(hDataCount[i]);
        !           490:                 hDataCount[i] = 0;
        !           491:             }
        !           492:             DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
        !           493:             return(1);
        !           494:         }
        !           495:         break;
        !           496: 
        !           497:     case XTYP_REQUEST:
        !           498:         pszComment = "Count data requested.";
        !           499:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           500:     case XTYP_ADVREQ:
        !           501:         Delay(RenderDelay, FALSE);
        !           502:         if (!hDataCount[iFmt]) {
        !           503:             hDataCount[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10, pXferInfo->hszItem,
        !           504:                     pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
        !           505:             if (pszData = DdeAccessData(hDataCount[iFmt], NULL)) {
        !           506:                 wsprintf(pszData, "%ld", count);
        !           507:                 DdeUnaccessData(hDataCount[iFmt]);
        !           508:             }
        !           509:         }
        !           510:         hData = hDataCount[iFmt];
        !           511:         if (!fAppowned)
        !           512:             hDataCount[iFmt] = 0;
        !           513:         return(hData);
        !           514:         break;
        !           515: 
        !           516:     case XTYP_ADVSTART:
        !           517:         return(1);
        !           518:     }
        !           519:     return(0);
        !           520: }
        !           521: 
        !           522: 
        !           523: /*
        !           524:  * This is not a runaway item.  Only Pokes make it change.
        !           525:  */
        !           526: HDDEDATA TestHugeXfer(
        !           527: PXFERINFO pXferInfo,
        !           528: WORD iFmt)
        !           529: {
        !           530:     BOOL fSuccess;
        !           531:     DWORD ulcb;
        !           532:     LPBYTE lpData;
        !           533:     WORD i;
        !           534:     HDDEDATA hData;
        !           535: 
        !           536:     switch (pXferInfo->wType) {
        !           537:     case XTYP_POKE:
        !           538:         ulcb = DdeGetData(pXferInfo->hData, NULL, 0, 0);
        !           539:         fSuccess = CheckHugeData(pXferInfo->hData);
        !           540:         if (fSuccess) {
        !           541:             pszComment = "Huge poke data successfully received.";
        !           542:         } else {
        !           543:             wsprintf(szComment, "%ld bytes of invalid Huge data received.", ulcb);
        !           544:             pszComment = szComment;
        !           545:         }
        !           546:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           547:         InvalidateRect(hwndServer, &rcHugeSize, TRUE);
        !           548:         if (fSuccess) {
        !           549:             for (i = 0; i < CFORMATS; i++) {
        !           550:                 if (hDataHuge[i]) {
        !           551:                     DdeFreeDataHandle(hDataHuge[i]);
        !           552:                     hDataHuge[i] = 0;
        !           553:                 }
        !           554:             }
        !           555:             /*
        !           556:              * Since callback data handles are only good for the duration of
        !           557:              * the callback, we must copy the data to our own data handle.
        !           558:              */
        !           559:             lpData = DdeAccessData(pXferInfo->hData, &cbHuge);
        !           560:             hDataHuge[iFmt] = DdeCreateDataHandle(idInst, lpData, cbHuge, 0,
        !           561:                     pXferInfo->hszItem, pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
        !           562:             DdeUnaccessData(pXferInfo->hData);
        !           563:             DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
        !           564:         }
        !           565:         return(fSuccess);
        !           566:         break;
        !           567: 
        !           568:     case XTYP_REQUEST:
        !           569:         pszComment = "Huge data requested.";
        !           570:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           571:     case XTYP_ADVREQ:
        !           572:         Delay(RenderDelay, FALSE);
        !           573:         if (!hDataHuge[iFmt]) {
        !           574:             cbHuge = (DWORD)rand() * 64L + 0x10000L;
        !           575:             wsprintf(szComment, "Generating huge data - length=%ld...", cbHuge);
        !           576:             pszComment = szComment;
        !           577:             InvalidateRect(hwndServer, &rcComment, TRUE);
        !           578:             UpdateWindow(hwndServer);
        !           579:             hDataHuge[iFmt] = CreateHugeDataHandle(cbHuge, 4325, 345, 5,
        !           580:                     pXferInfo->hszItem,
        !           581:                     pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
        !           582:             pszComment = "";
        !           583:             InvalidateRect(hwndServer, &rcComment, TRUE);
        !           584:             InvalidateRect(hwndServer, &rcHugeSize, TRUE);
        !           585:         }
        !           586:         hData = hDataHuge[iFmt];
        !           587:         if (!fAppowned)
        !           588:             hDataHuge[iFmt] = 0;
        !           589:         return(hData);
        !           590:         break;
        !           591: 
        !           592:     case XTYP_ADVSTART:
        !           593:         return(1);
        !           594:     }
        !           595:     return(0);
        !           596: }
        !           597: 
        !           598: 
        !           599: HDDEDATA HelpXfer(
        !           600: PXFERINFO pXferInfo,
        !           601: WORD iFmt)
        !           602: {
        !           603:     HDDEDATA hData;
        !           604: 
        !           605:     switch (pXferInfo->wType) {
        !           606:     case XTYP_REQUEST:
        !           607:         pszComment = "Help text requested.";
        !           608:         InvalidateRect(hwndServer, &rcComment, TRUE);
        !           609:     case XTYP_ADVREQ:
        !           610:         if (!hDataHelp[iFmt]) {
        !           611:             hDataHelp[iFmt] = DdeCreateDataHandle(idInst, szDdeHelp, strlen(szDdeHelp) + 1,
        !           612:                     0, pXferInfo->hszItem, pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
        !           613:         }
        !           614:         hData = hDataHelp[iFmt];
        !           615:         if (!fAppowned)
        !           616:             hDataHelp[iFmt] = 0;
        !           617:         return(hData);
        !           618:         break;
        !           619: 
        !           620:     case XTYP_ADVSTART:
        !           621:         return(1);
        !           622:     }
        !           623:     return(0);
        !           624: }
        !           625: 
        !           626: 
        !           627: /***************************** Private Function ****************************\
        !           628: *  This creates often used global hszs from standard global strings.
        !           629: *  It also fills the hsz fields of the topic and item tables.
        !           630: *
        !           631: \***************************************************************************/
        !           632: VOID Hszize()
        !           633: {
        !           634:     register ITEMLIST *pItemList;
        !           635:     WORD iTopic, iItem;
        !           636: 
        !           637:     hszAppName = DdeCreateStringHandle(idInst, szServer, 0);
        !           638: 
        !           639:     for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
        !           640:         topicList[iTopic].hszTopic =
        !           641:                 DdeCreateStringHandle(idInst, topicList[iTopic].pszTopic, 0);
        !           642:         pItemList = topicList[iTopic].pItemList;
        !           643:         for (iItem = 0; iItem < topicList[iTopic].cItems; iItem++) {
        !           644:             pItemList[iItem].hszItem =
        !           645:                     DdeCreateStringHandle(idInst, pItemList[iItem].pszItem, 0);
        !           646:         }
        !           647:     }
        !           648: }
        !           649: 
        !           650: 
        !           651: 
        !           652: 
        !           653: 
        !           654: /***************************** Private Function ****************************\
        !           655: *  This destroys often used global hszs from standard global strings.
        !           656: *
        !           657: \***************************************************************************/
        !           658: VOID UnHszize()
        !           659: {
        !           660:     register ITEMLIST *pItemList;
        !           661:     WORD iTopic, iItem;
        !           662: 
        !           663:     DdeFreeStringHandle(idInst, hszAppName);
        !           664: 
        !           665:     for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
        !           666:         DdeFreeStringHandle(idInst, topicList[iTopic].hszTopic);
        !           667:         pItemList = topicList[iTopic].pItemList;
        !           668:         for (iItem = 0; iItem < topicList[iTopic].cItems; iItem++) {
        !           669:             DdeFreeStringHandle(idInst, pItemList[iItem].hszItem);
        !           670:         }
        !           671:     }
        !           672: }
        !           673: 
        !           674: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.