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

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

unix.superglobalmegacorp.com

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