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.

1039 lines
38 KiB

  1. /*
  2. * OLE2UI.CPP
  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. #include "precomp.h"
  10. #include "common.h"
  11. #include "utility.h"
  12. #include "resimage.h"
  13. #include "iconbox.h"
  14. #include <commdlg.h>
  15. #include <stdarg.h>
  16. #include "strcache.h"
  17. OLEDBGDATA
  18. // Registered messages for use with all the dialogs, registered in LibMain
  19. UINT uMsgHelp;
  20. UINT uMsgEndDialog;
  21. UINT uMsgBrowse;
  22. UINT uMsgChangeIcon;
  23. UINT uMsgFileOKString;
  24. UINT uMsgCloseBusyDlg;
  25. UINT uMsgConvert;
  26. UINT uMsgChangeSource;
  27. UINT uMsgAddControl;
  28. UINT uMsgBrowseOFN;
  29. // local function prototypes
  30. INT_PTR CALLBACK PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
  31. INT_PTR CALLBACK UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
  32. // local definition
  33. #define WM_U_UPDATELINK (WM_USER+0x2000)
  34. #define WM_U_SHOWWINDOW (WM_USER+0x2001)
  35. // local structure definition
  36. typedef struct tagUPDATELINKS
  37. {
  38. LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container
  39. UINT cLinks; // total number of links
  40. UINT cUpdated; // number of links updated
  41. DWORD dwLink; // pointer to link
  42. BOOL fError; // error flag
  43. LPTSTR lpszTitle; // caption for dialog box
  44. } UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS;
  45. /*
  46. * OleUIInitialize
  47. *
  48. * NOTE: This function should only be called by your application IF it is
  49. * using the static-link version of this library. If the DLL version is
  50. * being used, this function is automatically called from the OLEDLG DLL's
  51. * LibMain.
  52. *
  53. * Purpose:
  54. * Initializes the OLE UI Library. Registers the OLE clipboard formats
  55. * used in the Paste Special dialog, registers private custom window
  56. * messages, and registers window classes of the "Result Image"
  57. * and "Icon Box" custom controls used in the UI dialogs.
  58. *
  59. * Parameters:
  60. *
  61. * hInstance HINSTANCE of the module where the UI library resources
  62. * and Dialog Procedures are contained. If you are calling
  63. * this function yourself, this should be the instance handle
  64. * of your application.
  65. *
  66. * hPrevInst HINSTANCE of the previous application instance.
  67. * This is the parameter passed in to your WinMain. For
  68. * the DLL version, this should always be set to zero (for
  69. * WIN16 DLLs).
  70. *
  71. * Return Value:
  72. * BOOL TRUE if initialization was successful.
  73. * FALSE otherwise.
  74. */
  75. #pragma code_seg(".text$initseg")
  76. BOOL bWin4; // TRUE if running Windows4 or greater
  77. BOOL bSharedData; // TRUE if running Win32s (it has shared data)
  78. static DWORD tlsIndex= (DWORD)-1;
  79. static TASKDATA taskData;
  80. STDAPI_(TASKDATA*) GetTaskData()
  81. {
  82. TASKDATA* pData;
  83. if (tlsIndex == (DWORD)-1)
  84. pData = &taskData;
  85. else
  86. pData = (TASKDATA*)TlsGetValue(tlsIndex);
  87. return pData;
  88. }
  89. DWORD WINAPI _AfxTlsAlloc()
  90. {
  91. DWORD dwResult = TlsAlloc();
  92. DWORD dwVersion = GetVersion();
  93. if ((dwVersion & 0x80000000) && (BYTE)dwVersion <= 3)
  94. {
  95. while (dwResult <= 2)
  96. dwResult = TlsAlloc();
  97. }
  98. return dwResult;
  99. }
  100. static int nInitCount;
  101. STDAPI_(BOOL) OleUIUnInitialize();
  102. STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance,
  103. HINSTANCE hPrevInst)
  104. {
  105. OleDbgOut1(TEXT("OleUIInitialize called.\r\n"));
  106. // Cache information about the windows version we are running
  107. DWORD dwVersion = GetVersion();
  108. bWin4 = LOBYTE(dwVersion) >= 4;
  109. bSharedData = !bWin4 && (dwVersion & 0x80000000);
  110. if (nInitCount == 0)
  111. {
  112. if (bSharedData)
  113. {
  114. // allocate thread local storage on Win32s
  115. tlsIndex = _AfxTlsAlloc();
  116. if (tlsIndex == (DWORD)-1)
  117. return FALSE;
  118. }
  119. }
  120. ++nInitCount;
  121. // Setup process local storage if necessary
  122. if (tlsIndex != (DWORD)-1)
  123. {
  124. void* pData = LocalAlloc(LPTR, sizeof(TASKDATA));
  125. if (pData == NULL)
  126. {
  127. if (nInitCount == 0)
  128. {
  129. OleUIUnInitialize();
  130. return FALSE;
  131. }
  132. }
  133. TlsSetValue(tlsIndex, pData);
  134. }
  135. // Initialize OleStd functions
  136. OleStdInitialize(hInstance, hInstance);
  137. // Register messages we need for the dialogs.
  138. uMsgHelp = RegisterWindowMessage(SZOLEUI_MSG_HELP);
  139. uMsgEndDialog = RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG);
  140. uMsgBrowse = RegisterWindowMessage(SZOLEUI_MSG_BROWSE);
  141. uMsgChangeIcon = RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON);
  142. uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING);
  143. uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG);
  144. uMsgConvert = RegisterWindowMessage(SZOLEUI_MSG_CONVERT);
  145. uMsgChangeSource = RegisterWindowMessage(SZOLEUI_MSG_CHANGESOURCE);
  146. uMsgAddControl = RegisterWindowMessage(SZOLEUI_MSG_ADDCONTROL);
  147. uMsgBrowseOFN = RegisterWindowMessage(SZOLEUI_MSG_BROWSE_OFN);
  148. if (!FResultImageInitialize(hInstance, hPrevInst))
  149. {
  150. OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n"));
  151. return 0;
  152. }
  153. if (!FIconBoxInitialize(hInstance, hPrevInst))
  154. {
  155. OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n"));
  156. return 0;
  157. }
  158. #if USE_STRING_CACHE==1
  159. // It is ok if this fails. InsertObject dialog can do without the cache
  160. // support. InsertObjCacheUninit will cleanup as appropriate.
  161. if (!InsertObjCacheInitialize())
  162. {
  163. OleDbgOut1(TEXT("OleUIInitiallize: InsertObjCacheInit failed."));
  164. }
  165. #endif
  166. return TRUE;
  167. }
  168. #pragma code_seg()
  169. /*
  170. * OleUIUnInitialize
  171. *
  172. * NOTE: This function should only be called by your application IF it is using
  173. * the static-link version of this library. If the DLL version is being used,
  174. * this function is automatically called from the DLL's LibMain.
  175. *
  176. * Purpose:
  177. * Uninitializes OLE UI libraries. Deletes any resources allocated by the
  178. * library.
  179. *
  180. * Return Value:
  181. * BOOL TRUE if successful, FALSE if not. Current implementation always
  182. * returns TRUE.
  183. */
  184. STDAPI_(BOOL) OleUIUnInitialize()
  185. {
  186. #if USE_STRING_CACHE==1
  187. InsertObjCacheUninitialize();
  188. #endif
  189. IconBoxUninitialize();
  190. ResultImageUninitialize();
  191. // Cleanup thread local storage
  192. if (tlsIndex != (DWORD)-1)
  193. {
  194. TASKDATA* pData = (TASKDATA*)TlsGetValue(tlsIndex);
  195. TlsSetValue(tlsIndex, NULL);
  196. if (pData != NULL)
  197. {
  198. if (pData->hInstCommCtrl != NULL)
  199. FreeLibrary(pData->hInstCommCtrl);
  200. if (pData->hInstShell != NULL)
  201. FreeLibrary(pData->hInstShell);
  202. if (pData->hInstComDlg != NULL)
  203. FreeLibrary(pData->hInstComDlg);
  204. LocalFree(pData);
  205. }
  206. }
  207. // Last chance cleanup
  208. if (nInitCount == 1)
  209. {
  210. // cleanup thread local storage
  211. if (tlsIndex != (DWORD)-1)
  212. {
  213. TlsFree(tlsIndex);
  214. tlsIndex = (DWORD)-1;
  215. }
  216. }
  217. if (nInitCount != 0)
  218. --nInitCount;
  219. return TRUE;
  220. }
  221. /*
  222. * OleUIAddVerbMenu
  223. *
  224. * Purpose:
  225. * Add the Verb menu for the specified object to the given menu. If the
  226. * object has one verb, we directly add the verb to the given menu. If
  227. * the object has multiple verbs we create a cascading sub-menu.
  228. *
  229. * Parameters:
  230. * lpObj LPOLEOBJECT pointing to the selected object. If this
  231. * is NULL, then we create a default disabled menu item.
  232. *
  233. * lpszShortType LPTSTR with short type name (AuxName==2) corresponding
  234. * to the lpOleObj. if the string is NOT known, then NULL
  235. * may be passed. if NULL is passed, then
  236. * IOleObject::GetUserType will be called to retrieve it.
  237. * if the caller has the string handy, then it is faster
  238. * to pass it in.
  239. *
  240. * hMenu HMENU in which to make modifications.
  241. *
  242. * uPos Position of the menu item
  243. *
  244. * uIDVerbMin UINT_PTR ID value at which to start the verbs.
  245. * verb_0 = wIDMVerbMin + verb_0
  246. * verb_1 = wIDMVerbMin + verb_1
  247. * verb_2 = wIDMVerbMin + verb_2
  248. * etc.
  249. * uIDVerbMax UINT_PTR maximum ID value allowed for object verbs.
  250. * if uIDVerbMax==0 then any ID value is allowed
  251. *
  252. * bAddConvert BOOL specifying whether or not to add a "Convert" item
  253. * to the bottom of the menu (with a separator).
  254. *
  255. * idConvert UINT ID value to use for the Convert menu item, if
  256. * bAddConvert is TRUE.
  257. *
  258. * lphMenu HMENU FAR * of the cascading verb menu if it's created.
  259. * If there is only one verb, this will be filled with NULL.
  260. *
  261. *
  262. * Return Value:
  263. * BOOL TRUE if lpObj was valid and we added at least one verb
  264. * to the menu. FALSE if lpObj was NULL and we created
  265. * a disabled default menu item
  266. */
  267. STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj,
  268. LPCTSTR lpszShortType,
  269. HMENU hMenu, UINT uPos,
  270. UINT uIDVerbMin, UINT uIDVerbMax,
  271. BOOL bAddConvert, UINT idConvert,
  272. HMENU FAR *lphMenu)
  273. {
  274. LPPERSISTSTORAGE lpPS=NULL;
  275. LPENUMOLEVERB lpEnumOleVerb = NULL;
  276. OLEVERB oleverb;
  277. LPCTSTR lpszShortTypeName = lpszShortType;
  278. LPTSTR lpszVerbName = NULL;
  279. HRESULT hrErr;
  280. BOOL fStatus;
  281. BOOL fIsLink = FALSE;
  282. BOOL fResult = TRUE;
  283. BOOL fAddConvertItem = FALSE;
  284. int cVerbs = 0;
  285. UINT uFlags = MF_BYPOSITION;
  286. static BOOL fFirstTime = TRUE;
  287. static TCHAR szBuffer[OLEUI_OBJECTMENUMAX];
  288. static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX];
  289. static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX];
  290. static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX];
  291. static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX];
  292. static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX];
  293. static TCHAR szUnknown[OLEUI_OBJECTMENUMAX];
  294. static TCHAR szEdit[OLEUI_OBJECTMENUMAX];
  295. static TCHAR szConvert[OLEUI_OBJECTMENUMAX];
  296. // Set fAddConvertItem flag
  297. if (bAddConvert & (idConvert != 0))
  298. fAddConvertItem = TRUE;
  299. // only need to load the strings the 1st time
  300. if (fFirstTime)
  301. {
  302. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITNOOBJCMD,
  303. szNoObjectCmd, OLEUI_OBJECTMENUMAX))
  304. return FALSE;
  305. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_1VERB,
  306. szLinkCmd1Verb, OLEUI_OBJECTMENUMAX))
  307. return FALSE;
  308. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_1VERB,
  309. szObjectCmd1Verb, OLEUI_OBJECTMENUMAX))
  310. return FALSE;
  311. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_NVERB,
  312. szLinkCmdNVerb, OLEUI_OBJECTMENUMAX))
  313. return FALSE;
  314. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_NVERB,
  315. szObjectCmdNVerb, OLEUI_OBJECTMENUMAX))
  316. return FALSE;
  317. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN,
  318. szUnknown, OLEUI_OBJECTMENUMAX))
  319. return FALSE;
  320. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDIT,
  321. szEdit, OLEUI_OBJECTMENUMAX))
  322. return FALSE;
  323. if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UICONVERT,
  324. szConvert, OLEUI_OBJECTMENUMAX) && fAddConvertItem)
  325. return FALSE;
  326. fFirstTime = FALSE;
  327. }
  328. // Delete whatever menu may happen to be here already.
  329. DeleteMenu(hMenu, uPos, uFlags);
  330. if (lphMenu == NULL || IsBadWritePtr(lphMenu, sizeof(HMENU)))
  331. {
  332. goto AVMError;
  333. }
  334. *lphMenu=NULL;
  335. if ((!lpOleObj) || IsBadReadPtr(lpOleObj, sizeof (IOleObject)))
  336. goto AVMError;
  337. if ((!lpszShortTypeName) || IsBadReadPtr(lpszShortTypeName, sizeof(TCHAR)))
  338. {
  339. // get the Short form of the user type name for the menu
  340. OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n"))
  341. hrErr = lpOleObj->GetUserType(
  342. USERCLASSTYPE_SHORT,
  343. (LPTSTR FAR*)&lpszShortTypeName);
  344. OLEDBG_END2
  345. if (NOERROR != hrErr) {
  346. OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr);
  347. }
  348. }
  349. // check if the object is a link
  350. fIsLink = OleStdIsOleLink((LPUNKNOWN)lpOleObj);
  351. // Get the verb enumerator from the OLE object
  352. OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n"))
  353. hrErr = lpOleObj->EnumVerbs(
  354. (LPENUMOLEVERB FAR*)&lpEnumOleVerb
  355. );
  356. OLEDBG_END2
  357. if (NOERROR != hrErr) {
  358. OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr);
  359. }
  360. if (!(*lphMenu = CreatePopupMenu()))
  361. goto AVMError;
  362. // loop through all verbs
  363. while (lpEnumOleVerb != NULL)
  364. {
  365. hrErr = lpEnumOleVerb->Next(
  366. 1,
  367. (LPOLEVERB)&oleverb,
  368. NULL
  369. );
  370. if (NOERROR != hrErr)
  371. break; // DONE! no more verbs
  372. /* OLE2NOTE: negative verb numbers and verbs that do not
  373. ** indicate ONCONTAINERMENU should NOT be put on the verb menu
  374. */
  375. if (oleverb.lVerb < 0 ||
  376. ! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU))
  377. {
  378. /* OLE2NOTE: we must still free the verb name string */
  379. if (oleverb.lpszVerbName)
  380. OleStdFree(oleverb.lpszVerbName);
  381. continue;
  382. }
  383. // we must free the previous verb name string
  384. if (lpszVerbName)
  385. OleStdFree(lpszVerbName);
  386. lpszVerbName = oleverb.lpszVerbName;
  387. if ( 0 == uIDVerbMax ||
  388. (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) )
  389. {
  390. fStatus = InsertMenu(
  391. *lphMenu,
  392. (UINT)-1,
  393. MF_BYPOSITION | (UINT)oleverb.fuFlags,
  394. uIDVerbMin+(UINT)oleverb.lVerb,
  395. lpszVerbName
  396. );
  397. if (! fStatus)
  398. goto AVMError;
  399. cVerbs++;
  400. }
  401. }
  402. // Add the separator and "Convert" menu item.
  403. if (fAddConvertItem)
  404. {
  405. if (0 == cVerbs)
  406. {
  407. LPTSTR lpsz;
  408. // if object has no verbs, then use "Convert" as the obj's verb
  409. lpsz = lpszVerbName = OleStdCopyString(szConvert);
  410. uIDVerbMin = (UINT)idConvert;
  411. // remove "..." from "Convert..." string; it will be added later
  412. if (lpsz)
  413. {
  414. while(*lpsz && *lpsz != '.')
  415. lpsz = CharNext(lpsz);
  416. *lpsz = '\0';
  417. }
  418. }
  419. if (cVerbs > 0)
  420. {
  421. fStatus = InsertMenu(*lphMenu,
  422. (UINT)-1,
  423. MF_BYPOSITION | MF_SEPARATOR,
  424. (UINT)0,
  425. (LPCTSTR)NULL);
  426. if (! fStatus)
  427. goto AVMError;
  428. }
  429. /* add convert menu */
  430. fStatus = InsertMenu(*lphMenu,
  431. (UINT)-1,
  432. MF_BYPOSITION,
  433. idConvert,
  434. (LPCTSTR)szConvert);
  435. if (! fStatus)
  436. goto AVMError;
  437. cVerbs++;
  438. }
  439. /*
  440. * Build the appropriate menu based on the number of verbs found
  441. *
  442. */
  443. if (cVerbs == 0)
  444. {
  445. // there are NO verbs (not even Convert...). set the menu to be
  446. // "<short type> &Object/Link" and gray it out.
  447. wsprintf(
  448. szBuffer,
  449. (fIsLink ? szLinkCmdNVerb : szObjectCmdNVerb),
  450. (lpszShortTypeName ? lpszShortTypeName : TEXT(""))
  451. );
  452. uFlags |= MF_GRAYED;
  453. fResult = FALSE;
  454. DestroyMenu(*lphMenu);
  455. *lphMenu = NULL;
  456. }
  457. else if (cVerbs == 1)
  458. {
  459. //One verb without Convert, one item.
  460. LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
  461. // strip ampersands from lpszVerbName to ensure that
  462. // the right character is used as the menu key
  463. LPTSTR pchIn;
  464. LPTSTR pchOut;
  465. pchIn = pchOut = lpszVerbName;
  466. while (*pchIn)
  467. {
  468. while (*pchIn && '&' == *pchIn)
  469. {
  470. pchIn++;
  471. }
  472. *pchOut = *pchIn;
  473. pchOut++;
  474. pchIn++;
  475. }
  476. *pchOut = 0;
  477. FormatString2(szBuffer, lpsz, lpszVerbName, lpszShortTypeName, OLEUI_OBJECTMENUMAX);
  478. // if only "verb" is "Convert..." then append the ellipses
  479. if (fAddConvertItem)
  480. lstrcat(szBuffer, TEXT("..."));
  481. DestroyMenu(*lphMenu);
  482. *lphMenu=NULL;
  483. }
  484. else
  485. {
  486. //Multiple verbs or one verb with Convert, add the cascading menu
  487. wsprintf(
  488. szBuffer,
  489. (fIsLink ? szLinkCmdNVerb: szObjectCmdNVerb),
  490. (lpszShortTypeName ? lpszShortTypeName : TEXT(""))
  491. );
  492. uFlags |= MF_ENABLED | MF_POPUP;
  493. #ifdef _WIN64
  494. //
  495. // Sundown: Checking with JerrySh for the validity of the HMENU truncation...........
  496. // If not valid, this'd require modifying the prototype of this function for
  497. // uIDVerbMin & uIDVerbMax and modifying sdk\inc\oledlg.h exposed interface.
  498. //
  499. OleDbgAssert( !(((ULONG_PTR)*lphMenu) >> 32) )
  500. #endif // _WIN64
  501. uIDVerbMin=(UINT)HandleToUlong(*lphMenu);
  502. }
  503. if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, szBuffer))
  504. {
  505. AVMError:
  506. InsertMenu(hMenu, uPos, MF_GRAYED | uFlags,
  507. uIDVerbMin, szNoObjectCmd);
  508. fResult = FALSE;
  509. }
  510. // Redraw the menu bar, if possible
  511. HWND hWndActive = GetActiveWindow();
  512. HMENU hMenuActive = GetMenu(hWndActive);
  513. if(hMenuActive == hMenu)
  514. {
  515. DrawMenuBar(hWndActive);
  516. }
  517. if (lpszVerbName)
  518. OleStdFree(lpszVerbName);
  519. if (!lpszShortType && lpszShortTypeName)
  520. OleStdFree((LPVOID)lpszShortTypeName);
  521. if (lpEnumOleVerb)
  522. lpEnumOleVerb->Release();
  523. return fResult;
  524. }
  525. /////////////////////////////////////////////////////////////////////////////
  526. // Support for special error prompts
  527. typedef struct tagPROMPTUSER
  528. {
  529. va_list argptr;
  530. UINT nIDD; // dialog/help ID
  531. LPTSTR szTitle;
  532. } PROMPTUSER, *PPROMPTUSER, FAR* LPPROMPTUSER;
  533. /* PromptUserDlgProc
  534. * -----------------
  535. *
  536. * Purpose:
  537. * Dialog procedure used by OleUIPromptUser(). Returns when a button is
  538. * clicked in the dialog box and the button id is return.
  539. *
  540. * Parameters:
  541. * hDlg
  542. * iMsg
  543. * wParam
  544. * lParam
  545. *
  546. * Returns:
  547. *
  548. */
  549. INT_PTR CALLBACK PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  550. {
  551. switch (iMsg)
  552. {
  553. case WM_INITDIALOG:
  554. {
  555. SendDlgItemMessage(hDlg, IDC_PU_ICON,
  556. STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_EXCLAMATION), 0L);
  557. LPPROMPTUSER lpPU = (LPPROMPTUSER)lParam;
  558. SetProp(hDlg, STRUCTUREPROP, lpPU);
  559. SetWindowText(hDlg, lpPU->szTitle);
  560. TCHAR szFormat[256];
  561. GetDlgItemText(hDlg, IDC_PU_TEXT, szFormat,
  562. sizeof(szFormat)/sizeof(TCHAR));
  563. TCHAR szBuf[256];
  564. wvsprintf(szBuf, szFormat, lpPU->argptr);
  565. SetDlgItemText(hDlg, IDC_PU_TEXT, szBuf);
  566. }
  567. return TRUE;
  568. case WM_COMMAND:
  569. EndDialog(hDlg, wParam);
  570. return TRUE;
  571. default:
  572. return FALSE;
  573. }
  574. }
  575. //+---------------------------------------------------------------------------
  576. //
  577. // Function: OleUIPromptUserInternal
  578. //
  579. // Synopsis: internal entry point to start the PromptUser dialog
  580. // Used to support both ANSI and Unicode entrypoints
  581. //
  582. // Arguments: [nTemplate] - dialog template ID
  583. // [szTitle] - the title string
  584. // [hwndParent] - the dialog's parent window
  585. // [arglist] - variable argument list
  586. //
  587. // History: 12-01-94 stevebl Created
  588. //
  589. //----------------------------------------------------------------------------
  590. int OleUIPromptUserInternal(int nTemplate, HWND hwndParent, LPTSTR szTitle, va_list arglist)
  591. {
  592. PROMPTUSER pu;
  593. pu.szTitle = szTitle;
  594. pu.argptr = arglist;
  595. pu.nIDD = nTemplate;
  596. return ((int)DialogBoxParam(_g_hOleStdResInst, MAKEINTRESOURCE(nTemplate), hwndParent,
  597. PromptUserDlgProc, (LPARAM)&pu));
  598. }
  599. /* OleUIPromptUser
  600. * ---------------
  601. *
  602. * Purpose:
  603. * Popup a dialog box with the specified template and returned the
  604. * response (button id) from the user.
  605. *
  606. * Parameters:
  607. * nTemplate resource number of the dialog
  608. * hwndParent parent of the dialog box
  609. * ... title of the dialog box followed by argument list
  610. * for the format string in the static control
  611. * (IDC_PU_TEXT) of the dialog box.
  612. * The caller has to make sure that the correct number
  613. * and type of argument are passed in.
  614. *
  615. * Returns:
  616. * button id selected by the user (template dependent)
  617. *
  618. * Comments:
  619. * the following message dialog boxes are supported:
  620. *
  621. * IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable
  622. * VARARG Parameters:
  623. * None.
  624. * Used for the following error codes:
  625. * OLE_E_CANT_BINDTOSOURCE
  626. * STG_E_PATHNOTFOUND
  627. * (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error
  628. * any unknown error if object is a link
  629. *
  630. * IDD_SERVERNOTFOUND -- server registered but NOT found
  631. * VARARG Parameters:
  632. * LPSTR lpszUserType -- user type name of object
  633. * Used for the following error codes:
  634. * CO_E_APPNOTFOUND
  635. * CO_E_APPDIDNTREG
  636. * any unknown error if object is an embedded object
  637. *
  638. * IDD_SERVERNOTREG -- server NOT registered
  639. * VARARG Parameters:
  640. * LPSTR lpszUserType -- user type name of object
  641. * Used for the following error codes:
  642. * REGDB_E_CLASSNOTREG
  643. * OLE_E_STATIC -- static object with no server registered
  644. *
  645. * IDD_LINKTYPECHANGED -- class of link source changed since last binding
  646. * VARARG Parameters:
  647. * LPSTR lpszUserType -- user type name of ole link source
  648. * Used for the following error codes:
  649. * OLE_E_CLASSDIFF
  650. *
  651. * IDD_LINKTYPECHANGED -- class of link source changed since last binding
  652. * VARARG Parameters:
  653. * LPSTR lpszUserType -- user type name of ole link source
  654. * Used for the following error codes:
  655. * OLE_E_CLASSDIFF
  656. *
  657. * IDD_OUTOFMEMORY -- out of memory
  658. * VARARG Parameters:
  659. * None.
  660. * Used for the following error codes:
  661. * E_OUTOFMEMORY
  662. *
  663. */
  664. int FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...)
  665. {
  666. va_list arglist;
  667. va_start(arglist, hwndParent);
  668. LPTSTR szTitle = va_arg(arglist, LPTSTR);
  669. int nRet = OleUIPromptUserInternal(nTemplate, hwndParent, szTitle, arglist);
  670. va_end(arglist);
  671. return nRet;
  672. }
  673. /* UpdateLinksDlgProc
  674. * ------------------
  675. *
  676. * Purpose:
  677. * Dialog procedure used by OleUIUpdateLinks(). It will enumerate all
  678. * all links in the container and updates all automatic links.
  679. * Returns when the Stop Button is clicked in the dialog box or when all
  680. * links are updated
  681. *
  682. * Parameters:
  683. * hDlg
  684. * iMsg
  685. * wParam
  686. * lParam pointer to the UPDATELINKS structure
  687. *
  688. * Returns:
  689. *
  690. */
  691. #define UPDATELINKS_STARTDELAY 2000 // delay before 1st link updates
  692. INT_PTR CALLBACK UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  693. {
  694. LPUPDATELINKS FAR* lplpUL = NULL;
  695. HANDLE gh;
  696. static BOOL fAbort = FALSE;
  697. // Process the temination message
  698. if (iMsg == uMsgEndDialog)
  699. {
  700. gh = RemoveProp(hDlg, STRUCTUREPROP);
  701. if (NULL != gh)
  702. {
  703. GlobalUnlock(gh);
  704. GlobalFree(gh);
  705. }
  706. EndDialog(hDlg, wParam);
  707. return TRUE;
  708. }
  709. switch (iMsg)
  710. {
  711. case WM_INITDIALOG:
  712. {
  713. gh = GlobalAlloc(GHND, sizeof(LPUPDATELINKS));
  714. SetProp(hDlg, STRUCTUREPROP, gh);
  715. if (NULL == gh)
  716. {
  717. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
  718. return FALSE;
  719. }
  720. fAbort = FALSE;
  721. lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh);
  722. if (!lplpUL)
  723. {
  724. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
  725. return FALSE;
  726. }
  727. if (bWin4)
  728. {
  729. if (StandardInitCommonControls() >= 0)
  730. {
  731. // get rect of the existing "progress" control
  732. RECT rect;
  733. GetWindowRect(GetDlgItem(hDlg, IDC_UL_METER), &rect);
  734. ScreenToClient(hDlg, ((POINT*)&rect)+0);
  735. ScreenToClient(hDlg, ((POINT*)&rect)+1);
  736. // create progress control in that rect
  737. HWND hProgress = CreateWindowEx(
  738. 0, PROGRESS_CLASS, NULL, WS_CHILD|WS_VISIBLE,
  739. rect.left, rect.top,
  740. rect.right-rect.left, rect.bottom-rect.top, hDlg,
  741. (HMENU)IDC_UL_PROGRESS, _g_hOleStdInst, NULL);
  742. if (hProgress != NULL)
  743. {
  744. // initialize the progress control
  745. SendMessage(hProgress, PBM_SETRANGE, 0, MAKELONG(0, 100));
  746. // hide the other "meter" control
  747. StandardShowDlgItem(hDlg, IDC_UL_METER, SW_HIDE);
  748. }
  749. }
  750. }
  751. *lplpUL = (LPUPDATELINKS)lParam;
  752. if ((*lplpUL)->lpszTitle)
  753. {
  754. SetWindowText(hDlg, (*lplpUL)->lpszTitle);
  755. }
  756. SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL);
  757. return TRUE;
  758. }
  759. case WM_TIMER:
  760. KillTimer(hDlg, 1);
  761. gh = GetProp(hDlg, STRUCTUREPROP);
  762. if (NULL!=gh)
  763. {
  764. // gh was locked previously, lock and unlock to get lplpUL
  765. lplpUL = (LPUPDATELINKS*)GlobalLock(gh);
  766. GlobalUnlock(gh);
  767. }
  768. if (! fAbort && lplpUL)
  769. PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL));
  770. else
  771. PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L);
  772. return 0;
  773. case WM_COMMAND: // Stop button
  774. fAbort = TRUE;
  775. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  776. return TRUE;
  777. case WM_U_UPDATELINK:
  778. {
  779. HRESULT hErr;
  780. int nPercent;
  781. RECT rc;
  782. TCHAR szPercent[5]; // 0% to 100%
  783. HBRUSH hbr;
  784. HDC hDC;
  785. HWND hwndMeter;
  786. MSG msg;
  787. DWORD dwUpdateOpt;
  788. LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam;
  789. lpUL->dwLink=lpUL->lpOleUILinkCntr->GetNextLink(lpUL->dwLink);
  790. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  791. {
  792. if (! IsDialogMessage(hDlg, &msg))
  793. {
  794. TranslateMessage(&msg);
  795. DispatchMessage(&msg);
  796. }
  797. }
  798. if (fAbort)
  799. return FALSE;
  800. if (!lpUL->dwLink)
  801. {
  802. // all links processed
  803. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  804. return TRUE;
  805. }
  806. hErr = lpUL->lpOleUILinkCntr->GetLinkUpdateOptions(
  807. lpUL->dwLink, (LPDWORD)&dwUpdateOpt);
  808. if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS))
  809. {
  810. hErr = lpUL->lpOleUILinkCntr->UpdateLink(lpUL->dwLink, FALSE, FALSE);
  811. lpUL->fError |= (hErr != NOERROR);
  812. lpUL->cUpdated++;
  813. nPercent = (lpUL->cLinks > 0) ? (lpUL->cUpdated * 100 / lpUL->cLinks) : 100;
  814. if (nPercent <= 100)
  815. {
  816. // update percentage
  817. wsprintf(szPercent, TEXT("%d%%"), nPercent);
  818. SetDlgItemText(hDlg, IDC_UL_PERCENT, szPercent);
  819. HWND hProgress = GetDlgItem(hDlg, IDC_UL_PROGRESS);
  820. if (hProgress == NULL)
  821. {
  822. // update indicator
  823. hwndMeter = GetDlgItem(hDlg, IDC_UL_METER);
  824. GetClientRect(hwndMeter, (LPRECT)&rc);
  825. InflateRect((LPRECT)&rc, -1, -1);
  826. rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left;
  827. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  828. if (hbr)
  829. {
  830. hDC = GetDC(hwndMeter);
  831. if (hDC)
  832. {
  833. FillRect(hDC, (LPRECT)&rc, hbr);
  834. ReleaseDC(hwndMeter, hDC);
  835. }
  836. DeleteObject(hbr);
  837. }
  838. }
  839. else
  840. {
  841. // update the progress indicator
  842. SendMessage(hProgress, PBM_SETPOS, nPercent, 0);
  843. }
  844. }
  845. }
  846. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  847. {
  848. if (! IsDialogMessage(hDlg, &msg))
  849. {
  850. TranslateMessage(&msg);
  851. DispatchMessage(&msg);
  852. }
  853. }
  854. PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam);
  855. }
  856. return TRUE;
  857. case WM_U_SHOWWINDOW:
  858. ShowWindow(hDlg, SW_SHOW);
  859. return TRUE;
  860. }
  861. return FALSE;
  862. }
  863. /* OleUIUpdateLinkS
  864. * ----------------
  865. *
  866. * Purpose:
  867. * Update all links in the Link Container and popup a dialog box which
  868. * shows the progress of the updating.
  869. * The process is stopped when the user press Stop button or when all
  870. * links are processed.
  871. *
  872. * Parameters:
  873. * lpOleUILinkCntr pointer to Link Container
  874. * hwndParent parent window of the dialog
  875. * lpszTitle title of the dialog box
  876. * cLinks total number of links
  877. *
  878. * Returns:
  879. * TRUE all links updated successfully or user aborted dialog
  880. * FALSE oherwise
  881. */
  882. STDAPI_(BOOL) OleUIUpdateLinks(
  883. LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks)
  884. {
  885. LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS));
  886. if (lpUL == NULL)
  887. return FALSE;
  888. BOOL fError = TRUE;
  889. // Validate interface.
  890. if (NULL == lpOleUILinkCntr || IsBadReadPtr(lpOleUILinkCntr, sizeof(IOleUILinkContainer)))
  891. goto Error;
  892. // Validate parent-window handle. NULL is considered valid.
  893. if (NULL != hwndParent && !IsWindow(hwndParent))
  894. goto Error;
  895. // Validate the dialog title. NULL is considered valid.
  896. if (NULL != lpszTitle && IsBadReadPtr(lpszTitle, 1))
  897. goto Error;
  898. if (cLinks < 0)
  899. goto Error;
  900. OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0));
  901. OleDbgAssert(lpUL);
  902. lpUL->lpOleUILinkCntr = lpOleUILinkCntr;
  903. lpUL->cLinks = cLinks;
  904. lpUL->cUpdated = 0;
  905. lpUL->dwLink = 0;
  906. lpUL->fError = FALSE;
  907. lpUL->lpszTitle = lpszTitle;
  908. DialogBoxParam(_g_hOleStdResInst, MAKEINTRESOURCE(IDD_UPDATELINKS),
  909. hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL);
  910. fError = lpUL->fError;
  911. Error:
  912. OleStdFree((LPVOID)lpUL);
  913. return !fError;
  914. }