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

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(
1.1.1.2 ! root       64: UINT wType,
        !            65: UINT wFmt,
1.1       root       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++) {
1.1.1.2 ! root      286:             strcpy(pszTopicList, topicList[i].pszTopic);
1.1       root      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++) {
1.1.1.2 ! root      352:             strcpy(pszItemList, pItemList[i].pszItem);
1.1       root      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++) {
1.1.1.2 ! root      397:         strcpy(pszT, aFormats[i].sz);
        !           398:         pszT += strlen(pszT);
1.1       root      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]) {
1.1.1.2 ! root      446:             hDataRand[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10,
        !           447:                     pXferInfo->hszItem, (UINT)pXferInfo->wFmt,
        !           448:                     fAppowned ? HDATA_APPOWNED : 0);
1.1       root      449:             if (pszData = DdeAccessData(hDataRand[iFmt], NULL)) {
                    450:                 wsprintf(pszData, "%d", seed);
                    451:                 DdeUnaccessData(hDataRand[iFmt]);
                    452:             }
                    453:         }
                    454:         hData = hDataRand[iFmt];
                    455:         if (!fAppowned)
                    456:             hDataRand[iFmt] = 0;
                    457:         return(hData);
                    458:         break;
                    459: 
                    460:     case XTYP_ADVSTART:
                    461:         return(1);
                    462:     }
                    463:     return(0);
                    464: }
                    465: 
                    466: /*
                    467:  * This is a runaway item.  Each time it is requested, it changes.
                    468:  * pokes just make it change again.
                    469:  */
                    470: HDDEDATA TestCountXfer(
                    471: PXFERINFO pXferInfo,
                    472: WORD iFmt)
                    473: {
                    474:     CHAR szT[16];   // SS==DS!
                    475:     LPSTR pszData;
                    476:     HDDEDATA hData;
                    477:     WORD i;
                    478: 
                    479:     switch (pXferInfo->wType) {
                    480:     case XTYP_POKE:
                    481:         // we expect an ascii number to replace the current count.
                    482:         pszComment = "Count poke received";
                    483:         InvalidateRect(hwndServer, &rcComment, TRUE);
                    484:         InvalidateRect(hwndServer, &rcCount, TRUE);
                    485:         if (DdeGetData(pXferInfo->hData, szT, 10, 0)) {
                    486:             szT[9] = '\0';  // just incase we overran.
                    487:             sscanf(szT, "%ld", &count);
                    488:             for (i = 0; i < CFORMATS; i++) {
                    489:                 if (hDataCount[i])
                    490:                     DdeFreeDataHandle(hDataCount[i]);
                    491:                 hDataCount[i] = 0;
                    492:             }
                    493:             DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
                    494:             return(1);
                    495:         }
                    496:         break;
                    497: 
                    498:     case XTYP_REQUEST:
                    499:         pszComment = "Count data requested.";
                    500:         InvalidateRect(hwndServer, &rcComment, TRUE);
                    501:     case XTYP_ADVREQ:
                    502:         Delay(RenderDelay, FALSE);
                    503:         if (!hDataCount[iFmt]) {
                    504:             hDataCount[iFmt] = DdeCreateDataHandle(idInst, NULL, 0, 10, pXferInfo->hszItem,
                    505:                     pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
                    506:             if (pszData = DdeAccessData(hDataCount[iFmt], NULL)) {
                    507:                 wsprintf(pszData, "%ld", count);
                    508:                 DdeUnaccessData(hDataCount[iFmt]);
                    509:             }
                    510:         }
                    511:         hData = hDataCount[iFmt];
                    512:         if (!fAppowned)
                    513:             hDataCount[iFmt] = 0;
                    514:         return(hData);
                    515:         break;
                    516: 
                    517:     case XTYP_ADVSTART:
                    518:         return(1);
                    519:     }
                    520:     return(0);
                    521: }
                    522: 
                    523: 
                    524: /*
                    525:  * This is not a runaway item.  Only Pokes make it change.
                    526:  */
                    527: HDDEDATA TestHugeXfer(
                    528: PXFERINFO pXferInfo,
                    529: WORD iFmt)
                    530: {
                    531:     BOOL fSuccess;
                    532:     DWORD ulcb;
                    533:     LPBYTE lpData;
                    534:     WORD i;
                    535:     HDDEDATA hData;
                    536: 
                    537:     switch (pXferInfo->wType) {
                    538:     case XTYP_POKE:
                    539:         ulcb = DdeGetData(pXferInfo->hData, NULL, 0, 0);
                    540:         fSuccess = CheckHugeData(pXferInfo->hData);
                    541:         if (fSuccess) {
                    542:             pszComment = "Huge poke data successfully received.";
                    543:         } else {
                    544:             wsprintf(szComment, "%ld bytes of invalid Huge data received.", ulcb);
                    545:             pszComment = szComment;
                    546:         }
                    547:         InvalidateRect(hwndServer, &rcComment, TRUE);
                    548:         InvalidateRect(hwndServer, &rcHugeSize, TRUE);
                    549:         if (fSuccess) {
                    550:             for (i = 0; i < CFORMATS; i++) {
                    551:                 if (hDataHuge[i]) {
                    552:                     DdeFreeDataHandle(hDataHuge[i]);
                    553:                     hDataHuge[i] = 0;
                    554:                 }
                    555:             }
                    556:             /*
                    557:              * Since callback data handles are only good for the duration of
                    558:              * the callback, we must copy the data to our own data handle.
                    559:              */
                    560:             lpData = DdeAccessData(pXferInfo->hData, &cbHuge);
                    561:             hDataHuge[iFmt] = DdeCreateDataHandle(idInst, lpData, cbHuge, 0,
                    562:                     pXferInfo->hszItem, pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
                    563:             DdeUnaccessData(pXferInfo->hData);
                    564:             DdePostAdvise(idInst, pXferInfo->hszTopic, pXferInfo->hszItem);
                    565:         }
                    566:         return(fSuccess);
                    567:         break;
                    568: 
                    569:     case XTYP_REQUEST:
                    570:         pszComment = "Huge data requested.";
                    571:         InvalidateRect(hwndServer, &rcComment, TRUE);
                    572:     case XTYP_ADVREQ:
                    573:         Delay(RenderDelay, FALSE);
                    574:         if (!hDataHuge[iFmt]) {
                    575:             cbHuge = (DWORD)rand() * 64L + 0x10000L;
                    576:             wsprintf(szComment, "Generating huge data - length=%ld...", cbHuge);
                    577:             pszComment = szComment;
                    578:             InvalidateRect(hwndServer, &rcComment, TRUE);
                    579:             UpdateWindow(hwndServer);
1.1.1.2 ! root      580:             hDataHuge[iFmt] = CreateHugeDataHandle((LONG)cbHuge, 4325, 345, 5,
1.1       root      581:                     pXferInfo->hszItem,
1.1.1.2 ! root      582:                     pXferInfo->wFmt, (WORD)(fAppowned ? HDATA_APPOWNED : 0));
1.1       root      583:             pszComment = "";
                    584:             InvalidateRect(hwndServer, &rcComment, TRUE);
                    585:             InvalidateRect(hwndServer, &rcHugeSize, TRUE);
                    586:         }
                    587:         hData = hDataHuge[iFmt];
                    588:         if (!fAppowned)
                    589:             hDataHuge[iFmt] = 0;
                    590:         return(hData);
                    591:         break;
                    592: 
                    593:     case XTYP_ADVSTART:
                    594:         return(1);
                    595:     }
                    596:     return(0);
                    597: }
                    598: 
                    599: 
                    600: HDDEDATA HelpXfer(
                    601: PXFERINFO pXferInfo,
                    602: WORD iFmt)
                    603: {
                    604:     HDDEDATA hData;
                    605: 
                    606:     switch (pXferInfo->wType) {
                    607:     case XTYP_REQUEST:
                    608:         pszComment = "Help text requested.";
                    609:         InvalidateRect(hwndServer, &rcComment, TRUE);
                    610:     case XTYP_ADVREQ:
                    611:         if (!hDataHelp[iFmt]) {
                    612:             hDataHelp[iFmt] = DdeCreateDataHandle(idInst, szDdeHelp, strlen(szDdeHelp) + 1,
                    613:                     0, pXferInfo->hszItem, pXferInfo->wFmt, fAppowned ? HDATA_APPOWNED : 0);
                    614:         }
                    615:         hData = hDataHelp[iFmt];
                    616:         if (!fAppowned)
                    617:             hDataHelp[iFmt] = 0;
                    618:         return(hData);
                    619:         break;
                    620: 
                    621:     case XTYP_ADVSTART:
                    622:         return(1);
                    623:     }
                    624:     return(0);
                    625: }
                    626: 
                    627: 
                    628: /***************************** Private Function ****************************\
                    629: *  This creates often used global hszs from standard global strings.
                    630: *  It also fills the hsz fields of the topic and item tables.
                    631: *
                    632: \***************************************************************************/
                    633: VOID Hszize()
                    634: {
                    635:     register ITEMLIST *pItemList;
                    636:     WORD iTopic, iItem;
                    637: 
                    638:     hszAppName = DdeCreateStringHandle(idInst, szServer, 0);
                    639: 
                    640:     for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
                    641:         topicList[iTopic].hszTopic =
                    642:                 DdeCreateStringHandle(idInst, topicList[iTopic].pszTopic, 0);
                    643:         pItemList = topicList[iTopic].pItemList;
                    644:         for (iItem = 0; iItem < topicList[iTopic].cItems; iItem++) {
                    645:             pItemList[iItem].hszItem =
                    646:                     DdeCreateStringHandle(idInst, pItemList[iItem].pszItem, 0);
                    647:         }
                    648:     }
                    649: }
                    650: 
                    651: 
                    652: 
                    653: 
                    654: 
                    655: /***************************** Private Function ****************************\
                    656: *  This destroys often used global hszs from standard global strings.
                    657: *
                    658: \***************************************************************************/
                    659: VOID UnHszize()
                    660: {
                    661:     register ITEMLIST *pItemList;
                    662:     WORD iTopic, iItem;
                    663: 
                    664:     DdeFreeStringHandle(idInst, hszAppName);
                    665: 
                    666:     for (iTopic = 0; iTopic < CTOPICS; iTopic++) {
                    667:         DdeFreeStringHandle(idInst, topicList[iTopic].hszTopic);
                    668:         pItemList = topicList[iTopic].pItemList;
                    669:         for (iItem = 0; iItem < topicList[iTopic].cItems; iItem++) {
                    670:             DdeFreeStringHandle(idInst, pItemList[iItem].hszItem);
                    671:         }
                    672:     }
                    673: }
                    674: 
                    675: 

unix.superglobalmegacorp.com

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