|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.