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.

1024 lines
30 KiB

  1. // mfcext.cpp : Defines the initialization routines for the DLL.
  2. //
  3. #include "stdafx.h"
  4. #include "mfcext.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. //
  11. // Note!
  12. //
  13. // If this DLL is dynamically linked against the MFC
  14. // DLLs, any functions exported from this DLL which
  15. // call into MFC must have the AFX_MANAGE_STATE macro
  16. // added at the very beginning of the function.
  17. //
  18. // For example:
  19. //
  20. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  21. // {
  22. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  23. // // normal function body here
  24. // }
  25. //
  26. // It is very important that this macro appear in each
  27. // function, prior to any calls into MFC. This means that
  28. // it must appear as the first statement within the
  29. // function, even before any object variable declarations
  30. // as their constructors may generate calls into the MFC
  31. // DLL.
  32. //
  33. // Please see MFC Technical Notes 33 and 58 for additional
  34. // details.
  35. //
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CMfcextApp
  38. BEGIN_MESSAGE_MAP(CMfcextApp, CWinApp)
  39. //{{AFX_MSG_MAP(CMfcextApp)
  40. // NOTE - the ClassWizard will add and remove mapping macros here.
  41. // DO NOT EDIT what you see in these blocks of generated code!
  42. //}}AFX_MSG_MAP
  43. END_MESSAGE_MAP()
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CMfcextApp construction
  46. CMfcextApp::CMfcextApp()
  47. {
  48. // TODO: add construction code here,
  49. // Place all significant initialization in InitInstance
  50. }
  51. /////////////////////////////////////////////////////////////////////////////
  52. // The one and only CMfcextApp object
  53. CMfcextApp theApp;
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CPropextApp initialization
  56. BOOL CMfcextApp::InitInstance()
  57. {
  58. // Register all OLE server (factories) as running. This enables the
  59. // OLE libraries to create objects from other applications.
  60. COleObjectFactory::RegisterAll();
  61. return TRUE;
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Special entry points required for inproc servers
  65. #if (_MFC_VER >= 0x300)
  66. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  67. {
  68. return AfxDllGetClassObject(rclsid, riid, ppv);
  69. }
  70. STDAPI DllCanUnloadNow(void)
  71. {
  72. return AfxDllCanUnloadNow();
  73. }
  74. #endif
  75. // by exporting DllRegisterServer, you can use regsvr.exe
  76. STDAPI DllRegisterServer(void)
  77. {
  78. COleObjectFactory::UpdateRegistryAll();
  79. HKEY hSubKey = NULL;
  80. DWORD dwDisp = 0;
  81. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\WAB\\WAB4\\ExtDisplay\\MailUser",
  82. 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisp))
  83. {
  84. UCHAR szEmpty[] = "";
  85. RegSetValueEx(hSubKey,"{BA9EE970-87A0-11D1-9ACF-00A0C91F9C8B}",0,REG_SZ, szEmpty, sizeof(szEmpty));
  86. RegCloseKey(hSubKey);
  87. }
  88. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\WAB\\WAB4\\ExtDisplay\\DistList",
  89. 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisp))
  90. {
  91. UCHAR szEmpty[] = "";
  92. RegSetValueEx(hSubKey,"{BA9EE970-87A0-11D1-9ACF-00A0C91F9C8B}",0,REG_SZ, szEmpty, sizeof(szEmpty));
  93. RegCloseKey(hSubKey);
  94. }
  95. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\WAB\\WAB4\\ExtContext",
  96. 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisp))
  97. {
  98. UCHAR szEmpty[] = "";
  99. RegSetValueEx(hSubKey,"{BA9EE970-87A0-11D1-9ACF-00A0C91F9C8B}",0,REG_SZ, szEmpty, sizeof(szEmpty));
  100. RegCloseKey(hSubKey);
  101. }
  102. return S_OK;
  103. }
  104. /////////////////////////////////////////////////////////////////////////////
  105. // CPropExt
  106. IMPLEMENT_DYNCREATE(CMfcExt, CCmdTarget)
  107. CMfcExt::CMfcExt()
  108. {
  109. EnableAutomation();
  110. // To keep the application running as long as an OLE automation
  111. // object is active, the constructor calls AfxOleLockApp.
  112. m_lpWED = NULL;
  113. m_lpWEDContext = NULL;
  114. m_lpPropObj = NULL;
  115. AfxOleLockApp();
  116. }
  117. CMfcExt::~CMfcExt()
  118. {
  119. // To terminate the application when all objects created with
  120. // with OLE automation, the destructor calls AfxOleUnlockApp.
  121. AfxOleUnlockApp();
  122. }
  123. void CMfcExt::OnFinalRelease()
  124. {
  125. // When the last reference for an automation object is released
  126. // OnFinalRelease is called. This implementation deletes the
  127. // object. Add additional cleanup required for your object before
  128. // deleting it from memory.
  129. if(m_lpPropObj)
  130. {
  131. m_lpPropObj->Release();
  132. m_lpPropObj = NULL;
  133. }
  134. delete this;
  135. }
  136. BEGIN_MESSAGE_MAP(CMfcExt, CCmdTarget)
  137. //{{AFX_MSG_MAP(CPropExt)
  138. // NOTE - the ClassWizard will add and remove mapping macros here.
  139. //}}AFX_MSG_MAP
  140. END_MESSAGE_MAP()
  141. BEGIN_DISPATCH_MAP(CMfcExt, CCmdTarget)
  142. //{{AFX_DISPATCH_MAP(CPropExt)
  143. // NOTE - the ClassWizard will add and remove mapping macros here.
  144. //}}AFX_DISPATCH_MAP
  145. END_DISPATCH_MAP()
  146. // {BA9EE970-87A0-11d1-9ACF-00A0C91F9C8B}
  147. IMPLEMENT_OLECREATE(CMfcExt, "WABSamplePropExtSheet", 0xba9ee970, 0x87a0, 0x11d1, 0x9a, 0xcf, 0x0, 0xa0, 0xc9, 0x1f, 0x9c, 0x8b);
  148. BEGIN_INTERFACE_MAP(CMfcExt, CCmdTarget)
  149. INTERFACE_PART(CMfcExt, IID_IShellPropSheetExt, MfcExt)
  150. INTERFACE_PART(CMfcExt, IID_IWABExtInit, WABInit)
  151. INTERFACE_PART(CMfcExt, IID_IContextMenu, ContextMenuExt)
  152. END_INTERFACE_MAP()
  153. // IUnknown for IShellPropSheet
  154. STDMETHODIMP CMfcExt::XMfcExt::QueryInterface(REFIID riid, void** ppv)
  155. {
  156. METHOD_PROLOGUE(CMfcExt, MfcExt);
  157. TRACE("CMfcExt::XMfcExt::QueryInterface\n");
  158. return pThis->ExternalQueryInterface(&riid, ppv);
  159. }
  160. STDMETHODIMP_(ULONG) CMfcExt::XMfcExt::AddRef(void)
  161. {
  162. METHOD_PROLOGUE(CMfcExt, MfcExt);
  163. return pThis->ExternalAddRef();
  164. }
  165. STDMETHODIMP_(ULONG) CMfcExt::XMfcExt::Release(void)
  166. {
  167. METHOD_PROLOGUE(CMfcExt, MfcExt);
  168. return pThis->ExternalRelease();
  169. }
  170. STDMETHODIMP CMfcExt::XMfcExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
  171. {
  172. return E_NOTIMPL;
  173. }
  174. // IUnknown for IShellExtInit
  175. STDMETHODIMP CMfcExt::XWABInit::QueryInterface(REFIID riid, void** ppv)
  176. {
  177. METHOD_PROLOGUE(CMfcExt, WABInit);
  178. TRACE("CMfcExt::XWABInit::QueryInterface\n");
  179. return pThis->ExternalQueryInterface(&riid, ppv);
  180. }
  181. STDMETHODIMP_(ULONG) CMfcExt::XWABInit::AddRef(void)
  182. {
  183. METHOD_PROLOGUE(CMfcExt, WABInit);
  184. return pThis->ExternalAddRef();
  185. }
  186. STDMETHODIMP_(ULONG) CMfcExt::XWABInit::Release(void)
  187. {
  188. METHOD_PROLOGUE(CMfcExt, WABInit);
  189. return pThis->ExternalRelease();
  190. }
  191. STDMETHODIMP CMfcExt::XWABInit::Initialize(LPWABEXTDISPLAY lpWABExtDisplay)
  192. {
  193. METHOD_PROLOGUE(CMfcExt, WABInit);
  194. TRACE("CMfcExt::XWABInit::Intialize\n");
  195. if (lpWABExtDisplay == NULL)
  196. {
  197. TRACE("CMfcExt::XWABInit::Initialize() no data object");
  198. return E_FAIL;
  199. }
  200. // However if this is a context menu extension, we need to hang
  201. // onto the propobj till such time as InvokeCommand is called ..
  202. // At this point just AddRef the propobj - this will ensure that the
  203. // data in the lpAdrList remains valid till we release the propobj..
  204. // When we get another ContextMenu initiation, we can release the
  205. // older cached propobj - if we dont get another initiation, we
  206. // release the cached object at shutdown time
  207. if(lpWABExtDisplay->ulFlags & WAB_CONTEXT_ADRLIST) // this means a IContextMenu operation is occuring
  208. {
  209. if(pThis->m_lpPropObj)
  210. {
  211. pThis->m_lpPropObj->Release();
  212. pThis->m_lpPropObj = NULL;
  213. }
  214. pThis->m_lpPropObj = lpWABExtDisplay->lpPropObj;
  215. pThis->m_lpPropObj->AddRef();
  216. pThis->m_lpWEDContext = lpWABExtDisplay;
  217. }
  218. else
  219. {
  220. // For property sheet extensions, the lpWABExtDisplay will
  221. // exist for the life of the property sheets ..
  222. pThis->m_lpWED = lpWABExtDisplay;
  223. }
  224. return S_OK;
  225. }
  226. // Globally cached hInstance for the DLL
  227. HINSTANCE hinstApp = NULL;
  228. // For the purposes of this sample, we will use 2 named properties,
  229. // HomeTown and SportsTeam
  230. // This demo's private GUID:
  231. // {2B6D7EE0-36AB-11d1-9ABC-00A0C91F9C8B}
  232. static const GUID WAB_ExtDemoGuid =
  233. { 0x2b6d7ee0, 0x36ab, 0x11d1, { 0x9a, 0xbc, 0x0, 0xa0, 0xc9, 0x1f, 0x9c, 0x8b } };
  234. static const LPTSTR lpMyPropNames[] =
  235. {
  236. "MyHomeTown",
  237. "MySportsTeam"
  238. };
  239. enum _MyTags
  240. {
  241. myHomeTown = 0,
  242. mySportsTeam,
  243. myMax
  244. };
  245. ULONG MyPropTags[myMax];
  246. ULONG PR_MY_HOMETOWN;
  247. ULONG PR_MY_SPORTSTEAM;
  248. //
  249. // Function prototypes:
  250. //
  251. HRESULT InitNamedProps(LPWABEXTDISPLAY lpWED);
  252. INT_PTR CALLBACK fnDetailsPropDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  253. void InitializeUI(HWND hDlg, LPWABEXTDISPLAY lpWED);
  254. void SetDataInUI(HWND hDlg, LPWABEXTDISPLAY lpWED);
  255. BOOL GetDataFromUI(HWND hDlg, LPWABEXTDISPLAY lpWED);
  256. UINT CALLBACK fnCallback( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );
  257. void UpdateDisplayNameInfo(HWND hDlg, LPWABEXTDISPLAY lpWED);
  258. BOOL bUpdatePropSheetData(HWND hDlg, LPWABEXTDISPLAY lpWED);
  259. /*//$$****************************************************************
  260. //
  261. // InitNamedProps
  262. //
  263. // Gets the PropTags for the Named Props this app is interested in
  264. //
  265. //********************************************************************/
  266. HRESULT InitNamedProps(LPWABEXTDISPLAY lpWED)
  267. {
  268. ULONG i;
  269. HRESULT hr = E_FAIL;
  270. LPSPropTagArray lptaMyProps = NULL;
  271. LPMAPINAMEID * lppMyPropNames;
  272. SCODE sc;
  273. LPMAILUSER lpMailUser = NULL;
  274. WCHAR szBuf[myMax][MAX_PATH];
  275. if(!lpWED)
  276. goto err;
  277. lpMailUser = (LPMAILUSER) lpWED->lpPropObj;
  278. if(!lpMailUser)
  279. goto err;
  280. sc = lpWED->lpWABObject->AllocateBuffer(sizeof(LPMAPINAMEID) * myMax,
  281. (LPVOID *) &lppMyPropNames);
  282. if(sc)
  283. {
  284. hr = ResultFromScode(sc);
  285. goto err;
  286. }
  287. for(i=0;i<myMax;i++)
  288. {
  289. sc = lpWED->lpWABObject->AllocateMore(sizeof(MAPINAMEID),
  290. lppMyPropNames,
  291. (LPVOID *)&(lppMyPropNames[i]));
  292. if(sc)
  293. {
  294. hr = ResultFromScode(sc);
  295. goto err;
  296. }
  297. lppMyPropNames[i]->lpguid = (LPGUID) &WAB_ExtDemoGuid;
  298. lppMyPropNames[i]->ulKind = MNID_STRING;
  299. *(szBuf[i]) = '\0';
  300. // Convert prop name to wide-char
  301. if ( !MultiByteToWideChar( GetACP(), 0, lpMyPropNames[i], -1, szBuf[i], sizeof(szBuf[i])) )
  302. {
  303. continue;
  304. }
  305. lppMyPropNames[i]->Kind.lpwstrName = (LPWSTR) szBuf[i];
  306. }
  307. hr = lpMailUser->GetIDsFromNames( myMax,
  308. lppMyPropNames,
  309. MAPI_CREATE,
  310. &lptaMyProps);
  311. if(HR_FAILED(hr))
  312. goto err;
  313. if(lptaMyProps)
  314. {
  315. // Set the property types on the returned props
  316. MyPropTags[myHomeTown] = PR_MY_HOMETOWN = CHANGE_PROP_TYPE(lptaMyProps->aulPropTag[myHomeTown], PT_TSTRING);
  317. MyPropTags[mySportsTeam] = PR_MY_SPORTSTEAM = CHANGE_PROP_TYPE(lptaMyProps->aulPropTag[mySportsTeam], PT_TSTRING);
  318. }
  319. err:
  320. if(lptaMyProps)
  321. lpWED->lpWABObject->FreeBuffer( lptaMyProps);
  322. if(lppMyPropNames)
  323. lpWED->lpWABObject->FreeBuffer( lppMyPropNames);
  324. return hr;
  325. }
  326. /*//$$****************************************************************
  327. //
  328. // fnDetailsPropDlgProc
  329. //
  330. // The dialog procedure that will handle all the windows messages for
  331. // the extended property page.
  332. //
  333. //********************************************************************/
  334. INT_PTR CALLBACK CMfcExt::MfcExtDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  335. {
  336. LPWABEXTDISPLAY lpWED = (LPWABEXTDISPLAY) GetWindowLong(hDlg, DWL_USER);
  337. switch(message)
  338. {
  339. case WM_INITDIALOG:
  340. //
  341. // The lParam on InitDialog contains the application data
  342. // Cache this on the dialog so we can retrieve it later.
  343. //
  344. {
  345. PROPSHEETPAGE * pps = (PROPSHEETPAGE *) lParam;
  346. LPWABEXTDISPLAY * lppWED = (LPWABEXTDISPLAY *) pps->lParam;
  347. if(lppWED)
  348. {
  349. SetWindowLong(hDlg,DWL_USER,(LPARAM)*lppWED);
  350. lpWED = *lppWED;
  351. }
  352. }
  353. // Initialize the named props for this prop sheet
  354. InitNamedProps(lpWED);
  355. // Initialize the UI appropriately
  356. InitializeUI(hDlg, lpWED);
  357. // Fill the UI with appropriate data
  358. SetDataInUI(hDlg, lpWED);
  359. return TRUE;
  360. break;
  361. case WM_COMMAND:
  362. switch(HIWORD(wParam)) //check the notification code
  363. {
  364. // If data changes, we should signal back to the WAB that
  365. // the data changed. If this flag is not set, the WAB will not
  366. // write the new data back to the store!!!
  367. case EN_CHANGE: //one of the edit boxes changed - dont care which
  368. lpWED->fDataChanged = TRUE;
  369. break;
  370. }
  371. break;
  372. case WM_NOTIFY:
  373. switch(((NMHDR FAR *)lParam)->code)
  374. {
  375. case PSN_SETACTIVE: //Page being activated
  376. // Get the latest display name info and update the
  377. // corresponding control
  378. UpdateDisplayNameInfo(hDlg, lpWED);
  379. break;
  380. case PSN_KILLACTIVE: //Losing activation to another page or OK
  381. //
  382. // Take all the data from this prop sheet and convert it to a
  383. // SPropValue array and place the data in an appropriate place.
  384. // The advantage of doing this in the KillActive notification is
  385. // that other property sheets can scan these property arrays and
  386. // if deisred, update data on other prop sheets based on this data
  387. //
  388. bUpdatePropSheetData(hDlg, lpWED);
  389. break;
  390. case PSN_RESET: //cancel
  391. break;
  392. case PSN_APPLY: //ok pressed
  393. if (!(lpWED->fReadOnly))
  394. {
  395. //
  396. // Check for any required properties here
  397. // If some required property is not filled in, you can prevent
  398. // the property sheet from closing
  399. //
  400. /*
  401. if (RequiredDataNotFilledIn())
  402. {
  403. // abort this OK ... ie dont let them close
  404. SetWindowLong(hDlg, DWL_MSGRESULT, TRUE);
  405. }
  406. */
  407. }
  408. break;
  409. }
  410. break;
  411. }
  412. return 0;
  413. }
  414. INT_PTR CALLBACK CMfcExt::MfcExtDlgProc2( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  415. {
  416. switch (message)
  417. {
  418. case WM_NOTIFY:
  419. switch (((NMHDR FAR *) lParam)->code)
  420. {
  421. case PSN_APPLY:
  422. SetWindowLong(hDlg, DWL_MSGRESULT, TRUE);
  423. break;
  424. case PSN_KILLACTIVE:
  425. SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
  426. return 1;
  427. break;
  428. case PSN_RESET:
  429. SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
  430. break;
  431. }
  432. }
  433. return FALSE;
  434. }
  435. int EditControls[] =
  436. {
  437. IDC_EXT_EDIT_HOME,
  438. IDC_EXT_EDIT_TEAM
  439. };
  440. /*//$$****************************************************************
  441. //
  442. // InitializeUI
  443. //
  444. // Rearranges/Sets UI based on input params
  445. //
  446. //********************************************************************/
  447. void InitializeUI(HWND hDlg, LPWABEXTDISPLAY lpWED)
  448. {
  449. // The WAB property sheets can be readonly when opening LDAP entries,
  450. // or vCards or other things. If the READONLY flag is set, set this
  451. // prop sheets controls to readonly
  452. //
  453. int i;
  454. if(!lpWED)
  455. return;
  456. for(i=0;i<myMax;i++)
  457. {
  458. SendDlgItemMessage( hDlg, EditControls[i], EM_SETREADONLY,
  459. (WPARAM) lpWED->fReadOnly, 0);
  460. SendDlgItemMessage( hDlg, EditControls[i], EM_SETLIMITTEXT,
  461. (WPARAM) MAX_PATH-1, 0);
  462. }
  463. return;
  464. }
  465. /*//$$****************************************************************
  466. //
  467. // SetDataInUI
  468. //
  469. // Fills in the controls with data passed in by the WAB
  470. //
  471. //********************************************************************/
  472. void SetDataInUI(HWND hDlg, LPWABEXTDISPLAY lpWED)
  473. {
  474. // Search for our private named properties and set them in the UI
  475. //
  476. ULONG ulcPropCount = 0;
  477. LPSPropValue lpPropArray = NULL;
  478. ULONG i = 0, j =0;
  479. if(!lpWED)
  480. return;
  481. // Get all the props from this object - one can also selectively
  482. // ask for specific props by passing in an SPropTagArray
  483. //
  484. if(!HR_FAILED(lpWED->lpPropObj->GetProps(NULL, 0,
  485. &ulcPropCount,
  486. &lpPropArray)))
  487. {
  488. if(ulcPropCount && lpPropArray)
  489. {
  490. for(i=0;i<ulcPropCount;i++)
  491. {
  492. for(j=0;j<myMax;j++)
  493. {
  494. if(lpPropArray[i].ulPropTag == MyPropTags[j])
  495. {
  496. SetWindowText( GetDlgItem(hDlg, EditControls[j]),
  497. lpPropArray[i].Value.LPSZ);
  498. break;
  499. }
  500. }
  501. }
  502. }
  503. }
  504. if(lpPropArray)
  505. lpWED->lpWABObject->FreeBuffer(lpPropArray);
  506. return;
  507. }
  508. /*//$$****************************************************************
  509. //
  510. // GetDataFromUI
  511. //
  512. // Retrieves data from the UI and passes back to the WAB
  513. //
  514. //********************************************************************/
  515. BOOL GetDataFromUI(HWND hDlg, LPWABEXTDISPLAY lpWED)
  516. {
  517. TCHAR szData[myMax][MAX_PATH];
  518. int i;
  519. ULONG ulIndex = 0;
  520. ULONG ulcPropCount = 0;
  521. LPSPropValue lpPropArray = NULL;
  522. SCODE sc;
  523. BOOL bRet = FALSE;
  524. // Did any data change that we have to care about ?
  525. // If nothing changed, old data will be retained by WAB
  526. //
  527. if(!lpWED->fDataChanged)
  528. return TRUE;
  529. // Check if we have any data to save ...
  530. for(i=0;i<myMax;i++)
  531. {
  532. *(szData[i]) = '\0';
  533. GetWindowText(GetDlgItem(hDlg, EditControls[i]), szData[i], MAX_PATH);
  534. if(lstrlen(szData[i]))
  535. ulcPropCount++;
  536. }
  537. if(!ulcPropCount) // no data
  538. return TRUE;
  539. // Else data exists. Create a return prop array to pass back to the WAB
  540. sc = lpWED->lpWABObject->AllocateBuffer(sizeof(SPropValue) * ulcPropCount,
  541. (LPVOID *)&lpPropArray);
  542. if (sc!=S_OK)
  543. goto out;
  544. for(i=0;i<myMax;i++)
  545. {
  546. int nLen = lstrlen(szData[i]);
  547. if(nLen)
  548. {
  549. lpPropArray[ulIndex].ulPropTag = MyPropTags[i];
  550. sc = lpWED->lpWABObject->AllocateMore( nLen+1, lpPropArray,
  551. (LPVOID *)&(lpPropArray[ulIndex].Value.LPSZ));
  552. if (sc!=S_OK)
  553. goto out;
  554. lstrcpy(lpPropArray[ulIndex].Value.LPSZ,szData[i]);
  555. ulIndex++;
  556. }
  557. }
  558. // Set this new data on the object
  559. //
  560. if(HR_FAILED(lpWED->lpPropObj->SetProps( ulcPropCount, lpPropArray, NULL)))
  561. goto out;
  562. // ** Important - do not call SaveChanges on the object
  563. // SaveChanges makes persistent changes and may modify/lose data if called at this point
  564. // The WAB will determine if its appropriate or not to call SaveChanges after the
  565. // ** user has closed the property sheets
  566. bRet = TRUE;
  567. out:
  568. if(lpPropArray)
  569. lpWED->lpWABObject->FreeBuffer(lpPropArray);
  570. return bRet;
  571. }
  572. /*//$$****************************************************************
  573. //
  574. // UpdateDisplayNameInfo
  575. //
  576. // Demonstrates how to read information from other sibling property
  577. // sheets when the user switches between pages
  578. //
  579. // This demo function attempts to get the updated display name info
  580. // when the user switches to this page in the UI
  581. //
  582. //********************************************************************/
  583. const SizedSPropTagArray(1, ptaName)=
  584. {
  585. 1,
  586. {
  587. PR_DISPLAY_NAME
  588. }
  589. };
  590. void UpdateDisplayNameInfo(HWND hDlg, LPWABEXTDISPLAY lpWED)
  591. {
  592. //
  593. // Scan all the updated information from all the other property sheets
  594. //
  595. ULONG i = 0, j=0;
  596. LPTSTR lpName = NULL;
  597. ULONG ulcPropCount = 0;
  598. LPSPropValue lpPropArray = NULL;
  599. if(!lpWED)
  600. return;
  601. // Each sheet should update its data on the object when it looses
  602. // focus and gets the PSN_KILLACTIVE message, provided the user has
  603. // made any changes. We just scan the object for the desired properties
  604. // and use them.
  605. // Ask only for the display name
  606. if(!HR_FAILED(lpWED->lpPropObj->GetProps( (LPSPropTagArray) &ptaName,
  607. 0,
  608. &ulcPropCount, &lpPropArray)))
  609. {
  610. if( ulcPropCount == 1 &&
  611. PROP_TYPE(lpPropArray[0].ulPropTag) == PT_TSTRING) // The call could succeed but there may be no DN
  612. { // in which case the PROP_TYPE will be PR_NULL
  613. lpName = lpPropArray[0].Value.LPSZ;
  614. }
  615. }
  616. if(lpName && lstrlen(lpName))
  617. SetDlgItemText(hDlg, IDC_STATIC_NAME, lpName);
  618. if(ulcPropCount && lpPropArray)
  619. lpWED->lpWABObject->FreeBuffer(lpPropArray);
  620. return;
  621. }
  622. /*//$$*********************************************************************
  623. //
  624. // UpdateOldPropTagsArray
  625. //
  626. // When we update the data on a particular property sheet, we want to update
  627. // all the properties related to that particular sheet. Since some properties
  628. // may have been deleted from the UI, we delete all relevant properties from
  629. // the property object
  630. //
  631. //**************************************************************************/
  632. BOOL UpdateOldPropTagsArray(LPWABEXTDISPLAY lpWED)
  633. {
  634. LPSPropTagArray lpPTA = NULL;
  635. SCODE sc = 0;
  636. int i =0;
  637. sc = lpWED->lpWABObject->AllocateBuffer(sizeof(SPropTagArray) + sizeof(ULONG)*(myMax),
  638. (LPVOID *)&lpPTA);
  639. if(!lpPTA || sc!=S_OK)
  640. return FALSE;
  641. lpPTA->cValues = myMax;
  642. for(i=0;i<myMax;i++)
  643. lpPTA->aulPropTag[i] = MyPropTags[i];
  644. // Delete any props in the original that may have been modified on this propsheet
  645. lpWED->lpPropObj->DeleteProps(lpPTA, NULL);
  646. if(lpPTA)
  647. lpWED->lpWABObject->FreeBuffer(lpPTA);
  648. return TRUE;
  649. }
  650. /*//$$*********************************************************************
  651. //
  652. // bUpdatePropSheetData
  653. //
  654. // We delete any properties relevant to us from the object, and set new
  655. // data from the property sheet onto the object
  656. //
  657. ****************************************************************************/
  658. BOOL bUpdatePropSheetData(HWND hDlg, LPWABEXTDISPLAY lpWED)
  659. {
  660. BOOL bRet = TRUE;
  661. if(!lpWED)
  662. return bRet;
  663. // ****Dont**** do anything if this is a READ_ONLY operation
  664. // In that case the memory variables are not all set up and this
  665. // prop sheet is not expected to return anything at all
  666. //
  667. if(!lpWED->fReadOnly)
  668. {
  669. // Delete old
  670. if(!UpdateOldPropTagsArray(lpWED))
  671. return FALSE;
  672. bRet = GetDataFromUI(hDlg, lpWED);
  673. }
  674. return bRet;
  675. }
  676. STDMETHODIMP CMfcExt::XMfcExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  677. {
  678. METHOD_PROLOGUE(CMfcExt, MfcExt);
  679. TRACE("CMfcExt::XMfcExt::AddPages\n");
  680. if(pThis->m_lpWED->fReadOnly)
  681. return NOERROR;
  682. PROPSHEETPAGE psp;
  683. hinstApp = AfxGetResourceHandle();
  684. psp.dwSize = sizeof(psp); // no extra data
  685. psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE ;
  686. psp.hInstance = hinstApp;
  687. psp.lParam = (LPARAM) &(pThis->m_lpWED);
  688. psp.pcRefParent = (UINT *)&(pThis->m_cRefThisDll);
  689. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP);
  690. psp.pfnDlgProc = pThis->MfcExtDlgProc;
  691. psp.pszTitle = "WAB Ext 1"; // Title for your tab
  692. pThis->m_hPage1 = ::CreatePropertySheetPage(&psp);
  693. if (pThis->m_hPage1)
  694. {
  695. if (!lpfnAddPage(pThis->m_hPage1, lParam))
  696. ::DestroyPropertySheetPage(pThis->m_hPage1);
  697. }
  698. // create another one, just for kicks
  699. psp.pfnDlgProc = pThis->MfcExtDlgProc2;
  700. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP2);
  701. psp.pszTitle = "WAB Ext 2";
  702. pThis->m_hPage2 = ::CreatePropertySheetPage(&psp);
  703. if (pThis->m_hPage2)
  704. {
  705. if (!lpfnAddPage(pThis->m_hPage2, lParam))
  706. ::DestroyPropertySheetPage(pThis->m_hPage2);
  707. }
  708. return NOERROR;
  709. }
  710. STDMETHODIMP CMfcExt::XContextMenuExt::QueryInterface(REFIID riid, void** ppv)
  711. {
  712. METHOD_PROLOGUE(CMfcExt, ContextMenuExt);
  713. TRACE("CMfcExt::XContextMenuExt::QueryInterface\n");
  714. return pThis->ExternalQueryInterface(&riid, ppv);
  715. }
  716. STDMETHODIMP_(ULONG) CMfcExt::XContextMenuExt::AddRef(void)
  717. {
  718. METHOD_PROLOGUE(CMfcExt, ContextMenuExt);
  719. return pThis->ExternalAddRef();
  720. }
  721. STDMETHODIMP_(ULONG) CMfcExt::XContextMenuExt::Release(void)
  722. {
  723. METHOD_PROLOGUE(CMfcExt, ContextMenuExt);
  724. return pThis->ExternalRelease();
  725. }
  726. STDMETHODIMP CMfcExt::XContextMenuExt::GetCommandString(UINT idCmd,UINT uFlags,UINT *pwReserved,LPSTR pszName,UINT cchMax)
  727. {
  728. if(uFlags & GCS_HELPTEXT)
  729. {
  730. switch (idCmd)
  731. {
  732. case 0:
  733. lstrcpy(pszName,"Collects E-Mail Addresses from selected entries.");
  734. break;
  735. case 1:
  736. lstrcpy(pszName,"Launches the Calculator (disabled when multiple entries are selected)");
  737. break;
  738. case 2:
  739. lstrcpy(pszName,"Launches Notepad (ignores WAB altogether).");
  740. break;
  741. }
  742. }
  743. return S_OK;
  744. }
  745. STDMETHODIMP CMfcExt::XContextMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
  746. {
  747. METHOD_PROLOGUE(CMfcExt, ContextMenuExt);
  748. LPWABEXTDISPLAY lpWEC = pThis->m_lpWEDContext;
  749. LPADRLIST lpAdrList = NULL;
  750. int nCmdId = (int) lpici->lpVerb;
  751. if(!lpWEC || !(lpWEC->ulFlags & WAB_CONTEXT_ADRLIST))
  752. return E_FAIL;
  753. lpAdrList = (LPADRLIST) lpWEC->lpv;
  754. switch(nCmdId)
  755. {
  756. case 0:
  757. {
  758. if(!lpAdrList || !lpAdrList->cEntries)
  759. {
  760. AfxMessageBox("Please select some entries first", MB_OK, 0);
  761. return E_FAIL;
  762. }
  763. CDlgContext DlgContext;
  764. DlgContext.m_lpAdrList = lpAdrList;
  765. DlgContext.DoModal();
  766. }
  767. break;
  768. case 1:
  769. ShellExecute(lpici->hwnd, "open", "calc.exe", NULL, NULL, SW_RESTORE);
  770. break;
  771. case 2:
  772. ShellExecute(lpici->hwnd, "open", "notepad.exe", NULL, NULL, SW_RESTORE);
  773. break;
  774. }
  775. return S_OK;
  776. }
  777. STDMETHODIMP CMfcExt::XContextMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
  778. {
  779. METHOD_PROLOGUE(CMfcExt, ContextMenuExt);
  780. LPWABEXTDISPLAY lpWEC = pThis->m_lpWEDContext;
  781. UINT idCmd = idCmdFirst;
  782. BOOL bAppendItems=TRUE, bMultiSelected = FALSE;
  783. UINT nNumCmd = 0;
  784. if(lpWEC && lpWEC->lpv)
  785. bMultiSelected = (((LPADRLIST)(lpWEC->lpv))->cEntries > 1);
  786. InsertMenu( hMenu, indexMenu++,
  787. MF_STRING | MF_BYPOSITION,
  788. idCmd++,
  789. "E-Mail Collecter");
  790. InsertMenu( hMenu, indexMenu++,
  791. MF_STRING | MF_BYPOSITION | (bMultiSelected ? MF_GRAYED : 0),
  792. idCmd++,
  793. "Calculator");
  794. InsertMenu( hMenu, indexMenu++,
  795. MF_STRING | MF_BYPOSITION,
  796. idCmd++,
  797. "Notepad");
  798. return (idCmd-idCmdFirst); //Must return number of menu
  799. }
  800. /////////////////////////////////////////////////////////////////////////////
  801. // CDlgContext dialog
  802. CDlgContext::CDlgContext(CWnd* pParent /*=NULL*/)
  803. : CDialog(CDlgContext::IDD, pParent)
  804. {
  805. //{{AFX_DATA_INIT(CDlgContext)
  806. // NOTE: the ClassWizard will add member initialization here
  807. //}}AFX_DATA_INIT
  808. }
  809. void CDlgContext::DoDataExchange(CDataExchange* pDX)
  810. {
  811. CDialog::DoDataExchange(pDX);
  812. //{{AFX_DATA_MAP(CDlgContext)
  813. // NOTE: the ClassWizard will add DDX and DDV calls here
  814. //}}AFX_DATA_MAP
  815. }
  816. BEGIN_MESSAGE_MAP(CDlgContext, CDialog)
  817. //{{AFX_MSG_MAP(CDlgContext)
  818. //}}AFX_MSG_MAP
  819. END_MESSAGE_MAP()
  820. /////////////////////////////////////////////////////////////////////////////
  821. // CDlgContext message handlers
  822. BOOL CDlgContext::OnInitDialog()
  823. {
  824. CDialog::OnInitDialog();
  825. CListBox * pListBox = (CListBox *) GetDlgItem(IDC_LIST_EMAIL);
  826. ULONG i = 0,j=0;
  827. for(i=0;i<m_lpAdrList->cEntries;i++)
  828. {
  829. LPSPropValue lpProps = m_lpAdrList->aEntries[i].rgPropVals;
  830. ULONG ulcPropCount = m_lpAdrList->aEntries[i].cValues;
  831. for(j=0;j<ulcPropCount;j++)
  832. {
  833. if(lpProps[j].ulPropTag == PR_EMAIL_ADDRESS)
  834. {
  835. pListBox->AddString(lpProps[j].Value.LPSZ);
  836. break;
  837. }
  838. }
  839. }
  840. return TRUE; // return TRUE unless you set the focus to a control
  841. // EXCEPTION: OCX Property Pages should return FALSE
  842. }