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.

1455 lines
57 KiB

  1. /*
  2. * CONVERT.CPP
  3. *
  4. * Implements the OleUIConvert function which invokes the complete
  5. * Convert dialog.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  8. */
  9. #include "precomp.h"
  10. #include "common.h"
  11. #include <stdlib.h>
  12. #include "utility.h"
  13. #include "iconbox.h"
  14. OLEDBGDATA
  15. // Internally used structure
  16. typedef struct tagCONVERT
  17. {
  18. // Keep this item first as the Standard* functions depend on it here.
  19. LPOLEUICONVERT lpOCV; // Original structure passed.
  20. UINT nIDD; // IDD of dialog (used for help info)
  21. /*
  22. * What we store extra in this structure besides the original caller's
  23. * pointer are those fields that we need to modify during the life of
  24. * the dialog but that we don't want to change in the original structure
  25. * until the user presses OK.
  26. */
  27. DWORD dwFlags; // Flags passed in
  28. HWND hListVisible; // listbox that is currently visible
  29. HWND hListInvisible; // listbox that is currently hidden
  30. CLSID clsid; // Class ID sent in to dialog: IN only
  31. DWORD dvAspect;
  32. BOOL fCustomIcon;
  33. UINT IconIndex; // index (in exe) of current icon
  34. LPTSTR lpszIconSource; // path to current icon source
  35. LPTSTR lpszCurrentObject;
  36. LPTSTR lpszConvertDefault;
  37. LPTSTR lpszActivateDefault;
  38. } CONVERT, *PCONVERT, FAR *LPCONVERT;
  39. // Internal function prototypes
  40. // CONVERT.CPP
  41. INT_PTR CALLBACK ConvertDialogProc(HWND, UINT, WPARAM, LPARAM);
  42. BOOL FConvertInit(HWND hDlg, WPARAM, LPARAM);
  43. void SetConvertResults(HWND, LPCONVERT);
  44. UINT FillClassList(CLSID clsid, HWND hList, HWND hListInvisible,
  45. LPTSTR FAR *lplpszCurrentClass, BOOL fIsLinkedObject, WORD wFormat,
  46. UINT cClsidExclude, LPCLSID lpClsidExclude, BOOL bAddSameClass);
  47. BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat);
  48. void SwapWindows(HWND, HWND, HWND);
  49. void ConvertCleanup(HWND hDlg, LPCONVERT lpCV);
  50. static void UpdateClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList);
  51. /*
  52. * OleUIConvert
  53. *
  54. * Purpose:
  55. * Invokes the standard OLE Change Type dialog box allowing the user
  56. * to change the type of the single specified object, or change the
  57. * type of all OLE objects of a specified type.
  58. *
  59. * Parameters:
  60. * lpCV LPOLEUICONVERT pointing to the in-out structure
  61. * for this dialog.
  62. *
  63. * Return Value:
  64. * UINT One of the following codes, indicating success or error:
  65. * OLEUI_SUCCESS Success
  66. * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
  67. */
  68. STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT lpCV)
  69. {
  70. HGLOBAL hMemDlg = NULL;
  71. UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpCV, sizeof(OLEUICONVERT),
  72. &hMemDlg);
  73. if (OLEUI_SUCCESS != uRet)
  74. return uRet;
  75. if (lpCV->hMetaPict != NULL && !IsValidMetaPict(lpCV->hMetaPict))
  76. {
  77. return(OLEUI_CTERR_HMETAPICTINVALID);
  78. }
  79. if ((lpCV->dwFlags & CF_SETCONVERTDEFAULT)
  80. && (!IsValidClassID(lpCV->clsidConvertDefault)))
  81. uRet = OLEUI_CTERR_CLASSIDINVALID;
  82. if ((lpCV->dwFlags & CF_SETACTIVATEDEFAULT)
  83. && (!IsValidClassID(lpCV->clsidActivateDefault)))
  84. uRet = OLEUI_CTERR_CLASSIDINVALID;
  85. if ((lpCV->dvAspect != DVASPECT_ICON) && (lpCV->dvAspect != DVASPECT_CONTENT))
  86. uRet = OLEUI_CTERR_DVASPECTINVALID;
  87. if ((lpCV->wFormat >= CF_CLIPBOARDMIN) && (lpCV->wFormat <= CF_CLIPBOARDMAX))
  88. {
  89. TCHAR szTemp[8];
  90. if (0 == GetClipboardFormatName(lpCV->wFormat, szTemp, 8))
  91. uRet = OLEUI_CTERR_CBFORMATINVALID;
  92. }
  93. if ((NULL != lpCV->lpszUserType)
  94. && (IsBadReadPtr(lpCV->lpszUserType, 1)))
  95. uRet = OLEUI_CTERR_STRINGINVALID;
  96. if ( (NULL != lpCV->lpszDefLabel)
  97. && (IsBadReadPtr(lpCV->lpszDefLabel, 1)) )
  98. uRet = OLEUI_CTERR_STRINGINVALID;
  99. if (0 != lpCV->cClsidExclude &&
  100. IsBadReadPtr(lpCV->lpClsidExclude, lpCV->cClsidExclude * sizeof(CLSID)))
  101. {
  102. uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
  103. }
  104. if (OLEUI_ERR_STANDARDMIN <= uRet)
  105. {
  106. return uRet;
  107. }
  108. UINT nIDD;
  109. if (!bWin4)
  110. nIDD = lpCV->dwFlags & CF_CONVERTONLY ? IDD_CONVERTONLY : IDD_CONVERT;
  111. else
  112. nIDD = lpCV->dwFlags & CF_CONVERTONLY ? IDD_CONVERTONLY4 : IDD_CONVERT4;
  113. // Now that we've validated everything, we can invoke the dialog.
  114. uRet = UStandardInvocation(ConvertDialogProc, (LPOLEUISTANDARD)lpCV,
  115. hMemDlg, MAKEINTRESOURCE(nIDD));
  116. return uRet;
  117. }
  118. /*
  119. * ConvertDialogProc
  120. *
  121. * Purpose:
  122. * Implements the OLE Convert dialog as invoked through the
  123. * OleUIConvert function.
  124. *
  125. * Parameters:
  126. * Standard
  127. *
  128. * Return Value:
  129. * Standard
  130. *
  131. */
  132. INT_PTR CALLBACK ConvertDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  133. {
  134. // Declare Win16/Win32 compatible WM_COMMAND parameters.
  135. COMMANDPARAMS(wID, wCode, hWndMsg);
  136. // This will fail under WM_INITDIALOG, where we allocate it.
  137. UINT uRet = 0;
  138. LPCONVERT lpCV = (LPCONVERT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  139. //If the hook processed the message, we're done.
  140. if (0 != uRet)
  141. return (INT_PTR)uRet;
  142. //Process the temination message
  143. if (iMsg == uMsgEndDialog)
  144. {
  145. EndDialog(hDlg, wParam);
  146. return TRUE;
  147. }
  148. // Process help message from Change Icon
  149. if (iMsg == uMsgHelp)
  150. {
  151. PostMessage(lpCV->lpOCV->hWndOwner, uMsgHelp, wParam, lParam);
  152. return FALSE;
  153. }
  154. switch (iMsg)
  155. {
  156. case WM_DESTROY:
  157. if (lpCV)
  158. {
  159. ConvertCleanup(hDlg, lpCV);
  160. StandardCleanup(lpCV, hDlg);
  161. }
  162. break;
  163. case WM_INITDIALOG:
  164. FConvertInit(hDlg, wParam, lParam);
  165. return TRUE;
  166. case WM_COMMAND:
  167. switch (wID)
  168. {
  169. case IDC_CV_ACTIVATELIST:
  170. case IDC_CV_CONVERTLIST:
  171. switch (wCode)
  172. {
  173. case LBN_SELCHANGE:
  174. // Change "Results" window to reflect current selection
  175. SetConvertResults(hDlg, lpCV);
  176. // Update the icon we display, if in display as icon mode
  177. if ((lpCV->dwFlags & CF_SELECTCONVERTTO) &&
  178. lpCV->dvAspect == DVASPECT_ICON && !lpCV->fCustomIcon)
  179. {
  180. UpdateClassIcon(hDlg, lpCV, hWndMsg);
  181. }
  182. break;
  183. case LBN_DBLCLK:
  184. SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
  185. break;
  186. }
  187. break;
  188. case IDC_CV_CONVERTTO:
  189. case IDC_CV_ACTIVATEAS:
  190. {
  191. HWND hList = lpCV->hListVisible;
  192. HWND hListInvisible = lpCV->hListInvisible;
  193. if (IDC_CV_CONVERTTO == wParam)
  194. {
  195. // User just click on the button again - it was
  196. // already selected.
  197. if (lpCV->dwFlags & CF_SELECTCONVERTTO)
  198. break;
  199. // If we're working with a linked object, don't
  200. // add the activate list - just the object's
  201. // class should appear in the listbox.
  202. SwapWindows(hDlg, hList, hListInvisible);
  203. lpCV->hListVisible = hListInvisible;
  204. lpCV->hListInvisible = hList;
  205. EnableWindow(lpCV->hListInvisible, FALSE);
  206. EnableWindow(lpCV->hListVisible, TRUE);
  207. // Update our flags.
  208. lpCV->dwFlags &= ~CF_SELECTACTIVATEAS;
  209. lpCV->dwFlags |= CF_SELECTCONVERTTO;
  210. }
  211. else
  212. {
  213. if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
  214. break;
  215. SwapWindows(hDlg, hList, hListInvisible);
  216. lpCV->hListVisible = hListInvisible;
  217. lpCV->hListInvisible = hList;
  218. EnableWindow(lpCV->hListInvisible, FALSE);
  219. EnableWindow(lpCV->hListVisible, TRUE);
  220. // Update our flags.
  221. lpCV->dwFlags |= CF_SELECTACTIVATEAS;
  222. lpCV->dwFlags &= ~CF_SELECTCONVERTTO;
  223. }
  224. LRESULT lRetVal;
  225. if (lpCV->dwFlags & CF_SELECTCONVERTTO)
  226. lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault);
  227. else
  228. lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault);
  229. if (LB_ERR == lRetVal)
  230. {
  231. TCHAR szCurrentObject[40];
  232. GetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, szCurrentObject, 40);
  233. SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)szCurrentObject);
  234. }
  235. // Turn updates back on.
  236. SendMessage(hDlg, WM_SETREDRAW, TRUE, 0L);
  237. InvalidateRect(lpCV->hListVisible, NULL, TRUE);
  238. UpdateWindow(lpCV->hListVisible);
  239. if ((lpCV->dvAspect & DVASPECT_ICON) && (lpCV->dwFlags & CF_SELECTCONVERTTO))
  240. UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible);
  241. // Hide the icon stuff when Activate is selected...show
  242. // it again when Convert is selected.
  243. BOOL fState = ((lpCV->dwFlags & CF_SELECTACTIVATEAS) ||
  244. (lpCV->dwFlags & CF_DISABLEDISPLAYASICON)) ?
  245. SW_HIDE : SW_SHOW;
  246. StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, fState);
  247. // Only display the icon if convert is selected AND
  248. // display as icon is checked.
  249. if ((SW_SHOW==fState) && (DVASPECT_ICON!=lpCV->dvAspect))
  250. fState = SW_HIDE;
  251. StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, fState);
  252. StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, fState);
  253. SetConvertResults(hDlg, lpCV);
  254. }
  255. break;
  256. case IDOK:
  257. {
  258. // Set output flags to current ones
  259. lpCV->lpOCV->dwFlags = lpCV->dwFlags;
  260. // Update the dvAspect and fObjectsIconChanged members
  261. // as appropriate.
  262. if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
  263. {
  264. // DON'T update aspect if activate as was selected.
  265. lpCV->lpOCV->fObjectsIconChanged = FALSE;
  266. }
  267. else
  268. lpCV->lpOCV->dvAspect = lpCV->dvAspect;
  269. // Get the new clsid
  270. TCHAR szBuffer[256];
  271. LRESULT iCurSel = SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0);
  272. SendMessage(lpCV->hListVisible, LB_GETTEXT, iCurSel, (LPARAM)szBuffer);
  273. LPTSTR lpszCLSID = PointerToNthField(szBuffer, 2, '\t');
  274. #if defined(WIN32) && !defined(UNICODE)
  275. OLECHAR wszCLSID[OLEUI_CCHKEYMAX];
  276. ATOW(wszCLSID, lpszCLSID, OLEUI_CCHKEYMAX);
  277. CLSIDFromString(wszCLSID, (&(lpCV->lpOCV->clsidNew)));
  278. #else
  279. CLSIDFromString(lpszCLSID, (&(lpCV->lpOCV->clsidNew)));
  280. #endif
  281. // Free the hMetaPict we got in.
  282. OleUIMetafilePictIconFree(lpCV->lpOCV->hMetaPict);
  283. // Get the hMetaPict (if display as icon is checked)
  284. if (DVASPECT_ICON == lpCV->dvAspect)
  285. lpCV->lpOCV->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  286. IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  287. else
  288. lpCV->lpOCV->hMetaPict = (HGLOBAL)NULL;
  289. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  290. }
  291. break;
  292. case IDCANCEL:
  293. {
  294. HGLOBAL hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  295. IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  296. OleUIMetafilePictIconFree(hMetaPict);
  297. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  298. }
  299. break;
  300. case IDC_OLEUIHELP:
  301. PostMessage(lpCV->lpOCV->hWndOwner,
  302. uMsgHelp, (WPARAM)hDlg, MAKELPARAM(IDD_CONVERT, 0));
  303. break;
  304. case IDC_CV_DISPLAYASICON:
  305. {
  306. BOOL fCheck = IsDlgButtonChecked(hDlg, wID);
  307. if (fCheck)
  308. lpCV->dvAspect = DVASPECT_ICON;
  309. else
  310. lpCV->dvAspect = DVASPECT_CONTENT;
  311. if (fCheck && !lpCV->fCustomIcon)
  312. UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible);
  313. // Show or hide the icon depending on the check state.
  314. int i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
  315. StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, i);
  316. StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, i);
  317. SetConvertResults(hDlg, lpCV);
  318. }
  319. break;
  320. case IDC_CV_CHANGEICON:
  321. {
  322. // Initialize the structure for the hook.
  323. OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci));
  324. ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  325. IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  326. ci.cbStruct = sizeof(ci);
  327. ci.hWndOwner= hDlg;
  328. ci.dwFlags = CIF_SELECTCURRENT;
  329. // Only show help if we're showing it for this dialog.
  330. if (lpCV->dwFlags & CF_SHOWHELPBUTTON)
  331. ci.dwFlags |= CIF_SHOWHELP;
  332. int iSel = (INT)SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0);
  333. // Get whole string
  334. LPTSTR pszString = (LPTSTR)OleStdMalloc(
  335. OLEUI_CCHLABELMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE);
  336. SendMessage(lpCV->hListVisible, LB_GETTEXT, iSel, (LPARAM)pszString);
  337. // Set pointer to CLSID (string)
  338. LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t');
  339. // Get the clsid to pass to change icon.
  340. #if defined(WIN32) && !defined(UNICODE)
  341. OLECHAR wszCLSID[OLEUI_CCHKEYMAX];
  342. ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX);
  343. CLSIDFromString(wszCLSID, &(ci.clsid));
  344. #else
  345. CLSIDFromString(pszCLSID, &(ci.clsid));
  346. #endif
  347. OleStdFree(pszString);
  348. // Let the hook in to customize Change Icon if desired.
  349. uRet = UStandardHook(lpCV, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
  350. if (0 == uRet)
  351. uRet= (OLEUI_OK == OleUIChangeIcon(&ci));
  352. // Update the display if necessary.
  353. if (0 != uRet)
  354. {
  355. SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET, 0,
  356. (LPARAM)ci.hMetaPict);
  357. // Update our custom/default flag
  358. if (ci.dwFlags & CIF_SELECTDEFAULT)
  359. lpCV->fCustomIcon = FALSE; // we're in default mode (icon changes on each LB selchange)
  360. else if (ci.dwFlags & CIF_SELECTFROMFILE)
  361. lpCV->fCustomIcon = TRUE; // we're in custom mode (icon doesn't change)
  362. // no change in fCustomIcon if user selected current
  363. lpCV->lpOCV->fObjectsIconChanged = TRUE;
  364. }
  365. }
  366. break;
  367. }
  368. break;
  369. }
  370. return FALSE;
  371. }
  372. /*
  373. * FConvertInit
  374. *
  375. * Purpose:
  376. * WM_INITIDIALOG handler for the Convert dialog box.
  377. *
  378. * Parameters:
  379. * hDlg HWND of the dialog
  380. * wParam WPARAM of the message
  381. * lParam LPARAM of the message
  382. *
  383. * Return Value:
  384. * BOOL Value to return for WM_INITDIALOG.
  385. */
  386. BOOL FConvertInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  387. {
  388. // Copy the structure at lParam into our instance memory.
  389. HFONT hFont; // non-bold version of dialog's font
  390. LPCONVERT lpCV = (LPCONVERT)LpvStandardInit(hDlg, sizeof(CONVERT), &hFont);
  391. // PvStandardInit send a termination to us already.
  392. if (NULL == lpCV)
  393. return FALSE;
  394. LPOLEUICONVERT lpOCV = (LPOLEUICONVERT)lParam;
  395. lpCV->lpOCV = lpOCV;
  396. lpCV->nIDD = IDD_CONVERT;
  397. lpCV->fCustomIcon = FALSE;
  398. // Copy other information from lpOCV that we might modify.
  399. lpCV->dwFlags = lpOCV->dwFlags;
  400. lpCV->clsid = lpOCV->clsid;
  401. lpCV->dvAspect = lpOCV->dvAspect;
  402. lpCV->hListVisible = GetDlgItem(hDlg, IDC_CV_ACTIVATELIST);
  403. lpCV->hListInvisible = GetDlgItem(hDlg, IDC_CV_CONVERTLIST);
  404. OleDbgAssert(lpCV->hListInvisible != NULL);
  405. lpCV->lpszCurrentObject = lpOCV->lpszUserType;
  406. lpOCV->clsidNew = CLSID_NULL;
  407. lpOCV->fObjectsIconChanged = FALSE;
  408. lpCV->lpszConvertDefault = (LPTSTR)OleStdMalloc(OLEUI_CCHLABELMAX_SIZE);
  409. lpCV->lpszActivateDefault = (LPTSTR)OleStdMalloc(OLEUI_CCHLABELMAX_SIZE);
  410. lpCV->lpszIconSource = (LPTSTR)OleStdMalloc(MAX_PATH_SIZE);
  411. if ((lpCV->lpszConvertDefault == NULL) ||
  412. (lpCV->lpszActivateDefault == NULL) ||
  413. (lpCV->lpszIconSource == NULL))
  414. {
  415. if (lpCV->lpszConvertDefault != NULL)
  416. OleStdFree (lpCV->lpszConvertDefault);
  417. if (lpCV->lpszActivateDefault != NULL)
  418. OleStdFree (lpCV->lpszActivateDefault);
  419. if (lpCV->lpszIconSource != NULL)
  420. OleStdFree (lpCV->lpszIconSource);
  421. // Gonna kill the window...
  422. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
  423. return FALSE;
  424. }
  425. // If we got a font, send it to the necessary controls.
  426. if (NULL != hFont)
  427. {
  428. SendDlgItemMessage(hDlg, IDC_CV_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L);
  429. SendDlgItemMessage(hDlg, IDC_CV_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
  430. }
  431. // Hide the help button if necessary
  432. if (!(lpCV->dwFlags & CF_SHOWHELPBUTTON))
  433. StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
  434. // Show or hide the Change icon button
  435. if (lpCV->dwFlags & CF_HIDECHANGEICON)
  436. DestroyWindow(GetDlgItem(hDlg, IDC_CV_CHANGEICON));
  437. // Fill the Object Type listbox with entries from the reg DB.
  438. UINT nRet = FillClassList(lpOCV->clsid, lpCV->hListVisible,
  439. lpCV->hListInvisible, &(lpCV->lpszCurrentObject),
  440. lpOCV->fIsLinkedObject, lpOCV->wFormat,
  441. lpOCV->cClsidExclude, lpOCV->lpClsidExclude,
  442. !(lpCV->dwFlags & CF_CONVERTONLY));
  443. if (nRet == -1)
  444. {
  445. // bring down dialog if error when filling list box
  446. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
  447. }
  448. // Set the name of the current object.
  449. SetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, lpCV->lpszCurrentObject);
  450. // Disable the "Activate As" button if the Activate list doesn't
  451. // have any objects in it.
  452. int cItemsActivate = (INT)SendMessage(lpCV->hListVisible, LB_GETCOUNT, 0, 0L);
  453. if (1 >= cItemsActivate || (lpCV->dwFlags & CF_DISABLEACTIVATEAS))
  454. StandardEnableDlgItem(hDlg, IDC_CV_ACTIVATEAS, FALSE);
  455. // Set the tab width in the list to push all the tabs off the side.
  456. RECT rect;
  457. if (lpCV->hListVisible != NULL)
  458. GetClientRect(lpCV->hListVisible, &rect);
  459. else
  460. GetClientRect(lpCV->hListInvisible, &rect);
  461. DWORD dw = GetDialogBaseUnits();
  462. rect.right = (8*rect.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
  463. if (lpCV->hListVisible != NULL)
  464. SendMessage(lpCV->hListVisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rect.right));
  465. SendMessage(lpCV->hListInvisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rect.right));
  466. // Make sure that either "Convert To" or "Activate As" is selected
  467. // and initialize listbox contents and selection accordingly
  468. if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
  469. {
  470. // Don't need to adjust listbox here because FillClassList
  471. // initializes to the "Activate As" state.
  472. CheckRadioButton(hDlg, IDC_CV_CONVERTTO, IDC_CV_ACTIVATEAS, IDC_CV_ACTIVATEAS);
  473. // Hide the icon stuff when Activate is selected...it gets shown
  474. // again when Convert is selected.
  475. StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, SW_HIDE);
  476. StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE);
  477. StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE);
  478. }
  479. else
  480. {
  481. // Default case. If user hasn't selected either flag, we will
  482. // come here anyway.
  483. // swap listboxes.
  484. HWND hWndTemp = lpCV->hListVisible;
  485. if (lpCV->dwFlags & CF_DISABLEDISPLAYASICON)
  486. {
  487. StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, SW_HIDE);
  488. StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE);
  489. StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE);
  490. }
  491. lpCV->dwFlags |= CF_SELECTCONVERTTO; // Make sure flag is set
  492. if (!(lpCV->dwFlags & CF_CONVERTONLY))
  493. CheckRadioButton(hDlg, IDC_CV_CONVERTTO, IDC_CV_ACTIVATEAS, IDC_CV_CONVERTTO);
  494. SwapWindows(hDlg, lpCV->hListVisible, lpCV->hListInvisible);
  495. lpCV->hListVisible = lpCV->hListInvisible;
  496. lpCV->hListInvisible = hWndTemp;
  497. if (lpCV->hListInvisible)
  498. EnableWindow(lpCV->hListInvisible, FALSE);
  499. EnableWindow(lpCV->hListVisible, TRUE);
  500. }
  501. // Initialize Default strings.
  502. // Default convert string is easy...just user the user type name from
  503. // the clsid we got, or the current object
  504. if ((lpCV->dwFlags & CF_SETCONVERTDEFAULT)
  505. && (IsValidClassID(lpCV->lpOCV->clsidConvertDefault)))
  506. {
  507. LPOLESTR lpszTemp = NULL;
  508. if (OleRegGetUserType(lpCV->lpOCV->clsidConvertDefault, USERCLASSTYPE_FULL,
  509. &lpszTemp) == NOERROR)
  510. {
  511. #if defined(WIN32) && !defined(UNICODE)
  512. WTOA(lpCV->lpszConvertDefault, lpszTemp, OLEUI_CCHLABELMAX);
  513. #else
  514. lstrcpyn(lpCV->lpszConvertDefault, lpszTemp, OLEUI_CCHLABELMAX);
  515. #endif
  516. OleStdFree(lpszTemp);
  517. }
  518. else
  519. {
  520. lstrcpy(lpCV->lpszConvertDefault, lpCV->lpszCurrentObject);
  521. }
  522. }
  523. else
  524. lstrcpy(lpCV->lpszConvertDefault,
  525. (lpCV->lpszCurrentObject ? lpCV->lpszCurrentObject : TEXT("")));
  526. // Default activate is a bit trickier. We want to use the user type
  527. // name if from the clsid we got (assuming we got one), or the current
  528. // object if it fails or we didn't get a clsid. But...if there's a
  529. // Treat As entry in the reg db, then we use that instead. So... the
  530. // logic boils down to this:
  531. //
  532. // if ("Treat As" in reg db)
  533. // use it;
  534. // else
  535. // if (CF_SETACTIVATEDEFAULT)
  536. // use it;
  537. // else
  538. // use current object;
  539. HKEY hKey;
  540. LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey);
  541. LPARAM lpRet;
  542. if (lRet != ERROR_SUCCESS)
  543. goto CheckInputFlag;
  544. LPOLESTR lpszCLSID;
  545. StringFromCLSID(lpCV->lpOCV->clsid, &lpszCLSID);
  546. TCHAR szKey[OLEUI_CCHKEYMAX];
  547. #if defined(WIN32) && !defined(UNICODE)
  548. WTOA(szKey, lpszCLSID, OLEUI_CCHKEYMAX);
  549. #else
  550. lstrcpy(szKey, lpszCLSID);
  551. #endif
  552. lstrcat(szKey, TEXT("\\TreatAs"));
  553. OleStdFree(lpszCLSID);
  554. TCHAR szValue[OLEUI_CCHKEYMAX];
  555. dw = OLEUI_CCHKEYMAX_SIZE;
  556. lRet = RegQueryValue(hKey, szKey, szValue, (LONG*)&dw);
  557. CLSID clsid;
  558. if (lRet != ERROR_SUCCESS)
  559. {
  560. RegCloseKey(hKey);
  561. goto CheckInputFlag;
  562. }
  563. else
  564. {
  565. #if defined(WIN32) && !defined(UNICODE)
  566. OLECHAR wszValue[OLEUI_CCHKEYMAX];
  567. ATOW(wszValue,szValue,OLEUI_CCHKEYMAX);
  568. CLSIDFromString(wszValue, &clsid);
  569. #else
  570. CLSIDFromString(szValue, &clsid);
  571. #endif
  572. LPOLESTR lpszTemp = NULL;
  573. if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &lpszTemp) == NOERROR)
  574. {
  575. if (lpCV->lpszActivateDefault)
  576. {
  577. #if defined(WIN32) && !defined(UNICODE)
  578. WTOA(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX);
  579. #else
  580. lstrcpyn(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX);
  581. #endif
  582. }
  583. OleStdFree(lpszTemp);
  584. }
  585. else
  586. {
  587. RegCloseKey(hKey);
  588. goto CheckInputFlag;
  589. }
  590. }
  591. RegCloseKey(hKey);
  592. goto SelectStringInListbox;
  593. CheckInputFlag:
  594. if ((lpCV->dwFlags & CF_SETACTIVATEDEFAULT)
  595. && (IsValidClassID(lpCV->lpOCV->clsidActivateDefault)))
  596. {
  597. LPOLESTR lpszTemp = NULL;
  598. if (OleRegGetUserType(lpCV->lpOCV->clsidActivateDefault, USERCLASSTYPE_FULL,
  599. &lpszTemp) == NOERROR)
  600. {
  601. #if defined(WIN32) && !defined(UNICODE)
  602. WTOA(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX);
  603. #else
  604. lstrcpyn(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX);
  605. #endif
  606. OleStdFree(lpszTemp);
  607. }
  608. else
  609. {
  610. lstrcpy(lpCV->lpszActivateDefault, lpCV->lpszCurrentObject);
  611. }
  612. }
  613. else
  614. if ((lpCV->lpszActivateDefault) && (lpCV->lpszCurrentObject))
  615. lstrcpy((lpCV->lpszActivateDefault), lpCV->lpszCurrentObject);
  616. SelectStringInListbox:
  617. if (lpCV->dwFlags & CF_SELECTCONVERTTO)
  618. lpRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault);
  619. else
  620. lpRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault);
  621. if (LB_ERR == lpRet)
  622. SendMessage(lpCV->hListVisible, LB_SETCURSEL, (WPARAM)0, 0L);
  623. if ((HGLOBAL)NULL != lpOCV->hMetaPict)
  624. {
  625. HGLOBAL hMetaPict = OleDuplicateData(lpOCV->hMetaPict, CF_METAFILEPICT, NULL);
  626. SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET,
  627. 0, (LPARAM)hMetaPict);
  628. lpCV->fCustomIcon = TRUE;
  629. }
  630. else
  631. {
  632. UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible);
  633. }
  634. // Initialize icon stuff
  635. if (DVASPECT_ICON == lpCV->dvAspect )
  636. {
  637. SendDlgItemMessage(hDlg, IDC_CV_DISPLAYASICON, BM_SETCHECK, TRUE, 0L);
  638. }
  639. else
  640. {
  641. // Hide & disable icon stuff
  642. StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE);
  643. StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE);
  644. }
  645. // Call the hook with lCustData in lParam
  646. UStandardHook((LPVOID)lpCV, hDlg, WM_INITDIALOG, wParam, lpOCV->lCustData);
  647. // Update results window
  648. SetConvertResults(hDlg, lpCV);
  649. // Update caption if lpszCaption was specified
  650. if (lpCV->lpOCV->lpszCaption && !IsBadReadPtr(lpCV->lpOCV->lpszCaption, 1))
  651. {
  652. SetWindowText(hDlg, lpCV->lpOCV->lpszCaption);
  653. }
  654. return TRUE;
  655. }
  656. /*
  657. * FillClassList
  658. *
  659. * Purpose:
  660. * Enumerates available OLE object classes from the registration
  661. * database that we can convert or activate the specified clsid from.
  662. *
  663. * Note that this function removes any prior contents of the listbox.
  664. *
  665. * Parameters:
  666. * clsid Class ID for class to find convert classes for
  667. * hList HWND to the listbox to fill.
  668. * hListActivate HWND to invisible listbox that stores "activate as" list.
  669. * lpszClassName LPSTR to put the (hr) class name of the clsid; we
  670. * do it here since we've already got the reg db open.
  671. * fIsLinkedObject BOOL is the original object a linked object
  672. * wFormat WORD specifying the format of the original class.
  673. * cClsidExclude UINT number of entries in exclude list
  674. * lpClsidExclude LPCLSID array classes to exclude for list
  675. *
  676. * Return Value:
  677. * UINT Number of strings added to the listbox, -1 on failure.
  678. */
  679. UINT FillClassList(CLSID clsid, HWND hListActivate, HWND hListConvert,
  680. LPTSTR FAR *lplpszCurrentClass, BOOL fIsLinkedObject,
  681. WORD wFormat, UINT cClsidExclude, LPCLSID lpClsidExclude, BOOL bAddSameClass)
  682. {
  683. // Clean out the existing strings.
  684. if (hListActivate)
  685. SendMessage(hListActivate, LB_RESETCONTENT, 0, 0L);
  686. OleDbgAssert(hListConvert != NULL);
  687. SendMessage(hListConvert, LB_RESETCONTENT, 0, 0L);
  688. // Open up the root key.
  689. HKEY hKey;
  690. LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey);
  691. LPARAM lpRet;
  692. if (ERROR_SUCCESS != lRet)
  693. return (UINT)-1;
  694. if (NULL == *lplpszCurrentClass)
  695. {
  696. #if defined(WIN32) && !defined(UNICODE)
  697. LPOLESTR wszCurrentClass;
  698. if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &wszCurrentClass) != NOERROR)
  699. #else
  700. if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, lplpszCurrentClass) != NOERROR)
  701. #endif
  702. {
  703. *lplpszCurrentClass = OleStdLoadString(_g_hOleStdResInst, IDS_PSUNKNOWNTYPE);
  704. if (*lplpszCurrentClass == NULL)
  705. {
  706. RegCloseKey(hKey);
  707. return (UINT)-1;
  708. }
  709. }
  710. #if defined(WIN32) && !defined(UNICODE)
  711. else
  712. {
  713. UINT uLen = WTOALEN(wszCurrentClass);
  714. *lplpszCurrentClass = (LPTSTR)OleStdMalloc(uLen);
  715. if (NULL == *lplpszCurrentClass)
  716. {
  717. RegCloseKey(hKey);
  718. OleStdFree(wszCurrentClass);
  719. return (UINT)-1;
  720. }
  721. WTOA(*lplpszCurrentClass, wszCurrentClass, uLen);
  722. OleStdFree(wszCurrentClass);
  723. }
  724. #endif
  725. }
  726. // Get the class name of the original class.
  727. LPTSTR lpszCLSID;
  728. #if defined(WIN32) && !defined(UNICODE)
  729. // This code does not report allocation errors because neither did
  730. // the original code before I extended it to support 32-bit ANSI builds.
  731. // (NOTE that the result of StringFromCLSID is never checked against
  732. // NULL after the #else case below, which contains the original code.)
  733. // In any event, if OleStdMalloc returns NULL, then the string will
  734. // simply be lost. Technically an error, but not a fatal one.
  735. LPOLESTR wszCLSID;
  736. StringFromCLSID(clsid, &wszCLSID);
  737. lpszCLSID = NULL;
  738. if (NULL != wszCLSID)
  739. {
  740. UINT uLen = WTOALEN(wszCLSID);
  741. lpszCLSID = (LPTSTR) OleStdMalloc(uLen);
  742. if (NULL != lpszCLSID)
  743. {
  744. WTOA(lpszCLSID, wszCLSID, uLen);
  745. }
  746. OleStdFree(wszCLSID);
  747. }
  748. #else
  749. StringFromCLSID(clsid, &lpszCLSID);
  750. #endif
  751. // Here, we step through the entire registration db looking for
  752. // class that can read or write the original class' format. We
  753. // maintain two lists - an activate list and a convert list. The
  754. // activate list is a subset of the convert list - activate == read/write
  755. // and convert == read. We swap the listboxes as needed with
  756. // SwapWindows, and keep track of which is which in the lpCV structure.
  757. // Every item has the following format:
  758. //
  759. // Class Name\tclsid\0
  760. UINT cStrings = 0;
  761. TCHAR szClass[OLEUI_CCHKEYMAX];
  762. lRet = RegEnumKey(hKey, cStrings++, szClass, sizeof(szClass) / sizeof(TCHAR));
  763. TCHAR szFormatKey[OLEUI_CCHKEYMAX];
  764. TCHAR szFormat[OLEUI_CCHKEYMAX];
  765. TCHAR szHRClassName[OLEUI_CCHKEYMAX];
  766. CLSID clsidForList;
  767. while (ERROR_SUCCESS == lRet)
  768. {
  769. UINT j;
  770. BOOL fExclude = FALSE;
  771. //Check if this CLSID is in the exclusion list.
  772. #if defined(WIN32) && !defined(UNICODE)
  773. OLECHAR wszClass[OLEUI_CCHKEYMAX];
  774. ATOW(wszClass, szClass, OLEUI_CCHKEYMAX);
  775. HRESULT hr = CLSIDFromString(wszClass, &clsidForList);
  776. #else
  777. HRESULT hr = CLSIDFromString(szClass, &clsidForList);
  778. #endif
  779. if (SUCCEEDED(hr))
  780. {
  781. for (j = 0; j < cClsidExclude; j++)
  782. {
  783. if (IsEqualCLSID(clsidForList, lpClsidExclude[j]))
  784. {
  785. fExclude=TRUE;
  786. break;
  787. }
  788. }
  789. if (fExclude)
  790. goto Next; // don't add this class to list
  791. }
  792. // Check for a \Conversion\Readwritable\Main - if its
  793. // readwriteable, then the class can be added to the ActivateAs
  794. // list.
  795. // NOTE: the presence of this key should NOT automatically be
  796. // used to add the class to the CONVERT list.
  797. lstrcpy(szFormatKey, szClass);
  798. lstrcat(szFormatKey, TEXT("\\Conversion\\Readwritable\\Main"));
  799. DWORD dw; dw = OLEUI_CCHKEYMAX_SIZE;
  800. lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw);
  801. if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat))
  802. {
  803. // Here, we've got a list of formats that this class can read
  804. // and write. We need to see if the original class' format is
  805. // in this list. We do that by looking for wFormat in
  806. // szFormat - if it in there, then we add this class to the
  807. // ACTIVATEAS list only. we do NOT automatically add it to the
  808. // CONVERT list. Readable and Readwritable format lists should
  809. // be handled separately.
  810. dw=OLEUI_CCHKEYMAX_SIZE;
  811. lRet=RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw);
  812. if (ERROR_SUCCESS == lRet && hListActivate != NULL)
  813. {
  814. // only add if not already in list
  815. lstrcat(szHRClassName, TEXT("\t"));
  816. if (LB_ERR == SendMessage(hListActivate, LB_FINDSTRING, 0, (LPARAM)szHRClassName))
  817. {
  818. lstrcat(szHRClassName, szClass);
  819. SendMessage(hListActivate, LB_ADDSTRING, 0, (LPARAM)szHRClassName);
  820. }
  821. }
  822. }
  823. // Here we'll check to see if the original class' format is in the
  824. // readable list. if so, we will add the class to the CONVERTLIST
  825. // We've got a special case for a linked object here.
  826. // If an object is linked, then the only class that
  827. // should appear in the convert list is the object's
  828. // class. So, here we check to see if the object is
  829. // linked. If it is, then we compare the classes. If
  830. // they aren't the same, then we just go to the next key.
  831. if (!fIsLinkedObject || lstrcmp(lpszCLSID, szClass) == 0)
  832. {
  833. //Check for a \Conversion\Readable\Main entry
  834. lstrcpy(szFormatKey, szClass);
  835. lstrcat(szFormatKey, TEXT("\\Conversion\\Readable\\Main"));
  836. // Check to see if this class can read the original class
  837. // format. If it can, add the string to the listbox as
  838. // CONVERT_LIST.
  839. dw = OLEUI_CCHKEYMAX_SIZE;
  840. lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw);
  841. if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat))
  842. {
  843. dw = OLEUI_CCHKEYMAX_SIZE;
  844. lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw);
  845. if (ERROR_SUCCESS == lRet)
  846. {
  847. // only add if not already in list
  848. lstrcat(szHRClassName, TEXT("\t"));
  849. if (LB_ERR == SendMessage(hListConvert, LB_FINDSTRING, 0, (LPARAM)szHRClassName))
  850. {
  851. lstrcat(szHRClassName, szClass);
  852. SendMessage(hListConvert, LB_ADDSTRING, 0, (LPARAM)szHRClassName);
  853. }
  854. }
  855. }
  856. }
  857. Next:
  858. //Continue with the next key.
  859. lRet = RegEnumKey(hKey, cStrings++, szClass, sizeof(szClass) / sizeof(TCHAR));
  860. } // end while
  861. // If the original class isn't already in the list, add it.
  862. if (bAddSameClass)
  863. {
  864. lstrcpy(szHRClassName, *lplpszCurrentClass);
  865. lstrcat(szHRClassName, TEXT("\t"));
  866. lstrcat(szHRClassName, lpszCLSID);
  867. if (hListActivate != NULL)
  868. {
  869. // only add it if it's not there already.
  870. lpRet = SendMessage(hListActivate, LB_FINDSTRING, (WPARAM)-1, (LPARAM)szHRClassName);
  871. if (LB_ERR == lpRet)
  872. SendMessage(hListActivate, LB_ADDSTRING, 0, (LPARAM)szHRClassName);
  873. }
  874. // only add it if it's not there already.
  875. lpRet = SendMessage(hListConvert, LB_FINDSTRING, (WPARAM)-1, (LPARAM)szHRClassName);
  876. if (LB_ERR == lpRet)
  877. SendMessage(hListConvert, LB_ADDSTRING, 0, (LPARAM)szHRClassName);
  878. }
  879. // Free the string we got from StringFromCLSID.
  880. OleStdFree(lpszCLSID);
  881. RegCloseKey(hKey);
  882. return cStrings; // return # of strings added
  883. }
  884. /*
  885. * OleUICanConvertOrActivateAs
  886. *
  887. * Purpose:
  888. * Determine if there is any OLE object class from the registration
  889. * database that we can convert or activate the specified clsid from.
  890. *
  891. * Parameters:
  892. * rClsid REFCLSID Class ID for class to find convert classes for
  893. * fIsLinkedObject BOOL is the original object a linked object
  894. * wFormat WORD specifying the format of the original class.
  895. *
  896. * Return Value:
  897. * BOOL TRUE if Convert command should be enabled, else FALSE
  898. */
  899. STDAPI_(BOOL) OleUICanConvertOrActivateAs(
  900. REFCLSID rClsid, BOOL fIsLinkedObject, WORD wFormat)
  901. {
  902. // Open up the root key.
  903. HKEY hKey;
  904. HRESULT hr;
  905. LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey);
  906. if (ERROR_SUCCESS != lRet)
  907. return FALSE;
  908. // Get the class name of the original class.
  909. LPTSTR lpszCLSID = NULL;
  910. #if defined(WIN32) && !defined(UNICODE)
  911. // This code does not report allocation errors because neither did
  912. // the original code before I extended it to support 32-bit ANSI builds.
  913. // In any event, if OleStdMalloc returns NULL, then the string will
  914. // simply be lost. Technically an error, but not a fatal one.
  915. // Since this routine has no way to report errors anyway (a design flaw
  916. // IMHO) I consider this to be marginally acceptable.
  917. LPOLESTR wszCLSID;
  918. StringFromCLSID(rClsid, &wszCLSID);
  919. lpszCLSID = NULL;
  920. if (NULL != wszCLSID)
  921. {
  922. UINT uLen = WTOALEN(wszCLSID);
  923. lpszCLSID = (LPTSTR) OleStdMalloc(uLen);
  924. if (NULL != lpszCLSID)
  925. {
  926. WTOA(lpszCLSID, wszCLSID, uLen);
  927. }
  928. OleStdFree(wszCLSID);
  929. }
  930. #else
  931. hr = StringFromCLSID(rClsid, &lpszCLSID);
  932. #endif
  933. if (FAILED(hr) || lpszCLSID == NULL) //out of memory, most likely
  934. return FALSE;
  935. // Here, we step through the entire registration db looking for
  936. // class that can read or write the original class' format.
  937. // This loop stops if a single class is found.
  938. UINT cStrings = 0;
  939. TCHAR szClass[OLEUI_CCHKEYMAX];
  940. lRet = RegEnumKey(hKey, cStrings++, szClass, sizeof(szClass) / sizeof(TCHAR));
  941. TCHAR szFormatKey[OLEUI_CCHKEYMAX];
  942. TCHAR szFormat[OLEUI_CCHKEYMAX];
  943. TCHAR szHRClassName[OLEUI_CCHKEYMAX];
  944. BOOL fEnableConvert = FALSE;
  945. while (ERROR_SUCCESS == lRet)
  946. {
  947. if (lstrcmp(lpszCLSID, szClass) == 0)
  948. goto next; // we don't want to consider the source class
  949. // Check for a \Conversion\ReadWriteable\Main entry first - if its
  950. // readwriteable, then we don't need to bother checking to see if
  951. // its readable.
  952. lstrcpy(szFormatKey, szClass);
  953. lstrcat(szFormatKey, TEXT("\\Conversion\\Readwritable\\Main"));
  954. DWORD dw; dw = OLEUI_CCHKEYMAX_SIZE;
  955. lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw);
  956. if (ERROR_SUCCESS != lRet)
  957. {
  958. // Try \\DataFormats\DefaultFile too
  959. lstrcpy(szFormatKey, szClass);
  960. lstrcat(szFormatKey, TEXT("\\DataFormats\\DefaultFile"));
  961. dw = OLEUI_CCHKEYMAX_SIZE;
  962. lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw);
  963. }
  964. if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat))
  965. {
  966. // Here, we've got a list of formats that this class can read
  967. // and write. We need to see if the original class' format is
  968. // in this list. We do that by looking for wFormat in
  969. // szFormat - if it in there, then we add this class to the
  970. // both lists and continue. If not, then we look at the
  971. // class' readable formats.
  972. dw = OLEUI_CCHKEYMAX_SIZE;
  973. lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw);
  974. if (ERROR_SUCCESS == lRet)
  975. {
  976. fEnableConvert = TRUE;
  977. break; // STOP -- found one!
  978. }
  979. }
  980. // We either didn't find the readwritable key, or the
  981. // list of readwritable formats didn't include the
  982. // original class format. So, here we'll check to
  983. // see if its in the readable list.
  984. // We've got a special case for a linked object here.
  985. // If an object is linked, then the only class that
  986. // should appear in the convert list is the object's
  987. // class. So, here we check to see if the object is
  988. // linked. If it is, then we compare the classes. If
  989. // they aren't the same, then we just go to the next key.
  990. else if (!fIsLinkedObject || lstrcmp(lpszCLSID, szClass) == 0)
  991. {
  992. // Check for a \Conversion\Readable\Main entry
  993. lstrcpy(szFormatKey, szClass);
  994. lstrcat(szFormatKey, TEXT("\\Conversion\\Readable\\Main"));
  995. // Check to see if this class can read the original class format.
  996. dw = OLEUI_CCHKEYMAX_SIZE;
  997. lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw);
  998. if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat))
  999. {
  1000. dw = OLEUI_CCHKEYMAX_SIZE;
  1001. lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw);
  1002. if (ERROR_SUCCESS == lRet)
  1003. {
  1004. fEnableConvert = TRUE;
  1005. break; // STOP -- found one!
  1006. }
  1007. }
  1008. }
  1009. next:
  1010. // Continue with the next key.
  1011. lRet = RegEnumKey(hKey, cStrings++, szClass, sizeof(szClass) / sizeof(TCHAR));
  1012. }
  1013. // Free the string we got from StringFromCLSID.
  1014. OleStdFree(lpszCLSID);
  1015. RegCloseKey(hKey);
  1016. return fEnableConvert;
  1017. }
  1018. /*
  1019. * FormatIncluded
  1020. *
  1021. * Purpose:
  1022. * Parses the string for format from the word.
  1023. *
  1024. * Parameters:
  1025. * szStringToSearch String to parse
  1026. * wFormat format to find
  1027. *
  1028. * Return Value:
  1029. * BOOL TRUE if format is found in string,
  1030. * FALSE otherwise.
  1031. */
  1032. BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat)
  1033. {
  1034. TCHAR szFormat[255];
  1035. if (wFormat < 0xC000)
  1036. wsprintf(szFormat, TEXT("%d"), wFormat);
  1037. else
  1038. GetClipboardFormatName(wFormat, szFormat, 255);
  1039. LPTSTR lpToken = szStringToSearch;
  1040. while (lpToken != NULL)
  1041. {
  1042. LPTSTR lpTokenNext = FindChar(lpToken, TEXT(','));
  1043. if (lpTokenNext != NULL)
  1044. {
  1045. *lpTokenNext = 0;
  1046. ++lpTokenNext;
  1047. }
  1048. if (0 == lstrcmpi(lpToken, szFormat))
  1049. return TRUE;
  1050. lpToken = lpTokenNext;
  1051. }
  1052. return FALSE;
  1053. }
  1054. /*
  1055. * UpdateClassIcon
  1056. *
  1057. * Purpose:
  1058. * Handles LBN_SELCHANGE for the Object Type listbox. On a selection
  1059. * change, we extract an icon from the server handling the currently
  1060. * selected object type using the utility function HIconFromClass.
  1061. * Note that we depend on the behavior of FillClassList to stuff the
  1062. * object class after a tab in the listbox string that we hide from
  1063. * view (see WM_INITDIALOG).
  1064. *
  1065. * Parameters
  1066. * hDlg HWND of the dialog box.
  1067. * lpCV LPCONVERT pointing to the dialog structure
  1068. * hList HWND of the Object Type listbox.
  1069. *
  1070. * Return Value:
  1071. * None
  1072. */
  1073. static void UpdateClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList)
  1074. {
  1075. if (GetDlgItem(hDlg, IDC_CV_ICONDISPLAY) == NULL)
  1076. return;
  1077. // Get current selection in the list box
  1078. int iSel= (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1079. if (LB_ERR == iSel)
  1080. return;
  1081. // Allocate a string to hold the entire listbox string
  1082. DWORD cb = (DWORD)SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
  1083. LPTSTR pszName = (LPTSTR)OleStdMalloc((cb+1) * sizeof(TCHAR));
  1084. if (pszName == NULL)
  1085. return;
  1086. // Get whole string
  1087. SendMessage(hList, LB_GETTEXT, iSel, (LPARAM)pszName);
  1088. // Set pointer to CLSID (string)
  1089. LPTSTR pszCLSID = PointerToNthField(pszName, 2, '\t');
  1090. // Create the class ID with this string.
  1091. CLSID clsid;
  1092. #if defined(WIN32) && !defined(UNICODE)
  1093. OLECHAR wszCLSID[OLEUI_CCHKEYMAX];
  1094. ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX);
  1095. HRESULT hr = CLSIDFromString(wszCLSID, &clsid);
  1096. #else
  1097. HRESULT hr = CLSIDFromString(pszCLSID, &clsid);
  1098. #endif
  1099. if (SUCCEEDED(hr))
  1100. {
  1101. // Get Icon for that CLSID
  1102. HGLOBAL hMetaPict = OleGetIconOfClass(clsid, NULL, TRUE);
  1103. // Replace current icon with the new one.
  1104. SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET, 1,
  1105. (LPARAM)hMetaPict);
  1106. }
  1107. OleStdFree(pszName);
  1108. }
  1109. /*
  1110. * SetConvertResults
  1111. *
  1112. * Purpose:
  1113. * Centralizes setting of the Result display in the Convert
  1114. * dialog. Handles loading the appropriate string from the module's
  1115. * resources and setting the text, displaying the proper result picture,
  1116. * and showing the proper icon.
  1117. *
  1118. * Parameters:
  1119. * hDlg HWND of the dialog box so we can access controls.
  1120. * lpCV LPCONVERT in which we assume that the dwFlags is
  1121. * set to the appropriate radio button selection, and
  1122. * the list box has the appropriate class selected.
  1123. *
  1124. * Return Value:
  1125. * None
  1126. */
  1127. void SetConvertResults(HWND hDlg, LPCONVERT lpCV)
  1128. {
  1129. HWND hList = lpCV->hListVisible;
  1130. /*
  1131. * We need scratch memory for loading the stringtable string, loading
  1132. * the object type from the listbox, loading the source object
  1133. * type, and constructing the final string. We therefore allocate
  1134. * four buffers as large as the maximum message length (512) plus
  1135. * the object type, guaranteeing that we have enough
  1136. * in all cases.
  1137. */
  1138. UINT i = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1139. UINT cch = 512+(UINT)SendMessage(hList, LB_GETTEXTLEN, i, 0L);
  1140. HGLOBAL hMem = GlobalAlloc(GHND, (DWORD)(4*cch)*sizeof(TCHAR));
  1141. if (NULL == hMem)
  1142. return;
  1143. LPTSTR lpszOutput = (LPTSTR)GlobalLock(hMem);
  1144. LPTSTR lpszSelObj = lpszOutput + cch;
  1145. LPTSTR lpszDefObj = lpszSelObj + cch;
  1146. LPTSTR lpszString = lpszDefObj + cch;
  1147. // Get selected object and null terminate human-readable name (1st field).
  1148. SendMessage(hList, LB_GETTEXT, i, (LPARAM)lpszSelObj);
  1149. LPTSTR pszT = PointerToNthField(lpszSelObj, 2, '\t');
  1150. pszT = CharPrev(lpszSelObj, pszT);
  1151. *pszT = '\0';
  1152. // Get default object
  1153. GetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, lpszDefObj, 512);
  1154. //Default is an empty string.
  1155. *lpszOutput=0;
  1156. if (lpCV->dwFlags & CF_SELECTCONVERTTO)
  1157. {
  1158. if (lpCV->lpOCV->fIsLinkedObject) // working with linked object
  1159. LoadString(_g_hOleStdResInst, IDS_CVRESULTCONVERTLINK, lpszOutput, cch);
  1160. else
  1161. {
  1162. if (0 !=lstrcmp(lpszDefObj, lpszSelObj))
  1163. {
  1164. // converting to a new class
  1165. if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTCONVERTTO, lpszString, cch))
  1166. FormatString2(lpszOutput, lpszString, lpszDefObj, lpszSelObj);
  1167. }
  1168. else
  1169. {
  1170. // converting to the same class (no conversion)
  1171. if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTNOCHANGE, lpszString, cch))
  1172. wsprintf(lpszOutput, lpszString, lpszDefObj);
  1173. }
  1174. }
  1175. if (lpCV->dvAspect == DVASPECT_ICON) // Display as icon is checked
  1176. {
  1177. if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTDISPLAYASICON, lpszString, cch))
  1178. lstrcat(lpszOutput, lpszString);
  1179. }
  1180. }
  1181. if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
  1182. {
  1183. if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTACTIVATEAS, lpszString, cch))
  1184. FormatString2(lpszOutput, lpszString, lpszDefObj, lpszSelObj);
  1185. // activating as a new class
  1186. if (0 != lstrcmp(lpszDefObj, lpszSelObj))
  1187. {
  1188. if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTACTIVATEDIFF, lpszString, cch))
  1189. lstrcat(lpszOutput, lpszString);
  1190. }
  1191. else // activating as itself.
  1192. {
  1193. lstrcat(lpszOutput, TEXT("."));
  1194. }
  1195. }
  1196. // If LoadString failed, we simply clear out the results (*lpszOutput=0 above)
  1197. SetDlgItemText(hDlg, IDC_CV_RESULTTEXT, lpszOutput);
  1198. GlobalUnlock(hMem);
  1199. GlobalFree(hMem);
  1200. }
  1201. /*
  1202. * ConvertCleanup
  1203. *
  1204. * Purpose:
  1205. * Performs convert-specific cleanup before Convert termination.
  1206. *
  1207. * Parameters:
  1208. * hDlg HWND of the dialog box so we can access controls.
  1209. *
  1210. * Return Value:
  1211. * None
  1212. */
  1213. void ConvertCleanup(HWND hDlg, LPCONVERT lpCV)
  1214. {
  1215. // Free our strings. Zero out the user type name string
  1216. // the the calling app doesn't free to it.
  1217. OleStdFree((LPVOID)lpCV->lpszConvertDefault);
  1218. OleStdFree((LPVOID)lpCV->lpszActivateDefault);
  1219. OleStdFree((LPVOID)lpCV->lpszIconSource);
  1220. if (lpCV->lpOCV->lpszUserType)
  1221. {
  1222. OleStdFree((LPVOID)lpCV->lpOCV->lpszUserType);
  1223. lpCV->lpOCV->lpszUserType = NULL;
  1224. }
  1225. if (lpCV->lpOCV->lpszDefLabel)
  1226. {
  1227. OleStdFree((LPVOID)lpCV->lpOCV->lpszDefLabel);
  1228. lpCV->lpOCV->lpszDefLabel = NULL;
  1229. }
  1230. }
  1231. /*
  1232. * SwapWindows
  1233. *
  1234. * Purpose:
  1235. * Moves hWnd1 to hWnd2's position and hWnd2 to hWnd1's position.
  1236. * Does NOT change sizes.
  1237. *
  1238. * Parameters:
  1239. * hDlg HWND of the dialog box so we can turn redraw off
  1240. *
  1241. * Return Value:
  1242. * None
  1243. */
  1244. void SwapWindows(HWND hDlg, HWND hWnd1, HWND hWnd2)
  1245. {
  1246. if (hWnd1 != NULL && hWnd2 != NULL)
  1247. {
  1248. RECT rect1; GetWindowRect(hWnd1, &rect1);
  1249. MapWindowPoints(NULL, hDlg, (LPPOINT)&rect1, 2);
  1250. RECT rect2; GetWindowRect(hWnd2, &rect2);
  1251. MapWindowPoints(NULL, hDlg, (LPPOINT)&rect2, 2);
  1252. SetWindowPos(hWnd1, NULL,
  1253. rect2.left, rect2.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  1254. SetWindowPos(hWnd2, NULL,
  1255. rect1.left, rect1.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  1256. }
  1257. }