|
|
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: } THREADINFO;
16:
17: DWORD TlsIndex;
18:
19: /*
20: * This is the default DDEML callback function for ProgHelp
21: */
22: HDDEDATA CALLBACK ProgHelpDdeCallback(
23: UINT wType,
24: UINT wFmt,
25: HCONV hConv,
26: HSZ hsz1,
27: HSZ hsz2,
28: HDDEDATA hData,
29: DWORD dwData1,
30: DWORD dwData2)
31: {
32: return(0);
33: }
34:
35:
36: /*
37: * This is the DLL init routine called by the system at attach/detatch time.
38: *
39: * We allocate a Tls for each thread that calls this DLL so that their state
40: * can be tracked independently.
41: */
42: BOOLEAN APIENTRY ProgHelpInit(
43: IN PVOID hmod,
44: ULONG Reason,
45: IN PCONTEXT pctx OPTIONAL)
46: {
47: THREADINFO *pti;
48: UNREFERENCED_PARAMETER(hmod);
49: UNREFERENCED_PARAMETER(pctx);
50:
51: switch (Reason) {
52: case DLL_PROCESS_ATTACH:
53: TlsIndex = TlsAlloc();
1.1.1.2 ! root 54:
! 55: case DLL_THREAD_ATTACH:
1.1 root 56: pti = (THREADINFO *)LocalAlloc(LPTR, sizeof(THREADINFO));
57: if (!pti) {
58: return(FALSE);
59: }
60: TlsSetValue(TlsIndex, pti);
61: break;
62:
63: case DLL_THREAD_DETACH:
64: case DLL_PROCESS_DETACH:
65: pti = TlsGetValue(TlsIndex);
66: LocalFree(pti);
1.1.1.2 ! root 67: if (Reason == DLL_PROCESS_DETACH) {
! 68: TlsFree(TlsIndex);
! 69: }
1.1 root 70: break;
71: }
72: return TRUE;
73: }
74:
75: /*
76: * An application must call this API first to establish a conversation
77: * with progman. DDEML initialization is done automatically if needed.
78: */
79: BOOL ConnectToProgman()
80: {
81: THREADINFO *pti;
82: HSZ hszProgman;
83:
84: pti = TlsGetValue(TlsIndex);
85:
86: if (!pti->idInst) {
87: if (DdeInitialize(&(pti->idInst), ProgHelpDdeCallback,
88: APPCMD_CLIENTONLY | CBF_SKIP_ALLNOTIFICATIONS,
89: 0L) != DMLERR_NO_ERROR) {
90: return(FALSE);
91: }
92: }
93:
94: if (pti->hConv == 0) {
95: hszProgman = DdeCreateStringHandle(pti->idInst, "Progman", 0);
96: pti->hConv = DdeConnect(pti->idInst, hszProgman, hszProgman, NULL);
97: }
98: return(pti->hConv != 0);
99: }
100:
101: /*
102: * This API should be called when operations with progman are complete.
103: * We shutdown DDEML here as well so we don't have to deal with it
1.1.1.2 ! root 104: * at DLL detatch time.
1.1 root 105: */
106: BOOL DisconnectFromProgman()
107: {
108: THREADINFO *pti;
109:
110: pti = TlsGetValue(TlsIndex);
111:
112: if (!pti->idInst) {
113: return(TRUE);
114: }
115:
116: if (pti->hConv) {
117: DdeDisconnect(pti->hConv);
118: pti->hConv = 0;
119: }
120:
121: DdeUninitialize(pti->idInst);
1.1.1.2 ! root 122: pti->idInst = 0;
1.1 root 123: return(TRUE);
124: }
125:
126:
127: /*
128: * This API sends an ASCII execute string to progman. It immediately returns
129: * and the results of the execute are not known. Calling applications should
130: * be aware that these transactions are done asynchronously. This allows
131: * this API to work under modal-loop conditions. DisconnectFromProgman()
132: * will not succeed until all transactions are complete.
133: */
134: BOOL ProgmanExecuteString(
135: LPCSTR pszExec)
136: {
137: THREADINFO *pti;
138: DWORD dwResult;
139:
140: pti = TlsGetValue(TlsIndex);
141:
142: if (!pti->idInst || !pti->hConv) {
143: return(FALSE);
144: }
145: if (!DdeClientTransaction((PBYTE)pszExec, strlen(pszExec) + 1,
146: pti->hConv, 0, 0, XTYP_EXECUTE, TIMEOUT_ASYNC, &dwResult)) {
147: return(FALSE);
148: }
149: return(TRUE);
150: }
151:
152:
153:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.