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.

411 lines
11 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: menudd.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Menu drag and drop - client
  7. *
  8. * History:
  9. * 10/29/96 GerardoB Created
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*
  14. * OLE's GUID initialization.
  15. */
  16. #include "initguid.h"
  17. /*
  18. * Macro to cast OLE's IDropTarget pointer to internal pointer.
  19. */
  20. #define PMNIDT(pdt) ((PMNIDROPTARGET)pdt)
  21. /*
  22. * The mndt* functions implement the IDropTarget interface.
  23. */
  24. /**************************************************************************\
  25. * mndtAddRef
  26. *
  27. * 10/28/96 GerardoB Created
  28. \**************************************************************************/
  29. ULONG mndtAddRef(
  30. LPDROPTARGET pdt)
  31. {
  32. return ++(PMNIDT(pdt)->dwRefCount);
  33. }
  34. /**************************************************************************\
  35. * mndtQueryInterface
  36. *
  37. * 10/28/96 GerardoB Created
  38. \**************************************************************************/
  39. HRESULT mndtQueryInterface(
  40. LPDROPTARGET pdt,
  41. REFIID riid,
  42. PVOID * ppvObj)
  43. {
  44. if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDropTarget)) {
  45. mndtAddRef(pdt);
  46. *ppvObj = pdt;
  47. return NOERROR;
  48. } else {
  49. return E_NOINTERFACE;
  50. }
  51. }
  52. /**************************************************************************\
  53. * mndtRelease
  54. *
  55. * 10/28/96 GerardoB Created
  56. \**************************************************************************/
  57. ULONG mndtRelease(
  58. LPDROPTARGET pdt)
  59. {
  60. if (--(PMNIDT(pdt)->dwRefCount) != 0) {
  61. return PMNIDT(pdt)->dwRefCount;
  62. }
  63. UserLocalFree(pdt);
  64. return NOERROR;
  65. }
  66. /**************************************************************************\
  67. * mndtDragOver
  68. *
  69. * 10/28/96 GerardoB Created
  70. \**************************************************************************/
  71. HRESULT mndtDragOver(
  72. LPDROPTARGET pdt,
  73. DWORD grfKeyState,
  74. POINTL ptl,
  75. LPDWORD pdwEffect)
  76. {
  77. MNDRAGOVERINFO mndoi;
  78. MENUGETOBJECTINFO mngoi;
  79. /*
  80. * Get the dragover info for the selection corresponding to this point
  81. */
  82. if (!NtUserMNDragOver((POINT *)&ptl, &mndoi)) {
  83. RIPMSG0(RIP_WARNING, "mndtDragOver: NtUserDragOver failed");
  84. *pdwEffect = DROPEFFECT_NONE;
  85. return NOERROR;
  86. }
  87. /*
  88. * If not switching items or crossing gap boundaries, pass the
  89. * the drag over.
  90. */
  91. if (!(mndoi.dwFlags & MNGOF_CROSSBOUNDARY)) {
  92. if (PMNIDT(pdt)->pidt != NULL) {
  93. return PMNIDT(pdt)->pidt->lpVtbl->DragOver(PMNIDT(pdt)->pidt, grfKeyState, ptl, pdwEffect);
  94. }
  95. } else {
  96. /*
  97. * DragLeave and Release the current item, if any
  98. */
  99. if (PMNIDT(pdt)->pidt != NULL) {
  100. PMNIDT(pdt)->pidt->lpVtbl->DragLeave(PMNIDT(pdt)->pidt);
  101. PMNIDT(pdt)->pidt->lpVtbl->Release(PMNIDT(pdt)->pidt);
  102. PMNIDT(pdt)->pidt = NULL;
  103. }
  104. /*
  105. * If an item is selected, Get the interface for it
  106. */
  107. if (mndoi.uItemIndex != MFMWFP_NOITEM) {
  108. mngoi.hmenu = mndoi.hmenu;
  109. mngoi.dwFlags = mndoi.dwFlags & MNGOF_GAP;
  110. mngoi.uPos = mndoi.uItemIndex;
  111. mngoi.riid = (PVOID)&IID_IDropTarget;
  112. mngoi.pvObj = NULL;
  113. if (MNGO_NOERROR == SendMessage(mndoi.hwndNotify, WM_MENUGETOBJECT, 0, (LPARAM)&mngoi)) {
  114. PMNIDT(pdt)->pidt = mngoi.pvObj;
  115. }
  116. }
  117. /*
  118. * If we got a new interface, AddRef and DragEnter it.
  119. */
  120. if (PMNIDT(pdt)->pidt != NULL) {
  121. PMNIDT(pdt)->pidt->lpVtbl->AddRef(PMNIDT(pdt)->pidt);
  122. return PMNIDT(pdt)->pidt->lpVtbl->DragEnter(PMNIDT(pdt)->pidt, PMNIDT(pdt)->pido, grfKeyState, ptl, pdwEffect);
  123. }
  124. }
  125. *pdwEffect = DROPEFFECT_NONE;
  126. return NOERROR;
  127. }
  128. /**************************************************************************\
  129. * mndtDragEnter
  130. *
  131. * 10/28/96 GerardoB Created
  132. \**************************************************************************/
  133. HRESULT mndtDragEnter(
  134. LPDROPTARGET pdt,
  135. LPDATAOBJECT pdo,
  136. DWORD grfKeyState,
  137. POINTL ptl,
  138. LPDWORD pdwEffect)
  139. {
  140. /*
  141. * Save the IDataObject.
  142. */
  143. PMNIDT(pdt)->pido = pdo;
  144. /*
  145. * DragEnter is the same as a DragOver; only that we will never fail it.
  146. */
  147. mndtDragOver(pdt, grfKeyState, ptl, pdwEffect);
  148. return NOERROR;
  149. }
  150. /**************************************************************************\
  151. * mndtDragLeave
  152. *
  153. * 10/28/96 GerardoB Created
  154. \**************************************************************************/
  155. HRESULT mndtDragLeave(
  156. LPDROPTARGET pdt)
  157. {
  158. /*
  159. * Let the kernel mode clean up.
  160. */
  161. NtUserMNDragLeave();
  162. /*
  163. * DragLeave and Release the current item, if any.
  164. */
  165. if (PMNIDT(pdt)->pidt != NULL) {
  166. PMNIDT(pdt)->pidt->lpVtbl->DragLeave(PMNIDT(pdt)->pidt);
  167. PMNIDT(pdt)->pidt->lpVtbl->Release(PMNIDT(pdt)->pidt);
  168. PMNIDT(pdt)->pidt = NULL;
  169. }
  170. return NOERROR;
  171. }
  172. /**************************************************************************\
  173. * mndtDrop
  174. *
  175. * 10/28/96 GerardoB Created
  176. \**************************************************************************/
  177. HRESULT mndtDrop(
  178. LPDROPTARGET pdt,
  179. LPDATAOBJECT pdo,
  180. DWORD grfKeyState,
  181. POINTL ptl,
  182. LPDWORD pdwEffect)
  183. {
  184. HRESULT hres;
  185. /*
  186. * If we got a target, pass the drop and release it.
  187. */
  188. if (PMNIDT(pdt)->pidt != NULL) {
  189. hres = PMNIDT(pdt)->pidt->lpVtbl->Drop(PMNIDT(pdt)->pidt, pdo, grfKeyState, ptl, pdwEffect);
  190. PMNIDT(pdt)->pidt->lpVtbl->Release(PMNIDT(pdt)->pidt);
  191. PMNIDT(pdt)->pidt = NULL;
  192. } else {
  193. *pdwEffect = DROPEFFECT_NONE;
  194. hres = NOERROR;
  195. }
  196. /*
  197. * Clean up.
  198. */
  199. mndtDragLeave(pdt);
  200. return hres;
  201. }
  202. /**************************************************************************\
  203. * Drop target VTable
  204. *
  205. \**************************************************************************/
  206. IDropTargetVtbl idtVtbl = {
  207. mndtQueryInterface,
  208. mndtAddRef,
  209. mndtRelease,
  210. mndtDragEnter,
  211. mndtDragOver,
  212. mndtDragLeave,
  213. mndtDrop
  214. };
  215. /**************************************************************************\
  216. * __ClientRegisterDragDrop
  217. *
  218. * 10/28/96 GerardoB Created
  219. \**************************************************************************/
  220. DWORD __ClientRegisterDragDrop(
  221. HWND * phwnd)
  222. {
  223. HRESULT hres = STATUS_UNSUCCESSFUL;
  224. PMNIDROPTARGET pmnidt;
  225. /*
  226. * Allocate the IDropTarget interface struct & additional data.
  227. */
  228. pmnidt = (PMNIDROPTARGET)UserLocalAlloc(HEAP_ZERO_MEMORY,
  229. sizeof(MNIDROPTARGET));
  230. if (pmnidt == NULL) {
  231. RIPMSG0(RIP_WARNING, "__ClientRegisterDragDrop allocation Failed");
  232. hres = STATUS_UNSUCCESSFUL;
  233. goto BackToKernel;
  234. }
  235. /*
  236. * Initialize it
  237. */
  238. pmnidt->idt.lpVtbl = &idtVtbl;
  239. /*
  240. * Call RegisterDragDrop
  241. */
  242. hres = (*(REGISTERDDPROC)gpfnOLERegisterDD)(*phwnd, (LPDROPTARGET)pmnidt);
  243. if (!SUCCEEDED(hres)) {
  244. RIPMSG1(RIP_WARNING, "__ClientRegisterDragDrop Failed:%#lx", hres);
  245. }
  246. BackToKernel:
  247. return UserCallbackReturn(NULL, 0, hres);
  248. }
  249. /**************************************************************************\
  250. * __ClientRevokeDragDrop
  251. *
  252. *
  253. * 10/28/96 GerardoB Created
  254. \**************************************************************************/
  255. DWORD __ClientRevokeDragDrop(
  256. HWND * phwnd)
  257. {
  258. HRESULT hres;
  259. /*
  260. * Call RevokeDragDrop.
  261. */
  262. hres = (*(REVOKEDDPROC)gpfnOLERevokeDD)(*phwnd);
  263. if (!SUCCEEDED(hres)) {
  264. RIPMSG1(RIP_WARNING, "__ClientRevokeDragDrop Failed: 0x%x", hres);
  265. }
  266. return UserCallbackReturn(NULL, 0, hres);
  267. }
  268. /**************************************************************************\
  269. * LoadOLEOnce
  270. *
  271. *
  272. * 10/31/96 GerardoB Created
  273. \**************************************************************************/
  274. NTSTATUS LoadOLEOnce(
  275. VOID)
  276. {
  277. NTSTATUS Status;
  278. OLEINITIALIZEPROC pfnOLEOleInitialize;
  279. /*
  280. * These are the functions that we'll call.
  281. */
  282. GETPROCINFO gpi [] = {
  283. {&((FARPROC)pfnOLEOleInitialize), (LPCSTR)"OleInitialize"},
  284. {&gpfnOLEOleUninitialize, (LPCSTR)"OleUninitialize"},
  285. {&gpfnOLERegisterDD, (LPCSTR)"RegisterDragDrop"},
  286. {&gpfnOLERevokeDD, (LPCSTR)"RevokeDragDrop"},
  287. {NULL, NULL}
  288. };
  289. GETPROCINFO * pgpi = gpi;
  290. /*
  291. * We should come here only once
  292. */
  293. UserAssert(ghinstOLE == NULL);
  294. /*
  295. * Load it
  296. */
  297. ghinstOLE = LoadLibrary(L"OLE32.DLL");
  298. if (ghinstOLE == NULL) {
  299. RIPMSG1(RIP_WARNING, "LoadOLEOnce: Failed to load OLE32.DLL: %#lx", GetLastError());
  300. goto OLEWontLoad;
  301. }
  302. /*
  303. * Get the address of all procs
  304. */
  305. while (pgpi->ppfn != NULL) {
  306. *(pgpi->ppfn) = GetProcAddress(ghinstOLE, pgpi->lpsz);
  307. if (*(pgpi->ppfn) == NULL) {
  308. RIPMSG2(RIP_WARNING, "LoadOLEOnce: GetProcAddress failed: '%s': %#lx",
  309. pgpi->lpsz, GetLastError());
  310. break;
  311. }
  312. pgpi++;
  313. }
  314. /*
  315. * If it got all procs, call OleInitialize.
  316. */
  317. if (pgpi->ppfn == NULL) {
  318. Status = (*pfnOLEOleInitialize)(NULL);
  319. if (SUCCEEDED(Status)) {
  320. goto BackToKernel;
  321. } else {
  322. RIPMSG1(RIP_WARNING, "LoadOLEOnce: OleInitialize failed:%#lx", Status);
  323. }
  324. }
  325. /*
  326. * Something failed; NULL out all function pointers, free the library,
  327. * and mark ghinstOLE so we won't come back here.
  328. */
  329. pgpi = gpi;
  330. while (pgpi->ppfn != NULL) {
  331. *(pgpi->ppfn) = NULL;
  332. pgpi++;
  333. }
  334. FreeLibrary(ghinstOLE);
  335. OLEWontLoad:
  336. ghinstOLE = OLEWONTLOAD;
  337. Status = STATUS_UNSUCCESSFUL;
  338. BackToKernel:
  339. return Status;
  340. }
  341. /**************************************************************************\
  342. * __ClientLoadOLE
  343. *
  344. *
  345. * 10/31/96 GerardoB Created
  346. \**************************************************************************/
  347. DWORD __ClientLoadOLE(
  348. PVOID p)
  349. {
  350. NTSTATUS Status;
  351. UNREFERENCED_PARAMETER(p);
  352. if (ghinstOLE == NULL) {
  353. Status = LoadOLEOnce();
  354. } else if (ghinstOLE == OLEWONTLOAD) {
  355. Status = STATUS_UNSUCCESSFUL;
  356. } else {
  357. UserAssert(gpfnOLERegisterDD != NULL);
  358. UserAssert(gpfnOLERevokeDD != NULL);
  359. Status = STATUS_SUCCESS;
  360. }
  361. return UserCallbackReturn(NULL, 0, Status);
  362. }