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.

473 lines
14 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ddemlcli.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * DDE Manager main client side module
  7. *
  8. * Created: 10/3/91 Sanford Staab
  9. *
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. // DDEML globals
  14. PCL_INSTANCE_INFO pciiList = NULL;
  15. RTL_CRITICAL_SECTION gcsDDEML;
  16. #if DBG
  17. PVOID gpDDEMLHeap;
  18. #endif
  19. /***************************************************************************\
  20. * DdeInitialize (DDEML API)
  21. *
  22. * Description:
  23. * Used two different ways:
  24. * 1) First time call (*pidInst == 0) - causes a DDEML instance to be
  25. * created for the calling process/thread. Creates a server side
  26. * event window, server side instance structure, DDE Access Object,
  27. * and client side instance structure. The callback function address
  28. * and filter flags (afCmd) are placed into these structures.
  29. * 2) Subsequent call (*pidInst == hInst) - updates filter flags in
  30. * client and server side structures.
  31. *
  32. * History:
  33. * 11-1-91 sanfords Created.
  34. \***************************************************************************/
  35. FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeInitializeA, LPDWORD, pidInst, PFNCALLBACK, pfnCallback, DWORD, afCmd, DWORD, ulRes)
  36. UINT DdeInitializeA(
  37. LPDWORD pidInst,
  38. PFNCALLBACK pfnCallback,
  39. DWORD afCmd,
  40. DWORD ulRes)
  41. {
  42. if (ulRes != 0) {
  43. return (DMLERR_INVALIDPARAMETER);
  44. }
  45. return (InternalDdeInitialize(pidInst, pfnCallback, afCmd, 0));
  46. }
  47. FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeInitializeW, LPDWORD, pidInst, PFNCALLBACK, pfnCallback, DWORD, afCmd, DWORD, ulRes)
  48. UINT DdeInitializeW(
  49. LPDWORD pidInst,
  50. PFNCALLBACK pfnCallback,
  51. DWORD afCmd,
  52. DWORD ulRes)
  53. {
  54. if (ulRes != 0) {
  55. return (DMLERR_INVALIDPARAMETER);
  56. }
  57. return (InternalDdeInitialize(pidInst, pfnCallback, afCmd, 1));
  58. }
  59. UINT InternalDdeInitialize(
  60. LPDWORD pidInst,
  61. PFNCALLBACK pfnCallback,
  62. DWORD afCmd,
  63. BOOL fUnicode)
  64. {
  65. UINT uiRet = DMLERR_MEMORY_ERROR;
  66. register PCL_INSTANCE_INFO pcii;
  67. if (afCmd & APPCLASS_MONITOR) {
  68. afCmd |= CBF_MONMASK;
  69. }
  70. if (afCmd & APPCMD_CLIENTONLY) {
  71. afCmd |= CBF_FAIL_CONNECTIONS;
  72. }
  73. EnterDDECrit;
  74. if (*pidInst != 0) {
  75. pcii = ValidateInstance((HANDLE)LongToHandle( *pidInst ));
  76. if (pcii == NULL) {
  77. uiRet = DMLERR_INVALIDPARAMETER;
  78. goto Exit;
  79. }
  80. // only allow certain bits to be changed on reinitialize call
  81. pcii->afCmd = (pcii->afCmd & ~(CBF_MASK | MF_MASK)) |
  82. (afCmd & (CBF_MASK | MF_MASK));
  83. LeaveDDECrit;
  84. NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, afCmd);
  85. return (DMLERR_NO_ERROR);
  86. }
  87. pcii = (PCL_INSTANCE_INFO)DDEMLAlloc(sizeof(CL_INSTANCE_INFO));
  88. if (pcii == NULL) {
  89. uiRet = DMLERR_MEMORY_ERROR;
  90. goto Exit;
  91. }
  92. pcii->plaNameService = (LATOM *)DDEMLAlloc(sizeof(LATOM));
  93. if (pcii->plaNameService == NULL) {
  94. uiRet = DMLERR_MEMORY_ERROR;
  95. goto Backout3;
  96. }
  97. // *pcii->plaNameService = 0; // zero init takes care of this
  98. pcii->cNameServiceAlloc = 1;
  99. /*
  100. * Flag this window as being create from a diff hmod as the app so
  101. * hotkeys don't take it as the first window created in the app and
  102. * assign it as the hotkey.
  103. */
  104. pcii->hwndMother = _CreateWindowEx(0, (LPTSTR)(gpsi->atomSysClass[ICLS_DDEMLMOTHER]), L"",
  105. WS_POPUP, 0, 0, 0, 0, (HWND)0,
  106. (HMENU)0, 0, (LPVOID)NULL, CW_FLAGS_DIFFHMOD);
  107. if (pcii->hwndMother == 0) {
  108. uiRet = DMLERR_SYS_ERROR;
  109. goto Backout2;
  110. }
  111. SetWindowLongPtr(pcii->hwndMother, GWLP_INSTANCE_INFO, (LONG_PTR)pcii);
  112. pcii->afCmd = afCmd | APPCMD_FILTERINITS;
  113. pcii->pfnCallback = pfnCallback;
  114. // pcii->LastError = DMLERR_NO_ERROR; // zero init
  115. pcii->tid = GetCurrentThreadId();
  116. // pcii->aServerLookup = NULL; // zero init
  117. // pcii->cServerLookupAlloc = 0; // zero init
  118. // pcii->ConvStartupState = 0; // zero init - Not blocked.
  119. // pcii->flags = 0; // zero init
  120. // pcii->cInDDEMLCallback = 0; // zero init
  121. // pcii->pLinkCounts = NULL; // zero init
  122. // Do this last when the client side is ready for whatever events
  123. // flying around may come charging in.
  124. LeaveDDECrit;
  125. uiRet = NtUserDdeInitialize(&pcii->hInstServer,
  126. &pcii->hwndEvent,
  127. &pcii->MonitorFlags,
  128. pcii->afCmd,
  129. pcii);
  130. EnterDDECrit;
  131. if (uiRet != DMLERR_NO_ERROR) {
  132. Backout:
  133. NtUserDestroyWindow(pcii->hwndMother);
  134. Backout2:
  135. DDEMLFree(pcii->plaNameService);
  136. Backout3:
  137. DDEMLFree(pcii);
  138. goto Exit;
  139. }
  140. pcii->hInstClient = AddInstance(pcii->hInstServer);
  141. *pidInst = HandleToUlong(pcii->hInstClient);
  142. if (pcii->hInstClient == 0) {
  143. LeaveDDECrit;
  144. NtUserCallOneParam((ULONG_PTR)pcii->hInstServer, SFI__CSDDEUNINITIALIZE);
  145. EnterDDECrit;
  146. uiRet = DMLERR_MEMORY_ERROR;
  147. goto Backout;
  148. }
  149. SetHandleData(pcii->hInstClient, (ULONG_PTR)pcii);
  150. pcii->next = pciiList;
  151. pciiList = pcii;
  152. if (fUnicode) {
  153. pcii->flags |= IIF_UNICODE;
  154. }
  155. uiRet = DMLERR_NO_ERROR;
  156. Exit:
  157. LeaveDDECrit;
  158. return (uiRet);
  159. }
  160. /***************************************************************************\
  161. * DdeUninitialize (DDEML API)
  162. *
  163. * Description:
  164. * Shuts down a DDEML instance and frees all associated resources.
  165. *
  166. * History:
  167. * 11-12-91 sanfords Created.
  168. \***************************************************************************/
  169. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeUninitialize, DWORD, idInst)
  170. BOOL DdeUninitialize(
  171. DWORD idInst)
  172. {
  173. PCL_INSTANCE_INFO pcii, pciiPrev;
  174. BOOL fRet = FALSE;
  175. CheckDDECritOut;
  176. EnterDDECrit;
  177. pcii = ValidateInstance((HANDLE)LongToHandle( idInst ));
  178. if (pcii == NULL) {
  179. BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
  180. goto Exit;
  181. }
  182. /*
  183. * If this thread is in the middle of a synchronous transaction or
  184. * a callback, we need to back out of those first.
  185. */
  186. if ((pcii->flags & IIF_IN_SYNC_XACT) || pcii->cInDDEMLCallback) {
  187. pcii->afCmd |= APPCMD_UNINIT_ASAP;
  188. fRet = TRUE;
  189. goto Exit;
  190. }
  191. ApplyFunctionToObjects(HTYPE_CONVERSATION_LIST, InstFromHandle(pcii->hInstClient),
  192. (PFNHANDLEAPPLY)DdeDisconnectList);
  193. ApplyFunctionToObjects(HTYPE_CLIENT_CONVERSATION, InstFromHandle(pcii->hInstClient),
  194. (PFNHANDLEAPPLY)DdeDisconnect);
  195. ApplyFunctionToObjects(HTYPE_SERVER_CONVERSATION, InstFromHandle(pcii->hInstClient),
  196. (PFNHANDLEAPPLY)DdeDisconnect);
  197. ApplyFunctionToObjects(HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(pcii->hInstClient),
  198. (PFNHANDLEAPPLY)WaitForZombieTerminate);
  199. ApplyFunctionToObjects(HTYPE_DATA_HANDLE, InstFromHandle(pcii->hInstClient),
  200. (PFNHANDLEAPPLY)ApplyFreeDataHandle);
  201. LeaveDDECrit;
  202. NtUserCallOneParam((ULONG_PTR)pcii->hInstServer, SFI__CSDDEUNINITIALIZE);
  203. NtUserDestroyWindow(pcii->hwndMother);
  204. EnterDDECrit;
  205. DDEMLFree(pcii->plaNameService);
  206. DestroyInstance(pcii->hInstClient);
  207. // unlink pcii from pciiList
  208. if (pciiList == pcii) {
  209. pciiList = pciiList->next;
  210. } else {
  211. for (pciiPrev = pciiList; pciiPrev != NULL && pciiPrev->next != pcii;
  212. pciiPrev = pciiPrev->next) {
  213. ;
  214. }
  215. if (pciiPrev != NULL) {
  216. pciiPrev->next = pcii->next;
  217. }
  218. }
  219. DDEMLFree(pcii);
  220. fRet = TRUE;
  221. Exit:
  222. LeaveDDECrit;
  223. return (fRet);
  224. }
  225. /***************************************************************************\
  226. * DdeNameService (DDEML API)
  227. *
  228. * Description:
  229. * Registers, and Unregisters service names and sets the Initiate filter
  230. * state for an instance.
  231. *
  232. * History:
  233. * 11-1-91 sanfords Created.
  234. \***************************************************************************/
  235. HDDEDATA DdeNameService(
  236. DWORD idInst,
  237. HSZ hsz1, // service name
  238. HSZ hsz2, // reserved for future enhancements
  239. UINT afCmd) // DNS_ flags.
  240. {
  241. BOOL fRet = TRUE;
  242. LATOM *plaNameService;
  243. PCL_INSTANCE_INFO pcii;
  244. EnterDDECrit;
  245. pcii = ValidateInstance((HANDLE)LongToHandle( idInst ));
  246. if (pcii == NULL) {
  247. BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
  248. fRet = FALSE;
  249. goto Exit;
  250. }
  251. if ((hsz1 && ValidateHSZ(hsz1) == HSZT_INVALID) || hsz2 != 0) {
  252. SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
  253. fRet = FALSE;
  254. goto Exit;
  255. }
  256. if (afCmd & DNS_FILTERON && !(pcii->afCmd & APPCMD_FILTERINITS)) {
  257. pcii->afCmd |= APPCMD_FILTERINITS;
  258. NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd);
  259. }
  260. if (afCmd & DNS_FILTEROFF && (pcii->afCmd & APPCMD_FILTERINITS)) {
  261. pcii->afCmd &= ~APPCMD_FILTERINITS;
  262. NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd);
  263. }
  264. if (afCmd & (DNS_REGISTER | DNS_UNREGISTER)) {
  265. GATOM ga;
  266. if (pcii->afCmd & APPCMD_CLIENTONLY) {
  267. SetLastDDEMLError(pcii, DMLERR_DLL_USAGE);
  268. fRet = FALSE;
  269. goto Exit;
  270. }
  271. if (hsz1 == 0) {
  272. if (afCmd & DNS_REGISTER) {
  273. /*
  274. * registering NULL is not allowed!
  275. */
  276. SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
  277. fRet = FALSE;
  278. goto Exit;
  279. }
  280. /*
  281. * unregistering NULL is just like unregistering each
  282. * registered name.
  283. *
  284. * 10/19/90 - made this a synchronous event so that hsz
  285. * can be freed by calling app after this call completes
  286. * without us having to keep a copy around forever.
  287. */
  288. plaNameService = pcii->plaNameService;
  289. while (*plaNameService != 0) {
  290. ga = LocalToGlobalAtom(*plaNameService);
  291. DeleteAtom(*plaNameService);
  292. LeaveDDECrit;
  293. RegisterService(FALSE, ga, pcii->hwndMother);
  294. EnterDDECrit;
  295. GlobalDeleteAtom(ga);
  296. plaNameService++;
  297. }
  298. pcii->cNameServiceAlloc = 1;
  299. *pcii->plaNameService = 0;
  300. goto Exit;
  301. }
  302. if (afCmd & DNS_REGISTER) {
  303. plaNameService = (LATOM *)DDEMLReAlloc(pcii->plaNameService,
  304. sizeof(LATOM) * ++pcii->cNameServiceAlloc);
  305. if (plaNameService == NULL) {
  306. SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
  307. pcii->cNameServiceAlloc--;
  308. fRet = FALSE;
  309. goto Exit;
  310. } else {
  311. pcii->plaNameService = plaNameService;
  312. }
  313. IncLocalAtomCount(LATOM_FROM_HSZ(hsz1)); // NameService copy
  314. plaNameService[pcii->cNameServiceAlloc - 2] = LATOM_FROM_HSZ(hsz1);
  315. plaNameService[pcii->cNameServiceAlloc - 1] = 0;
  316. } else { // DNS_UNREGISTER
  317. plaNameService = pcii->plaNameService;
  318. while (*plaNameService != 0 && *plaNameService != LATOM_FROM_HSZ(hsz1)) {
  319. plaNameService++;
  320. }
  321. if (*plaNameService == 0) {
  322. goto Exit; // not found just exit
  323. }
  324. //
  325. // fill empty slot with last entry and fill last entry with 0
  326. //
  327. pcii->cNameServiceAlloc--;
  328. *plaNameService = pcii->plaNameService[pcii->cNameServiceAlloc - 1];
  329. pcii->plaNameService[pcii->cNameServiceAlloc - 1] = 0;
  330. }
  331. ga = LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1));
  332. LeaveDDECrit;
  333. RegisterService((afCmd & DNS_REGISTER) ? TRUE : FALSE, ga,
  334. pcii->hwndMother);
  335. EnterDDECrit;
  336. GlobalDeleteAtom(ga);
  337. }
  338. Exit:
  339. LeaveDDECrit;
  340. return ((HDDEDATA)IntToPtr( fRet ));
  341. }
  342. /***************************************************************************\
  343. * DdeGetLastError (DDEML API)
  344. *
  345. * Description:
  346. * Returns last error code set for the instance given.
  347. *
  348. * History:
  349. * 11-12-91 sanfords Created.
  350. \***************************************************************************/
  351. FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeGetLastError, DWORD, idInst)
  352. UINT DdeGetLastError(
  353. DWORD idInst)
  354. {
  355. UINT uiRet = 0;
  356. PCL_INSTANCE_INFO pcii;
  357. EnterDDECrit;
  358. pcii = ValidateInstance((HANDLE)LongToHandle( idInst ));
  359. if (pcii == NULL) {
  360. uiRet = DMLERR_INVALIDPARAMETER;
  361. goto Exit;
  362. }
  363. uiRet = pcii->LastError;
  364. pcii->LastError = DMLERR_NO_ERROR;
  365. Exit:
  366. LeaveDDECrit;
  367. return (uiRet);
  368. }
  369. /***************************************************************************\
  370. * DdeImpersonateClient()
  371. *
  372. * Description:
  373. * Does security impersonation for DDEML server apps.
  374. * This API should only be called with server side hConvs;
  375. *
  376. * History:
  377. * 5-4-92 sanfords Created.
  378. \***************************************************************************/
  379. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeImpersonateClient, HCONV, hConv)
  380. BOOL DdeImpersonateClient(
  381. HCONV hConv)
  382. {
  383. PCONV_INFO pcoi;
  384. PCL_INSTANCE_INFO pcii;
  385. BOOL fRet = FALSE;
  386. EnterDDECrit;
  387. pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
  388. HTYPE_SERVER_CONVERSATION, HINST_ANY);
  389. if (pcoi == NULL) {
  390. BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
  391. goto Exit;
  392. }
  393. pcii = PciiFromHandle((HANDLE)hConv);
  394. if (pcii == NULL) {
  395. BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
  396. goto Exit;
  397. }
  398. fRet = NtUserImpersonateDdeClientWindow(pcoi->hwndPartner, pcoi->hwndConv);
  399. Exit:
  400. LeaveDDECrit;
  401. return (fRet);
  402. }