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

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

unix.superglobalmegacorp.com

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