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.

464 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: STDINIT.C
  3. *
  4. * This module contains functions used in the involved initiate sequence.
  5. *
  6. * Created: 3/21/91 Sanfords
  7. *
  8. * Copyright (c) 1991 Microsoft Corporation
  9. \***************************************************************************/
  10. #include "ddemlp.h"
  11. /*
  12. * WM_CREATE ClientWndProc processing
  13. */
  14. long ClientCreate(
  15. HWND hwnd,
  16. PAPPINFO pai)
  17. {
  18. PCLIENTINFO pci;
  19. static DWORD defid = (DWORD)QID_SYNC;
  20. static XFERINFO defXferInfo = {
  21. &defid,
  22. 1L,
  23. XTYP_CONNECT,
  24. DDEFMT_TEXT,
  25. 0L,
  26. 0L,
  27. };
  28. /*
  29. * allocate and initialize the client window info.
  30. */
  31. SEMENTER();
  32. if(!(pci = (PCLIENTINFO)FarAllocMem(pai->hheapApp, sizeof(CLIENTINFO)))) {
  33. SEMLEAVE();
  34. SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
  35. return(1); /* aboart creation - low memory */
  36. }
  37. SetWindowLong(hwnd, GWL_PCI, (DWORD)pci);
  38. SetWindowWord(hwnd, GWW_CHECKVAL, ++hwInst);
  39. pci->ci.pai = pai;
  40. // pci->ci.xad.hUser = 0L;
  41. pci->ci.xad.state = XST_NULL;
  42. pci->ci.xad.pXferInfo = &defXferInfo; //???
  43. pci->ci.fs = ST_CLIENT | (pai->wFlags & AWF_DEFCREATESTATE ? ST_BLOCKED : 0);
  44. if (GetWindowLong(GetParent(hwnd), GWL_WNDPROC) == (LONG)ConvListWndProc)
  45. pci->ci.fs |= ST_INLIST;
  46. // pci->ci.hConvPartner = NULL;
  47. // pci->ci.hszServerApp = NULL;
  48. // pci->ci.hszTopic = NULL;
  49. pci->pQ = NULL; /* don't create until we need one */
  50. pci->pClientAdvList = CreateLst(pai->hheapApp, sizeof(ADVLI));
  51. SEMLEAVE();
  52. }
  53. /***************************** Private Function ****************************\
  54. * This routine returns the hwnd of a newly created and connected DDE
  55. * client or NULL if failure.
  56. *
  57. * History: created 1/6/89 sanfords
  58. \***************************************************************************/
  59. HWND GetDDEClientWindow(
  60. PAPPINFO pai,
  61. HWND hwndParent,
  62. HWND hwndSend, // NULL -> broadcast
  63. HSZ hszSvc,
  64. ATOM aTopic,
  65. PCONVCONTEXT pCC)
  66. {
  67. HWND hwnd;
  68. PCLIENTINFO pci;
  69. SEMCHECKOUT();
  70. if(!(hwnd = CreateWindow(SZCLIENTCLASS, szNull, WS_CHILD, 0, 0, 0, 0, hwndParent,
  71. NULL, hInstance, &pai))) {
  72. return(NULL);
  73. }
  74. pci = (PCLIENTINFO)GetWindowLong(hwnd, GWL_PCI);
  75. SEMENTER();
  76. /*
  77. * we need to set this info BEFORE we do the synchronous initiate
  78. * so the INITIATEACK msg is done correctly.
  79. */
  80. pci->ci.xad.state = XST_INIT1;
  81. pci->ci.xad.LastError = DMLERR_NO_ERROR;
  82. pci->ci.hszSvcReq = hszSvc;
  83. pci->ci.aServerApp = LOWORD(hszSvc);
  84. pci->ci.aTopic = aTopic;
  85. pci->ci.CC = pCC ? *pCC : CCDef;
  86. SEMLEAVE();
  87. if (hwndSend) {
  88. pci->hwndInit = hwndSend;
  89. SendMessage(hwndSend, WM_DDE_INITIATE, hwnd,
  90. MAKELONG((ATOM)hszSvc, aTopic));
  91. } else {
  92. IE ie = {
  93. hwnd, pci, aTopic
  94. };
  95. EnumWindows(InitEnum, (LONG)(IE FAR *)&ie);
  96. }
  97. if (pci->ci.xad.state == XST_INIT1) { // no connections?
  98. DestroyWindow(hwnd);
  99. return(NULL);
  100. }
  101. pci->ci.xad.state = XST_CONNECTED; // fully ready now.
  102. pci->ci.fs |= ST_CONNECTED;
  103. return(hwnd);
  104. }
  105. BOOL FAR PASCAL InitEnum(
  106. HWND hwnd,
  107. IE FAR *pie)
  108. {
  109. pie->pci->hwndInit = hwnd;
  110. SendMessage(hwnd, WM_DDE_INITIATE, pie->hwnd,
  111. MAKELONG((ATOM)pie->pci->ci.hszSvcReq, pie->aTopic));
  112. return((pie->pci->ci.fs & ST_INLIST) || pie->pci->ci.xad.state == XST_INIT1);
  113. }
  114. void ServerFrameInitConv(
  115. PAPPINFO pai,
  116. HWND hwndFrame,
  117. HWND hwndClient,
  118. ATOM aApp,
  119. ATOM aTopic)
  120. {
  121. HSZPAIR hp[2];
  122. PHSZPAIR php;
  123. DWORD dwRet;
  124. LPBYTE pdata;
  125. HWND hwndServer;
  126. BOOL fWild, fIsLocal, fIsSelf = FALSE;
  127. PCLIENTINFO pci;
  128. SEMCHECKOUT();
  129. if (pai->afCmd & CBF_FAIL_CONNECTIONS) {
  130. return;
  131. }
  132. /*
  133. * If we are filtering and no app names are registered, quit.
  134. */
  135. if ((pai->afCmd & APPCMD_FILTERINITS) &&
  136. QPileItemCount(pai->pAppNamePile) == 0) {
  137. return;
  138. }
  139. fIsLocal = ((FARPROC)GetWindowLong(hwndClient,GWL_WNDPROC) == (FARPROC)ClientWndProc);
  140. if (fIsLocal) {
  141. pci = (PCLIENTINFO)GetWindowLong(hwndClient, GWL_PCI);
  142. fIsSelf = (pci->ci.pai == pai);
  143. /*
  144. * filter out inits from ourselves
  145. */
  146. if (pai->afCmd & CBF_FAIL_SELFCONNECTIONS && fIsSelf) {
  147. return;
  148. }
  149. }
  150. hp[0].hszSvc = (HSZ)aApp;
  151. /*
  152. * filter out unwanted app names.
  153. */
  154. if (aApp && (pai->afCmd & APPCMD_FILTERINITS) &&
  155. !FindPileItem(pai->pAppNamePile, CmpWORD, (LPBYTE)&aApp, 0))
  156. return;
  157. hp[0].hszTopic = aTopic;
  158. hp[1].hszSvc = hp[1].hszTopic = 0L;
  159. fWild = (hp[0].hszSvc == 0L || hp[0].hszTopic == 0L);
  160. dwRet = DoCallback(pai, NULL, hp[0].hszTopic,
  161. hp[0].hszSvc, 0, (fWild ? XTYP_WILDCONNECT : XTYP_CONNECT),
  162. 0L, fIsLocal ? (DWORD)&pci->ci.CC : 0L, fIsSelf ? 1 : 0);
  163. if (dwRet == NULL)
  164. return;
  165. if (fWild) {
  166. pdata = GLOBALLOCK(HIWORD(dwRet));
  167. php = (PHSZPAIR)pdata;
  168. } else {
  169. php = &hp[0];
  170. pdata = NULL;
  171. }
  172. /*
  173. * now php points to a 0 terminated list of hszpairs to respond to.
  174. */
  175. SEMENTER();
  176. while (QueryHszLength(php->hszSvc) && QueryHszLength(php->hszTopic)) {
  177. PSERVERINFO psi;
  178. SEMLEAVE();
  179. if ((hwndServer = CreateServerWindow(pai, (ATOM)php->hszTopic,
  180. fIsLocal ? &pci->ci.CC : &CCDef)) == 0)
  181. return;
  182. SEMENTER();
  183. /*
  184. * have the server respond
  185. */
  186. psi = (PSERVERINFO)GetWindowLong(hwndServer, GWL_PCI);
  187. psi->ci.hConvPartner = fIsLocal ? MAKEHCONV(hwndClient) : (HCONV)hwndClient;
  188. psi->ci.hwndFrame = hwndFrame;
  189. psi->ci.fs |= ST_CONNECTED;
  190. if (fIsSelf) {
  191. psi->ci.fs |= ST_ISSELF;
  192. pci->ci.fs |= ST_ISSELF;
  193. }
  194. psi->ci.xad.state = XST_CONNECTED;
  195. psi->ci.hszSvcReq = (HSZ)aApp;
  196. psi->ci.aServerApp = (ATOM)php->hszSvc;
  197. psi->ci.aTopic = (ATOM)php->hszTopic;
  198. MONCONN(psi->ci.pai, psi->ci.aServerApp, psi->ci.aTopic,
  199. hwndClient, hwndServer, TRUE);
  200. IncHszCount(aApp); // for server window to keep
  201. IncHszCount(LOWORD(php->hszSvc));
  202. IncHszCount(LOWORD(php->hszTopic));
  203. IncHszCount(LOWORD(php->hszSvc)); // for client to remove on ack
  204. IncHszCount(LOWORD(php->hszTopic));
  205. #ifdef DEBUG
  206. cAtoms -= 2; // we are giving these away
  207. #endif
  208. SEMLEAVE();
  209. SendMessage(hwndClient, WM_DDE_ACK, hwndServer,
  210. MAKELONG(LOWORD(php->hszSvc), LOWORD(php->hszTopic)));
  211. /*
  212. * confirm initialization to server app - synchronously
  213. */
  214. DoCallback(pai, MAKEHCONV(hwndServer), php->hszTopic, php->hszSvc,
  215. 0, XTYP_CONNECT_CONFIRM, 0L, 0L, fIsSelf ? 1 : 0);
  216. SEMENTER();
  217. php++;
  218. }
  219. if (pdata) {
  220. GLOBALUNLOCK(HIWORD(dwRet));
  221. FreeDataHandle(pai, dwRet, TRUE);
  222. }
  223. SEMLEAVE();
  224. SEMCHECKOUT();
  225. }
  226. HWND CreateServerWindow(
  227. PAPPINFO pai,
  228. ATOM aTopic,
  229. PCONVCONTEXT pCC)
  230. {
  231. HWND hwndServer;
  232. SEMCHECKOUT();
  233. /*
  234. * make a server root window if needed....
  235. */
  236. if (pai->hwndSvrRoot == 0) {
  237. /*
  238. * NO - make one.
  239. */
  240. if ((pai->hwndSvrRoot = CreateWindow(SZCONVLISTCLASS, szNull, WS_CHILD,
  241. 0, 0, 0, 0, pai->hwndDmg, NULL, hInstance, 0L)) == NULL) {
  242. SETLASTERROR(pai, DMLERR_SYS_ERROR);
  243. return(NULL);
  244. }
  245. }
  246. /*
  247. * Create the server window
  248. */
  249. if ((hwndServer = CreateWindow(SZSERVERCLASS, szNull, WS_CHILD,
  250. 0, 0, 0, 0, pai->hwndSvrRoot, NULL, hInstance, &pai)) == NULL) {
  251. SETLASTERROR(pai, DMLERR_SYS_ERROR);
  252. return(NULL);
  253. }
  254. ((PSERVERINFO)GetWindowLong(hwndServer, GWL_PCI))->ci.CC = *pCC;
  255. return(hwndServer);
  256. }
  257. /*
  258. * WM_CREATE ServerWndProc processing
  259. */
  260. long ServerCreate(
  261. HWND hwnd,
  262. PAPPINFO pai)
  263. {
  264. PSERVERINFO psi;
  265. /*
  266. * allocate and initialize the server window info.
  267. */
  268. SEMENTER();
  269. if (!(psi = (PSERVERINFO)FarAllocMem(pai->hheapApp, sizeof(SERVERINFO)))) {
  270. SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
  271. return(1);
  272. }
  273. SEMLEAVE();
  274. psi->ci.pai = pai;
  275. // psi->ci.xad.hUser = 0L;
  276. psi->ci.xad.state = XST_NULL;
  277. psi->ci.fs = pai->wFlags & AWF_DEFCREATESTATE ? ST_BLOCKED : 0;
  278. SetWindowLong(hwnd, GWL_PCI, (DWORD)psi);
  279. SetWindowWord(hwnd, GWW_CHECKVAL, ++hwInst);
  280. return(0);
  281. }
  282. /*
  283. * Client response to a WM_DDE_ACK message when ACK to INITIATE expected.
  284. */
  285. BOOL ClientInitAck(hwnd, pci, hwndServer, aApp, aTopic)
  286. HWND hwnd;
  287. PCLIENTINFO pci;
  288. HWND hwndServer;
  289. ATOM aApp;
  290. ATOM aTopic;
  291. {
  292. HWND hwndClient;
  293. PCLIENTINFO pciNew;
  294. #ifdef DEBUG
  295. cAtoms += 2; // the incomming atoms need to be accounted for.
  296. #endif
  297. SEMCHECKOUT();
  298. switch (pci->ci.xad.state) {
  299. case XST_INIT1:
  300. /*
  301. * first one back... lock in!
  302. */
  303. pci->ci.xad.state = XST_INIT2;
  304. MONCONN(pci->ci.pai, aApp, aTopic, hwnd, hwndServer, TRUE);
  305. if (GetWindowLong(hwndServer, GWL_WNDPROC) == (LONG)ServerWndProc) {
  306. pci->ci.fs |= ST_ISLOCAL;
  307. pci->ci.hConvPartner = MAKEHCONV(hwndServer);
  308. } else {
  309. pci->ci.hConvPartner = (HCONV)hwndServer;
  310. if (aApp == aProgmanHack) {
  311. // PROGMAN HACK!!!!
  312. IncHszCount(aApp);
  313. IncHszCount(aTopic);
  314. #ifdef DEBUG
  315. cAtoms -= 2;
  316. #endif
  317. }
  318. }
  319. pci->ci.aServerApp = aApp;
  320. pci->ci.aTopic = aTopic;
  321. if (!pci->ci.hwndFrame) // remember the frame this was sent to.
  322. pci->ci.hwndFrame = pci->hwndInit;
  323. IncHszCount(LOWORD(pci->ci.hszSvcReq)); // keep this for ourselves
  324. break;
  325. case XST_INIT2:
  326. // Extra ack...
  327. // throw away if from our partner or if we are not in a list.
  328. if (hwndServer == (HWND)pci->ci.hConvPartner ||
  329. GetParent(hwnd) == pci->ci.pai->hwndDmg) {
  330. Abort:
  331. TRACETERM((szT, "ClientInitAck: Extra ack terminate: %x->%x\n", hwndServer, hwnd));
  332. PostMessage(hwndServer, WM_DDE_TERMINATE, hwnd, 0L);
  333. FreeHsz(aApp);
  334. FreeHsz(aTopic);
  335. break;
  336. }
  337. if (GetWindowLong(hwndServer, GWL_WNDPROC) != (LONG)ServerWndProc) {
  338. // Non Local Extra Ack... terminate and attempt reconnection.
  339. TRACETERM((szT, "ClientInitAck: Extra ack terminate and reconnect: %x->%x\n", hwndServer, hwnd));
  340. PostMessage(hwndServer, WM_DDE_TERMINATE, hwnd, 0L);
  341. GetDDEClientWindow(pci->ci.pai, GetParent(hwnd),
  342. pci->hwndInit, aApp, aTopic, &pci->ci.CC);
  343. // PROGMAN HACK!!!!
  344. if (aApp != aProgmanHack) {
  345. FreeHsz(aApp);
  346. FreeHsz(aTopic);
  347. }
  348. break;
  349. }
  350. // Local Extra Ack... create a client window, set it up to be talking
  351. // to the server window and tell the server window to change
  352. // partners.
  353. hwndClient = CreateWindow(SZCLIENTCLASS, szNull, WS_CHILD,
  354. 0, 0, 0, 0, GetParent(hwnd), NULL, hInstance, &(pci->ci.pai));
  355. if (!hwndClient) {
  356. SETLASTERROR(pci->ci.pai, DMLERR_SYS_ERROR);
  357. goto Abort;
  358. }
  359. pciNew = (PCLIENTINFO)GetWindowLong(hwndClient, GWL_PCI);
  360. pciNew->ci.xad.state = XST_CONNECTED;
  361. pciNew->ci.xad.LastError = DMLERR_NO_ERROR;
  362. pciNew->ci.aServerApp = aApp;
  363. pciNew->ci.hszSvcReq = pci->ci.hszSvcReq;
  364. IncHszCount(LOWORD(pciNew->ci.hszSvcReq));
  365. pciNew->ci.aTopic = aTopic;
  366. pciNew->ci.hConvPartner = MAKEHCONV(hwndServer);
  367. pciNew->ci.hwndFrame = pci->hwndInit;
  368. pciNew->ci.fs |= ST_CONNECTED | ST_ISLOCAL;
  369. MONCONN(pciNew->ci.pai, aApp, aTopic, hwnd, hwndServer, TRUE);
  370. SendMessage(hwndServer, UMSR_CHGPARTNER, hwndClient, 0L);
  371. break;
  372. }
  373. return(TRUE);
  374. }