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.

1802 lines
57 KiB

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