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

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

unix.superglobalmegacorp.com

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