Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 lines
12 KiB

  1. /***************************************************************************/
  2. /** Microsoft Windows **/
  3. /** Copyright(c) Microsoft Corp., 1991, 1992 **/
  4. /***************************************************************************/
  5. /****************************************************************************
  6. dde.cpp
  7. Aug 92, JimH
  8. May 93, JimH chico port
  9. Member functions for DDE, DDEServer, and DDEClient are here.
  10. ****************************************************************************/
  11. #include "hearts.h"
  12. #include "dde.h"
  13. #include "debug.h"
  14. // declare DDE objects
  15. DDEClient *ddeClient;
  16. DDEServer *ddeServer;
  17. /****************************************************************************
  18. DDE:DDE
  19. performs basic DDEML initialization.
  20. m_bResult is TRUE if everything works.
  21. ****************************************************************************/
  22. DDE::DDE(const TCHAR *server, const TCHAR *topic, DDECALLBACK CallBack,
  23. DWORD filters) : m_idInst(0), m_CallBack(NULL)
  24. {
  25. // Check for basic compatibility, ie protect mode
  26. // m_bResult = ( (LOBYTE(GetVersion()) > 2) && (GetWinFlags() & WF_PMODE) )
  27. // ? TRUE : FALSE;
  28. m_bResult = TRUE;
  29. if (!m_bResult)
  30. return;
  31. m_data.Empty(); // clear CString object
  32. // Set callback function and filters from passed-in parameters
  33. if (!SetCallBack(CallBack))
  34. return;
  35. SetFilters(filters);
  36. if (!Initialize())
  37. {
  38. m_idInst = 0;
  39. return;
  40. }
  41. // create CString objects and HSZ handles for server and topic
  42. m_server = server;
  43. m_topic = topic;
  44. m_hServer = CreateStrHandle(m_server);
  45. m_hTopic = CreateStrHandle(m_topic);
  46. }
  47. /****************************************************************************
  48. DDE::~DDE
  49. cleans up string handles and DDEML-uninitializes
  50. ****************************************************************************/
  51. DDE::~DDE()
  52. {
  53. if (!m_idInst)
  54. return;
  55. DestroyStrHandle(m_hServer);
  56. DestroyStrHandle(m_hTopic);
  57. ::DdeUninitialize(m_idInst);
  58. FreeProcInstance((FARPROC)m_CallBack);
  59. }
  60. /****************************************************************************
  61. DDE:CreateDataHandle
  62. converts data to a HDDEDATA handle.
  63. ****************************************************************************/
  64. HDDEDATA DDE::CreateDataHandle(void FAR *pdata, DWORD size, HSZ hItem)
  65. {
  66. return ::DdeCreateDataHandle(m_idInst, // instance ID
  67. (LPBYTE)pdata, // data to convert
  68. size, // size of data
  69. 0, // offset of data
  70. hItem, // corresponding string handle
  71. CF_OWNERDISPLAY,// clipboard format
  72. 0); // creation flags, system owns
  73. }
  74. /****************************************************************************
  75. DDE:CreateStrHandle
  76. converts a string into a HSZ. The codepage defaults to CP_WINANSI.
  77. ****************************************************************************/
  78. HSZ DDE::CreateStrHandle(LPCTSTR str, int codepage)
  79. {
  80. HSZ hsz = NULL;
  81. if (m_idInst)
  82. hsz = ::DdeCreateStringHandle(m_idInst, str, codepage);
  83. if (hsz == NULL)
  84. m_bResult = FALSE;
  85. return hsz;
  86. }
  87. /****************************************************************************
  88. DDE::DestroyStrHandle
  89. frees HSZ created by CreateStrHandle
  90. ****************************************************************************/
  91. void DDE::DestroyStrHandle(HSZ hsz)
  92. {
  93. if (m_idInst && hsz)
  94. ::DdeFreeStringHandle(m_idInst, hsz);
  95. }
  96. /****************************************************************************
  97. DDE:GetData
  98. Like GetDataString, this function retrieves data represented by
  99. hData provided in callback function. However, the buffer must be
  100. provided by the caller. The len parameter defaults to 0 meaning
  101. the caller promises pdata points to a large enough buffer.
  102. ****************************************************************************/
  103. PBYTE DDE::GetData(HDDEDATA hData, PBYTE pdata, DWORD len)
  104. {
  105. DWORD datalen = ::DdeGetData(hData, NULL, 0, 0);
  106. if (len == 0)
  107. len = datalen;
  108. ::DdeGetData(hData, pdata, min(len, datalen), 0);
  109. return pdata;
  110. }
  111. /****************************************************************************
  112. DDE:GetDataString
  113. The default value of hData is NULL meaning just return the current
  114. m_data string. Otherwise get associated DDE data. The caller does
  115. not have to provide a CString buffer.
  116. ****************************************************************************/
  117. CString DDE::GetDataString(HDDEDATA hData)
  118. {
  119. if (hData == NULL) // default paramenter
  120. return m_data;
  121. DWORD len = ::DdeGetData(hData, NULL, 0, 0); // find length
  122. TCHAR *pdata = m_data.GetBuffer((int)len);
  123. ::DdeGetData(hData, (LPBYTE)pdata, len, 0);
  124. m_data.ReleaseBuffer();
  125. return m_data;
  126. }
  127. /****************************************************************************
  128. DDE::Initialize
  129. performs DDEML initialization
  130. ****************************************************************************/
  131. BOOL DDE::Initialize()
  132. {
  133. m_initerr = (WORD)::DdeInitialize(&m_idInst, (PFNCALLBACK)m_CallBack,
  134. m_filters, 0);
  135. m_bResult = (m_initerr == DMLERR_NO_ERROR);
  136. return m_bResult;
  137. }
  138. /****************************************************************************
  139. DDE::SetCallBack
  140. ****************************************************************************/
  141. BOOL DDE::SetCallBack(DDECALLBACK CallBack)
  142. {
  143. if (m_CallBack)
  144. FreeProcInstance((FARPROC)m_CallBack);
  145. m_CallBack = (DDECALLBACK)MakeProcInstance((FARPROC)CallBack,
  146. AfxGetInstanceHandle());
  147. m_bResult = (m_CallBack != NULL);
  148. return m_bResult;
  149. }
  150. /****************************************************************************
  151. DDEServer functions
  152. ****************************************************************************/
  153. /****************************************************************************
  154. DDEServer::DDEServer
  155. registers server name
  156. ****************************************************************************/
  157. DDEServer::DDEServer(const TCHAR *server, const TCHAR *topic,
  158. DDECALLBACK ServerCallBack, DWORD filters) :
  159. DDE(server, topic, ServerCallBack, filters)
  160. {
  161. if (!m_bResult)
  162. return;
  163. if (::DdeNameService(m_idInst, m_hServer, NULL, DNS_REGISTER) == 0)
  164. m_bResult = FALSE;
  165. }
  166. /****************************************************************************
  167. DDEServer::~DDEServer
  168. unregisters server name
  169. ****************************************************************************/
  170. DDEServer::~DDEServer()
  171. {
  172. ::DdeNameService(m_idInst, NULL, NULL, DNS_UNREGISTER);
  173. }
  174. /****************************************************************************
  175. DDEServer::PostAdvise
  176. notify clients that data has changed
  177. ****************************************************************************/
  178. BOOL DDEServer::PostAdvise(HSZ hItem)
  179. {
  180. return ::DdePostAdvise(m_idInst, m_hTopic, hItem);
  181. }
  182. /****************************************************************************
  183. DDEClient functions
  184. ****************************************************************************/
  185. /****************************************************************************
  186. DDEClient::DDEClient
  187. after DDE construction, connect to specified server and topic.
  188. m_bResult indicates success or failure.
  189. ****************************************************************************/
  190. DDEClient::DDEClient(const TCHAR *server, const TCHAR *topic,
  191. DDECALLBACK ClientCallBack, DWORD filters) :
  192. DDE(server, topic, ClientCallBack, filters)
  193. {
  194. if (!m_bResult) // if DDE construction failed
  195. return;
  196. m_timeout = m_deftimeout = TIMEOUT_ASYNC; // default to asynch trans
  197. m_hConv = ::DdeConnect(m_idInst, m_hServer, m_hTopic, NULL);
  198. if (m_hConv == NULL)
  199. m_bResult = FALSE;
  200. }
  201. /****************************************************************************
  202. DDEClient::~DDEClient
  203. disconnects from server
  204. ****************************************************************************/
  205. DDEClient::~DDEClient()
  206. {
  207. ::DdeDisconnect(m_hConv);
  208. }
  209. /****************************************************************************
  210. DDEClient:Poke
  211. Use this function to send general unsolicited data to the server.
  212. String data can be sent more conveniently using string Poke below.
  213. ****************************************************************************/
  214. BOOL DDEClient::Poke(HSZ hItem, void FAR *pdata, DWORD len, DWORD uTimeout)
  215. {
  216. if (uTimeout == NULL) // default
  217. m_timeout = m_deftimeout;
  218. else
  219. m_timeout = uTimeout;
  220. ClientTransaction((LPBYTE)pdata, len, hItem, XTYP_POKE, CF_OWNERDISPLAY);
  221. return m_bResult;
  222. }
  223. BOOL DDEClient::Poke(HSZ hItem, const TCHAR *string, DWORD uTimeout)
  224. {
  225. if (uTimeout == NULL) // default
  226. m_timeout = m_deftimeout;
  227. else
  228. m_timeout = uTimeout;
  229. ClientTransaction((void FAR *)string, lstrlen(string)+1, hItem, XTYP_POKE);
  230. return m_bResult;
  231. }
  232. /****************************************************************************
  233. DDEClient::RequestString
  234. DDEClient::RequestData
  235. These request a synchronous update from server on specified item.
  236. RequestString returns a BOOL which says if the request succeeded.
  237. Get the result from GetDataString(void).
  238. RequestData returns a HDDEDATA. If it is not NULL, pass it to
  239. GetData() along with a buffer to copy the result in to.
  240. ****************************************************************************/
  241. BOOL DDEClient::RequestString(HSZ hItem, DWORD uTimeout)
  242. {
  243. if (uTimeout == NULL) // default
  244. m_timeout = m_deftimeout;
  245. else
  246. m_timeout = uTimeout;
  247. HDDEDATA hData = ClientTransaction(NULL, 0, hItem, XTYP_REQUEST);
  248. if (m_bResult)
  249. GetDataString(hData);
  250. else
  251. m_data.Empty();
  252. return m_bResult;
  253. }
  254. HDDEDATA DDEClient::RequestData(HSZ hItem, DWORD uTimeout)
  255. {
  256. if (uTimeout == NULL) // default
  257. m_timeout = m_deftimeout;
  258. else
  259. m_timeout = uTimeout;
  260. HDDEDATA hData = ClientTransaction(NULL, 0, hItem, XTYP_REQUEST,
  261. CF_OWNERDISPLAY);
  262. return hData;
  263. }
  264. /****************************************************************************
  265. DDEClient::StartAdviseLoop
  266. This function sets up a hotlink with the server on the specified item.
  267. It returns TRUE if the link was set up successfully.
  268. Setting up a warm link would involve changing the XTYP.
  269. ****************************************************************************/
  270. BOOL DDEClient::StartAdviseLoop(HSZ hItem)
  271. {
  272. ClientTransaction(NULL, 0, hItem, XTYP_ADVSTART);
  273. return m_bResult;
  274. }
  275. /****************************************************************************
  276. DDEClient::ClientTransaction
  277. an internal wrapper for ::DdeClientTransaction()
  278. ****************************************************************************/
  279. HDDEDATA DDEClient::ClientTransaction(void FAR *lpvData, DWORD cbData,
  280. HSZ hItem, UINT uType, UINT uFmt)
  281. {
  282. HDDEDATA hData = ::DdeClientTransaction(
  283. (LPBYTE)lpvData, // data to send to server
  284. cbData, // size of data in bytes
  285. m_hConv, // conversation handle
  286. hItem, // handle of item name string
  287. uFmt, // clipboard format
  288. uType, // XTYP_* type
  289. m_timeout, // timeout duration in milliseconds
  290. NULL); // transaction result, not used
  291. m_bResult = (hData != FALSE);
  292. return hData;
  293. }