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.

2332 lines
68 KiB

  1. /*******************************************************************************
  2. *
  3. *
  4. *
  5. * idrgdrp.c - Drag and Drop code for dropping vCards in and out of the WAB
  6. * Several Formats are droppable into other apps:
  7. * Within the WAB, we drop entryids
  8. * Within different WABs we drop flat buffers containing full Property
  9. * arrays (but Named Propery data is lost in the process)(sometimes)
  10. * We provide data as vCard files that can be dropped into anything asking
  11. * for CF_HDROP
  12. * We also create a text buffer and drop that into CF_TEXT requesters
  13. * The text buffers only hold the same data as the tooltip ..
  14. *
  15. * created 5/97 - vikramm
  16. *
  17. * (c) Microsoft Corp, 1997
  18. *
  19. ********************************************************************************/
  20. #include <_apipch.h>
  21. const TCHAR szVCardExt[] = TEXT(".vcf");
  22. //
  23. // IWABDocHost jump tables is defined here...
  24. //
  25. IWAB_DRAGDROP_Vtbl vtblIWAB_DRAGDROP = {
  26. VTABLE_FILL
  27. IWAB_DRAGDROP_QueryInterface,
  28. IWAB_DRAGDROP_AddRef,
  29. IWAB_DRAGDROP_Release,
  30. };
  31. IWAB_DROPTARGET_Vtbl vtblIWAB_DROPTARGET = {
  32. VTABLE_FILL
  33. (IWAB_DROPTARGET_QueryInterface_METHOD *) IWAB_DRAGDROP_QueryInterface,
  34. (IWAB_DROPTARGET_AddRef_METHOD *) IWAB_DRAGDROP_AddRef,
  35. (IWAB_DROPTARGET_Release_METHOD *) IWAB_DRAGDROP_Release,
  36. IWAB_DROPTARGET_DragEnter,
  37. IWAB_DROPTARGET_DragOver,
  38. IWAB_DROPTARGET_DragLeave,
  39. IWAB_DROPTARGET_Drop
  40. };
  41. IWAB_DROPSOURCE_Vtbl vtblIWAB_DROPSOURCE = {
  42. VTABLE_FILL
  43. (IWAB_DROPSOURCE_QueryInterface_METHOD *) IWAB_DRAGDROP_QueryInterface,
  44. (IWAB_DROPSOURCE_AddRef_METHOD *) IWAB_DRAGDROP_AddRef,
  45. (IWAB_DROPSOURCE_Release_METHOD *) IWAB_DRAGDROP_Release,
  46. IWAB_DROPSOURCE_QueryContinueDrag,
  47. IWAB_DROPSOURCE_GiveFeedback,
  48. };
  49. IWAB_DATAOBJECT_Vtbl vtblIWAB_DATAOBJECT = {
  50. VTABLE_FILL
  51. IWAB_DATAOBJECT_QueryInterface,
  52. IWAB_DATAOBJECT_AddRef,
  53. IWAB_DATAOBJECT_Release,
  54. IWAB_DATAOBJECT_GetData,
  55. IWAB_DATAOBJECT_GetDataHere,
  56. IWAB_DATAOBJECT_QueryGetData,
  57. IWAB_DATAOBJECT_GetCanonicalFormatEtc,
  58. IWAB_DATAOBJECT_SetData,
  59. IWAB_DATAOBJECT_EnumFormatEtc,
  60. IWAB_DATAOBJECT_DAdvise,
  61. IWAB_DATAOBJECT_DUnadvise,
  62. IWAB_DATAOBJECT_EnumDAdvise
  63. };
  64. IWAB_ENUMFORMATETC_Vtbl vtblIWAB_ENUMFORMATETC = {
  65. VTABLE_FILL
  66. IWAB_ENUMFORMATETC_QueryInterface,
  67. IWAB_ENUMFORMATETC_AddRef,
  68. IWAB_ENUMFORMATETC_Release,
  69. IWAB_ENUMFORMATETC_Next,
  70. IWAB_ENUMFORMATETC_Skip,
  71. IWAB_ENUMFORMATETC_Reset,
  72. IWAB_ENUMFORMATETC_Clone,
  73. };
  74. extern void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost);
  75. extern void LocalFreeSBinary(LPSBinary lpsb);
  76. extern BOOL bIsGroupSelected(HWND hWndLV, LPSBinary lpsbEID);
  77. extern void UpdateLV(LPBWI lpbwi);
  78. //registered clipboard formats
  79. CLIPFORMAT g_cfWABFlatBuffer = 0;
  80. const TCHAR c_szWABFlatBuffer[] = TEXT("WABFlatBuffer");
  81. CLIPFORMAT g_cfWABEntryIDList = 0;
  82. const TCHAR c_szWABEntryIDList[] = TEXT("WABEntryIDList");
  83. ///////////////////////////////////////////////////////////////////////////////
  84. // Helper functions to keep track of and delete *.vcf files in temp directory,
  85. // created by drag/drop
  86. //
  87. typedef struct _tagVFileList
  88. {
  89. LPTSTR lptszFilename;
  90. struct _tagVFileList * pNext;
  91. } VFILENAMELIST, *PVFILENAMELIST;
  92. static VFILENAMELIST * s_pFileNameList = NULL;
  93. static BOOL bAddToNameList(LPTSTR lptszFilename);
  94. static void DeleteFilesInList();
  95. //$$//////////////////////////////////////////////////////////////////////////
  96. //
  97. // Creates a New IWABDocHost Object
  98. //
  99. //////////////////////////////////////////////////////////////////////////////
  100. HRESULT HrCreateIWABDragDrop(LPIWABDRAGDROP * lppIWABDragDrop)
  101. {
  102. LPIWABDRAGDROP lpIWABDragDrop = NULL;
  103. SCODE sc;
  104. HRESULT hr = hrSuccess;
  105. //
  106. // Allocate space for the IAB structure
  107. //
  108. if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABDRAGDROP), (LPVOID *) &lpIWABDragDrop))) {
  109. hr = ResultFromScode(sc);
  110. goto err;
  111. }
  112. MAPISetBufferName(lpIWABDragDrop, TEXT("WAB Drag Drop Data Object"));
  113. ZeroMemory(lpIWABDragDrop, sizeof(IWABDRAGDROP));
  114. lpIWABDragDrop->lpVtbl = &vtblIWAB_DRAGDROP;
  115. lpIWABDragDrop->lpIWDD = lpIWABDragDrop;
  116. sc = MAPIAllocateMore(sizeof(IWABDROPTARGET), lpIWABDragDrop, &(lpIWABDragDrop->lpIWABDropTarget));
  117. if(sc)
  118. goto err;
  119. ZeroMemory(lpIWABDragDrop->lpIWABDropTarget, sizeof(IWABDROPTARGET));
  120. lpIWABDragDrop->lpIWABDropTarget->lpVtbl = &vtblIWAB_DROPTARGET;
  121. lpIWABDragDrop->lpIWABDropTarget->lpIWDD = lpIWABDragDrop;
  122. sc = MAPIAllocateMore(sizeof(IWABDROPSOURCE), lpIWABDragDrop, &(lpIWABDragDrop->lpIWABDropSource));
  123. if(sc)
  124. goto err;
  125. ZeroMemory(lpIWABDragDrop->lpIWABDropSource, sizeof(IWABDROPSOURCE));
  126. lpIWABDragDrop->lpIWABDropSource->lpVtbl = &vtblIWAB_DROPSOURCE;
  127. lpIWABDragDrop->lpIWABDropSource->lpIWDD = lpIWABDragDrop;
  128. lpIWABDragDrop->lpVtbl->AddRef(lpIWABDragDrop);
  129. *lppIWABDragDrop = lpIWABDragDrop;
  130. if(g_cfWABFlatBuffer == 0)
  131. {
  132. g_cfWABFlatBuffer = (CLIPFORMAT) RegisterClipboardFormat(c_szWABFlatBuffer);
  133. g_cfWABEntryIDList = (CLIPFORMAT) RegisterClipboardFormat(c_szWABEntryIDList);
  134. }
  135. /*
  136. if (g_cfFileContents == 0)
  137. {
  138. g_cfFileContents = RegisterClipboardFormat(c_szFileContents);
  139. g_cfFileGroupDescriptor = RegisterClipboardFormat(c_szFileGroupDescriptor);
  140. }
  141. */
  142. err:
  143. return hr;
  144. }
  145. //$$//////////////////////////////////////////////////////////////////////////
  146. //
  147. // Release the IWABDragDrop object
  148. //
  149. //////////////////////////////////////////////////////////////////////////////
  150. void ReleaseWABDragDrop(LPIWABDRAGDROP lpIWABDragDrop)
  151. {
  152. MAPIFreeBuffer(lpIWABDragDrop);
  153. // WAB is closing down. Delete any *.vcf files left in temp directory
  154. DeleteFilesInList();
  155. }
  156. BOOL bCheckFileType(LPIWABDROPTARGET lpIWABDropTarget, LPDATAOBJECT pDataObj, DWORD * pdwEffect)
  157. {
  158. #ifndef WIN16
  159. FORMATETC fmte = {lpIWABDropTarget->lpIWDD->m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  160. #else
  161. FORMATETC fmte;
  162. #endif
  163. STGMEDIUM medium;
  164. BOOL bRet = FALSE;
  165. #ifdef WIN16 // Set fmte member value.
  166. fmte.cfFormat = lpIWABDropTarget->lpIWDD->m_cfAccept;
  167. fmte.ptd = NULL;
  168. fmte.dwAspect = DVASPECT_CONTENT;
  169. fmte.lindex = -1;
  170. fmte.tymed = TYMED_HGLOBAL;
  171. #endif
  172. *pdwEffect = lpIWABDropTarget->lpIWDD->m_dwEffect;
  173. if (pDataObj &&
  174. SUCCEEDED(pDataObj->lpVtbl->GetData(pDataObj, &fmte, &medium)))
  175. {
  176. HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
  177. // Enumerate the files and check them
  178. if(hDrop)
  179. {
  180. TCHAR szFile[MAX_PATH];
  181. UINT cFiles;
  182. UINT iFile;
  183. // Let's work through the files given to us
  184. cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
  185. for (iFile = 0; iFile < cFiles; ++iFile)
  186. {
  187. DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
  188. // As long as any file is a vCard we can use it
  189. if(SubstringSearch(szFile, (LPTSTR) szVCardExt))
  190. {
  191. bRet = TRUE;
  192. break;
  193. }
  194. }
  195. }
  196. GlobalUnlock(medium.hGlobal);
  197. }
  198. if (medium.pUnkForRelease)
  199. medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
  200. else
  201. GlobalFree(medium.hGlobal);
  202. return bRet;
  203. }
  204. /**
  205. *
  206. * The Interface methods
  207. *
  208. *
  209. ***/
  210. STDMETHODIMP_(ULONG)
  211. IWAB_DRAGDROP_AddRef(LPIWABDRAGDROP lpIWABDragDrop)
  212. {
  213. return(++(lpIWABDragDrop->lcInit));
  214. }
  215. STDMETHODIMP_(ULONG)
  216. IWAB_DRAGDROP_Release(LPIWABDRAGDROP lpIWABDragDrop)
  217. {
  218. if(--(lpIWABDragDrop->lcInit)==0 &&
  219. lpIWABDragDrop == lpIWABDragDrop->lpIWDD)
  220. {
  221. ReleaseWABDragDrop(lpIWABDragDrop);
  222. return 0;
  223. }
  224. return(lpIWABDragDrop->lcInit);
  225. }
  226. STDMETHODIMP
  227. IWAB_DRAGDROP_QueryInterface(LPIWABDRAGDROP lpIWABDragDrop,
  228. REFIID lpiid,
  229. LPVOID * lppNewObj)
  230. {
  231. LPVOID lp = NULL;
  232. if(!lppNewObj)
  233. return MAPI_E_INVALID_PARAMETER;
  234. *lppNewObj = NULL;
  235. if(IsEqualIID(lpiid, &IID_IUnknown))
  236. lp = (LPVOID) lpIWABDragDrop;
  237. if(IsEqualIID(lpiid, &IID_IDropTarget))
  238. {
  239. DebugTrace(TEXT("WABDropTarget:QI - IDropTarget\n"));
  240. lp = (LPVOID) (LPDROPTARGET) lpIWABDragDrop->lpIWDD->lpIWABDropTarget;
  241. }
  242. if(IsEqualIID(lpiid, &IID_IDropSource))
  243. {
  244. DebugTrace(TEXT("WABDropSource:QI - IDropSource\n"));
  245. lp = (LPVOID) (LPDROPSOURCE) lpIWABDragDrop->lpIWDD->lpIWABDropSource;
  246. }
  247. if(!lp)
  248. {
  249. return E_NOINTERFACE;
  250. }
  251. ((LPIWABDRAGDROP) lp)->lpVtbl->AddRef((LPIWABDRAGDROP) lp);
  252. *lppNewObj = lp;
  253. return S_OK;
  254. }
  255. STDMETHODIMP
  256. IWAB_DROPTARGET_DragEnter( LPIWABDROPTARGET lpIWABDropTarget,
  257. IDataObject * pDataObj,
  258. DWORD grfKeyState,
  259. POINTL pt,
  260. DWORD * pdwEffect)
  261. {
  262. LPENUMFORMATETC penum = NULL;
  263. HRESULT hr;
  264. FORMATETC fmt;
  265. ULONG ulCount = 0;
  266. LPBWI lpbwi = (LPBWI) lpIWABDropTarget->lpIWDD->m_lpv;
  267. if(!pdwEffect || !pDataObj)
  268. return E_INVALIDARG;
  269. *pdwEffect = DROPEFFECT_NONE;
  270. if(lpIWABDropTarget->lpIWDD->m_bSource)
  271. {
  272. // if this is true thent he drag started in the ListView
  273. // if we are currently over the treeview, then we can say ok ...
  274. // otherwise we have to say no
  275. POINT pt1;
  276. pt1.x = pt.x;
  277. pt1.y = pt.y;
  278. if(bwi_hWndTV == WindowFromPoint(pt1))
  279. {
  280. *pdwEffect = DROPEFFECT_COPY;
  281. lpIWABDropTarget->lpIWDD->m_bOverTV = TRUE;
  282. lpIWABDropTarget->lpIWDD->m_cfAccept = g_cfWABEntryIDList;
  283. }
  284. }
  285. else
  286. {
  287. lpIWABDropTarget->lpIWDD->m_dwEffect = DROPEFFECT_NONE;
  288. lpIWABDropTarget->lpIWDD->m_cfAccept = 0;
  289. // lets get the enumerator from the IDataObject, and see if the format we take is
  290. // available
  291. hr = pDataObj->lpVtbl->EnumFormatEtc(pDataObj, DATADIR_GET, &penum);
  292. if(SUCCEEDED(hr) && penum)
  293. {
  294. hr = penum->lpVtbl->Reset(penum);
  295. while(SUCCEEDED(hr=penum->lpVtbl->Next(penum, 1, &fmt, &ulCount)) && ulCount)
  296. {
  297. if( fmt.cfFormat==CF_HDROP || fmt.cfFormat==g_cfWABFlatBuffer)
  298. {
  299. lpIWABDropTarget->lpIWDD->m_cfAccept=fmt.cfFormat;
  300. break;
  301. }
  302. }
  303. }
  304. if(penum)
  305. penum->lpVtbl->Release(penum);
  306. if( (lpIWABDropTarget->lpIWDD->m_cfAccept == CF_HDROP &&
  307. bCheckFileType(lpIWABDropTarget, pDataObj, pdwEffect))
  308. || lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABFlatBuffer)
  309. {
  310. //if(grfKeyState & MK_CONTROL)
  311. //{
  312. *pdwEffect = DROPEFFECT_COPY;
  313. // lpIWABDropTarget->lpIWDD->m_bIsCopyOperation = TRUE;
  314. //}
  315. //else
  316. // *pdwEffect = DROPEFFECT_MOVE;
  317. }
  318. }
  319. if(*pdwEffect != DROPEFFECT_NONE)
  320. {
  321. lpIWABDropTarget->lpIWDD->m_pIDataObject = pDataObj;
  322. pDataObj->lpVtbl->AddRef(pDataObj);
  323. }
  324. return NOERROR;
  325. }
  326. //
  327. // FUNCTION: ::UpdateDragDropHilite()
  328. //
  329. // PURPOSE: Called by the various IDropTarget interfaces to move the drop
  330. // selection to the correct place in our listview.
  331. //
  332. // PARAMETERS:
  333. // <in> *ppt - Contains the point that the mouse is currently at. If this
  334. // is NULL, then the function removes any previous UI.
  335. //
  336. HTREEITEM UpdateDragDropHilite(LPBWI lpbwi, POINTL *ppt, ULONG * lpulObjType)
  337. {
  338. TV_HITTESTINFO tvhti;
  339. HTREEITEM htiTarget = NULL;
  340. // If a position was provided
  341. if (ppt)
  342. {
  343. // Figure out which item is selected
  344. tvhti.pt.x = ppt->x;
  345. tvhti.pt.y = ppt->y;
  346. ScreenToClient(bwi_hWndTV, &tvhti.pt);
  347. htiTarget = TreeView_HitTest(bwi_hWndTV, &tvhti);
  348. // Only if the cursor is over something do we relock the window.
  349. if (htiTarget)
  350. TreeView_SelectDropTarget(bwi_hWndTV, htiTarget);
  351. if(lpulObjType)
  352. {
  353. // Determine the object type if requested
  354. TV_ITEM tvI = {0};
  355. tvI.mask = TVIF_PARAM;
  356. tvI.hItem = htiTarget;
  357. if(TreeView_GetItem(bwi_hWndTV, &tvI) && tvI.lParam)
  358. *lpulObjType = ((LPTVITEM_STUFF)tvI.lParam)->ulObjectType;
  359. }
  360. }
  361. else
  362. TreeView_SelectDropTarget(bwi_hWndTV, NULL);
  363. return htiTarget;
  364. }
  365. STDMETHODIMP
  366. IWAB_DROPTARGET_DragOver( LPIWABDROPTARGET lpIWABDropTarget,
  367. DWORD grfKeyState,
  368. POINTL pt,
  369. DWORD * pdwEffect)
  370. {
  371. if(lpIWABDropTarget->lpIWDD->m_bSource)
  372. {
  373. if(lpIWABDropTarget->lpIWDD->m_bOverTV)
  374. {
  375. ULONG ulObjType = 0;
  376. if(UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, &pt, &ulObjType))
  377. {
  378. if(ulObjType == MAPI_ABCONT)
  379. *pdwEffect = DROPEFFECT_MOVE;
  380. else
  381. *pdwEffect = DROPEFFECT_COPY;
  382. }
  383. else
  384. *pdwEffect = DROPEFFECT_NONE;
  385. }
  386. else
  387. *pdwEffect = DROPEFFECT_NONE;
  388. }
  389. else
  390. if(lpIWABDropTarget->lpIWDD->m_pIDataObject)
  391. {
  392. // Anything going from the WAB to anywhere else is a COPY operation .. hence
  393. // always override to mark it as a copy operation so that the appropriate cursor is shown
  394. //
  395. DWORD m_dwEffect = lpIWABDropTarget->lpIWDD->m_dwEffect;
  396. if((*pdwEffect&DROPEFFECT_COPY)==DROPEFFECT_COPY)
  397. m_dwEffect=DROPEFFECT_COPY;
  398. if((*pdwEffect&DROPEFFECT_MOVE)==DROPEFFECT_MOVE)
  399. m_dwEffect=DROPEFFECT_COPY;//DROPEFFECT_MOVE;
  400. *pdwEffect &= ~(DROPEFFECT_MOVE|DROPEFFECT_COPY);
  401. *pdwEffect |= m_dwEffect;
  402. lpIWABDropTarget->lpIWDD->m_dwEffect = m_dwEffect;
  403. }
  404. else
  405. {
  406. *pdwEffect = DROPEFFECT_NONE;
  407. }
  408. return NOERROR;
  409. }
  410. STDMETHODIMP
  411. IWAB_DROPTARGET_DragLeave( LPIWABDROPTARGET lpIWABDropTarget)
  412. {
  413. if(lpIWABDropTarget->lpIWDD->m_bSource)
  414. {
  415. if(lpIWABDropTarget->lpIWDD->m_bOverTV)
  416. {
  417. UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, NULL, NULL);
  418. lpIWABDropTarget->lpIWDD->m_bOverTV = FALSE;
  419. }
  420. }
  421. if(lpIWABDropTarget->lpIWDD->m_pIDataObject)
  422. {
  423. lpIWABDropTarget->lpIWDD->m_pIDataObject->lpVtbl->Release(lpIWABDropTarget->lpIWDD->m_pIDataObject);
  424. lpIWABDropTarget->lpIWDD->m_pIDataObject = NULL;
  425. }
  426. lpIWABDropTarget->lpIWDD->m_bIsCopyOperation = FALSE;
  427. lpIWABDropTarget->lpIWDD->m_dwEffect = 0;
  428. lpIWABDropTarget->lpIWDD->m_cfAccept = 0;
  429. return NOERROR;
  430. }
  431. /*
  432. - DropVCardFiles
  433. -
  434. * Gets the files based on the file names dropped in ..
  435. *
  436. */
  437. void DropVCardFiles(LPBWI lpbwi, STGMEDIUM medium)
  438. {
  439. HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
  440. TCHAR szFile[MAX_PATH];
  441. UINT cFiles=0, iFile=0;
  442. // Let's work through the files given to us
  443. cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
  444. for (iFile = 0; iFile < cFiles; ++iFile)
  445. {
  446. DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
  447. // As long as any file is a vCard we can use it
  448. if(SubstringSearch(szFile, (LPTSTR) szVCardExt))
  449. {
  450. if(!(HR_FAILED(OpenAndAddVCard(lpbwi, szFile))))
  451. {
  452. // if this is not a copy operation - remove original
  453. //if(!lpIWABDropTarget->lpIWDD->m_bIsCopyOperation)
  454. //*pdwEffect = DROPEFFECT_MOVE; //we want to remove the temp file from the system
  455. //else
  456. // *pdwEffect = DROPEFFECT_COPY;
  457. }
  458. }
  459. }
  460. GlobalUnlock(medium.hGlobal);
  461. }
  462. /*
  463. - DropFlatBuffer
  464. -
  465. * Gets the files based on the file names dropped in ..
  466. *
  467. */
  468. void DropFlatBuffer(LPBWI lpbwi, STGMEDIUM medium)
  469. {
  470. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  471. LPBYTE lpBuf = (LPBYTE)GlobalLock(medium.hGlobal);
  472. if(lpBuf)
  473. {
  474. LPBYTE lp = lpBuf;
  475. ULONG cItems = 0, i=0;
  476. CopyMemory(&cItems, lp, sizeof(ULONG));
  477. lp+=sizeof(ULONG);
  478. for(i=0;i<cItems;i++)
  479. {
  480. LPBYTE lpsz = NULL;
  481. ULONG cbsz = 0, ulcProps = 0;
  482. CopyMemory(&ulcProps, lp, sizeof(ULONG));
  483. lp+=sizeof(ULONG);
  484. CopyMemory(&cbsz, lp, sizeof(ULONG));
  485. lp+=sizeof(ULONG);
  486. lpsz = LocalAlloc(LMEM_ZEROINIT, cbsz);
  487. if(lpsz)
  488. {
  489. LPSPropValue lpProps = NULL;
  490. CopyMemory(lpsz, lp, cbsz);
  491. lp+=cbsz;
  492. if(!HR_FAILED(HrGetPropArrayFromBuffer(lpsz, cbsz, ulcProps, 0, &lpProps)))
  493. {
  494. ULONG cbEID = 0;
  495. LPENTRYID lpEID = NULL;
  496. ULONG ulObjType = MAPI_MAILUSER, j =0;
  497. for(j=0;j<ulcProps;j++)
  498. {
  499. if(lpProps[j].ulPropTag == PR_OBJECT_TYPE)
  500. ulObjType = lpProps[j].Value.l;
  501. else
  502. if(lpProps[j].ulPropTag == PR_ENTRYID) // if dropped from another wab entryid is irrelevant
  503. {
  504. if(lpProps[j].Value.bin.lpb)
  505. LocalFree(lpProps[j].Value.bin.lpb);
  506. lpProps[j].Value.bin.lpb = NULL;
  507. lpProps[j].ulPropTag = PR_NULL;
  508. }
  509. else// if dropped from another wab remove the folder parent property
  510. if(lpProps[j].ulPropTag == PR_WAB_FOLDER_PARENT || lpProps[j].ulPropTag == PR_WAB_FOLDER_PARENT_OLDPROP)
  511. {
  512. ULONG k = 0;
  513. for(k=0;k<lpProps[j].Value.MVbin.cValues;k++)
  514. {
  515. if(lpProps[j].Value.MVbin.lpbin[k].lpb)
  516. LocalFree(lpProps[j].Value.MVbin.lpbin[k].lpb);
  517. }
  518. LocalFreeAndNull((LPVOID *) (&(lpProps[j].Value.MVbin.lpbin)));
  519. lpProps[j].ulPropTag = PR_NULL;
  520. }
  521. else // if this contact was synced with Hotmail, remove the server, mod, and contact IDs
  522. // [PaulHi] 12/2/98 Raid #58486
  523. if ( (lpProps[j].ulPropTag == PR_WAB_HOTMAIL_SERVERIDS) ||
  524. (lpProps[j].ulPropTag == PR_WAB_HOTMAIL_MODTIMES) ||
  525. (lpProps[j].ulPropTag == PR_WAB_HOTMAIL_CONTACTIDS) )
  526. {
  527. ULONG k=0;
  528. Assert(PROP_TYPE(lpProps[j].ulPropTag) == PT_MV_TSTRING);
  529. for(k=0;k<lpProps[j].Value.MVSZ.cValues;k++)
  530. {
  531. if (lpProps[j].Value.MVSZ.LPPSZ[k])
  532. LocalFree(lpProps[j].Value.MVSZ.LPPSZ[k]);
  533. }
  534. LocalFreeAndNull((LPVOID *) (lpProps[j].Value.MVSZ.LPPSZ));
  535. lpProps[j].Value.MVSZ.cValues = 0;
  536. lpProps[j].ulPropTag = PR_NULL;
  537. }
  538. }
  539. {
  540. LPSBinary lpsbEID = NULL;
  541. ULONG ulContObjType = 0;
  542. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulContObjType, FALSE);
  543. // [PaulHi] 12/1/98 Raid #58486. Changed CREATE_CHECK_DUP_STRICT flag
  544. // to zero (0) so user can copy/paste without restriction.
  545. if(!HR_FAILED(HrCreateNewEntry(bwi_lpAdrBook,
  546. bwi_hWndAB, ulObjType,
  547. (lpsbEID) ? lpsbEID->cb : 0,
  548. (LPENTRYID) ((lpsbEID) ? lpsbEID->lpb : NULL),
  549. ulContObjType,
  550. 0, TRUE,
  551. ulcProps, lpProps,
  552. &cbEID, &lpEID)))
  553. {
  554. UpdateLV(lpbwi);
  555. if(lpEID)
  556. MAPIFreeBuffer(lpEID);
  557. }
  558. if(lpsbEID)
  559. LocalFreeSBinary(lpsbEID);
  560. }
  561. LocalFreePropArray(NULL, ulcProps, &lpProps);
  562. }
  563. LocalFree(lpsz);
  564. }
  565. }
  566. }
  567. GlobalUnlock(medium.hGlobal);
  568. }
  569. /*
  570. - DropEntryIDs
  571. -
  572. * Gets the files based on the entryids
  573. * EntryIDs only get used when it is an internal only drop
  574. * on a treeview item - so we check if this is dropped on
  575. * a folder or if it is dropped on a group
  576. *
  577. * If on a group, we add the item to the group
  578. * If on a folder, we add the item to the folder
  579. *
  580. *
  581. * If the src was a group and the destination a folder, we dont do anything to the
  582. * group but we update the items parent folder to not contain the old parent and we
  583. * update the item to point to the new folder as a parent
  584. *
  585. * If the src was a folder and the destination a folder, we update the parent folder for the
  586. * item and we add the item to the dest folders list ..
  587. *
  588. * If the src was a group and the destination a group, we dont do anything to anyone - just add
  589. * the item as a group
  590. * If the src was a folder and the destination a group, then we dont to anything to anyone
  591. *
  592. * Within the WABs, all drops on folders are moves.
  593. */
  594. BOOL DropEntryIDs(LPBWI lpbwi, STGMEDIUM medium, POINTL pt, LPSBinary lpsbEID, ULONG ulObjType)
  595. {
  596. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  597. LPBYTE lpBuf = (LPBYTE)GlobalLock(medium.hGlobal);
  598. SBinary sb = {0};
  599. ULONG ulObjectType = 0;
  600. BOOL bRet = FALSE;
  601. LPTSTR lpWABFile = NULL;
  602. ULONG cProps = 0;
  603. LPSPropValue lpProps = NULL;
  604. if(!lpBuf)
  605. goto out;
  606. if(!lpsbEID && !ulObjType)
  607. {
  608. TV_ITEM tvI = {0};
  609. // Find out what exactly is the item we dropped stuff on
  610. tvI.hItem = UpdateDragDropHilite(lpbwi, &pt, NULL);
  611. if(!tvI.hItem)
  612. goto out;
  613. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  614. if(TreeView_GetItem(bwi_hWndTV, &tvI) && tvI.lParam)
  615. {
  616. LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
  617. if(lptvStuff)
  618. {
  619. ulObjectType = lptvStuff->ulObjectType;
  620. if(lptvStuff->lpsbEID)
  621. {
  622. sb.cb = lptvStuff->lpsbEID->cb;
  623. sb.lpb = lptvStuff->lpsbEID->lpb;
  624. }
  625. }
  626. }
  627. }
  628. else
  629. {
  630. sb.cb = lpsbEID->cb;
  631. sb.lpb = lpsbEID->lpb;
  632. ulObjectType = ulObjType;
  633. }
  634. // Get our data from the drop and convert into an array of entryids
  635. {
  636. LPBYTE lp = lpBuf;
  637. ULONG i=0, cb = 0;
  638. ULONG_PTR ulIAB = 0;
  639. ULONG ulWABFile = 0;
  640. // Verify that this is the same lpIAB thats involved
  641. CopyMemory(&ulIAB, lp, sizeof(ULONG_PTR));
  642. lp+=sizeof(ULONG_PTR);
  643. CopyMemory(&ulWABFile, lp, sizeof(ULONG));
  644. lp+=sizeof(ULONG);
  645. lpWABFile = LocalAlloc(LMEM_ZEROINIT, ulWABFile);
  646. if(!lpWABFile)
  647. goto out;
  648. CopyMemory(lpWABFile, lp, ulWABFile);
  649. lp+=ulWABFile;
  650. if(ulIAB != (ULONG_PTR) bwi_lpIAB)
  651. {
  652. // this came from a different IAdrBook object - double check that its
  653. // not the same file in a different process
  654. LPTSTR lpWAB = GetWABFileName(((LPIAB)bwi_lpIAB)->lpPropertyStore->hPropertyStore, TRUE);
  655. if(lstrcmp(lpWAB, lpWABFile))
  656. goto out; //different
  657. }
  658. CopyMemory(&cProps, lp, sizeof(ULONG));
  659. lp+=sizeof(ULONG);
  660. CopyMemory(&cb, lp, sizeof(ULONG));
  661. lp+=sizeof(ULONG);
  662. if(!HR_FAILED(HrGetPropArrayFromBuffer(lp , cb, cProps, 0, &lpProps)))
  663. {
  664. for(i=0;i<cProps;i++)
  665. {
  666. if(lpProps[i].ulPropTag == PR_ENTRYID)
  667. {
  668. if(HR_FAILED(AddEntryToContainer(bwi_lpAdrBook,
  669. ulObjectType,
  670. sb.cb, (LPENTRYID) sb.lpb,
  671. lpProps[i].Value.bin.cb,
  672. (LPENTRYID) lpProps[i].Value.bin.lpb)))
  673. {
  674. goto out;
  675. }
  676. //break;
  677. }
  678. }
  679. }
  680. else goto out;
  681. }
  682. bRet = TRUE;
  683. out:
  684. LocalFreePropArray(NULL, cProps, &lpProps);
  685. GlobalUnlock(medium.hGlobal);
  686. if(lpWABFile)
  687. LocalFree(lpWABFile);
  688. return bRet;
  689. }
  690. /*
  691. -
  692. -
  693. *
  694. *
  695. */
  696. STDMETHODIMP
  697. IWAB_DROPTARGET_Drop( LPIWABDROPTARGET lpIWABDropTarget,
  698. IDataObject * pDataObj,
  699. DWORD grfKeyState,
  700. POINTL pt,
  701. DWORD * pdwEffect)
  702. {
  703. #ifndef WIN16
  704. FORMATETC fmte = {lpIWABDropTarget->lpIWDD->m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  705. #else
  706. FORMATETC fmte;
  707. #endif
  708. STGMEDIUM medium = {0};
  709. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  710. #ifdef WIN16
  711. fmte.cfFormat = lpIWABDropTarget->lpIWDD->m_cfAccept;
  712. fmte.ptd = NULL;
  713. fmte.dwAspect = DVASPECT_CONTENT;
  714. fmte.lindex = -1;
  715. fmte.tymed = TYMED_HGLOBAL;
  716. #endif
  717. if (pDataObj &&
  718. SUCCEEDED(pDataObj->lpVtbl->GetData(pDataObj, &fmte, &medium)))
  719. {
  720. if(lpIWABDropTarget->lpIWDD->m_cfAccept == CF_HDROP)
  721. {
  722. DropVCardFiles((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium);
  723. }
  724. else
  725. if(lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABFlatBuffer)
  726. {
  727. DropFlatBuffer((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium);
  728. }
  729. else
  730. if(lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABEntryIDList)
  731. {
  732. DropEntryIDs((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium, pt, NULL, 0);
  733. if(lpIWABDropTarget->lpIWDD->m_bOverTV)
  734. {
  735. UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, NULL, NULL);
  736. lpIWABDropTarget->lpIWDD->m_bOverTV = FALSE;
  737. }
  738. }
  739. }
  740. if (medium.pUnkForRelease)
  741. medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
  742. else
  743. GlobalFree(medium.hGlobal);
  744. if(pDataObj)
  745. {
  746. pDataObj->lpVtbl->Release(pDataObj);
  747. if(pDataObj == lpIWABDropTarget->lpIWDD->m_pIDataObject)
  748. lpIWABDropTarget->lpIWDD->m_pIDataObject = NULL;
  749. }
  750. return NOERROR;
  751. }
  752. /***** DropSource Interfaces *****/
  753. STDMETHODIMP
  754. IWAB_DROPSOURCE_QueryContinueDrag(LPIWABDROPSOURCE lpIWABDropSource,
  755. BOOL fEscapePressed,
  756. DWORD grfKeyState)
  757. {
  758. if (fEscapePressed)
  759. return DRAGDROP_S_CANCEL;
  760. // initialize ourself with the drag begin button
  761. if (lpIWABDropSource->lpIWDD->m_grfInitialKeyState == 0)
  762. lpIWABDropSource->lpIWDD->m_grfInitialKeyState = (grfKeyState & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON));
  763. if (!(grfKeyState & lpIWABDropSource->lpIWDD->m_grfInitialKeyState))
  764. {
  765. lpIWABDropSource->lpIWDD->m_grfInitialKeyState = 0;
  766. return DRAGDROP_S_DROP;
  767. }
  768. else
  769. return S_OK;
  770. return NOERROR;
  771. }
  772. STDMETHODIMP
  773. IWAB_DROPSOURCE_GiveFeedback(LPIWABDROPSOURCE lpIWABDropSource,
  774. DWORD dwEffect)
  775. {
  776. return DRAGDROP_S_USEDEFAULTCURSORS;
  777. }
  778. /****************************************************************************
  779. *
  780. * DataObject Methods
  781. *
  782. ****************************************************************************/
  783. /*
  784. - HrGetTempFile
  785. -
  786. * szTempFile - will contain full file name on returning
  787. * szDisplayName - name for this contact - therefore name of file to create
  788. * cbEntryID, lpEntryID - entryids
  789. *
  790. */
  791. HRESULT HrGetTempFile(LPADRBOOK lpAdrBook,
  792. LPTSTR szTempFile,
  793. DWORD cchSizeTempFile,
  794. LPTSTR szDisplayName,
  795. ULONG cbEntryID,
  796. LPENTRYID lpEntryID)
  797. {
  798. TCHAR szTemp[MAX_PATH];
  799. TCHAR szName[MAX_PATH];
  800. ULONG ulObjType = 0;
  801. DWORD dwPath = 0;
  802. HRESULT hr = E_FAIL;
  803. LPMAILUSER lpMailUser = NULL;
  804. if(!cbEntryID || !lpEntryID || !szTempFile)
  805. goto out;
  806. //Get the Temporary File Name
  807. dwPath = GetTempPath(CharSizeOf(szTemp), szTemp);
  808. if(!dwPath)
  809. goto out;
  810. StrCpyN(szName, szDisplayName, ARRAYSIZE(szName));
  811. // Truncated display names have ellipses in them - get rid of these ellipses
  812. if(lstrlen(szName) > 30)
  813. {
  814. LPTSTR lp = szName;
  815. while(*lp)
  816. {
  817. if(*lp == '.' && *(lp+1) == '.' && *(lp+2) == '.')
  818. {
  819. *lp = '\0';
  820. break;
  821. }
  822. lp = CharNext(lp);
  823. }
  824. }
  825. // There is always the possibility that the display name + the temp path will exceed
  826. // Max Path .. in which case reduce the display name to say 8.3 characters ..
  827. if(dwPath + lstrlen(szName) + CharSizeOf(szVCardExt) + 2 > CharSizeOf(szTemp))
  828. {
  829. szName[8] = '\0'; // This is totally arbitrary
  830. }
  831. TrimIllegalFileChars(szName);
  832. StrCatBuff(szTemp, szName, ARRAYSIZE(szTemp));
  833. StrCatBuff(szTemp, szVCardExt, ARRAYSIZE(szTemp));
  834. DebugTrace(TEXT("Creating vCard file: %s\n"), szTemp);
  835. StrCpyN(szTempFile, szTemp, cchSizeTempFile);
  836. // Get a MailUser corresponding to the given entryids
  837. if (hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  838. cbEntryID,
  839. lpEntryID,
  840. NULL, // interface
  841. 0, // flags
  842. &ulObjType,
  843. (LPUNKNOWN *)&lpMailUser))
  844. {
  845. DebugTraceResult( TEXT("OpenEntry failed:"), hr);
  846. goto out;
  847. }
  848. hr = VCardCreate(lpAdrBook,
  849. 0, 0,
  850. szTemp,
  851. lpMailUser);
  852. out:
  853. if(lpMailUser)
  854. lpMailUser->lpVtbl->Release(lpMailUser);
  855. return hr;
  856. }
  857. ///////////////////////////////////////////////////////////////////////////////
  858. // Helper functions to manage VCard temp file list and clean up
  859. //
  860. BOOL bAddToNameList(LPTSTR lptszFilename)
  861. {
  862. VFILENAMELIST * pFileItem = NULL;
  863. VFILENAMELIST * pList = NULL;
  864. if (!lptszFilename || *lptszFilename == '\0')
  865. {
  866. // Invalid arguments
  867. return FALSE;
  868. }
  869. pFileItem = LocalAlloc(LMEM_ZEROINIT, sizeof(VFILENAMELIST));
  870. if (!pFileItem)
  871. return FALSE;
  872. {
  873. DWORD cchSize = (lstrlen(lptszFilename)+1);
  874. pFileItem->lptszFilename = LocalAlloc(LMEM_ZEROINIT, (sizeof(TCHAR) * cchSize));
  875. if (!pFileItem->lptszFilename)
  876. {
  877. LocalFree(pFileItem);
  878. return FALSE;
  879. }
  880. StrCpyN(pFileItem->lptszFilename, lptszFilename, cchSize);
  881. }
  882. pList = s_pFileNameList;
  883. if (pList == NULL)
  884. {
  885. s_pFileNameList = pFileItem;
  886. }
  887. else
  888. {
  889. while (pList->pNext)
  890. pList = pList->pNext;
  891. pList->pNext = pFileItem;
  892. }
  893. return TRUE;
  894. }
  895. void DeleteFilesInList()
  896. {
  897. // Delete files and clean up list
  898. VFILENAMELIST * pList = s_pFileNameList;
  899. VFILENAMELIST * pNext = NULL;
  900. while (pList)
  901. {
  902. if (pList->lptszFilename)
  903. {
  904. DeleteFile(pList->lptszFilename);
  905. LocalFree(pList->lptszFilename);
  906. }
  907. pNext = pList->pNext;
  908. LocalFree(pList);
  909. pList = pNext;
  910. }
  911. s_pFileNameList = NULL;
  912. }
  913. //$$///////////////////////////////////////////////////////////////////////
  914. //
  915. // HrBuildHDrop - builds the HDrop structure for dropping files to the
  916. // drop target
  917. //
  918. ///////////////////////////////////////////////////////////////////////////
  919. HRESULT HrBuildHDrop(LPIWABDATAOBJECT lpIWABDataObject)
  920. {
  921. HWND m_hwndList = lpIWABDataObject->m_hWndLV;
  922. LPDROPFILES lpDrop=0;
  923. LPVOID *rglpvTemp=NULL;
  924. ULONG *rglpcch=NULL;
  925. int cFiles, i, iItem= -1;
  926. ULONG cch;
  927. ULONG cb;
  928. HRESULT hr = E_FAIL;
  929. TCHAR szTempFile[MAX_PATH];
  930. cFiles=ListView_GetSelectedCount(m_hwndList);
  931. if(!cFiles)
  932. return E_FAIL; // nothing to build
  933. // Walk the list and find out how much space we need.
  934. rglpvTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPVOID)*cFiles);
  935. rglpcch = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cFiles);
  936. if(!rglpvTemp || !rglpcch)
  937. goto errorMemory;
  938. cFiles=0;
  939. cch = 0;
  940. cb = 0;
  941. while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
  942. LVNI_SELECTED|LVNI_ALL))!=-1))
  943. {
  944. LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
  945. LPSTR lpszA = NULL;
  946. if (!lpItem)
  947. {
  948. hr=E_FAIL;
  949. goto error;
  950. }
  951. if(lpItem->ulObjectType == MAPI_DISTLIST)
  952. continue;
  953. // Take this object and turn it into a temporary vCard
  954. // We will delete this temporary vCard file when this DataObject is released
  955. hr=HrGetTempFile( lpIWABDataObject->m_lpAdrBook,
  956. szTempFile,
  957. ARRAYSIZE(szTempFile),
  958. lpItem->szDisplayName,
  959. lpItem->cbEntryID, lpItem->lpEntryID);
  960. if (FAILED(hr))
  961. goto error;
  962. // Add temporary VCard files to list for later clean up
  963. if ( !bAddToNameList(szTempFile) )
  964. {
  965. Assert(0);
  966. }
  967. // [PaulHi] 4/6/99 Raid 75071 Convert to ANSI depending on whether
  968. // the OS is Win9X or WinNT
  969. if (g_bRunningOnNT)
  970. {
  971. rglpcch[cFiles] = lstrlen(szTempFile) + 1;
  972. rglpvTemp[cFiles] = LocalAlloc(LMEM_FIXED, (rglpcch[cFiles]*sizeof(WCHAR)));
  973. if (!rglpvTemp[cFiles])
  974. goto errorMemory;
  975. StrCpyN((LPWSTR)rglpvTemp[cFiles], szTempFile, rglpcch[cFiles]);
  976. }
  977. else
  978. {
  979. rglpvTemp[cFiles] = ConvertWtoA(szTempFile);
  980. if (!rglpvTemp[cFiles])
  981. goto errorMemory;
  982. rglpcch[cFiles] = lstrlenA(rglpvTemp[cFiles]) + 1;
  983. }
  984. cch += rglpcch[cFiles];
  985. cFiles++;
  986. }
  987. if(cFiles == 0) //e.g. only groups were selected
  988. {
  989. hr=S_OK;
  990. goto error;
  991. }
  992. cch += 1; //double-null term at end.
  993. // Fill in the path names.
  994. // [PaulHi] 4/6/99 Raid 75071 Use Unicode names for WinNT and ANSI
  995. // names for Win9X.
  996. if (g_bRunningOnNT)
  997. {
  998. LPWSTR lpwszPath = NULL;
  999. // Allocate the buffer and fill it in.
  1000. cb = (cch * sizeof(WCHAR)) + sizeof(DROPFILES);
  1001. if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpDrop))
  1002. goto errorMemory;
  1003. ZeroMemory(lpDrop, cb);
  1004. lpDrop->pFiles = sizeof(DROPFILES);
  1005. lpDrop->fWide = TRUE;
  1006. lpwszPath = (LPWSTR)((BYTE *)lpDrop + sizeof(DROPFILES));
  1007. for (i=0; i<cFiles; i++)
  1008. {
  1009. StrCpyN(lpwszPath, (LPWSTR)rglpvTemp[i], cch);
  1010. lpwszPath += rglpcch[i];
  1011. }
  1012. }
  1013. else
  1014. {
  1015. LPSTR lpszPath = NULL;
  1016. // Allocate the buffer and fill it in.
  1017. cb = cch + sizeof(DROPFILES);
  1018. if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpDrop))
  1019. goto errorMemory;
  1020. ZeroMemory(lpDrop, cb);
  1021. lpDrop->pFiles = sizeof(DROPFILES);
  1022. lpszPath = (LPSTR)((BYTE *)lpDrop + sizeof(DROPFILES));
  1023. for(i=0; i<cFiles; i++)
  1024. {
  1025. StrCpyNA(lpszPath, (LPSTR)rglpvTemp[i], cch);
  1026. lpszPath += rglpcch[i];
  1027. }
  1028. }
  1029. lpIWABDataObject->pDatahDrop = (LPVOID)lpDrop;
  1030. lpIWABDataObject->cbDatahDrop = cb;
  1031. // Don't free the dropfiles struct
  1032. lpDrop = NULL;
  1033. hr = NOERROR;
  1034. error:
  1035. if (rglpvTemp)
  1036. {
  1037. for(i=0; i<cFiles; i++)
  1038. LocalFree(rglpvTemp[i]);
  1039. LocalFree(rglpvTemp);
  1040. }
  1041. LocalFreeAndNull(&rglpcch);
  1042. return hr;
  1043. errorMemory:
  1044. hr=E_OUTOFMEMORY;
  1045. goto error;
  1046. }
  1047. /*
  1048. - HrBuildcfText - builds the CF_TEXT data for dropping info
  1049. -
  1050. *
  1051. *
  1052. */
  1053. HRESULT HrBuildcfText(LPIWABDATAOBJECT lpIWABDataObject)
  1054. {
  1055. HWND m_hwndList = lpIWABDataObject->m_hWndLV;
  1056. LPTSTR lpszText = NULL;
  1057. int i, cSel;
  1058. LV_ITEM lvi;
  1059. ULONG cb = 0;
  1060. HRESULT hr = E_FAIL;
  1061. LPTSTR * rglpszTemp = NULL;
  1062. LPSTR lpA = NULL;
  1063. LPWSTR lpW = NULL;
  1064. cSel=ListView_GetSelectedCount(m_hwndList);
  1065. if(!cSel)
  1066. return E_FAIL; // nothing to build
  1067. lvi.mask = LVIF_PARAM;
  1068. lvi.iSubItem = 0;
  1069. lvi.iItem=-1;
  1070. // Collate how much space we need
  1071. rglpszTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPTSTR)*cSel);
  1072. if(!rglpszTemp)
  1073. goto errorMemory;
  1074. cSel = 0;
  1075. while(((lvi.iItem=ListView_GetNextItem(m_hwndList, lvi.iItem,
  1076. LVNI_SELECTED|LVNI_ALL))!=-1))
  1077. {
  1078. LPTSTR lp = NULL;
  1079. if(!HR_FAILED(HrGetLVItemDataString(lpIWABDataObject->m_lpAdrBook,
  1080. m_hwndList, lvi.iItem, &lp)))
  1081. {
  1082. rglpszTemp[cSel] = lp;
  1083. cb += sizeof(TCHAR)*(lstrlen(lp) + lstrlen(szCRLF) + lstrlen(szCRLF) + 1);
  1084. }
  1085. cSel++;
  1086. }
  1087. // Allocate the buffer and fill it in.
  1088. if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpszText))
  1089. goto errorMemory;
  1090. ZeroMemory(lpszText, cb);
  1091. for(i=0; i<cSel; i++)
  1092. {
  1093. StrCatBuff(lpszText, rglpszTemp[i], cb / sizeof(lpszText[0]));
  1094. StrCatBuff(lpszText, szCRLF, cb / sizeof(lpszText[0]));
  1095. StrCatBuff(lpszText, szCRLF, cb / sizeof(lpszText[0]));
  1096. }
  1097. lpIWABDataObject->pDataTextW = (LPVOID) lpszText;
  1098. lpIWABDataObject->cbDataTextW = cb;
  1099. if(ScWCToAnsiMore((LPALLOCATEMORE) (&MAPIAllocateMore), lpIWABDataObject, lpszText, &lpA))
  1100. goto error;
  1101. lpIWABDataObject->pDataTextA = lpA;
  1102. lpIWABDataObject->cbDataTextA = lstrlenA(lpA)+1;
  1103. hr = NOERROR;
  1104. error:
  1105. if (rglpszTemp)
  1106. {
  1107. for(i=0; i<cSel; i++)
  1108. if(rglpszTemp[i])
  1109. LocalFree(rglpszTemp[i]);
  1110. LocalFree(rglpszTemp);
  1111. }
  1112. return hr;
  1113. errorMemory:
  1114. hr=E_OUTOFMEMORY;
  1115. goto error;
  1116. }
  1117. /*
  1118. - HrBuildcfFlatBuffer - builds the CF_TEXT data for dropping info
  1119. -
  1120. *
  1121. *
  1122. */
  1123. HRESULT HrBuildcfFlatBuffer(LPIWABDATAOBJECT lpIWABDataObject)
  1124. {
  1125. HWND m_hwndList = lpIWABDataObject->m_hWndLV;
  1126. LPSTR lpszText = NULL, lpBuf = NULL;
  1127. int i, cSel, iItem= -1;
  1128. ULONG cb = 0, cbBuf = 0;
  1129. HRESULT hr = E_FAIL;
  1130. LPBYTE * rglpTemp = NULL;
  1131. ULONG * cbTemp = NULL;
  1132. ULONG * cbProps = NULL;
  1133. cSel=ListView_GetSelectedCount(m_hwndList);
  1134. if(!cSel)
  1135. return E_FAIL; // nothing to build
  1136. // Collate how much space we need
  1137. rglpTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPBYTE)*cSel);
  1138. if(!rglpTemp)
  1139. goto errorMemory;
  1140. // Collate how much space we need
  1141. cbTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cSel);
  1142. if(!cbTemp)
  1143. goto errorMemory;
  1144. // Collate how much space we need
  1145. cbProps = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cSel);
  1146. if(!cbProps)
  1147. goto errorMemory;
  1148. cSel = 0;
  1149. cb = sizeof(ULONG);
  1150. while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
  1151. LVNI_SELECTED|LVNI_ALL))!=-1))
  1152. {
  1153. LPMAILUSER lpMailUser = NULL;
  1154. LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
  1155. LPADRBOOK lpAdrBook = lpIWABDataObject->m_lpAdrBook;
  1156. LPSPropValue lpProps = NULL;
  1157. ULONG ulcProps = 0;
  1158. ULONG ulObjType = 0;
  1159. if (!lpItem)
  1160. {
  1161. hr=E_FAIL;
  1162. goto error;
  1163. }
  1164. if(lpItem->ulObjectType == MAPI_DISTLIST)
  1165. continue;
  1166. // Get a MailUser corresponding to the given entryids
  1167. if (!HR_FAILED(lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  1168. lpItem->cbEntryID,
  1169. lpItem->lpEntryID,
  1170. NULL, // interface
  1171. 0, // flags
  1172. &ulObjType,
  1173. (LPUNKNOWN *)&lpMailUser)))
  1174. {
  1175. if(!HR_FAILED(lpMailUser->lpVtbl->GetProps(lpMailUser, NULL, MAPI_UNICODE, &ulcProps, &lpProps)))
  1176. {
  1177. if(!HR_FAILED(HrGetBufferFromPropArray( ulcProps, lpProps,
  1178. &(cbTemp[cSel]),
  1179. &(rglpTemp[cSel]))))
  1180. {
  1181. cbProps[cSel] = ulcProps;
  1182. if(cbTemp[cSel] && rglpTemp[cSel])
  1183. cb += cbTemp[cSel] + sizeof(ULONG) + sizeof(ULONG) + 1;
  1184. cSel++;
  1185. }
  1186. if(lpProps)
  1187. MAPIFreeBuffer(lpProps);
  1188. }
  1189. if(lpMailUser)
  1190. lpMailUser->lpVtbl->Release(lpMailUser);
  1191. }
  1192. }
  1193. if(!cSel)
  1194. goto error; // nothing to build
  1195. // Allocate the buffer and fill it in.
  1196. if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpszText))
  1197. goto errorMemory;
  1198. ZeroMemory(lpszText, cb);
  1199. lpBuf = lpszText;
  1200. CopyMemory(lpBuf, &cSel, sizeof(ULONG));
  1201. lpBuf += sizeof(ULONG);
  1202. for(i=0; i<cSel; i++)
  1203. {
  1204. CopyMemory(lpBuf, &(cbProps[i]), sizeof(ULONG));
  1205. lpBuf+=sizeof(ULONG);
  1206. CopyMemory(lpBuf, &(cbTemp[i]), sizeof(ULONG));
  1207. lpBuf+=sizeof(ULONG);
  1208. CopyMemory(lpBuf, rglpTemp[i], cbTemp[i]);
  1209. lpBuf+=cbTemp[i];
  1210. }
  1211. lpIWABDataObject->pDataBuffer = (LPVOID) lpszText;
  1212. lpIWABDataObject->cbDataBuffer = cb;
  1213. hr = NOERROR;
  1214. error:
  1215. if (rglpTemp)
  1216. {
  1217. for(i=0; i<cSel; i++)
  1218. if(rglpTemp[i])
  1219. LocalFree(rglpTemp[i]);
  1220. LocalFree(rglpTemp);
  1221. }
  1222. if(cbProps)
  1223. LocalFree(cbProps);
  1224. if(cbTemp)
  1225. LocalFree(cbTemp);
  1226. return hr;
  1227. errorMemory:
  1228. hr=E_OUTOFMEMORY;
  1229. goto error;
  1230. }
  1231. /*
  1232. - HrBuildcfEIDList - Builds an SPropValue array that only has entryid's in it
  1233. - When doing internal-only drops, we scan this list of entryids and
  1234. - use the entryids for adding items to items instead of physically
  1235. - adding the contents of the item
  1236. *
  1237. */
  1238. HRESULT HrBuildcfEIDList(LPIWABDATAOBJECT lpIWABDataObject)
  1239. {
  1240. HWND m_hwndList = lpIWABDataObject->m_hWndLV;
  1241. ULONG cb = 0, cProps = 0, cbTotal=0;
  1242. HRESULT hr = E_FAIL;
  1243. LPSPropValue lpProps = 0;
  1244. LPBYTE lpBufEID = NULL, lp = NULL, lpTemp = NULL;
  1245. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1246. LPBWI lpbwi = (LPBWI) lpIWABDataObject->m_lpv;
  1247. LPTSTR lpWABFile = GetWABFileName( ((LPIAB)bwi_lpIAB)->lpPropertyStore->hPropertyStore, TRUE);
  1248. int iItem = -1;
  1249. cProps=ListView_GetSelectedCount(m_hwndList);
  1250. if(!cProps)
  1251. return E_FAIL; // nothing to build
  1252. lpProps = LocalAlloc(LMEM_ZEROINIT, sizeof(SPropValue)*cProps);
  1253. if(!lpProps)
  1254. goto errorMemory;
  1255. cProps = 0;
  1256. while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
  1257. LVNI_SELECTED|LVNI_ALL))!=-1))
  1258. {
  1259. LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
  1260. if (!lpItem)
  1261. goto error;
  1262. lpProps[cProps].ulPropTag = PR_ENTRYID;
  1263. lpProps[cProps].Value.bin.lpb = LocalAlloc(LMEM_ZEROINIT, lpItem->cbEntryID);
  1264. if(!lpProps[cProps].Value.bin.lpb)
  1265. goto errorMemory;
  1266. CopyMemory(lpProps[cProps].Value.bin.lpb, lpItem->lpEntryID, lpItem->cbEntryID);
  1267. lpProps[cProps].Value.bin.cb = lpItem->cbEntryID;
  1268. cProps++;
  1269. }
  1270. if(!cProps)
  1271. goto error; // nothing to build
  1272. // Convert this proparray to a buffer
  1273. if(HR_FAILED(hr = HrGetBufferFromPropArray( cProps, lpProps,
  1274. &cb, &lpBufEID)))
  1275. goto error;
  1276. cbTotal = cb+ sizeof(ULONG) //lpIAB
  1277. + sizeof(ULONG) + sizeof(TCHAR)*(lstrlen(lpWABFile) + 1) // WAB File Name
  1278. + sizeof(ULONG) //cProps
  1279. + sizeof(ULONG); //cb;
  1280. // Allocate the buffer and fill it in.
  1281. if(MAPIAllocateMore(cbTotal, lpIWABDataObject, (LPVOID*) &lp))
  1282. goto errorMemory;
  1283. ZeroMemory(lp, cbTotal);
  1284. lpTemp = lp;
  1285. {
  1286. // tag this data with the pointer address identifying the current
  1287. // iadrbook object
  1288. ULONG_PTR ulIAB = (ULONG_PTR) bwi_lpIAB;
  1289. ULONG ulWAB = lstrlen(lpWABFile)+1;
  1290. CopyMemory(lpTemp, &ulIAB, sizeof(ULONG_PTR));
  1291. lpTemp += sizeof(ULONG_PTR);
  1292. CopyMemory(lpTemp, &ulWAB, sizeof(ULONG));
  1293. lpTemp += sizeof(ULONG);
  1294. CopyMemory(lpTemp, lpWABFile, ulWAB);
  1295. lpTemp += ulWAB;
  1296. }
  1297. CopyMemory(lpTemp, &cProps, sizeof(ULONG));
  1298. lpTemp += sizeof(ULONG);
  1299. CopyMemory(lpTemp, &cb, sizeof(ULONG));
  1300. lpTemp += sizeof(ULONG);
  1301. CopyMemory(lpTemp, lpBufEID, cb);
  1302. lpIWABDataObject->pDataEID = lp;
  1303. lpIWABDataObject->cbDataEID = cbTotal;
  1304. hr = NOERROR;
  1305. error:
  1306. LocalFreePropArray(NULL, cProps, &lpProps);
  1307. if(lpBufEID)
  1308. LocalFree(lpBufEID);
  1309. return hr;
  1310. errorMemory:
  1311. hr=E_OUTOFMEMORY;
  1312. goto error;
  1313. }
  1314. /*
  1315. - HrCreateIWABDataObject
  1316. -
  1317. * Creates a WAB Data Object
  1318. * Data is created from current selection in the hWndLV list view
  1319. * bDataNow - means collect the raw data now or do it later
  1320. * For Drag-Drops we do it later since the drag-drop operation is synchronous and
  1321. * the ListView wont lose its selection
  1322. * For Copy/Paste we get the data now at creation time since user may choose to paste
  1323. * at some later time at which point we may have completely lost the data
  1324. */
  1325. HRESULT HrCreateIWABDataObject(LPVOID lpv, LPADRBOOK lpAdrBook, HWND hWndLV,
  1326. LPIWABDATAOBJECT * lppIWABDataObject, BOOL bGetDataNow, BOOL bIsGroup)
  1327. {
  1328. LPIWABDATAOBJECT lpIWABDataObject = NULL;
  1329. SCODE sc;
  1330. HRESULT hr = hrSuccess;
  1331. //
  1332. // Allocate space for the IAB structure
  1333. //
  1334. if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABDATAOBJECT), (LPVOID *) &lpIWABDataObject))) {
  1335. hr = ResultFromScode(sc);
  1336. goto err;
  1337. }
  1338. MAPISetBufferName(lpIWABDataObject, TEXT("WAB Data Object"));
  1339. ZeroMemory(lpIWABDataObject, sizeof(IWABDATAOBJECT));
  1340. lpIWABDataObject->lpVtbl = &vtblIWAB_DATAOBJECT;
  1341. lpIWABDataObject->lpVtbl->AddRef(lpIWABDataObject);
  1342. lpIWABDataObject->m_lpAdrBook = lpAdrBook;
  1343. lpAdrBook->lpVtbl->AddRef(lpAdrBook);
  1344. lpIWABDataObject->m_hWndLV = hWndLV;
  1345. lpIWABDataObject->m_lpv = lpv;
  1346. lpIWABDataObject->m_bObjectIsGroup = bIsGroup;
  1347. if(bGetDataNow)
  1348. {
  1349. if(HR_FAILED(HrBuildHDrop(lpIWABDataObject)))
  1350. goto err;
  1351. if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
  1352. goto err;
  1353. if(HR_FAILED(HrBuildcfFlatBuffer(lpIWABDataObject)))
  1354. goto err;
  1355. if(HR_FAILED(HrBuildcfEIDList(lpIWABDataObject)))
  1356. goto err;
  1357. }
  1358. if(g_cfWABFlatBuffer == 0)
  1359. {
  1360. g_cfWABFlatBuffer = (CLIPFORMAT) RegisterClipboardFormat(c_szWABFlatBuffer);
  1361. g_cfWABEntryIDList = (CLIPFORMAT) RegisterClipboardFormat(c_szWABEntryIDList);
  1362. }
  1363. *lppIWABDataObject = lpIWABDataObject;
  1364. return hr;
  1365. err:
  1366. if(lpIWABDataObject)
  1367. MAPIFreeBuffer(lpIWABDataObject);
  1368. *lppIWABDataObject = NULL;
  1369. return hr;
  1370. }
  1371. /*
  1372. -
  1373. -
  1374. *
  1375. *
  1376. */
  1377. void ReleaseWABDataObject(LPIWABDATAOBJECT lpIWABDataObject)
  1378. {
  1379. // Ideally we should clean up any files that were created in <TEMPDIR> ..
  1380. // however, there is a problem when dropping to the shell - OLE doesnt
  1381. // seem to get to these files until after we've deleted them and then
  1382. // pops up error messages.
  1383. // So we'll just let these files lie as is.
  1384. /*
  1385. STGMEDIUM medium;
  1386. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  1387. if (lpIWABDataObject &&
  1388. SUCCEEDED(lpIWABDataObject->lpVtbl->GetData(lpIWABDataObject, &fmte, &medium)))
  1389. {
  1390. HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
  1391. // Enumerate the files and delete them
  1392. {
  1393. TCHAR szFile[MAX_PATH];
  1394. UINT cFiles;
  1395. UINT iFile;
  1396. // Let's work through the files given to us
  1397. cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
  1398. for (iFile = 0; iFile < cFiles; ++iFile)
  1399. {
  1400. DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
  1401. DeleteFile(szFile);
  1402. }
  1403. }
  1404. GlobalUnlock(medium.hGlobal);
  1405. }
  1406. if (medium.pUnkForRelease)
  1407. medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
  1408. else
  1409. GlobalFree(medium.hGlobal);
  1410. */
  1411. if(lpIWABDataObject->m_lpAdrBook)
  1412. lpIWABDataObject->m_lpAdrBook->lpVtbl->Release(lpIWABDataObject->m_lpAdrBook);
  1413. lpIWABDataObject->m_hWndLV = NULL;
  1414. MAPIFreeBuffer(lpIWABDataObject);
  1415. }
  1416. STDMETHODIMP_(ULONG)
  1417. IWAB_DATAOBJECT_AddRef(LPIWABDATAOBJECT lpIWABDataObject)
  1418. {
  1419. return(++(lpIWABDataObject->lcInit));
  1420. }
  1421. STDMETHODIMP_(ULONG)
  1422. IWAB_DATAOBJECT_Release(LPIWABDATAOBJECT lpIWABDataObject)
  1423. {
  1424. if(--(lpIWABDataObject->lcInit)==0)
  1425. {
  1426. ReleaseWABDataObject(lpIWABDataObject);
  1427. return 0;
  1428. }
  1429. return(lpIWABDataObject->lcInit);
  1430. }
  1431. STDMETHODIMP
  1432. IWAB_DATAOBJECT_QueryInterface( LPIWABDATAOBJECT lpIWABDataObject,
  1433. REFIID lpiid,
  1434. LPVOID * lppNewObj)
  1435. {
  1436. LPVOID lp = NULL;
  1437. if(!lppNewObj)
  1438. return MAPI_E_INVALID_PARAMETER;
  1439. *lppNewObj = NULL;
  1440. if(IsEqualIID(lpiid, &IID_IUnknown))
  1441. lp = (LPVOID) lpIWABDataObject;
  1442. if(IsEqualIID(lpiid, &IID_IDataObject))
  1443. {
  1444. lp = (LPVOID) (LPDATAOBJECT) lpIWABDataObject;
  1445. }
  1446. if(!lp)
  1447. {
  1448. return E_NOINTERFACE;
  1449. }
  1450. lpIWABDataObject->lpVtbl->AddRef(lpIWABDataObject);
  1451. *lppNewObj = lp;
  1452. return S_OK;
  1453. }
  1454. STDMETHODIMP
  1455. IWAB_DATAOBJECT_GetDataHere( LPIWABDATAOBJECT lpIWABDataObject,
  1456. FORMATETC * pFormatetc,
  1457. STGMEDIUM * pmedium)
  1458. {
  1459. DebugTrace(TEXT("IDataObject: GetDataHere\n"));
  1460. return E_NOTIMPL;
  1461. }
  1462. STDMETHODIMP
  1463. IWAB_DATAOBJECT_GetData(LPIWABDATAOBJECT lpIWABDataObject,
  1464. FORMATETC * pformatetcIn,
  1465. STGMEDIUM * pmedium)
  1466. {
  1467. HRESULT hres = E_INVALIDARG;
  1468. LPVOID pv = NULL;
  1469. DebugTrace(TEXT("IDataObject: GetData ->"));
  1470. pmedium->hGlobal = NULL;
  1471. pmedium->pUnkForRelease = NULL;
  1472. if( (pformatetcIn->tymed & TYMED_HGLOBAL)
  1473. && ( g_cfWABEntryIDList == pformatetcIn->cfFormat ||
  1474. g_cfWABFlatBuffer == pformatetcIn->cfFormat ||
  1475. CF_HDROP == pformatetcIn->cfFormat ||
  1476. CF_TEXT == pformatetcIn->cfFormat ||
  1477. CF_UNICODETEXT == pformatetcIn->cfFormat ) )
  1478. {
  1479. LPVOID lp = NULL;
  1480. ULONG cb = 0;
  1481. if (lpIWABDataObject->m_bObjectIsGroup &&
  1482. pformatetcIn->cfFormat != g_cfWABEntryIDList)
  1483. return E_FAIL;
  1484. if(g_cfWABEntryIDList == pformatetcIn->cfFormat)
  1485. {
  1486. DebugTrace(TEXT("cfWABEntryIDList requested \n"));
  1487. if(!lpIWABDataObject->cbDataEID && !lpIWABDataObject->pDataEID)
  1488. {
  1489. if(HR_FAILED(HrBuildcfEIDList(lpIWABDataObject)))
  1490. return E_FAIL;
  1491. }
  1492. cb = lpIWABDataObject->cbDataEID;
  1493. lp = (LPVOID)lpIWABDataObject->pDataEID;
  1494. }
  1495. else if(g_cfWABFlatBuffer == pformatetcIn->cfFormat)
  1496. {
  1497. DebugTrace(TEXT("cfWABFlatBuffer requested \n"));
  1498. if(!lpIWABDataObject->cbDataBuffer && !lpIWABDataObject->pDataBuffer)
  1499. {
  1500. if(HR_FAILED(HrBuildcfFlatBuffer(lpIWABDataObject)))
  1501. return E_FAIL;
  1502. }
  1503. cb = lpIWABDataObject->cbDataBuffer;
  1504. lp = (LPVOID)lpIWABDataObject->pDataBuffer;
  1505. }
  1506. else if (CF_HDROP == pformatetcIn->cfFormat)
  1507. {
  1508. DebugTrace(TEXT("CF_HDROP requested \n"));
  1509. // Time to go create the actual files on disk and pass that information back
  1510. if(!lpIWABDataObject->cbDatahDrop && !lpIWABDataObject->pDatahDrop)
  1511. {
  1512. if(HR_FAILED(HrBuildHDrop(lpIWABDataObject)))
  1513. return E_FAIL;
  1514. }
  1515. cb = lpIWABDataObject->cbDatahDrop;
  1516. lp = (LPVOID)lpIWABDataObject->pDatahDrop;
  1517. }
  1518. else if(CF_TEXT == pformatetcIn->cfFormat)
  1519. {
  1520. DebugTrace(TEXT("CF_TEXT requested \n"));
  1521. if(!lpIWABDataObject->cbDataTextA && !lpIWABDataObject->pDataTextA)
  1522. {
  1523. if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
  1524. return E_FAIL;
  1525. }
  1526. cb = lpIWABDataObject->cbDataTextA;
  1527. lp = (LPVOID)lpIWABDataObject->pDataTextA;
  1528. }
  1529. else if(CF_UNICODETEXT == pformatetcIn->cfFormat)
  1530. {
  1531. DebugTrace(TEXT("CF_UNICODETEXT requested \n"));
  1532. if(!lpIWABDataObject->cbDataTextW && !lpIWABDataObject->pDataTextW)
  1533. {
  1534. if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
  1535. return E_FAIL;
  1536. }
  1537. cb = lpIWABDataObject->cbDataTextW;
  1538. lp = (LPVOID)lpIWABDataObject->pDataTextW;
  1539. }
  1540. if(!cb || !lp)
  1541. return (E_FAIL);
  1542. // Make a copy of the data for this pInfo
  1543. pmedium->hGlobal = GlobalAlloc(GMEM_SHARE | GHND, cb);
  1544. if (!pmedium->hGlobal)
  1545. return (E_OUTOFMEMORY);
  1546. pv = GlobalLock(pmedium->hGlobal);
  1547. CopyMemory(pv, lp, cb);
  1548. GlobalUnlock(pmedium->hGlobal);
  1549. // Fill in the pStgMedium struct
  1550. if (pformatetcIn->tymed & TYMED_HGLOBAL)
  1551. {
  1552. pmedium->tymed = TYMED_HGLOBAL;
  1553. return (S_OK);
  1554. }
  1555. }
  1556. return hres;
  1557. }
  1558. STDMETHODIMP
  1559. IWAB_DATAOBJECT_QueryGetData(LPIWABDATAOBJECT lpIWABDataObject,
  1560. FORMATETC * pformatetcIn)
  1561. {
  1562. DebugTrace(TEXT("IDataObject: QueryGetData: %d "),pformatetcIn->cfFormat);
  1563. // if (pformatetcIn->cfFormat == g_cfFileContents ||
  1564. // pformatetcIn->cfFormat == g_cfFileGroupDescriptor)
  1565. if (lpIWABDataObject->m_bObjectIsGroup)
  1566. {
  1567. if(pformatetcIn->cfFormat == g_cfWABEntryIDList)
  1568. {
  1569. DebugTrace(TEXT("S_OK\n"));
  1570. return S_OK;
  1571. }
  1572. else
  1573. {
  1574. DebugTrace(TEXT("S_FALSE\n"));
  1575. return DV_E_FORMATETC;
  1576. }
  1577. }
  1578. else
  1579. if (pformatetcIn->cfFormat == g_cfWABEntryIDList ||
  1580. pformatetcIn->cfFormat == g_cfWABFlatBuffer ||
  1581. pformatetcIn->cfFormat == CF_HDROP ||
  1582. pformatetcIn->cfFormat == CF_TEXT ||
  1583. pformatetcIn->cfFormat == CF_UNICODETEXT)
  1584. {
  1585. DebugTrace(TEXT("S_OK\n"));
  1586. return S_OK;
  1587. }
  1588. else
  1589. {
  1590. DebugTrace(TEXT("S_FALSE\n"));
  1591. return DV_E_FORMATETC;
  1592. }
  1593. return NOERROR;
  1594. }
  1595. STDMETHODIMP
  1596. IWAB_DATAOBJECT_GetCanonicalFormatEtc( LPIWABDATAOBJECT lpIWABDataObject,
  1597. FORMATETC * pFormatetcIn,
  1598. FORMATETC * pFormatetcOut)
  1599. {
  1600. DebugTrace(TEXT("IDataObject: GetCanonicalFormatEtc\n"));
  1601. return DATA_S_SAMEFORMATETC;
  1602. }
  1603. STDMETHODIMP
  1604. IWAB_DATAOBJECT_SetData( LPIWABDATAOBJECT lpIWABDataObject,
  1605. FORMATETC * pFormatetc,
  1606. STGMEDIUM * pmedium,
  1607. BOOL fRelease)
  1608. {
  1609. DebugTrace(TEXT("IDataObject: SetData\n"));
  1610. return E_NOTIMPL;
  1611. }
  1612. STDMETHODIMP
  1613. IWAB_DATAOBJECT_EnumFormatEtc( LPIWABDATAOBJECT lpIWABDataObject,
  1614. DWORD dwDirection,
  1615. IEnumFORMATETC ** ppenumFormatetc)
  1616. {
  1617. FORMATETC fmte[5] = {
  1618. // {g_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1619. // {g_cfFileGroupDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1620. {g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1621. {g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1622. {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1623. {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1624. {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1625. };
  1626. int nType = 0;
  1627. DebugTrace(TEXT("IDataObject: EnumFormatEtc\n"));
  1628. if(lpIWABDataObject->m_bObjectIsGroup)
  1629. nType = 1;
  1630. else
  1631. nType = sizeof(fmte)/sizeof(FORMATETC);
  1632. return HrCreateIWABEnumFORMATETC(nType, fmte,
  1633. (LPIWABENUMFORMATETC *) ppenumFormatetc);
  1634. }
  1635. STDMETHODIMP
  1636. IWAB_DATAOBJECT_DAdvise(LPIWABDATAOBJECT lpIWABDataObject,
  1637. FORMATETC * pFormatetc,
  1638. DWORD advf,
  1639. IAdviseSink * pAdvSink,
  1640. DWORD * pdwConnection)
  1641. {
  1642. DebugTrace(TEXT("IDataObject: DAdvise\n"));
  1643. return OLE_E_ADVISENOTSUPPORTED;
  1644. }
  1645. STDMETHODIMP
  1646. IWAB_DATAOBJECT_DUnadvise( LPIWABDATAOBJECT lpIWABDataObject,
  1647. DWORD dwConnection)
  1648. {
  1649. DebugTrace(TEXT("IDataObject: DUnadvise\n"));
  1650. return OLE_E_ADVISENOTSUPPORTED;
  1651. }
  1652. STDMETHODIMP
  1653. IWAB_DATAOBJECT_EnumDAdvise( LPIWABDATAOBJECT lpIWABDataObject,
  1654. IEnumSTATDATA ** ppenumAdvise)
  1655. {
  1656. DebugTrace(TEXT("IDataObject: EnumDAdvise\n"));
  1657. return OLE_E_ADVISENOTSUPPORTED;
  1658. }
  1659. /*--------------------------------------------------------------------------------*/
  1660. /****************************************************************************
  1661. *
  1662. * STDEnumFmt Methods
  1663. *
  1664. ****************************************************************************/
  1665. HRESULT HrCreateIWABEnumFORMATETC( UINT cfmt,
  1666. const FORMATETC afmt[],
  1667. LPIWABENUMFORMATETC *ppenumFormatEtc)
  1668. {
  1669. LPIWABENUMFORMATETC lpIWABEnumFORMATETC = NULL;
  1670. SCODE sc;
  1671. HRESULT hr = hrSuccess;
  1672. if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABENUMFORMATETC)+(cfmt - 1) * sizeof(FORMATETC), (LPVOID *) &lpIWABEnumFORMATETC))) {
  1673. hr = ResultFromScode(sc);
  1674. goto err;
  1675. }
  1676. MAPISetBufferName(lpIWABEnumFORMATETC, TEXT("WAB EnumFORMATETC Object"));
  1677. ZeroMemory(lpIWABEnumFORMATETC, sizeof(IWABENUMFORMATETC));
  1678. lpIWABEnumFORMATETC->lpVtbl = &vtblIWAB_ENUMFORMATETC;
  1679. lpIWABEnumFORMATETC->lpVtbl->AddRef(lpIWABEnumFORMATETC);
  1680. lpIWABEnumFORMATETC->cfmt = cfmt;
  1681. lpIWABEnumFORMATETC->ifmt = 0;
  1682. MoveMemory(lpIWABEnumFORMATETC->afmt, afmt, cfmt * sizeof(FORMATETC));
  1683. *ppenumFormatEtc = lpIWABEnumFORMATETC;
  1684. err:
  1685. return hr;
  1686. }
  1687. void ReleaseWABEnumFORMATETC(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
  1688. {
  1689. MAPIFreeBuffer(lpIWABEnumFORMATETC);
  1690. }
  1691. STDMETHODIMP_(ULONG)
  1692. IWAB_ENUMFORMATETC_AddRef(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
  1693. {
  1694. return(++(lpIWABEnumFORMATETC->lcInit));
  1695. }
  1696. STDMETHODIMP_(ULONG)
  1697. IWAB_ENUMFORMATETC_Release(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
  1698. {
  1699. if(--(lpIWABEnumFORMATETC->lcInit)==0)
  1700. {
  1701. ReleaseWABEnumFORMATETC(lpIWABEnumFORMATETC);
  1702. return 0;
  1703. }
  1704. return(lpIWABEnumFORMATETC->lcInit);
  1705. }
  1706. STDMETHODIMP
  1707. IWAB_ENUMFORMATETC_QueryInterface( LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
  1708. REFIID lpiid,
  1709. LPVOID * lppNewObj)
  1710. {
  1711. LPVOID lp = NULL;
  1712. if(!lppNewObj)
  1713. return MAPI_E_INVALID_PARAMETER;
  1714. *lppNewObj = NULL;
  1715. if(IsEqualIID(lpiid, &IID_IUnknown))
  1716. lp = (LPVOID) lpIWABEnumFORMATETC;
  1717. if(IsEqualIID(lpiid, &IID_IEnumFORMATETC))
  1718. {
  1719. lp = (LPVOID) (LPENUMFORMATETC) lpIWABEnumFORMATETC;
  1720. }
  1721. if(!lp)
  1722. {
  1723. return E_NOINTERFACE;
  1724. }
  1725. lpIWABEnumFORMATETC->lpVtbl->AddRef(lpIWABEnumFORMATETC);
  1726. *lppNewObj = lp;
  1727. return S_OK;
  1728. }
  1729. STDMETHODIMP
  1730. IWAB_ENUMFORMATETC_Next(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
  1731. ULONG celt,
  1732. FORMATETC *rgelt,
  1733. ULONG *pceltFethed)
  1734. {
  1735. UINT cfetch;
  1736. HRESULT hres = S_FALSE; // assume less numbers
  1737. if (lpIWABEnumFORMATETC->ifmt < lpIWABEnumFORMATETC->cfmt)
  1738. {
  1739. cfetch = lpIWABEnumFORMATETC->cfmt - lpIWABEnumFORMATETC->ifmt;
  1740. if (cfetch >= celt)
  1741. {
  1742. cfetch = celt;
  1743. hres = S_OK;
  1744. }
  1745. CopyMemory(rgelt, &(lpIWABEnumFORMATETC->afmt[lpIWABEnumFORMATETC->ifmt]), cfetch * sizeof(FORMATETC));
  1746. lpIWABEnumFORMATETC->ifmt += cfetch;
  1747. }
  1748. else
  1749. {
  1750. cfetch = 0;
  1751. }
  1752. if (pceltFethed)
  1753. *pceltFethed = cfetch;
  1754. return hres;
  1755. }
  1756. STDMETHODIMP
  1757. IWAB_ENUMFORMATETC_Skip(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
  1758. ULONG celt)
  1759. {
  1760. lpIWABEnumFORMATETC->ifmt += celt;
  1761. if (lpIWABEnumFORMATETC->ifmt > lpIWABEnumFORMATETC->cfmt)
  1762. {
  1763. lpIWABEnumFORMATETC->ifmt = lpIWABEnumFORMATETC->cfmt;
  1764. return S_FALSE;
  1765. }
  1766. return S_OK;
  1767. }
  1768. STDMETHODIMP
  1769. IWAB_ENUMFORMATETC_Reset(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
  1770. {
  1771. lpIWABEnumFORMATETC->ifmt = 0;
  1772. return S_OK;
  1773. }
  1774. STDMETHODIMP
  1775. IWAB_ENUMFORMATETC_Clone(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
  1776. LPENUMFORMATETC * ppenum)
  1777. {
  1778. return HrCreateIWABEnumFORMATETC( lpIWABEnumFORMATETC->cfmt,
  1779. lpIWABEnumFORMATETC->afmt,
  1780. (LPIWABENUMFORMATETC *) ppenum);
  1781. }
  1782. /********************************************************************************/
  1783. /*
  1784. -
  1785. - bIsPasteData
  1786. *
  1787. * Checks if there is pastable data on the clipboard -
  1788. * if this data is being dropped within the same WAB,
  1789. * then we can look for the entryids else we ask for
  1790. * flat-buffer or cf-hdrop
  1791. */
  1792. BOOL bIsPasteData()
  1793. {
  1794. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1795. LPDATAOBJECT lpDataObject = NULL;
  1796. BOOL bRet = FALSE;
  1797. OleGetClipboard(&lpDataObject);
  1798. if(lpDataObject)
  1799. {
  1800. FORMATETC fe[3] =
  1801. {
  1802. {g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1803. {g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1804. {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1805. };
  1806. ULONG i = 0;
  1807. for(i=0;i<sizeof(fe)/sizeof(FORMATETC);i++)
  1808. {
  1809. if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fe[i])))
  1810. {
  1811. // TBD - ideally before accepting CF_HDROP as a valid format, we
  1812. // should make sure the droppable files are indeed vCard files ...
  1813. bRet = TRUE;
  1814. break;
  1815. }
  1816. }
  1817. }
  1818. if(lpDataObject)
  1819. lpDataObject->lpVtbl->Release(lpDataObject);
  1820. return bRet;
  1821. }
  1822. //////////////////////////////////////////////////////////////////////////
  1823. // Helper function to determine drop target type
  1824. //
  1825. // bIsDropTargetGroup()
  1826. //////////////////////////////////////////////////////////////////////////
  1827. BOOL bIsDropTargetGroup(LPBWI lpbwi)
  1828. {
  1829. // The drop target can be in either the List View or Tree View control.
  1830. // First check the List View.
  1831. BOOL fRtn = FALSE;
  1832. SBinary sb = {0};
  1833. if ( (GetFocus() == bwi_hWndListAB) &&
  1834. bIsGroupSelected(bwi_hWndListAB, &sb) )
  1835. {
  1836. fRtn = TRUE;
  1837. }
  1838. else
  1839. {
  1840. // Next try the Tree View control.
  1841. LPSBinary lpsbEID = NULL;
  1842. ULONG ulObjectType = 0;
  1843. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
  1844. fRtn = (ulObjectType == MAPI_DISTLIST);
  1845. }
  1846. return fRtn;
  1847. }
  1848. /*
  1849. - PasteData
  1850. -
  1851. * Pastes data when user chooses to paste data (from a menu)
  1852. *
  1853. */
  1854. HRESULT HrPasteData(LPBWI lpbwi)
  1855. {
  1856. HRESULT hr = S_OK;
  1857. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1858. LPDATAOBJECT lpDataObject = NULL;
  1859. STGMEDIUM medium = {0};
  1860. LPSBinary lpsbEID = NULL;
  1861. SBinary sb = {0};
  1862. FORMATETC fmte[3] =
  1863. {
  1864. {g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1865. {g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1866. {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  1867. };
  1868. // this only got called if valid pastable data existed
  1869. OleGetClipboard(&lpDataObject);
  1870. if(lpDataObject)
  1871. {
  1872. // [PaulHi] 12/1/98 Raid #58486
  1873. // First check for a flat buffer. We prefer to paste a new contact (i.e.,
  1874. // new entryid) based on the clipboard flat buffer, UNLESS we are pasting
  1875. // to a group or distribution list. Only existing entryids can be added to
  1876. // a group.
  1877. BOOL bGroupTarget = bIsDropTargetGroup(lpbwi);
  1878. if( !bGroupTarget &&
  1879. (NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[1]))) )
  1880. {
  1881. // yes - we are the pasting within the same wab
  1882. if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[1], &medium)))
  1883. {
  1884. DropFlatBuffer(lpbwi, medium);
  1885. }
  1886. goto out;
  1887. }
  1888. // next check if entryids are available
  1889. if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[0])))
  1890. {
  1891. // yes entryids are available - but is this the source of the date ?
  1892. // entryids are only useful when dropping between the wab and itself
  1893. if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[0], &medium)))
  1894. {
  1895. ULONG ulObjType = 0;
  1896. POINTL pt = {0};
  1897. if(!bIsGroupSelected(bwi_hWndListAB, &sb))
  1898. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjType, FALSE);
  1899. else
  1900. lpsbEID = &sb;
  1901. if(!DropEntryIDs(lpbwi, medium, pt, lpsbEID, ulObjType))
  1902. {
  1903. //Something failed - try another format)
  1904. if (medium.pUnkForRelease)
  1905. {
  1906. medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
  1907. medium.pUnkForRelease = NULL;
  1908. }
  1909. else if(medium.hGlobal)
  1910. {
  1911. GlobalFree(medium.hGlobal);
  1912. medium.hGlobal = NULL;
  1913. }
  1914. }
  1915. else
  1916. goto out;
  1917. }
  1918. }
  1919. // otherwise we're just dropping files
  1920. if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[2])))
  1921. {
  1922. // yes - we are the pasting within the same wab
  1923. if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[2], &medium)))
  1924. {
  1925. DropVCardFiles(lpbwi, medium);
  1926. }
  1927. goto out;
  1928. }
  1929. }
  1930. hr = E_FAIL;
  1931. out:
  1932. if(lpsbEID != &sb)
  1933. LocalFreeSBinary(lpsbEID);
  1934. if (medium.pUnkForRelease)
  1935. medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
  1936. else if(medium.hGlobal)
  1937. GlobalFree(medium.hGlobal);
  1938. if(lpDataObject)
  1939. lpDataObject->lpVtbl->Release(lpDataObject);
  1940. return hr;
  1941. }