Annotation of mstools/samples/ddeml/client/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:  *                                                                         *
                     14:  *  MODULE      : dde.c                                                    *
                     15:  *                                                                         *
                     16:  *  PURPOSE     : Contains routines for handling of DDE interaction with   *
                     17:  *                DDEML.                                                   *
                     18:  *                                                                         *
                     19:  ***************************************************************************/
                     20: #include "client.h"
                     21: #include <string.h>
                     22: #include <memory.h>
                     23: #include "infoctrl.h"
1.1.1.2   root       24: #include "huge.h"
1.1       root       25: 
                     26: CHAR szT[100];
                     27: 
                     28: /****************************************************************************
                     29:  *                                                                          *
                     30:  *  FUNCTION   : CreateXactionWindow()                                      *
                     31:  *                                                                          *
                     32:  *  PURPOSE    : Creates a transaction window for the given transaction     *
                     33:  *               under the given conversation window.                       *
                     34:  *                                                                          *
                     35:  *  RETURNS    : TRUE  - If successful.                                     *
                     36:  *               FALSE - otherwise.                                         *
                     37:  *                                                                          *
                     38:  ****************************************************************************/
                     39: HWND CreateXactionWindow(
                     40: HWND hwndMDI,
                     41: XACT *pxact)
                     42: {
                     43:     PSTR pszFmt, pszItem;
                     44:     PSTR pData;
                     45:     HWND hwnd;
                     46: 
                     47:     pszItem = GetHSZName(pxact->hszItem);
                     48:     pszFmt = GetFormatName(pxact->wFmt);
                     49:     pData = GetTextData(pxact->hDdeData);
                     50: 
                     51:     /*
                     52:      *   �type/opts������� ITEM ���������������retĿ    GWL_USER=pxact
                     53:      *   �                                         �
                     54:      *   �                                         �
                     55:      *   �                                         �
                     56:      *   �                                         �
                     57:      *   �                 DATA                    �
                     58:      *   �                                         �
                     59:      *   �                                         �
                     60:      *   �                                         �
                     61:      *   �                                         �
                     62:      *   �state/error����� FORMAT ����������Result��
                     63:      */
                     64:     hwnd = CreateInfoCtrl((LPSTR)pData,
                     65:             (INT)SendMessage(hwndMDI, UM_GETNEXTCHILDX, 0, 0L),
                     66:             (INT)SendMessage(hwndMDI, UM_GETNEXTCHILDY, 0, 0L),
                     67:             200, 100, hwndMDI, hInst,
                     68:             Type2String(pxact->wType, pxact->fsOptions), pszItem, NULL,
                     69:             "Starting", (LPSTR)pszFmt, NULL,
                     70:             ICSTY_SHOWFOCUS, 0, (DWORD)(LPSTR)pxact);
                     71:     MyFree(pszItem);
                     72:     MyFree(pszFmt);
                     73:     MyFree(pData);
                     74:     return(hwnd);
                     75: }
                     76: 
                     77: 
                     78: 
                     79: 
                     80: /****************************************************************************
                     81:  *                                                                          *
                     82:  *  FUNCTION   : ProcessTransaction()                                       *
                     83:  *                                                                          *
                     84:  *  PURPOSE    : Processes synchronous transactions entirely and starts     *
                     85:  *               async transactions.  Transaction attempts result in a      *
                     86:  *               transaction window being created which displays the state  *
                     87:  *               or results of the transaction.  (the callback function     *
                     88:  *               updates these windows as it gets calls) Transaction        *
                     89:  *               windows stay around until abandoned by the user or until   *
                     90:  *               the conversation is disconnected.  Advise Data and Advise  *
                     91:  *               Stop transactions are special.  We don't create a new      *
                     92:  *               window if the associated advise start transaction window   *
                     93:  *               can be found.                                              *
                     94:  *                                                                          *
                     95:  *  RETURNS    : TRUE  - If successful.                                     *
                     96:  *               FALSE - otherwise.                                         *
                     97:  *                                                                          *
                     98:  ****************************************************************************/
                     99: BOOL ProcessTransaction(
                    100: XACT *pxact)
                    101: {
                    102:     CONVINFO ci;
                    103:     HWND hwndInfoCtrl = 0;
                    104: 
                    105:     /* create transaction window to show we tried (except in ADVSTOP case) */
                    106: 
                    107:     pxact = (XACT *)memcpy(MyAlloc(sizeof(XACT)), (PSTR)pxact, sizeof(XACT));
                    108:     ci.cb = sizeof(CONVINFO);
                    109:     DdeQueryConvInfo(pxact->hConv, QID_SYNC, &ci); // ci.hUser==hConv
                    110:     if (pxact->wType == XTYP_ADVSTOP) {
                    111:         hwndInfoCtrl = FindAdviseChild((HWND)ci.hUser, pxact->hszItem,
                    112:                 pxact->wFmt);
                    113:         if (hwndInfoCtrl) {
                    114:             SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_UL,
                    115:                     (DWORD)(LPSTR)Type2String(pxact->wType, pxact->fsOptions));
                    116:             DdeFreeStringHandle(idInst, pxact->hszItem);
                    117:         }
                    118:     }
                    119:     /*
                    120:      * If we still need to create a transaction window, do so here.
                    121:      */
                    122:     if (!hwndInfoCtrl) {
                    123:         hwndInfoCtrl = CreateXactionWindow((HWND)ci.hUser, pxact);
                    124:         if (!hwndInfoCtrl) {
                    125:             MyFree(pxact);
                    126:             return 0;
                    127:         }
                    128:         SetFocus(hwndInfoCtrl);
                    129:     }
                    130:     /*
                    131:      * Disable callbacks for this conversation now if the XOPT_DISABLEFIRST
                    132:      * option is set.  This tests disabling asynchronous transactions
                    133:      * before they are completed.
                    134:      */
                    135:     if (pxact->fsOptions & XOPT_DISABLEFIRST)
                    136:         DdeEnableCallback(idInst, pxact->hConv, EC_DISABLE);
                    137:     /*
                    138:      * Adjust the timeout for asynchronous transactions.
                    139:      */
                    140:     if (pxact->fsOptions & XOPT_ASYNC)
                    141:         pxact->ulTimeout = TIMEOUT_ASYNC;
                    142: 
                    143:     /*
                    144:      * start transaction with DDEML here
                    145:      */
                    146:     pxact->ret = DdeClientTransaction((LPBYTE)pxact->hDdeData, 0xFFFFFFFF,
                    147:             pxact->hConv, pxact->hszItem, pxact->wFmt,
                    148:             pxact->wType,
                    149:             pxact->ulTimeout, (LPDWORD)&pxact->Result);
                    150: 
                    151:     /*
                    152:      * show return value in transaction window
                    153:      */
                    154:     wsprintf(szT, "ret=%lx", pxact->ret);
                    155:     SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_UR, (DWORD)(LPSTR)szT);
                    156: 
                    157:     /*
                    158:      * show result or ID value in transaction window
                    159:      */
                    160:     wsprintf(szT, pxact->fsOptions & XOPT_ASYNC ? "ID=%ld" :
                    161:             "result=0x%lx", pxact->Result);
                    162:     SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LR, (DWORD)(LPSTR)szT);
                    163: 
                    164:     if ((pxact->fsOptions & XOPT_ASYNC) && pxact->ret) {
                    165:         /*
                    166:          * asynchronous successful start - link transaction to window.
                    167:          */
                    168:         DdeSetUserHandle(pxact->hConv, pxact->Result, (DWORD)hwndInfoCtrl);
                    169: 
                    170:         /*
                    171:          * Abandon started async transaction after initiated if
                    172:          * XOPT_ABANDONAFTERSTART is chosen.  This tests the mid-transaction
                    173:          * abandoning code.
                    174:          */
                    175:         if (pxact->fsOptions & XOPT_ABANDONAFTERSTART)
                    176:             DdeAbandonTransaction(idInst, pxact->hConv, pxact->Result);
                    177:         /*
                    178:          * show actual status
                    179:          */
                    180:         ci.cb = sizeof(CONVINFO);
                    181:         DdeQueryConvInfo(pxact->hConv, pxact->Result, &ci);
                    182:         SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LL,
                    183:                 (DWORD)(LPSTR)State2String(ci.wConvst));
                    184:     } else {
                    185:         /*
                    186:          * Synchronous transactions are completed already so pass on to
                    187:          * CompleteTransaction right away.
                    188:          */
                    189:         CompleteTransaction(hwndInfoCtrl, pxact);
                    190:     }
                    191:     return TRUE;
                    192: }
                    193: 
                    194: 
                    195: 
                    196: 
                    197: 
                    198: /****************************************************************************
                    199:  *                                                                          *
                    200:  *  FUNCTION   : CompleteTransaction()                                      *
                    201:  *                                                                          *
                    202:  *  PURPOSE    : This handles completed synchronous and asynchronous        *
                    203:  *               transactions as well as failed attempted transactions.     *
                    204:  *                                                                          *
                    205:  *  RETURNS    : TRUE  - If successful.                                     *
                    206:  *               FALSE - otherwise.                                         *
                    207:  *                                                                          *
                    208:  ****************************************************************************/
                    209: VOID CompleteTransaction(
                    210: HWND hwndInfoCtrl,
                    211: XACT *pxact)
                    212: {
                    213:     PSTR psz;
                    214: 
                    215:     if (pxact->ret) {
                    216:         /*
                    217:          * Successful transaction case
                    218:          */
                    219:         SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LL,
                    220:                 (DWORD)(LPSTR)"Completed");
                    221: 
                    222:         if (pxact->wType == XTYP_REQUEST) {
                    223:             /*
                    224:              * Show resulting data
                    225:              */
                    226:             psz = GetTextData((HDDEDATA)pxact->ret);
1.1.1.2   root      227:             if (!DdeCmpStringHandles(pxact->hszItem, hszHuge) &&
                    228:                     !CheckHugeData((HDDEDATA)pxact->ret)) {
                    229:                 SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_CENTER,
                    230:                         (DWORD)(LPSTR)"Invalid Huge Data");
                    231:             } else {
                    232:                 SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_CENTER,
                    233:                         (DWORD)(LPSTR)psz);
                    234:             }
