Leaked source code of windows server 2003
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.

543 lines
16 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: callback.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * DDE Manager callback related functions
  7. *
  8. * Created: 11/11/91 Sanford Staab
  9. *
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /***************************************************************************\
  14. * DoCallback
  15. *
  16. * Description:
  17. * Performs a synchronous callback to the given instance's callback proc.
  18. *
  19. * History:
  20. * 11-12-91 sanfords Created.
  21. \***************************************************************************/
  22. HDDEDATA DoCallback(
  23. PCL_INSTANCE_INFO pcii,
  24. WORD wType,
  25. WORD wFmt,
  26. HCONV hConv,
  27. HSZ hsz1,
  28. HSZ hsz2,
  29. HDDEDATA hData,
  30. ULONG_PTR dw1,
  31. ULONG_PTR dw2)
  32. {
  33. HDDEDATA hDataRet;
  34. PCLIENTINFO pci;
  35. CheckDDECritIn;
  36. /*
  37. * Zombie conversations don't generate callbacks!
  38. */
  39. if (hConv && TypeFromHandle(hConv) == HTYPE_ZOMBIE_CONVERSATION) {
  40. return(0);
  41. }
  42. pci = GetClientInfo();
  43. pci->cInDDEMLCallback++;
  44. pcii->cInDDEMLCallback++;
  45. LeaveDDECrit;
  46. CheckDDECritOut;
  47. /*
  48. * Bug 246472 - joejo
  49. * fixup all DDE Callbacks since some apps make their callbacks
  50. * C-Style instead of PASCAL.
  51. */
  52. hDataRet = UserCallDDECallback(*pcii->pfnCallback, (UINT)wType, (UINT)wFmt, hConv, hsz1, hsz2,
  53. hData, dw1, dw2);
  54. EnterDDECrit;
  55. pcii->cInDDEMLCallback--;
  56. pci->cInDDEMLCallback--;
  57. if (!(pcii->afCmd & APPCLASS_MONITOR) && pcii->MonitorFlags & MF_CALLBACKS) {
  58. PEVENT_PACKET pep;
  59. pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) +
  60. sizeof(MONCBSTRUCT));
  61. if (pep != NULL) {
  62. pep->EventType = MF_CALLBACKS;
  63. pep->fSense = TRUE;
  64. pep->cbEventData = sizeof(MONCBSTRUCT);
  65. #define pcbs ((MONCBSTRUCT *)&pep->Data)
  66. pcbs->cb = sizeof(MONCBSTRUCT);
  67. pcbs->dwTime = NtGetTickCount();
  68. pcbs->hTask = (HANDLE)LongToHandle( pcii->tid );
  69. pcbs->dwRet = HandleToUlong(hDataRet);
  70. pcbs->wType = wType;
  71. pcbs->wFmt = wFmt;
  72. pcbs->hConv = hConv;
  73. pcbs->hsz1 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1));
  74. pcbs->hsz2 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz2));
  75. pcbs->hData = hData;
  76. pcbs->dwData1 = dw1;
  77. pcbs->dwData2 = dw2;
  78. if (((wType == XTYP_CONNECT) || (wType == XTYP_WILDCONNECT)) && dw1) {
  79. RtlCopyMemory(&pcbs->cc, (PVOID)dw1, sizeof(CONVCONTEXT));
  80. }
  81. LeaveDDECrit;
  82. if (wType & XCLASS_DATA) {
  83. if (hDataRet && hDataRet != CBR_BLOCK) {
  84. pcbs->cbData = DdeGetData(hDataRet, (LPBYTE)pcbs->Data, 32, 0);
  85. }
  86. } else if (hData) {
  87. pcbs->cbData = DdeGetData(hData, (LPBYTE)pcbs->Data, 32, 0);
  88. }
  89. Event(pep);
  90. EnterDDECrit;
  91. GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz1));
  92. GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz2));
  93. DDEMLFree(pep);
  94. #undef pcbs
  95. }
  96. }
  97. return (hDataRet);
  98. }
  99. /***************************************************************************\
  100. * _ClientEventCallback
  101. *
  102. * Description:
  103. * Called from the server side to perform event callbacks.
  104. *
  105. * History:
  106. * 11-12-91 sanfords Created.
  107. \***************************************************************************/
  108. DWORD _ClientEventCallback(
  109. PCL_INSTANCE_INFO pcii,
  110. PEVENT_PACKET pep)
  111. {
  112. HDDEDATA hData;
  113. EnterDDECrit;
  114. switch (pep->EventType) {
  115. case 0: // MonitorFlags change event - everybody gets it
  116. pcii->MonitorFlags = pep->Data;
  117. break;
  118. case MF_CALLBACKS:
  119. {
  120. MONCBSTRUCT mcb;
  121. mcb = *((MONCBSTRUCT *)&pep->Data);
  122. mcb.hsz1 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz1));
  123. mcb.hsz2 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz2));
  124. if ( mcb.wType == XTYP_REGISTER ||
  125. mcb.wType == XTYP_UNREGISTER) {
  126. mcb.hsz2 = INST_SPECIFIC_HSZ_FROM_LATOM((LATOM)(ULONG_PTR)mcb.hsz2);
  127. }
  128. hData = InternalCreateDataHandle(pcii, (LPSTR)&mcb,
  129. pep->cbEventData, 0,
  130. HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
  131. if (hData) {
  132. DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
  133. pep->EventType);
  134. InternalFreeDataHandle((HDDEDATA)hData, TRUE);
  135. DeleteAtom(LATOM_FROM_HSZ(mcb.hsz1));
  136. DeleteAtom(LATOM_FROM_HSZ(mcb.hsz2));
  137. }
  138. }
  139. break;
  140. case MF_LINKS:
  141. {
  142. MONLINKSTRUCT ml;
  143. ml = *((MONLINKSTRUCT *)&pep->Data);
  144. ml.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszSvc));
  145. ml.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszTopic));
  146. ml.hszItem = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszItem));
  147. hData = InternalCreateDataHandle(pcii, (LPSTR)&ml,
  148. pep->cbEventData, 0,
  149. HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
  150. if (hData) {
  151. DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
  152. pep->EventType);
  153. InternalFreeDataHandle((HDDEDATA)hData, TRUE);
  154. DeleteAtom(LATOM_FROM_HSZ(ml.hszSvc));
  155. DeleteAtom(LATOM_FROM_HSZ(ml.hszTopic));
  156. DeleteAtom(LATOM_FROM_HSZ(ml.hszItem));
  157. }
  158. }
  159. break;
  160. case MF_CONV:
  161. {
  162. MONCONVSTRUCT mc;
  163. mc = *((MONCONVSTRUCT *)&pep->Data);
  164. mc.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszSvc));
  165. mc.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszTopic));
  166. hData = InternalCreateDataHandle(pcii, (LPSTR)&mc,
  167. pep->cbEventData, 0,
  168. HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
  169. if (hData) {
  170. DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
  171. pep->EventType);
  172. InternalFreeDataHandle((HDDEDATA)hData, TRUE);
  173. DeleteAtom(LATOM_FROM_HSZ(mc.hszSvc));
  174. DeleteAtom(LATOM_FROM_HSZ(mc.hszTopic));
  175. }
  176. }
  177. break;
  178. case MF_HSZ_INFO:
  179. if (!(pcii->flags & IIF_UNICODE)) {
  180. LPSTR pszAnsi;
  181. /*
  182. * Translate HSZ string back into ANSI
  183. */
  184. if (WCSToMB(((PMONHSZSTRUCT)&pep->Data)->str,
  185. ((int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb) / sizeof(WCHAR),
  186. &pszAnsi,
  187. (int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb,
  188. TRUE)) {
  189. strcpy(((PMONHSZSTRUCTA)&pep->Data)->str, pszAnsi);
  190. UserLocalFree(pszAnsi);
  191. }
  192. ((PMONHSZSTRUCT)&pep->Data)->cb = sizeof(MONHSZSTRUCTA);
  193. }
  194. // fall through
  195. case MF_SENDMSGS:
  196. case MF_POSTMSGS:
  197. if (pep->EventType == MF_POSTMSGS) {
  198. PMONMSGSTRUCT pmms = (PMONMSGSTRUCT)&pep->Data;
  199. BYTE buf[32];
  200. /*
  201. * We may need to translate the Execute string to/from
  202. * UNICODE depending on what type of monitor this is
  203. * going to.
  204. */
  205. if (pmms->wMsg == WM_DDE_EXECUTE) {
  206. BOOL fUnicodeText;
  207. int flags;
  208. flags = (IS_TEXT_UNICODE_UNICODE_MASK |
  209. IS_TEXT_UNICODE_REVERSE_MASK |
  210. (IS_TEXT_UNICODE_NOT_UNICODE_MASK &
  211. (~IS_TEXT_UNICODE_ILLEGAL_CHARS)) |
  212. IS_TEXT_UNICODE_NOT_ASCII_MASK);
  213. #ifdef ISTEXTUNICODE_WORKS
  214. fUnicodeText = RtlIsTextUnicode(pmms->dmhd.Data,
  215. min(32, pmms->dmhd.cbData), &flags);
  216. #else
  217. fUnicodeText = (*(LPSTR)pmms->dmhd.Data == '\0');
  218. #endif
  219. if (pcii->flags & IIF_UNICODE && !fUnicodeText) {
  220. /* Ascii->UNICODE */
  221. RtlMultiByteToUnicodeN((LPWSTR)buf, 32, NULL,
  222. (LPSTR)&pmms->dmhd.Data,
  223. min(32, pmms->dmhd.cbData));
  224. RtlCopyMemory(&pmms->dmhd.Data, buf, 32);
  225. } else if (!(pcii->flags & IIF_UNICODE) && fUnicodeText) {
  226. /* UNICODE->Ascii */
  227. RtlUnicodeToMultiByteN((LPSTR)buf, 32, NULL,
  228. (LPWSTR)&pmms->dmhd.Data,
  229. min(32, pmms->dmhd.cbData));
  230. RtlCopyMemory(&pmms->dmhd.Data, buf, 32);
  231. }
  232. }
  233. }
  234. case MF_ERRORS:
  235. hData = InternalCreateDataHandle(pcii, (LPSTR)&pep->Data,
  236. pep->cbEventData, 0,
  237. HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
  238. if (hData) {
  239. DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
  240. pep->EventType);
  241. InternalFreeDataHandle((HDDEDATA)hData, TRUE);
  242. }
  243. break;
  244. }
  245. LeaveDDECrit;
  246. return (0);
  247. }
  248. /***************************************************************************\
  249. * EnableEnumProc
  250. *
  251. * Description:
  252. * Helper function for applying pees->wCmd to each client and server
  253. * DDEML window.
  254. *
  255. * History:
  256. * 11-12-91 sanfords Created.
  257. \***************************************************************************/
  258. BOOL EnableEnumProc(
  259. HWND hwnd,
  260. PENABLE_ENUM_STRUCT pees)
  261. {
  262. PCONV_INFO pcoi;
  263. for (pcoi = (PCONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI);
  264. pcoi != NULL; pcoi = pcoi->next) {
  265. pcoi->cLocks++;
  266. *pees->pfRet |= SetEnableState(pcoi, pees->wCmd);
  267. if (pees->wCmd2) {
  268. /*
  269. * Only let ES_CHECKQUEUEONCE be done on one window but
  270. * don't stop the wCmd from getting to all the other
  271. * windows.
  272. */
  273. if (SetEnableState(pcoi, pees->wCmd2) &&
  274. pees->wCmd2 == EC_CHECKQUEUEONCE) {
  275. pees->wCmd2 = 0;
  276. }
  277. }
  278. pcoi->cLocks--;
  279. if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
  280. FreeConversationResources(pcoi);
  281. break;
  282. }
  283. }
  284. return (TRUE);
  285. }
  286. /***************************************************************************\
  287. * DdeEnableCallback (DDEML API)
  288. *
  289. * Description:
  290. * Turns on and off asynchronous callbacks (BLOCKABLE).
  291. *
  292. * History:
  293. * 11-12-91 sanfords Created.
  294. \***************************************************************************/
  295. FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeEnableCallback, DWORD, idInst, HCONV, hConv, UINT, wCmd)
  296. BOOL DdeEnableCallback(
  297. DWORD idInst,
  298. HCONV hConv,
  299. UINT wCmd)
  300. {
  301. BOOL fRet = FALSE;
  302. PCL_INSTANCE_INFO pcii;
  303. PCONV_INFO pcoi;
  304. ENABLE_ENUM_STRUCT ees;
  305. EnterDDECrit;
  306. pcii = (PCL_INSTANCE_INFO)ValidateInstance((HANDLE)LongToHandle( idInst ));
  307. if (pcii == NULL) {
  308. BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
  309. goto Exit;
  310. }
  311. switch (wCmd) {
  312. case EC_QUERYWAITING:
  313. case EC_DISABLE:
  314. case EC_ENABLEONE:
  315. case EC_ENABLEALL:
  316. break;
  317. default:
  318. SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
  319. goto Exit;
  320. }
  321. if (hConv) {
  322. pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
  323. HTYPE_CLIENT_CONVERSATION, InstFromHandle(idInst));
  324. if (pcoi == NULL) {
  325. pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
  326. HTYPE_SERVER_CONVERSATION, InstFromHandle(idInst));
  327. }
  328. if (pcoi == NULL) {
  329. SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
  330. goto Exit;
  331. }
  332. pcoi->cLocks++;
  333. fRet = SetEnableState(pcoi, wCmd);
  334. switch (wCmd) {
  335. case EC_ENABLEALL:
  336. case EC_ENABLEONE:
  337. CheckForQueuedMessages(pcoi);
  338. }
  339. pcoi->cLocks--;
  340. if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
  341. FreeConversationResources(pcoi);
  342. }
  343. } else {
  344. if (wCmd == EC_ENABLEONE) {
  345. wCmd = EC_ENABLEONEOFALL;
  346. }
  347. switch (wCmd) {
  348. case EC_ENABLEONEOFALL:
  349. pcii->ConvStartupState = ST_BLOCKNEXT | ST_BLOCKALLNEXT;
  350. break;
  351. case EC_DISABLE:
  352. pcii->ConvStartupState = ST_BLOCKED;
  353. break;
  354. case EC_ENABLEALL:
  355. pcii->ConvStartupState = 0;
  356. break;
  357. }
  358. ees.pfRet = &fRet;
  359. ees.wCmd = (WORD)wCmd;
  360. switch (wCmd) {
  361. case EC_ENABLEALL:
  362. ees.wCmd2 = EC_CHECKQUEUE;
  363. break;
  364. case EC_ENABLEONEOFALL:
  365. ees.wCmd2 = EC_CHECKQUEUEONCE;
  366. break;
  367. default:
  368. ees.wCmd2 = 0;
  369. }
  370. EnumChildWindows(pcii->hwndMother, (WNDENUMPROC)EnableEnumProc,
  371. (LPARAM)&ees);
  372. }
  373. Exit:
  374. LeaveDDECrit;
  375. return (fRet);
  376. }
  377. /***************************************************************************\
  378. * SetEnableState
  379. *
  380. * Description:
  381. * Sets the given conversation's enable state based on the EC_ flag
  382. * given.
  383. *
  384. * Returns: fSuccess/fProcessed.
  385. *
  386. * History:
  387. * 11-19-91 sanfords Created.
  388. \***************************************************************************/
  389. BOOL SetEnableState(
  390. PCONV_INFO pcoi,
  391. UINT wCmd)
  392. {
  393. BOOL fRet = TRUE;
  394. switch (wCmd) {
  395. case EC_CHECKQUEUEONCE:
  396. case EC_CHECKQUEUE:
  397. fRet = CheckForQueuedMessages(pcoi);
  398. break;
  399. case EC_QUERYWAITING:
  400. fRet = !(pcoi->dmqOut == NULL ||
  401. (pcoi->dmqOut->next == NULL &&
  402. GetClientInfo()->CI_flags & CI_PROCESSING_QUEUE));
  403. break;
  404. case EC_DISABLE:
  405. pcoi->state |= ST_BLOCKED;
  406. pcoi->state &= ~(ST_BLOCKNEXT | ST_BLOCKALLNEXT);
  407. break;
  408. case EC_ENABLEONE:
  409. pcoi->state &= ~ST_BLOCKED;
  410. pcoi->state |= ST_BLOCKNEXT;
  411. break;
  412. case EC_ENABLEONEOFALL:
  413. pcoi->state &= ~ST_BLOCKED;
  414. pcoi->state |= (ST_BLOCKNEXT | ST_BLOCKALLNEXT);
  415. break;
  416. case EC_ENABLEALL:
  417. pcoi->state &= ~(ST_BLOCKED | ST_BLOCKNEXT | ST_BLOCKALLNEXT);
  418. break;
  419. default:
  420. return(FALSE);
  421. }
  422. return (fRet);
  423. }
  424. /***************************************************************************\
  425. * _ClientGetDDEHookData
  426. *
  427. * Description:
  428. * Callback from server to extract data from lParam and place it into
  429. * the pdmhd for use by DDESPY apps. This does a very similar thing
  430. * to the CopyDDEDataIn/Out apis but this only grabs a limited amount
  431. * of the data suitable for posting to the DDESPY app(s). This should
  432. * be merged with the Copy APIs eventually.
  433. *
  434. * History:
  435. * 12-16-91 sanfords Created.
  436. \***************************************************************************/
  437. DWORD _ClientGetDDEHookData(
  438. UINT message,
  439. LPARAM lParam,
  440. PDDEML_MSG_HOOK_DATA pdmhd)
  441. {
  442. PBYTE pb;
  443. HANDLE hDDE;
  444. UnpackDDElParam(message, lParam, &pdmhd->uiLo, &pdmhd->uiHi);
  445. switch (message) {
  446. case WM_DDE_DATA:
  447. case WM_DDE_POKE:
  448. case WM_DDE_ADVISE:
  449. hDDE = (HANDLE)pdmhd->uiLo;
  450. break;
  451. case WM_DDE_EXECUTE:
  452. hDDE = (HANDLE)pdmhd->uiHi;
  453. break;
  454. case WM_DDE_ACK:
  455. case WM_DDE_REQUEST:
  456. case WM_DDE_UNADVISE:
  457. case WM_DDE_TERMINATE:
  458. pdmhd->cbData = 0;
  459. return (1);
  460. }
  461. pdmhd->cbData = (DWORD)UserGlobalSize(hDDE);
  462. if (pdmhd->cbData) {
  463. USERGLOBALLOCK(hDDE, pb);
  464. if (pb == NULL) {
  465. pdmhd->cbData = 0;
  466. } else {
  467. RtlCopyMemory(&pdmhd->Data, pb, min(pdmhd->cbData,
  468. sizeof(DDEML_MSG_HOOK_DATA) -
  469. FIELD_OFFSET(DDEML_MSG_HOOK_DATA, Data)));
  470. USERGLOBALUNLOCK(hDDE);
  471. }
  472. }
  473. return (1);
  474. }