Annotation of mstools/samples/ddeml/ddeprog/proghelp.c, revision 1.1

1.1     ! root        1: /*****************************************************************************\
        !             2: * PROGHELP.C
        !             3: *
        !             4: * Main module to implement a simple DDEML service DLL that makes interaction
        !             5: * with progman simple.
        !             6: \*****************************************************************************/
        !             7: 
        !             8: #include <windows.h>
        !             9: #include <ddeml.h>
        !            10: #include <string.h>
        !            11: 
        !            12: typedef struct {
        !            13:     HCONV hConv;
        !            14:     DWORD idInst;
        !            15:     int cTransactionsInProgress;
        !            16: } THREADINFO;
        !            17: 
        !            18: DWORD TlsIndex;
        !            19: 
        !            20: /*
        !            21:  * This is the default DDEML callback function for ProgHelp
        !            22:  */
        !            23: HDDEDATA CALLBACK ProgHelpDdeCallback(
        !            24: UINT wType,
        !            25: UINT wFmt,
        !            26: HCONV hConv,
        !            27: HSZ hsz1,
        !            28: HSZ hsz2,
        !            29: HDDEDATA hData,
        !            30: DWORD dwData1,
        !            31: DWORD dwData2)
        !            32: {
        !            33:     THREADINFO *pti;
        !            34: 
        !            35:     switch (wType) {
        !            36:     case XTYP_XACT_COMPLETE:
        !            37:         pti = TlsGetValue(TlsIndex);
        !            38:         pti->cTransactionsInProgress--;
        !            39:         break;
        !            40:     }
        !            41:     return(0);
        !            42: }
        !            43: 
        !            44: 
        !            45: /*
        !            46:  * This is the DLL init routine called by the system at attach/detatch time.
        !            47:  *
        !            48:  * We allocate a Tls for each thread that calls this DLL so that their state
        !            49:  * can be tracked independently.
        !            50:  */
        !            51: BOOLEAN APIENTRY ProgHelpInit(
        !            52: IN PVOID hmod,
        !            53: ULONG Reason,
        !            54: IN PCONTEXT pctx OPTIONAL)
        !            55: {
        !            56:     THREADINFO *pti;
        !            57:     UNREFERENCED_PARAMETER(hmod);
        !            58:     UNREFERENCED_PARAMETER(pctx);
        !            59: 
        !            60:     switch (Reason) {
        !            61:     case DLL_THREAD_ATTACH:
        !            62:     case DLL_PROCESS_ATTACH:
        !            63:         TlsIndex = TlsAlloc();
        !            64:         pti = (THREADINFO *)LocalAlloc(LPTR, sizeof(THREADINFO));
        !            65:         if (!pti) {
        !            66:             return(FALSE);
        !            67:         }
        !            68:         TlsSetValue(TlsIndex, pti);
        !            69:         break;
        !            70: 
        !            71:     case DLL_THREAD_DETACH:
        !            72:     case DLL_PROCESS_DETACH:
        !            73:         pti = TlsGetValue(TlsIndex);
        !            74:         LocalFree(pti);
        !            75:         TlsFree(TlsIndex);
        !            76:         break;
        !            77:     }
        !            78:     return TRUE;
        !            79: }
        !            80: 
        !            81: /*
        !            82:  * An application must call this API first to establish a conversation
        !            83:  * with progman.  DDEML initialization is done automatically if needed.
        !            84:  */
        !            85: BOOL ConnectToProgman()
        !            86: {
        !            87:     THREADINFO *pti;
        !            88:     HSZ hszProgman;
        !            89: 
        !            90:     pti = TlsGetValue(TlsIndex);
        !            91: 
        !            92:     if (!pti->idInst) {
        !            93:         if (DdeInitialize(&(pti->idInst), ProgHelpDdeCallback,
        !            94:                 APPCMD_CLIENTONLY | CBF_SKIP_ALLNOTIFICATIONS,
        !            95:                 0L) != DMLERR_NO_ERROR) {
        !            96:             return(FALSE);
        !            97:         }
        !            98:     }
        !            99: 
        !           100:     if (pti->hConv == 0) {
        !           101:         hszProgman = DdeCreateStringHandle(pti->idInst, "Progman", 0);
        !           102:         pti->hConv = DdeConnect(pti->idInst, hszProgman, hszProgman, NULL);
        !           103:     }
        !           104:     return(pti->hConv != 0);
        !           105: }
        !           106: 
        !           107: /*
        !           108:  * This API should be called when operations with progman are complete.
        !           109:  * We shutdown DDEML here as well so we don't have to deal with it
        !           110:  * at DLL detatch time.  FALSE is returned if there are any transactions
        !           111:  * still in progress.  This lets the calling application know that it
        !           112:  * must wait awhile longer for progman to complete its processing and
        !           113:  * then try disconnecting again later.
        !           114:  */
        !           115: BOOL DisconnectFromProgman()
        !           116: {
        !           117:     THREADINFO *pti;
        !           118: 
        !           119:     pti = TlsGetValue(TlsIndex);
        !           120: 
        !           121:     if (pti->cTransactionsInProgress) {
        !           122:         return(FALSE);
        !           123:     }
        !           124: 
        !           125:     if (!pti->idInst) {
        !           126:         return(TRUE);
        !           127:     }
        !           128: 
        !           129:     if (pti->hConv) {
        !           130:         DdeDisconnect(pti->hConv);
        !           131:         pti->hConv = 0;
        !           132:     }
        !           133: 
        !           134:     DdeUninitialize(pti->idInst);
        !           135:     return(TRUE);
        !           136: }
        !           137: 
        !           138: 
        !           139: /*
        !           140:  * This API sends an ASCII execute string to progman.  It immediately returns
        !           141:  * and the results of the execute are not known.  Calling applications should
        !           142:  * be aware that these transactions are done asynchronously.  This allows
        !           143:  * this API to work under modal-loop conditions.  DisconnectFromProgman()
        !           144:  * will not succeed until all transactions are complete.
        !           145:  */
        !           146: BOOL ProgmanExecuteString(
        !           147: LPCSTR pszExec)
        !           148: {
        !           149:     THREADINFO *pti;
        !           150:     DWORD dwResult;
        !           151: 
        !           152:     pti = TlsGetValue(TlsIndex);
        !           153: 
        !           154:     if (!pti->idInst || !pti->hConv) {
        !           155:         return(FALSE);
        !           156:     }
        !           157:     if (!DdeClientTransaction((PBYTE)pszExec, strlen(pszExec) + 1,
        !           158:             pti->hConv, 0, 0, XTYP_EXECUTE, TIMEOUT_ASYNC, &dwResult)) {
        !           159:         return(FALSE);
        !           160:     }
        !           161:     pti->cTransactionsInProgress++;
        !           162:     return(TRUE);
        !           163: }
        !           164: 
        !           165: 
        !           166: 

unix.superglobalmegacorp.com

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