1.1       root      235:             MyFree(psz);
                    236:             /*
                    237:              * free returned data since it is displayed.
                    238:              */
                    239:             DdeFreeDataHandle(pxact->ret);
                    240:             pxact->ret = 0L;
1.1.1.3 ! root      241:             SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_UR, 0);
1.1       root      242:         }
                    243:     } else {
                    244:         /*
                    245:          * failed - show error result.
                    246:          */
                    247:         SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LL,
                    248:                 (DWORD)(LPSTR)Error2String(DdeGetLastError(idInst)));
                    249:     }
                    250:     pxact->fsOptions |= XOPT_COMPLETED;
                    251: }
                    252: 
                    253: 
                    254: 
                    255: 
                    256: /****************************************************************************
                    257:  *                                                                          *
                    258:  *  FUNCTION   : DdeCallback()                                              *
                    259:  *                                                                          *
                    260:  *  PURPOSE    : This handles all callbacks from the DDEML.  This handles   *
                    261:  *               updating of the associated conversation and any special    *
                    262:  *               testing cases such as blocking callbacks etc.              *
                    263:  *                                                                          *
                    264:  *               For the most part, clients only handle advise data and     *
                    265:  *               asynchronous transaction completion here.                  *
                    266:  *                                                                          *
                    267:  *  RETURNS    : Results vary depending on transaction type.                *
                    268:  *                                                                          *
                    269:  ****************************************************************************/
                    270: HDDEDATA CALLBACK DdeCallback(
                    271: UINT wType,
                    272: UINT wFmt,
                    273: HCONV hConv,
                    274: HSZ hsz1,
                    275: HSZ hsz2,
                    276: HDDEDATA hData,
                    277: DWORD lData1,
                    278: DWORD lData2)
                    279: {
                    280:     HWND hwnd;
                    281:     CONVINFO ci;
                    282:     XACT *pxact;
                    283: 
                    284:     if (hConv) {
                    285:         /*
                    286:          * update conversation status if it changed.
                    287:          */
                    288:         MYCONVINFO *pmci;
                    289: 
                    290:         ci.cb = sizeof(CONVINFO);
                    291:         if (!DdeQueryConvInfo(hConv, QID_SYNC, &ci) || (!IsWindow((HWND)ci.hUser))) {
                    292:             /*
                    293:              * This conversation does not yet have a corresponding MDI window
                    294:              * or is disconnected.
                    295:              */
                    296:             return 0;
                    297:         }
                    298:         if (pmci = (MYCONVINFO *)GetWindowLong((HWND)ci.hUser, 0)) {
                    299:             if (pmci->ci.wStatus != ci.wStatus ||
                    300:                     pmci->ci.wConvst != ci.wConvst ||
                    301:                     pmci->ci.wLastError != ci.wLastError) {
                    302:                 /*
                    303:                  * Things have changed, updated the conversation window.
                    304:                  */
                    305:                 InvalidateRect((HWND)ci.hUser, NULL, TRUE);
                    306:             }
                    307:             if (ci.wConvst & ST_INLIST) {
                    308:                 /*
                    309:                  * update the associated list window (if any) as well.
                    310:                  */
                    311:                 if (hwnd = FindListWindow(ci.hConvList))
                    312:                     InvalidateRect(hwnd, NULL, TRUE);
                    313:             }
                    314:         }
                    315:     }
                    316: 
                    317:     /*
                    318:      * handle special block on next callback option here.  This demonstrates
                    319:      * the CBR_BLOCK feature.
                    320:      */
                    321:     if (fBlockNextCB && !(wType & XTYPF_NOBLOCK)) {
                    322:         fBlockNextCB = FALSE;
                    323:         return(CBR_BLOCK);
                    324:     }
                    325: 
                    326:     /*
                    327:      * handle special termination here.  This demonstrates that at any time
                    328:      * a client can drop a conversation.
                    329:      */
                    330:     if (fTermNextCB && hConv && wType != XTYP_DISCONNECT) {
                    331:         fTermNextCB = FALSE;
                    332:         MyDisconnect(hConv);
                    333:         return(0);
                    334:     }
                    335: 
                    336:     /*
                    337:      * Now we begin sort out what to do.
                    338:      */
                    339:     switch (wType) {
                    340:     case XTYP_REGISTER:
                    341:     case XTYP_UNREGISTER:
                    342:         /*
                    343:          * This is where the client would insert code to keep track of
                    344:          * what servers are available.  This could cause the initiation
                    345:          * of some conversations.
                    346:          */
                    347:         break;
                    348: 
                    349:     case XTYP_DISCONNECT:
                    350:         if (fAutoReconnect) {
                    351:             /*
                    352:              * attempt a reconnection
                    353:              */
                    354:             if (hConv = DdeReconnect(hConv)) {
                    355:                 AddConv(ci.hszServiceReq, ci.hszTopic, hConv, FALSE);
                    356:                 return 0;
                    357:             }
                    358:         }
                    359: 
                    360:         /*
                    361:          * update conv window to show its new state.
                    362:          */
                    363:         SendMessage((HWND)ci.hUser, UM_DISCONNECTED, 0, 0);
                    364:         return 0;
                    365:         break;
                    366: 
                    367:     case XTYP_ADVDATA:
                    368:         /*
                    369:          * data from an active advise loop (from a server)
                    370:          */
                    371:         Delay(wDelay);
                    372:         hwnd = FindAdviseChild((HWND)ci.hUser, hsz2, wFmt);
                    373:         if (!IsWindow(hwnd)) {
                    374:             PSTR pszItem, pszFmt;
                    375:             /*
                    376:              * AdviseStart window is gone, make a new one.
                    377:              */
                    378:             pxact = (XACT *)MyAlloc(sizeof(XACT));
                    379:             pxact->wType = wType;
                    380:             pxact->hConv = hConv;
                    381:             pxact->wFmt = wFmt;
                    382:             pxact->hszItem = hsz2;
                    383:             DdeKeepStringHandle(idInst, hsz2);
                    384: 
                    385:             pszItem = GetHSZName(hsz2);
                    386:             pszFmt = GetFormatName(wFmt);
                    387: 
                    388:             hwnd = CreateInfoCtrl(NULL,
                    389:                     (INT)SendMessage((HWND)ci.hUser, UM_GETNEXTCHILDX, 0, 0L),
                    390:                     (INT)SendMessage((HWND)ci.hUser, UM_GETNEXTCHILDY, 0, 0L),
                    391:                     200, 100,
                    392:                     (HWND)ci.hUser, hInst,
                    393:                     Type2String(wType, 0), (LPSTR)pszItem, NULL,
                    394:                     NULL, (LPSTR)pszFmt, NULL,
                    395:                     ICSTY_SHOWFOCUS, 0, (DWORD)(LPSTR)pxact);
                    396: 
                    397:             MyFree(pszFmt);
                    398:             MyFree(pszItem);
                    399: 
                    400:             if (!IsWindow(hwnd))
                    401:                 return(DDE_FNOTPROCESSED);
                    402:         }
                    403:         if (!hData) {
                    404:             /*
                    405:              * XTYPF_NODATA case - request the info. (we do this synchronously
                    406:              * for simplicity)
                    407:              */
                    408:             hData = DdeClientTransaction(NULL, 0L, hConv, hsz2, wFmt,
                    409:                     XTYP_REQUEST, DefTimeout, NULL);
                    410:         }
                    411:         if (hData) {
                    412:             PSTR pData;
                    413:             /*
                    414:              * Show incomming data on corresponding transaction window.
                    415:              */
                    416:             pData = GetTextData(hData);
                    417:             SendMessage(hwnd, ICM_SETSTRING, ICSID_CENTER, (DWORD)(LPSTR)pData);
                    418:             MyFree(pData);
                    419:             DdeFreeDataHandle(hData);
                    420:         }
                    421:         SendMessage(hwnd, ICM_SETSTRING, ICSID_LL, (DWORD)(LPSTR)"Advised");
                    422:         return(DDE_FACK);
                    423:         break;
                    424: 
                    425:     case XTYP_XACT_COMPLETE:
                    426:         /*
                    427:          * An asynchronous transaction has completed.  Show the results.
                    428:          *
                    429:          * ...unless the XOPT_BLOCKRESULT is chosen.
                    430:          */
                    431: 
                    432:         ci.cb = sizeof(CONVINFO);
                    433:         if (DdeQueryConvInfo(hConv, lData1, &ci) &&
                    434:                 IsWindow((HWND)ci.hUser) &&
                    435:                 (pxact = (XACT *)GetWindowLong((HWND)ci.hUser, GWL_USER))) {
                    436: 
                    437:             if (pxact->fsOptions & XOPT_BLOCKRESULT) {
                    438:                 pxact->fsOptions &= ~XOPT_BLOCKRESULT;
                    439:                 return(CBR_BLOCK);
                    440:             }
                    441: 
                    442:             pxact->Result = lData2;
                    443:             pxact->ret = hData;
                    444:             CompleteTransaction((HWND)ci.hUser, pxact);
                    445:         }
                    446:         break;
                    447:     }
                    448: }
                    449: 
                    450: 
                    451: 
                    452: 
                    453: 
                    454: 
                    455: 
                    456: /****************************************************************************
                    457:  *                                                                          *
                    458:  *  FUNCTION   : FindAdviseChild()                                          *
                    459:  *                                                                          *
                    460:  *  PURPOSE    : Search through the child windows of hwndMDI for an info    *
                    461:  *               ctrl that has the same Item and format and is an           *
                    462:  *               ADVSTART ADVSTOP or ADVDATA transaction window.            *
                    463:  *                                                                          *
                    464:  *               We use these to show the associated advise data.           *
                    465:  *                                                                          *
                    466:  *  RETURNS    : The transaction window handle or 0 on failure.             *
                    467:  *                                                                          *
                    468:  ****************************************************************************/
                    469: HWND FindAdviseChild(
                    470: HWND hwndMDI,
                    471: HSZ hszItem,
                    472: DWORD wFmt)
                    473: {
                    474:     HWND hwnd, hwndStart;
                    475:     XACT *pxact;
                    476: 
                    477:     if (!IsWindow(hwndMDI))
                    478:         return 0;
                    479: 
                    480:     hwnd = hwndStart = GetWindow(hwndMDI, GW_CHILD);
                    481:     while (hwnd && IsChild(hwndMDI, hwnd)) {
                    482:         pxact = (XACT *)GetWindowLong(hwnd, GWL_USER);
                    483:         if (pxact &&
                    484:                 (pxact)->wFmt == wFmt &&
                    485:                 (pxact)->hszItem == hszItem &&
                    486:                 (
                    487:                     ((pxact->wType & XTYP_ADVSTART) == XTYP_ADVSTART) ||
                    488:                     (pxact->wType == XTYP_ADVSTOP) ||
                    489:                     (pxact->wType == XTYP_ADVDATA)
                    490:                 )
                    491:            ) {
                    492:             return(hwnd);
                    493:         }
                    494:         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
                    495:         if (hwnd == hwndStart)
                    496:             return 0;
                    497:     }
                    498:     return 0;
                    499: }
                    500: 
                    501: 
                    502: 
                    503: /****************************************************************************
                    504:  *                                                                          *
                    505:  *  FUNCTION   : FindListWindow()                                           *
                    506:  *                                                                          *
                    507:  *  PURPOSE    : Locates the list window associated with this conversation  *
                    508:  *               list.                                                      *
                    509:  *                                                                          *
                    510:  *  RETURNS    : The window handle of the list window or 0 on failure.      *
                    511:  *                                                                          *
                    512:  ****************************************************************************/
                    513: HWND FindListWindow(
                    514: HCONVLIST hConvList)
                    515: {
                    516:     HWND hwnd;
                    517:     MYCONVINFO *pmci;
                    518: 
                    519:     hwnd = GetWindow(hwndMDIClient, GW_CHILD);
                    520:     while (hwnd) {
                    521:         if (GetWindowLong(hwnd, GWL_WNDPROC) == (LONG)MDIChildWndProc) {
                    522:             pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
                    523:             if (pmci != NULL && pmci->fList && pmci->hConv == hConvList)
                    524:                 return(hwnd);
                    525:         }
                    526:         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
                    527:     }
                    528:     return 0;
                    529: }
                    530: 
                    531: 
                    532: 
                    533: 
                    534: /****************************************************************************
                    535:  *                                                                          *
                    536:  *  FUNCTION   : GetTextData()                                              *
                    537:  *                                                                          *
                    538:  *  PURPOSE    : Allocates and returns a pointer to the data contained in   *
                    539:  *               hData.  This assumes that hData points to text data and    *
                    540:  *               will properly handle huge text data by leaving out the     *
                    541:  *               middle of the string and placing the size of the string    *
                    542:  *               into this string portion.                                  *
                    543:  *                                                                          *
                    544:  *  RETURNS    : A pointer to the allocated string.                         *
                    545:  *                                                                          *
                    546:  ****************************************************************************/
                    547: PSTR GetTextData(
                    548: HDDEDATA hData)
                    549: {
                    550:     PSTR psz;
                    551:     DWORD cb;
                    552: 
                    553: #define CBBUF  1024
                    554: 
1.1.1.3 ! root      555:     if (hData == 0) {
1.1       root      556:         return(NULL);
                    557:     }
                    558: 
                    559:     cb = DdeGetData(hData, NULL, 0, 0);
                    560:     if (!hData || !cb)
                    561:         return NULL;
                    562: 
                    563:     if (cb > CBBUF) {                // possibly HUGE object!
                    564:         psz = MyAlloc(CBBUF);
                    565:         DdeGetData(hData, psz, CBBUF - 46, 0L);
                    566:         wsprintf(&psz[CBBUF - 46], "<---Size=%ld", cb);
                    567:     } else {
                    568:         psz = MyAlloc((DWORD)cb);
                    569:         DdeGetData(hData, (LPBYTE)psz, cb, 0L);
                    570:     }
                    571:     return psz;
                    572: #undef CBBUF
                    573: }
                    574: 
                    575: 
                    576: 
                    577: 
                    578: 
                    579: 
                    580: 
                    581: /****************************************************************************
                    582:  *                                                                          *
                    583:  *  FUNCTION   : MyGetClipboardFormatName()                                 *
                    584:  *                                                                          *
                    585:  *  PURPOSE    : Properly retrieves the string associated with a clipboard  *
                    586:  *               format.  If the format does not have a string associated   *
                    587:  *               with it, the string #dddd is returned.                     *
                    588:  *                                                                          *
                    589:  *  RETURNS    : The number of characters copied into lpstr or 0 on error.  *
                    590:  *                                                                          *
                    591:  ****************************************************************************/
                    592: INT MyGetClipboardFormatName(
                    593: DWORD fmt,
                    594: LPSTR lpstr,
                    595: INT cbMax)
                    596: {
                    597:     if (fmt < 0xc000) {
                    598:         // predefined or integer format - just get the atom string
                    599:         // wierdly enough, GetClipboardFormatName() doesn't support this.
1.1.1.2   root      600:         return(GlobalGetAtomName((ATOM)fmt, lpstr, cbMax));
1.1       root      601:     } else {
                    602:         return(GetClipboardFormatName(fmt, lpstr, cbMax));
                    603:     }
                    604: }
                    605: 
                    606: 
                    607: 
                    608: 
                    609: 
                    610: /****************************************************************************
                    611:  *                                                                          *
                    612:  *  FUNCTION   : GetFormatName()                                            *
                    613:  *                                                                          *
                    614:  *  PURPOSE    : allocates and returns a pointer to a string representing   *
                    615:  *               a format.  Use MyFree() to free this string.               *
                    616:  *                                                                          *
                    617:  *  RETURNS    : The number of characters copied into lpstr or 0 on error.  *
                    618:  *                                                                          *
                    619:  ****************************************************************************/
                    620: PSTR GetFormatName(
                    621: DWORD wFmt)
                    622: {
                    623:     PSTR psz;
                    624:     DWORD cb;
                    625: 
                    626:     if (wFmt == 1) {
                    627:         psz = MyAlloc(8);
                    628:         strcpy(psz, "CF_TEXT");
                    629:         return psz;
                    630:     }
                    631:     psz = MyAlloc(255);
                    632:     *psz = '\0';
                    633:     cb = GetClipboardFormatName(wFmt, psz, 255) + 1;
                    634:     return((PSTR)LocalReAlloc((HANDLE)psz, cb, LMEM_MOVEABLE));
                    635: }
                    636: 
                    637: 
                    638: 
                    639: 
                    640: /****************************************************************************
                    641:  *                                                                          *
                    642:  *  FUNCTION   : MyDisconnect()                                             *
                    643:  *                                                                          *
                    644:  *  PURPOSE    : Disconnects the given conversation after updating the      *
                    645:  *               associated conversation window.                            *
                    646:  *                                                                          *
                    647:  *  RETURNS    : TRUE on success, FALSE on failuer.                         *
                    648:  *                                                                          *
                    649:  ****************************************************************************/
                    650: BOOL MyDisconnect(
                    651: HCONV hConv)
                    652: {
                    653:     CONVINFO ci;
                    654:     HWND hwnd;
                    655:     // before we disconnect, invalidate the associated list window - if
                    656:     // applicable.
                    657: 
                    658:     ci.cb = sizeof(CONVINFO);
                    659: 
                    660:     if (DdeQueryConvInfo(hConv, QID_SYNC, &ci) && ci.hConvList &&
                    661:             (hwnd = FindListWindow(ci.hConvList)))
                    662:         InvalidateRect(hwnd, NULL, TRUE);
                    663:     return(DdeDisconnect(hConv));
                    664: }

unix.superglobalmegacorp.com

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