|
|
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.