Source code of Windows XP (NT5)
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.

971 lines
32 KiB

  1. /*
  2. * OLE2UI.C
  3. *
  4. * Contains initialization routines and miscellaneous API implementations for
  5. * the OLE 2.0 User Interface Support Library.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  8. */
  9. #define STRICT 1
  10. #include "ole2ui.h"
  11. #include "common.h"
  12. #include "utility.h"
  13. #include "resimage.h"
  14. #include "iconbox.h"
  15. #include <commdlg.h>
  16. #define WINDLL 1 // make far pointer version of stdargs.h
  17. #include <stdarg.h>
  18. // NOTE: If this code is being compiled for a DLL, then we need to define
  19. // our OLE2UI debug symbols here (with the OLEDBGDATA_MAIN macro). If we're
  20. // compiling for a static LIB, then the application we link to must
  21. // define these symbols -- we just need to make an external reference here
  22. // (with the macro OLEDBGDATA).
  23. #ifdef DLL_VER
  24. OLEDBGDATA_MAIN(TEXT("OLE2UI"))
  25. #else
  26. OLEDBGDATA
  27. #endif
  28. //The DLL instance handle shared amongst all dialogs.
  29. HINSTANCE ghInst;
  30. //Registered messages for use with all the dialogs, registered in LibMain
  31. UINT uMsgHelp=0;
  32. UINT uMsgEndDialog=0;
  33. UINT uMsgBrowse=0;
  34. UINT uMsgChangeIcon=0;
  35. UINT uMsgFileOKString=0;
  36. UINT uMsgCloseBusyDlg=0;
  37. //Clipboard formats used by PasteSpecial
  38. UINT cfObjectDescriptor;
  39. UINT cfLinkSrcDescriptor;
  40. UINT cfEmbedSource;
  41. UINT cfEmbeddedObject;
  42. UINT cfLinkSource;
  43. UINT cfOwnerLink;
  44. UINT cfFileName;
  45. // local function prototypes
  46. BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
  47. BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
  48. // local definition
  49. #define WM_U_UPDATELINK WM_USER
  50. // local structure definition
  51. typedef struct tagUPDATELINKS
  52. {
  53. LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container
  54. UINT cLinks; // total number of links
  55. UINT cUpdated; // number of links updated
  56. DWORD dwLink; // pointer to link
  57. BOOL fError; // error flag
  58. LPTSTR lpszTitle; // caption for dialog box
  59. } UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS;
  60. /*
  61. * OleUIInitialize
  62. *
  63. * NOTE: This function should only be called by your application IF it is
  64. * using the static-link version of this library. If the DLL version is
  65. * being used, this function is automatically called from the OLE2UI DLL's
  66. * LibMain.
  67. *
  68. * Purpose:
  69. * Initializes the OLE UI Library. Registers the OLE clipboard formats
  70. * used in the Paste Special dialog, registers private custom window
  71. * messages, and registers window classes of the "Result Image"
  72. * and "Icon Box" custom controls used in the UI dialogs.
  73. *
  74. * Parameters:
  75. *
  76. * hInstance HINSTANCE of the module where the UI library resources
  77. * and Dialog Procedures are contained. If you are calling
  78. * this function yourself, this should be the instance handle
  79. * of your application.
  80. *
  81. * hPrevInst HINSTANCE of the previous application instance.
  82. * This is the parameter passed in to your WinMain. For
  83. * the DLL version, this should always be set to zero (for
  84. * WIN16 DLLs).
  85. *
  86. * lpszClassIconBox
  87. * LPTSTR containing the name you assigned to the symbol
  88. * SZCLASSICONBOX (this symbol is defined in UICLASS.H
  89. * which is generated in the MAKEFILE).
  90. *
  91. * This name is used as the window class name
  92. * when registering the IconBox custom control used in the
  93. * UI dialogs. In order to handle mutliple apps running
  94. * with this library, you must make this name unique to your
  95. * application.
  96. *
  97. * For the DLL version: Do NOT call this function directly
  98. * from your application, it is called automatically from
  99. * the DLL's LibMain.
  100. *
  101. * For the static library version: This should be set to
  102. * the symbol SZCLASSICONBOX. This symbol is defined in
  103. * UICLASS.H.
  104. *
  105. * lpszClassResImage
  106. * LPTSTR containing the name you assigned to the symbol
  107. * SZCLASSRESULTIMAGE. See the description of
  108. * lpszClassIconBox above for more info.
  109. *
  110. * Return Value:
  111. * BOOL TRUE if initialization was successful.
  112. * FALSE if either the "Magic Number" did not verify, or one of
  113. * the window classes could not be registered. If the
  114. * "Magic Number" did not verify, then the resources
  115. * in your module are of a different version than the
  116. * ones you compiled with.
  117. */
  118. STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance,
  119. HINSTANCE hPrevInst,
  120. LPTSTR lpszClassIconBox,
  121. LPTSTR lpszClassResImage)
  122. {
  123. HRSRC hr;
  124. HGLOBAL hg;
  125. LPWORD lpdata;
  126. OleDbgOut1(TEXT("OleUIInitialize called.\r\n"));
  127. ghInst=hInstance;
  128. // Verify that we have the correct resources added to our application
  129. // by checking the "VERIFICATION" resource with the magic number we've
  130. // compiled into our app.
  131. OutputDebugString(TEXT("Entering OleUIInitialize\n"));
  132. if ((hr = FindResource(hInstance, TEXT("VERIFICATION"), RT_RCDATA)) == NULL)
  133. goto ResourceLoadError;
  134. if ((hg = LoadResource(hInstance, hr)) == NULL)
  135. goto ResourceLoadError;
  136. if ((lpdata = (LPWORD)LockResource(hg)) == NULL)
  137. goto ResourceLockError;
  138. if ((WORD)*lpdata != (WORD)OLEUI_VERSION_MAGIC)
  139. goto ResourceReadError;
  140. // OK, resource versions match. Contine on.
  141. UnlockResource(hg);
  142. FreeResource(hg);
  143. OleDbgOut1(TEXT("OleUIInitialize: Resource magic number verified.\r\n"));
  144. // Register messages we need for the dialogs. If
  145. uMsgHelp =RegisterWindowMessage(SZOLEUI_MSG_HELP);
  146. uMsgEndDialog =RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG);
  147. uMsgBrowse =RegisterWindowMessage(SZOLEUI_MSG_BROWSE);
  148. uMsgChangeIcon=RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON);
  149. uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING);
  150. uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG);
  151. // Register Clipboard Formats used by PasteSpecial dialog.
  152. cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  153. cfLinkSrcDescriptor= RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
  154. cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
  155. cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  156. cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE);
  157. cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK);
  158. cfFileName = RegisterClipboardFormat(CF_FILENAME);
  159. if (!FResultImageInitialize(hInstance, hPrevInst, lpszClassResImage))
  160. {
  161. OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n"));
  162. return 0;
  163. }
  164. if (!FIconBoxInitialize(hInstance, hPrevInst, lpszClassIconBox))
  165. {
  166. OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n"));
  167. return 0;
  168. }
  169. return TRUE;
  170. ResourceLoadError:
  171. OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to find version verification resource.\r\n"));
  172. return FALSE;
  173. ResourceLockError:
  174. OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to lock version verification resource.\r\n"));
  175. FreeResource(hg);
  176. return FALSE;
  177. ResourceReadError:
  178. OleDbgOut1(TEXT("OleUIInitialize: ERROR - Version verification values did not compare.\r\n"));
  179. {TCHAR buf[255];
  180. wsprintf(buf, TEXT("resource read 0x%X, my value is 0x%X\n"), (WORD)*lpdata, (WORD)OLEUI_VERSION_MAGIC);
  181. OutputDebugString(buf);
  182. }
  183. UnlockResource(hg);
  184. FreeResource(hg);
  185. return FALSE;
  186. }
  187. /*
  188. * OleUIUnInitialize
  189. *
  190. * NOTE: This function should only be called by your application IF it is using
  191. * the static-link version of this library. If the DLL version is being used,
  192. * this function is automatically called from the DLL's LibMain.
  193. *
  194. * Purpose:
  195. * Uninitializes OLE UI libraries. Deletes any resources allocated by the
  196. * library.
  197. *
  198. * Return Value:
  199. * BOOL TRUE if successful, FALSE if not. Current implementation always
  200. * returns TRUE.
  201. */
  202. STDAPI_(BOOL) OleUIUnInitialize()
  203. {
  204. IconBoxUninitialize();
  205. ResultImageUninitialize();
  206. return TRUE;
  207. }
  208. /*
  209. * OleUIAddVerbMenu
  210. *
  211. * Purpose:
  212. * Add the Verb menu for the specified object to the given menu. If the
  213. * object has one verb, we directly add the verb to the given menu. If
  214. * the object has multiple verbs we create a cascading sub-menu.
  215. *
  216. * Parameters:
  217. * lpObj LPOLEOBJECT pointing to the selected object. If this
  218. * is NULL, then we create a default disabled menu item.
  219. *
  220. * lpszShortType LPTSTR with short type name (AuxName==2) corresponding
  221. * to the lpOleObj. if the string is NOT known, then NULL
  222. * may be passed. if NULL is passed, then
  223. * IOleObject::GetUserType will be called to retrieve it.
  224. * if the caller has the string handy, then it is faster
  225. * to pass it in.
  226. *
  227. * hMenu HMENU in which to make modifications.
  228. *
  229. * uPos Position of the menu item
  230. *
  231. * uIDVerbMin UINT ID value at which to start the verbs.
  232. * verb_0 = wIDMVerbMin + verb_0
  233. * verb_1 = wIDMVerbMin + verb_1
  234. * verb_2 = wIDMVerbMin + verb_2
  235. * etc.
  236. * uIDVerbMax UINT maximum ID value allowed for object verbs.
  237. * if uIDVerbMax==0 then any ID value is allowed
  238. *
  239. * bAddConvert BOOL specifying whether or not to add a "Convert" item
  240. * to the bottom of the menu (with a separator).
  241. *
  242. * idConvert UINT ID value to use for the Convert menu item, if
  243. * bAddConvert is TRUE.
  244. *
  245. * lphMenu HMENU FAR * of the cascading verb menu if it's created.
  246. * If there is only one verb, this will be filled with NULL.
  247. *
  248. *
  249. * Return Value:
  250. * BOOL TRUE if lpObj was valid and we added at least one verb
  251. * to the menu. FALSE if lpObj was NULL and we created
  252. * a disabled default menu item
  253. */
  254. STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj,
  255. LPTSTR lpszShortType,
  256. HMENU hMenu,
  257. UINT uPos,
  258. UINT uIDVerbMin,
  259. UINT uIDVerbMax,
  260. BOOL bAddConvert,
  261. UINT idConvert,
  262. HMENU FAR *lphMenu)
  263. {
  264. LPPERSISTSTORAGE lpPS=NULL;
  265. LPENUMOLEVERB lpEnumOleVerb = NULL;
  266. OLEVERB oleverb;
  267. LPUNKNOWN lpUnk;
  268. LPTSTR lpszShortTypeName = lpszShortType;
  269. LPTSTR lpszVerbName = NULL;
  270. HRESULT hrErr;
  271. BOOL fStatus;
  272. BOOL fIsLink = FALSE;
  273. BOOL fResult = TRUE;
  274. BOOL fAddConvertItem = FALSE;
  275. int cVerbs = 0;
  276. UINT uFlags = MF_BYPOSITION;
  277. static BOOL fFirstTime = TRUE;
  278. static TCHAR szBuffer[OLEUI_OBJECTMENUMAX];
  279. static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX];
  280. static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX];
  281. static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX];
  282. static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX];
  283. static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX];
  284. static TCHAR szUnknown[OLEUI_OBJECTMENUMAX];
  285. static TCHAR szEdit[OLEUI_OBJECTMENUMAX];
  286. static TCHAR szConvert[OLEUI_OBJECTMENUMAX];
  287. *lphMenu=NULL;
  288. // Set fAddConvertItem flag
  289. if (bAddConvert & (idConvert != 0))
  290. fAddConvertItem = TRUE;
  291. // only need to load the strings the 1st time
  292. if (fFirstTime) {
  293. if (0 == LoadString(ghInst, IDS_OLE2UIEDITNOOBJCMD,
  294. (LPTSTR)szNoObjectCmd, OLEUI_OBJECTMENUMAX))
  295. return FALSE;
  296. if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_1VERB,
  297. (LPTSTR)szLinkCmd1Verb, OLEUI_OBJECTMENUMAX))
  298. return FALSE;
  299. if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_1VERB,
  300. (LPTSTR)szObjectCmd1Verb, OLEUI_OBJECTMENUMAX))
  301. return FALSE;
  302. if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_NVERB,
  303. (LPTSTR)szLinkCmdNVerb, OLEUI_OBJECTMENUMAX))
  304. return FALSE;
  305. if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_NVERB,
  306. (LPTSTR)szObjectCmdNVerb, OLEUI_OBJECTMENUMAX))
  307. return FALSE;
  308. if (0 == LoadString(ghInst, IDS_OLE2UIUNKNOWN,
  309. (LPTSTR)szUnknown, OLEUI_OBJECTMENUMAX))
  310. return FALSE;
  311. if (0 == LoadString(ghInst, IDS_OLE2UIEDIT,
  312. (LPTSTR)szEdit, OLEUI_OBJECTMENUMAX))
  313. return FALSE;
  314. if ( (0 == LoadString(ghInst, IDS_OLE2UICONVERT,
  315. (LPTSTR)szConvert, OLEUI_OBJECTMENUMAX)) && fAddConvertItem)
  316. return FALSE;
  317. fFirstTime = FALSE;
  318. }
  319. // Delete whatever menu may happen to be here already.
  320. DeleteMenu(hMenu, uPos, uFlags);
  321. if (!lpOleObj)
  322. goto AVMError;
  323. if (! lpszShortTypeName) {
  324. // get the Short form of the user type name for the menu
  325. OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n"))
  326. hrErr = CallIOleObjectGetUserTypeA(
  327. lpOleObj,
  328. USERCLASSTYPE_SHORT,
  329. (LPTSTR FAR*)&lpszShortTypeName
  330. );
  331. OLEDBG_END2
  332. if (NOERROR != hrErr) {
  333. OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr);
  334. }
  335. }
  336. // check if the object is a link (it is a link if it support IOleLink)
  337. hrErr = lpOleObj->lpVtbl->QueryInterface(
  338. lpOleObj,
  339. &IID_IOleLink,
  340. (LPVOID FAR*)&lpUnk
  341. );
  342. if (NOERROR == hrErr) {
  343. fIsLink = TRUE;
  344. OleStdRelease(lpUnk);
  345. }
  346. // Get the verb enumerator from the OLE object
  347. OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n"))
  348. hrErr = lpOleObj->lpVtbl->EnumVerbs(
  349. lpOleObj,
  350. (LPENUMOLEVERB FAR*)&lpEnumOleVerb
  351. );
  352. OLEDBG_END2
  353. if (NOERROR != hrErr) {
  354. OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr);
  355. }
  356. if (!(*lphMenu = CreatePopupMenu()))
  357. goto AVMError;
  358. // loop through all verbs
  359. while (lpEnumOleVerb != NULL) { // forever
  360. hrErr = lpEnumOleVerb->lpVtbl->Next(
  361. lpEnumOleVerb,
  362. 1,
  363. (LPOLEVERB)&oleverb,
  364. NULL
  365. );
  366. if (NOERROR != hrErr)
  367. break; // DONE! no more verbs
  368. /* OLE2NOTE: negative verb numbers and verbs that do not
  369. ** indicate ONCONTAINERMENU should NOT be put on the verb menu
  370. */
  371. if (oleverb.lVerb < 0 ||
  372. ! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) {
  373. /* OLE2NOTE: we must still free the verb name string */
  374. if (oleverb.lpszVerbName)
  375. OleStdFree(oleverb.lpszVerbName);
  376. continue;
  377. }
  378. // we must free the previous verb name string
  379. if (lpszVerbName)
  380. OleStdFreeString(lpszVerbName, NULL);
  381. CopyAndFreeOLESTR(oleverb.lpszVerbName, &lpszVerbName);
  382. if ( 0 == uIDVerbMax ||
  383. (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) ) {
  384. fStatus = InsertMenu(
  385. *lphMenu,
  386. (UINT)-1,
  387. MF_BYPOSITION | (UINT)oleverb.fuFlags,
  388. uIDVerbMin+(UINT)oleverb.lVerb,
  389. (LPTSTR)lpszVerbName
  390. );
  391. if (! fStatus)
  392. goto AVMError;
  393. cVerbs++;
  394. }
  395. }
  396. // Add the separator and "Convert" menu item.
  397. if (fAddConvertItem) {
  398. if (0 == cVerbs) {
  399. LPTSTR lpsz;
  400. // if object has no verbs, then use "Convert" as the obj's verb
  401. lpsz = lpszVerbName = OleStdCopyString(szConvert, NULL);
  402. uIDVerbMin = idConvert;
  403. // remove "..." from "Convert..." string; it will be added later
  404. if (lpsz) {
  405. while(*lpsz && *lpsz != TEXT('.'))
  406. lpsz++;
  407. *lpsz = TEXT('\0');
  408. }
  409. }
  410. if (cVerbs > 0) {
  411. fStatus = InsertMenu(*lphMenu,
  412. (UINT)-1,
  413. MF_BYPOSITION | MF_SEPARATOR,
  414. (UINT)0,
  415. (LPCTSTR)NULL);
  416. if (! fStatus)
  417. goto AVMError;
  418. }
  419. /* add convert menu */
  420. fStatus = InsertMenu(*lphMenu,
  421. (UINT)-1,
  422. MF_BYPOSITION,
  423. idConvert,
  424. (LPCTSTR)szConvert);
  425. if (! fStatus)
  426. goto AVMError;
  427. cVerbs++;
  428. }
  429. /*
  430. * Build the appropriate menu based on the number of verbs found
  431. *
  432. * NOTE: Localized verb menus may require a different format.
  433. * to assist in localization of the single verb case, the
  434. * szLinkCmd1Verb and szObjectCmd1Verb format strings start
  435. * with either a '0' (note: NOT '\0'!) or a '1':
  436. * leading '0' -- verb type
  437. * leading '1' -- type verb
  438. */
  439. if (cVerbs == 0) {
  440. // there are NO verbs (not even Convert...). set the menu to be
  441. // "<short type> &Object/Link" and gray it out.
  442. wsprintf(
  443. szBuffer,
  444. (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb),
  445. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
  446. );
  447. uFlags |= MF_GRAYED;
  448. #if defined( OBSOLETE )
  449. //No verbs. Create a default using Edit as the verb.
  450. LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
  451. if (*lpsz == TEXT('0')) {
  452. wsprintf(szBuffer, lpsz+1, (LPSTR)szEdit,
  453. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
  454. );
  455. }
  456. else {
  457. wsprintf(szBuffer, lpsz+1,
  458. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")),
  459. (LPTSTR)szEdit
  460. );
  461. }
  462. #endif
  463. fResult = FALSE;
  464. DestroyMenu(*lphMenu);
  465. *lphMenu = NULL;
  466. }
  467. else if (cVerbs == 1) {
  468. //One verb without Convert, one item.
  469. LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
  470. if (*lpsz == TEXT('0')) {
  471. wsprintf(szBuffer, lpsz+1, lpszVerbName,
  472. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
  473. );
  474. }
  475. else {
  476. wsprintf(szBuffer, lpsz+1,
  477. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")),
  478. lpszVerbName
  479. );
  480. }
  481. // if only "verb" is "Convert..." then append the ellipses
  482. if (fAddConvertItem)
  483. lstrcat(szBuffer, TEXT("..."));
  484. DestroyMenu(*lphMenu);
  485. *lphMenu=NULL;
  486. }
  487. else {
  488. //Multiple verbs or one verb with Convert, add the cascading menu
  489. wsprintf(
  490. szBuffer,
  491. (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb),
  492. (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
  493. );
  494. uFlags |= MF_ENABLED | MF_POPUP;
  495. uIDVerbMin=(UINT)*lphMenu;
  496. }
  497. if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, (LPTSTR)szBuffer))
  498. AVMError:
  499. {
  500. InsertMenu(hMenu, uPos, MF_GRAYED | uFlags,
  501. uIDVerbMin, (LPTSTR)szNoObjectCmd);
  502. #if defined( OBSOLETE )
  503. HMENU hmenuDummy = CreatePopupMenu();
  504. InsertMenu(hMenu, uPos, MF_GRAYED | MF_POPUP | uFlags,
  505. (UINT)hmenuDummy, (LPTSTR)szNoObjectCmd);
  506. #endif
  507. fResult = FALSE;
  508. }
  509. if (lpszVerbName)
  510. OleStdFreeString(lpszVerbName, NULL);
  511. if (!lpszShortType && lpszShortTypeName)
  512. OleStdFreeString(lpszShortTypeName, NULL);
  513. if (lpEnumOleVerb)
  514. lpEnumOleVerb->lpVtbl->Release(lpEnumOleVerb);
  515. return fResult;
  516. }
  517. /* PromptUserDlgProc
  518. * -----------------
  519. *
  520. * Purpose:
  521. * Dialog procedure used by OleUIPromptUser(). Returns when a button is
  522. * clicked in the dialog box and the button id is return.
  523. *
  524. * Parameters:
  525. * hDlg
  526. * iMsg
  527. * wParam
  528. * lParam
  529. *
  530. * Returns:
  531. *
  532. */
  533. BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  534. {
  535. switch (iMsg) {
  536. case WM_INITDIALOG:
  537. {
  538. LPTSTR lpszTitle;
  539. TCHAR szBuf[256];
  540. TCHAR szFormat[256];
  541. va_list *parglist;
  542. if (!lParam) {
  543. EndDialog(hDlg, -1);
  544. return FALSE;
  545. }
  546. //
  547. // lParam is really a va_list *. We called va_start and va_end in
  548. // the function that calls this.
  549. //
  550. parglist = (va_list *) lParam;
  551. lpszTitle = va_arg(*parglist, LPTSTR);
  552. SetWindowText(hDlg, lpszTitle);
  553. GetDlgItemText(hDlg, ID_PU_TEXT,(LPTSTR)szFormat,sizeof(szFormat)/sizeof(TCHAR));
  554. wvsprintf((LPTSTR)szBuf, (LPTSTR)szFormat, *parglist);
  555. SetDlgItemText(hDlg, ID_PU_TEXT, (LPTSTR)szBuf);
  556. return TRUE;
  557. }
  558. case WM_COMMAND:
  559. EndDialog(hDlg, wParam);
  560. return TRUE;
  561. default:
  562. return FALSE;
  563. }
  564. }
  565. /* OleUIPromptUser
  566. * ---------------
  567. *
  568. * Purpose:
  569. * Popup a dialog box with the specified template and returned the
  570. * response (button id) from the user.
  571. *
  572. * Parameters:
  573. * nTemplate resource number of the dialog
  574. * hwndParent parent of the dialog box
  575. * ... title of the dialog box followed by argument list
  576. * for the format string in the static control
  577. * (ID_PU_TEXT) of the dialog box.
  578. * The caller has to make sure that the correct number
  579. * and type of argument are passed in.
  580. *
  581. * Returns:
  582. * button id selected by the user (template dependent)
  583. *
  584. * Comments:
  585. * the following message dialog boxes are supported:
  586. *
  587. * IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable
  588. * VARARG Parameters:
  589. * None.
  590. * Used for the following error codes:
  591. * OLE_E_CANT_BINDTOSOURCE
  592. * STG_E_PATHNOTFOUND
  593. * (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error
  594. * any unknown error if object is a link
  595. *
  596. * IDD_SERVERNOTFOUND -- server registered but NOT found
  597. * VARARG Parameters:
  598. * LPSTR lpszUserType -- user type name of object
  599. * Used for the following error codes:
  600. * CO_E_APPNOTFOUND
  601. * CO_E_APPDIDNTREG
  602. * any unknown error if object is an embedded object
  603. *
  604. * IDD_SERVERNOTREG -- server NOT registered
  605. * VARARG Parameters:
  606. * LPSTR lpszUserType -- user type name of object
  607. * Used for the following error codes:
  608. * REGDB_E_CLASSNOTREG
  609. * OLE_E_STATIC -- static object with no server registered
  610. *
  611. * IDD_LINKTYPECHANGED -- class of link source changed since last binding
  612. * VARARG Parameters:
  613. * LPSTR lpszUserType -- user type name of ole link source
  614. * Used for the following error codes:
  615. * OLE_E_CLASSDIFF
  616. *
  617. * IDD_LINKTYPECHANGED -- class of link source changed since last binding
  618. * VARARG Parameters:
  619. * LPSTR lpszUserType -- user type name of ole link source
  620. * Used for the following error codes:
  621. * OLE_E_CLASSDIFF
  622. *
  623. * IDD_OUTOFMEMORY -- out of memory
  624. * VARARG Parameters:
  625. * None.
  626. * Used for the following error codes:
  627. * E_OUTOFMEMORY
  628. *
  629. */
  630. int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...)
  631. {
  632. int nRet;
  633. va_list arglist;
  634. LPARAM lParam;
  635. //
  636. // We want to pass the variable list of arguments to PrompUserDlgProc,
  637. // but we can't just pass arglist because arglist is not always the
  638. // same size as an LPARAM (e.g. on Alpha va_list is a structure).
  639. // So, we pass the a pointer to the arglist instead.
  640. //
  641. va_start(arglist, hwndParent);
  642. lParam = (LPARAM) &arglist;
  643. nRet = DialogBoxParam(ghInst, MAKEINTRESOURCE(nTemplate), hwndParent,
  644. PromptUserDlgProc, lParam);
  645. va_end(arglist);
  646. return nRet;
  647. }
  648. /* UpdateLinksDlgProc
  649. * ------------------
  650. *
  651. * Purpose:
  652. * Dialog procedure used by OleUIUpdateLinks(). It will enumerate all
  653. * all links in the container and updates all automatic links.
  654. * Returns when the Stop Button is clicked in the dialog box or when all
  655. * links are updated
  656. *
  657. * Parameters:
  658. * hDlg
  659. * iMsg
  660. * wParam
  661. * lParam pointer to the UPDATELINKS structure
  662. *
  663. * Returns:
  664. *
  665. */
  666. BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  667. {
  668. LPUPDATELINKS FAR* lplpUL = NULL;
  669. HANDLE gh;
  670. static BOOL fAbort = FALSE;
  671. //Process the temination message
  672. if (iMsg==uMsgEndDialog)
  673. {
  674. gh = RemoveProp(hDlg, STRUCTUREPROP);
  675. if (NULL!=gh) {
  676. GlobalUnlock(gh);
  677. GlobalFree(gh);
  678. }
  679. EndDialog(hDlg, wParam);
  680. return TRUE;
  681. }
  682. switch (iMsg) {
  683. case WM_INITDIALOG:
  684. {
  685. gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(LPUPDATELINKS));
  686. SetProp(hDlg, STRUCTUREPROP, gh);
  687. if (NULL==gh)
  688. {
  689. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
  690. return FALSE;
  691. }
  692. fAbort = FALSE;
  693. lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh);
  694. if (lplpUL) {
  695. *lplpUL = (LPUPDATELINKS)lParam;
  696. SetWindowText(hDlg, (*lplpUL)->lpszTitle);
  697. SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL);
  698. return TRUE;
  699. } else {
  700. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
  701. return FALSE;
  702. }
  703. }
  704. case WM_TIMER:
  705. KillTimer(hDlg, 1);
  706. gh = GetProp(hDlg, STRUCTUREPROP);
  707. if (NULL!=gh) {
  708. // gh was locked previously, lock and unlock to get lplpUL
  709. lplpUL = GlobalLock(gh);
  710. GlobalUnlock(gh);
  711. }
  712. if (! fAbort && lplpUL)
  713. PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL));
  714. else
  715. PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L);
  716. return 0;
  717. case WM_COMMAND: // Stop button
  718. fAbort = TRUE;
  719. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  720. return TRUE;
  721. case WM_U_UPDATELINK:
  722. {
  723. HRESULT hErr;
  724. int nPercent;
  725. RECT rc;
  726. TCHAR szPercent[5]; // 0% to 100%
  727. HBRUSH hbr;
  728. HDC hDC;
  729. HWND hwndMeter;
  730. MSG msg;
  731. DWORD dwUpdateOpt;
  732. LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam;
  733. lpUL->dwLink=lpUL->lpOleUILinkCntr->lpVtbl->GetNextLink(
  734. lpUL->lpOleUILinkCntr,
  735. lpUL->dwLink
  736. );
  737. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  738. if (! IsDialogMessage(hDlg, &msg)) {
  739. TranslateMessage(&msg);
  740. DispatchMessage(&msg);
  741. }
  742. }
  743. if (fAbort)
  744. return FALSE;
  745. if (!lpUL->dwLink) { // all links processed
  746. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  747. return TRUE;
  748. }
  749. hErr = lpUL->lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions(
  750. lpUL->lpOleUILinkCntr,
  751. lpUL->dwLink,
  752. (LPDWORD)&dwUpdateOpt
  753. );
  754. if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS)) {
  755. hErr = lpUL->lpOleUILinkCntr->lpVtbl->UpdateLink(
  756. lpUL->lpOleUILinkCntr,
  757. lpUL->dwLink,
  758. FALSE, // fMessage
  759. FALSE // ignored
  760. );
  761. lpUL->fError |= (hErr != NOERROR);
  762. lpUL->cUpdated++;
  763. nPercent = lpUL->cUpdated * 100 / lpUL->cLinks;
  764. if (nPercent <= 100) { // do NOT advance % beyond 100%
  765. // update percentage
  766. wsprintf((LPTSTR)szPercent, TEXT("%d%%"), nPercent);
  767. SetDlgItemText(hDlg, ID_PU_PERCENT, (LPTSTR)szPercent);
  768. // update indicator
  769. hwndMeter = GetDlgItem(hDlg, ID_PU_METER);
  770. GetClientRect(hwndMeter, (LPRECT)&rc);
  771. InflateRect((LPRECT)&rc, -1, -1);
  772. rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left;
  773. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  774. if (hbr) {
  775. hDC = GetDC(hwndMeter);
  776. if (hDC) {
  777. FillRect(hDC, (LPRECT)&rc, hbr);
  778. ReleaseDC(hwndMeter, hDC);
  779. }
  780. DeleteObject(hbr);
  781. }
  782. }
  783. }
  784. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  785. if (! IsDialogMessage(hDlg, &msg)) {
  786. TranslateMessage(&msg);
  787. DispatchMessage(&msg);
  788. }
  789. }
  790. PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam);
  791. return TRUE;
  792. }
  793. default:
  794. return FALSE;
  795. }
  796. }
  797. /* OleUIUpdateLink
  798. * ---------------
  799. *
  800. * Purpose:
  801. * Update all links in the Link Container and popup a dialog box which
  802. * shows the progress of the updating.
  803. * The process is stopped when the user press Stop button or when all
  804. * links are processed.
  805. *
  806. * Parameters:
  807. * lpOleUILinkCntr pointer to Link Container
  808. * hwndParent parent window of the dialog
  809. * lpszTitle title of the dialog box
  810. * cLinks total number of links
  811. *
  812. * Returns:
  813. * TRUE all links updated successfully
  814. * FALSE otherwise
  815. */
  816. STDAPI_(BOOL) OleUIUpdateLinks(LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks)
  817. {
  818. LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS));
  819. BOOL fError;
  820. OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0));
  821. OleDbgAssert(lpUL);
  822. lpUL->lpOleUILinkCntr = lpOleUILinkCntr;
  823. lpUL->cLinks = cLinks;
  824. lpUL->cUpdated = 0;
  825. lpUL->dwLink = 0;
  826. lpUL->fError = FALSE;
  827. lpUL->lpszTitle = lpszTitle;
  828. DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_UPDATELINKS),
  829. hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL);
  830. fError = lpUL->fError;
  831. OleStdFree((LPVOID)lpUL);
  832. return !fError;
  833. }