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.

2387 lines
66 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: icon.cpp
  7. //
  8. // Contents: Functions to create DVASPECT_ICON metafile from a filename
  9. // or class ID
  10. //
  11. // Classes:
  12. //
  13. // Functions:
  14. // OleGetIconOfFile
  15. // OleGetIconOfClass
  16. // OleMetafilePictFromIconAndLabel
  17. //
  18. // HIconAndSourceFromClass: Extracts the first icon in a class's
  19. // server path and returns the path and icon index to
  20. // caller.
  21. // FIconFileFromClass: Retrieves the path to the exe/dll
  22. // containing the default icon, and the index of the icon.
  23. // IconLabelTextOut
  24. // XformWidthInPixelsToHimetric
  25. // Converts an int width into HiMetric units
  26. // XformWidthInHimetricToPixels
  27. // Converts an int width from HiMetric units
  28. // XformHeightInPixelsToHimetric
  29. // Converts an int height into HiMetric units
  30. // XformHeightInHimetricToPixels
  31. // Converts an int height from HiMetric units
  32. //
  33. // History: dd-mmm-yy Author Comment
  34. // 24-Nov-93 alexgo 32bit port
  35. // 15-Dec-93 alexgo fixed some bad UNICODE string handling
  36. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  37. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  38. // memory allocations.
  39. // 26-Apr-94 AlexT Add tracing, fix bugs, etc
  40. // 27-Dec-94 alexgo fixed multithreading problems, added
  41. // support for quoted icon names
  42. //
  43. // Notes:
  44. //
  45. //--------------------------------------------------------------------------
  46. #include <le2int.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <ctype.h>
  50. #include <commdlg.h>
  51. #include <memory.h>
  52. #include <cderr.h>
  53. #include <resource.h>
  54. #include "icon.h"
  55. #define OLEUI_CCHKEYMAX 256
  56. #define OLEUI_CCHPATHMAX 256
  57. #define OLEUI_CCHLABELMAX 42
  58. #define ICONINDEX 0
  59. #define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
  60. #define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
  61. #define PTS_PER_INCH 72 // number points (font size) per inch
  62. #define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
  63. #define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
  64. static OLECHAR const gszDefIconLabelKey[] =
  65. OLESTR( "Software\\Microsoft\\OLE2\\DefaultIconLabel");
  66. #define IS_SEPARATOR(c) ( (c) == OLESTR(' ') || (c) == OLESTR('\\') || (c) == OLESTR('/') || (c) == OLESTR('\t') || (c) == OLESTR('!') || (c) == OLESTR(':') )
  67. //REVIEW: what about the \\ case for UNC filenames, could it be considered a delimter also?
  68. #define IS_FILENAME_DELIM(c) ( (c) == OLESTR('\\') || (c) == OLESTR('/') || (c) == OLESTR(':') )
  69. #ifdef WIN32
  70. #define LSTRCPYN(lpdst, lpsrc, cch) \
  71. (\
  72. lpdst[cch-1] = OLESTR('\0'), \
  73. lstrcpynW(lpdst, lpsrc, cch-1)\
  74. )
  75. #else
  76. #define LSTRCPYN(lpdst, lpsrc, cch) \
  77. (\
  78. lpdst[cch-1] = OLESTR('\0'), \
  79. lstrncpy(lpdst, lpsrc, cch-1)\
  80. )
  81. #endif
  82. void IconLabelTextOut(HDC hDC, HFONT hFont, int nXStart, int nYStart,
  83. UINT fuOptions, RECT FAR * lpRect, LPCSTR lpszString,
  84. UINT cchString);
  85. /*******
  86. *
  87. * ICON METAFILE FORMAT:
  88. *
  89. * The metafile generated with OleMetafilePictFromIconAndLabel contains
  90. * the following records which are used by the functions in DRAWICON.C
  91. * to draw the icon with and without the label and to extract the icon,
  92. * label, and icon source/index.
  93. *
  94. * SetWindowOrg
  95. * SetWindowExt
  96. * DrawIcon:
  97. * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
  98. * AND mask, one for the image bits.
  99. * Escape with the comment "IconOnly"
  100. * This indicates where to stop record enumeration to draw only
  101. * the icon.
  102. * SetTextColor
  103. * SetBkColor
  104. * CreateFont
  105. * SelectObject on the font.
  106. * ExtTextOut
  107. * One or more ExtTextOuts occur if the label is wrapped. The
  108. * text in these records is used to extract the label.
  109. * SelectObject on the old font.
  110. * DeleteObject on the font.
  111. * Escape with a comment that contains the path to the icon source (ANSI).
  112. * Escape with a comment that is the string of the icon index (ANSI).
  113. *
  114. * Additional optional fields (new for 32-bit OLE, and only present if icon
  115. * source or label was not translatable):
  116. *
  117. * Escape with a comment that contains the string
  118. * "OLE: Icon label next (Unicode)" (ANSI string)
  119. * Escape with a comment that contains the Unicode label
  120. *
  121. * Escape with a comment that contains the string
  122. * "OLE: Icon source next (Unicode)" (ANSI string)
  123. * Escape with a comment that contains the path to the icon source (UNICODE)
  124. *
  125. *******/
  126. //+-------------------------------------------------------------------------
  127. //
  128. // Function: OleGetIconOfFile (public)
  129. //
  130. // Synopsis: Returns a hMetaPict containing an icon and label (filename)
  131. // for the specified filename
  132. //
  133. // Effects:
  134. //
  135. // Arguments: [lpszPath] -- LPOLESTR path including filename to use
  136. // [fUseAsLabel] -- if TRUE, use the filename as the icon's
  137. // label; no label if FALSE
  138. //
  139. // Requires: lpszPath != NULL
  140. //
  141. // Returns: HGLOBAL to the hMetaPict
  142. //
  143. // Signals:
  144. //
  145. // Modifies:
  146. //
  147. // Algorithm: tries to get the icon from the class ID or from the
  148. // exe associated with the file extension.
  149. //
  150. // History: dd-mmm-yy Author Comment
  151. // 27-Nov-93 alexgo first 32bit port (minor cleanup)
  152. // 15-Dec-93 alexgo changed lstrlen to _xstrlen
  153. // 27-Dec-93 erikgav chicago port
  154. // 28-Dec-94 alexgo fixed multithreading problems
  155. //
  156. // Notes:
  157. //
  158. //--------------------------------------------------------------------------
  159. STDAPI_(HGLOBAL) OleGetIconOfFile(LPOLESTR lpszPath, BOOL fUseFileAsLabel)
  160. {
  161. OLETRACEIN((API_OleGetIconOfFile, PARAMFMT("lpszPath= %ws, fUseFileAsLabel= %B"),
  162. lpszPath, fUseFileAsLabel));
  163. VDATEHEAP();
  164. HGLOBAL hMetaPict = NULL;
  165. BOOL fUseGenericDocIcon = FALSE;
  166. BOOL bRet;
  167. OLECHAR szIconFile[OLEUI_CCHPATHMAX];
  168. OLECHAR szLabel[OLEUI_CCHLABELMAX];
  169. OLECHAR szDocument[OLEUI_CCHLABELMAX];
  170. CLSID clsid;
  171. HICON hDefIcon = NULL;
  172. UINT IconIndex = 0;
  173. UINT cchPath;
  174. BOOL fGotLabel = FALSE;
  175. HRESULT hResult = E_FAIL;
  176. UINT uFlags;
  177. LEDebugOut((DEB_TRACE, "%p _IN OleGetIconOfFile (%p, %d)\n",
  178. NULL, lpszPath, fUseFileAsLabel));
  179. *szIconFile = OLESTR('\0');
  180. *szDocument = OLESTR('\0');
  181. if (NULL == lpszPath)
  182. {
  183. // The spec allows a NULL lpszPath...
  184. hMetaPict = NULL;
  185. goto ErrRtn;
  186. }
  187. SHFILEINFO shfi;
  188. uFlags = (SHGFI_ICON | SHGFI_LARGEICON | SHGFI_DISPLAYNAME |
  189. SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
  190. _xmemset(&shfi, 0, sizeof(shfi));
  191. if (fUseFileAsLabel)
  192. uFlags |= SHGFI_LINKOVERLAY;
  193. if (OleSHGetFileInfo( lpszPath, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), uFlags))
  194. {
  195. if (shfi.iIcon == 0)
  196. {
  197. // Destroy the returned icon
  198. DestroyIcon(shfi.hIcon);
  199. // REVIEW: if non-NULL path str, do we want parameter validation?
  200. hResult = GetClassFile(lpszPath, &clsid);
  201. // use the clsid we got to get to the icon
  202. if( NOERROR == hResult )
  203. {
  204. hDefIcon = HIconAndSourceFromClass(clsid, szIconFile, &IconIndex);
  205. }
  206. }
  207. else
  208. {
  209. hDefIcon = shfi.hIcon;
  210. hResult = NOERROR;
  211. OLECHAR szUnicodeLabel[OLEUI_CCHLABELMAX];
  212. #ifdef _CHICAGO_
  213. LPTSTR lpszDisplayName;
  214. if (fUseFileAsLabel)
  215. lpszDisplayName = shfi.szDisplayName;
  216. else
  217. lpszDisplayName = shfi.szTypeName;
  218. if(MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, lpszDisplayName,
  219. -1, szUnicodeLabel, OLEUI_CCHLABELMAX) )
  220. {
  221. LSTRCPYN(szLabel, szUnicodeLabel,
  222. sizeof(szLabel)/sizeof(OLECHAR) );
  223. }
  224. #else
  225. if (fUseFileAsLabel)
  226. LSTRCPYN(szLabel, shfi.szDisplayName, sizeof(szLabel)/sizeof(OLECHAR));
  227. else
  228. LSTRCPYN(szLabel, shfi.szTypeName, sizeof(szLabel)/sizeof(OLECHAR));
  229. #endif
  230. fGotLabel = TRUE;
  231. // need to fill out szIconFile, which is the path to the file in which the icon
  232. // was extracted. Unfortunately, the shell can't return this value to us, so we
  233. // must get the file that OLE would have used in the fallback case. This could
  234. // be inconsistant with the shell if the application has installed a custom icon
  235. // handler.
  236. hResult = GetClassFile(lpszPath, &clsid);
  237. if( NOERROR == hResult )
  238. {
  239. FIconFileFromClass(clsid, szIconFile, OLEUI_CCHPATHMAX, &IconIndex);
  240. }
  241. }
  242. }
  243. cchPath = _xstrlen(lpszPath);
  244. if ((NOERROR != hResult) || (NULL == hDefIcon))
  245. {
  246. WORD index = 0;
  247. // we need to copy into a large buffer because the second
  248. // parameter of ExtractAssociatedIcon (the path name) is an
  249. // in/out
  250. _xstrcpy(szIconFile, lpszPath);
  251. hDefIcon = OleExtractAssociatedIcon(g_hmodOLE2, szIconFile, &index);
  252. IconIndex = index;
  253. }
  254. if (fUseGenericDocIcon || hDefIcon <= (HICON)1)
  255. {
  256. DWORD dwLen;
  257. dwLen = GetModuleFileName(g_hmodOLE2,
  258. szIconFile,
  259. sizeof(szIconFile) / sizeof(OLECHAR));
  260. if (0 == dwLen)
  261. {
  262. LEDebugOut((DEB_WARN,
  263. "OleGetIconOfFile: GetModuleFileName failed - %ld",
  264. GetLastError()));
  265. goto ErrRtn;
  266. }
  267. IconIndex = ICONINDEX;
  268. hDefIcon = LoadIcon(g_hmodOLE2, MAKEINTRESOURCE(DEFICON));
  269. }
  270. // Now let's get the label we want to use.
  271. if (fGotLabel)
  272. {
  273. // Do nothing
  274. }
  275. else if (fUseFileAsLabel)
  276. {
  277. // This assumes the path uses only '\', '/', and '.' as separators
  278. // strip off path, so we just have the filename.
  279. LPOLESTR lpszBeginFile;
  280. // set pointer to END of path, so we can walk backwards
  281. // through it.
  282. lpszBeginFile = lpszPath + cchPath - 1;
  283. while ((lpszBeginFile >= lpszPath) &&
  284. (!IS_FILENAME_DELIM(*lpszBeginFile)))
  285. {
  286. #ifdef WIN32
  287. lpszBeginFile--;
  288. #else
  289. lpszBeginFile = CharPrev(lpszPath, lpszBeginFile);
  290. #endif
  291. }
  292. lpszBeginFile++; // step back over the delimiter
  293. // LSTRCPYN takes count of characters!
  294. LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel) / sizeof(OLECHAR));
  295. }
  296. // use the short user type (AuxUserType2) for the label
  297. else if (0 == OleStdGetAuxUserType(clsid, AUXUSERTYPE_SHORTNAME,
  298. szLabel, OLEUI_CCHLABELMAX, NULL))
  299. {
  300. if (OLESTR('\0')==szDocument[0]) // review, this is always true
  301. {
  302. LONG lRet;
  303. LONG lcb;
  304. lcb = sizeof (szDocument);
  305. lRet = RegQueryValue(HKEY_CLASSES_ROOT, gszDefIconLabelKey,
  306. szDocument, &lcb);
  307. #if DBG==1
  308. if (ERROR_SUCCESS != lRet)
  309. {
  310. LEDebugOut((DEB_WARN,
  311. "RegQueryValue for default icon label failed - %d\n",
  312. GetLastError()));
  313. }
  314. #endif
  315. // NULL out last byte of string so don't rely on Reg behavior if buffer isn't big enough
  316. szDocument[OLEUI_CCHLABELMAX -1] = OLESTR('\0');
  317. }
  318. _xstrcpy(szLabel, szDocument);
  319. }
  320. hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon, szLabel,
  321. szIconFile, IconIndex);
  322. bRet = DestroyIcon(hDefIcon);
  323. Win4Assert(bRet && "DestroyIcon failed");
  324. ErrRtn:
  325. LEDebugOut((DEB_TRACE, "%p OUT OleGetIconOfFile( %lx )\n",
  326. hMetaPict ));
  327. OLETRACEOUTEX((API_OleGetIconOfFile, RETURNFMT("%h"), hMetaPict));
  328. return hMetaPict;
  329. }
  330. //+-------------------------------------------------------------------------
  331. //
  332. // Function: GetAssociatedExectutable
  333. //
  334. // Synopsis: Finds the executables associated with the provided extension
  335. //
  336. // Effects:
  337. //
  338. // Arguments: [lpszExtension] -- pointer to the extension
  339. // [lpszExecutable] -- where to put the executable name
  340. // (assumes OLEUIPATHMAX OLECHAR buffer
  341. // from calling function)
  342. //
  343. // Requires: lpszExecutable must be large enough to hold the path
  344. //
  345. // Returns: TRUE if exe found, FALSE otherwise
  346. //
  347. // Signals:
  348. //
  349. // Modifies:
  350. //
  351. // Algorithm: Queries reg database
  352. //
  353. // History: dd-mmm-yy Author Comment
  354. // 27-Nov-93 alexgo 32bit port
  355. // 15-Dec-93 alexgo fixed bug calculating size of strings
  356. // 26-Apr-94 AlexT Tracing, bug fixes
  357. //
  358. // Notes:
  359. //
  360. //--------------------------------------------------------------------------
  361. BOOL FAR PASCAL GetAssociatedExecutable(LPOLESTR lpszExtension,
  362. LPOLESTR lpszExecutable)
  363. {
  364. VDATEHEAP();
  365. BOOL bRet;
  366. HKEY hKey;
  367. LONG dw;
  368. LRESULT lRet;
  369. OLECHAR szValue[OLEUI_CCHKEYMAX];
  370. OLECHAR szKey[OLEUI_CCHKEYMAX];
  371. LPOLESTR lpszTemp, lpszExe;
  372. LEDebugOut((DEB_ITRACE, "%p _IN GetAssociatedExecutable (%p, %p)\n",
  373. NULL, lpszExtension, lpszExecutable));
  374. // REVIEW: actually returns a LONG, which is indeed an LRESULT, not
  375. // sure why the distinction here
  376. lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
  377. if (ERROR_SUCCESS != lRet)
  378. {
  379. bRet = FALSE;
  380. goto ErrRtn;
  381. }
  382. dw = sizeof(szValue);
  383. lRet = RegQueryValue(hKey, lpszExtension, szValue, &dw);
  384. if (ERROR_SUCCESS != lRet)
  385. {
  386. RegCloseKey(hKey);
  387. bRet = FALSE;
  388. goto ErrRtn;
  389. }
  390. // szValue now has ProgID
  391. _xstrcpy(szKey, szValue);
  392. _xstrcat(szKey, OLESTR("\\Shell\\Open\\Command"));
  393. // RegQueryValue wants *bytes*, not characters
  394. dw = sizeof(szValue);
  395. lRet = RegQueryValue(hKey, szKey, szValue, &dw);
  396. RegCloseKey(hKey);
  397. if (ERROR_SUCCESS != lRet)
  398. {
  399. bRet = FALSE;
  400. goto ErrRtn;
  401. }
  402. // szValue now has an executable name in it. Let's null-terminate
  403. // at the first post-executable space (so we don't have cmd line
  404. // args.
  405. lpszTemp = szValue;
  406. PUSHORT pCharTypes;
  407. pCharTypes = (PUSHORT)_alloca (sizeof (USHORT) * (lstrlenW(lpszTemp) + 1));
  408. if (pCharTypes == NULL)
  409. {
  410. goto ErrRtn;
  411. }
  412. GetStringTypeW (CT_CTYPE1, lpszTemp, -1, pCharTypes);
  413. while ((OLESTR('\0') != *lpszTemp) && (pCharTypes[lpszTemp - szValue] & C1_SPACE))
  414. {
  415. lpszTemp++; // Strip off leading spaces
  416. }
  417. lpszExe = lpszTemp;
  418. while ((OLESTR('\0') != *lpszTemp) && ((pCharTypes[lpszTemp - szValue] & C1_SPACE) == 0))
  419. {
  420. lpszTemp++; // Set through exe name
  421. }
  422. // null terminate at first space (or at end).
  423. *lpszTemp = OLESTR('\0');
  424. Win4Assert(_xstrlen(lpszExe) < OLEUI_CCHPATHMAX &&
  425. "GetAssociatedFile too long");
  426. _xstrcpy(lpszExecutable, lpszExe);
  427. bRet = TRUE;
  428. ErrRtn:
  429. LEDebugOut((DEB_ITRACE, "%p OUT GetAssociatedExecutable( %d )\n",
  430. bRet ));
  431. return bRet;
  432. }
  433. //+-------------------------------------------------------------------------
  434. //
  435. // Function: OleGetIconOfClass (public)
  436. //
  437. // Synopsis: returns a hMetaPict containing an icon and label for the
  438. // specified class ID
  439. //
  440. // Effects:
  441. //
  442. // Arguments: [rclsid] -- the class ID to use
  443. // [lpszLabel] -- the label for the icon
  444. // [fUseTypeAsLabel] -- if TRUE, use the clsid's user type
  445. // as the label
  446. //
  447. // Requires:
  448. //
  449. // Returns: HGLOBAL
  450. //
  451. // Signals:
  452. //
  453. // Modifies:
  454. //
  455. // Algorithm:
  456. //
  457. // History: dd-mmm-yy Author Comment
  458. // 15-Dec-93 alexgo fixed small bugs with Unicode strings
  459. // 27-Nov-93 alexgo 32bit port
  460. //
  461. // Notes:
  462. //
  463. //--------------------------------------------------------------------------
  464. STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPOLESTR lpszLabel,
  465. BOOL fUseTypeAsLabel)
  466. {
  467. OLETRACEIN((API_OleGetIconOfClass,
  468. PARAMFMT("rclisd= %I, lpszLabel= %p, fUseTypeAsLabel= %B"),
  469. &rclsid, lpszLabel, fUseTypeAsLabel));
  470. VDATEHEAP();
  471. BOOL bRet;
  472. OLECHAR szLabel[OLEUI_CCHLABELMAX];
  473. OLECHAR szIconFile[OLEUI_CCHPATHMAX];
  474. OLECHAR szDocument[OLEUI_CCHLABELMAX];
  475. HICON hDefIcon;
  476. UINT IconIndex;
  477. HGLOBAL hMetaPict = NULL;
  478. LEDebugOut((DEB_TRACE, "%p _IN OleGetIconOfClass (%p, %p, %d)\n",
  479. NULL, &rclsid, lpszLabel, fUseTypeAsLabel));
  480. *szLabel = OLESTR('\0');
  481. *szDocument = OLESTR('\0');
  482. #if DBG==1
  483. if (fUseTypeAsLabel && (NULL != lpszLabel))
  484. {
  485. LEDebugOut((DEB_WARN,
  486. "Ignoring non-NULL lpszLabel passed to OleGetIconOfClass\n"));
  487. }
  488. #endif
  489. if (!fUseTypeAsLabel) // Use string passed in as label
  490. {
  491. if (NULL != lpszLabel)
  492. {
  493. // LSTRCPYN takes count of characters!
  494. LSTRCPYN(szLabel, lpszLabel, sizeof(szLabel) / sizeof(OLECHAR));
  495. }
  496. }
  497. // Use AuxUserType2 (short name) as label
  498. else if (0 == OleStdGetAuxUserType(rclsid, AUXUSERTYPE_SHORTNAME,
  499. szLabel,
  500. sizeof(szLabel) / sizeof(OLECHAR),
  501. NULL))
  502. {
  503. // If we can't get the AuxUserType2, then try the long name
  504. if (0 == OleStdGetUserTypeOfClass(rclsid,
  505. szLabel,
  506. sizeof(szLabel) / sizeof(OLECHAR),
  507. NULL))
  508. {
  509. if (OLESTR('\0') == szDocument[0])
  510. {
  511. // RegQueryValue expects number of *bytes*
  512. LONG lRet;
  513. LONG lcb;
  514. lcb = sizeof(szDocument);
  515. lRet = RegQueryValue(HKEY_CLASSES_ROOT, gszDefIconLabelKey,
  516. szDocument, &lcb);
  517. #if DBG==1
  518. if (ERROR_SUCCESS != lRet)
  519. {
  520. LEDebugOut((DEB_WARN,
  521. "RegQueryValue for default icon label failed - %d\n",
  522. GetLastError()));
  523. }
  524. #endif
  525. // NULL out last byte of string so don't rely on Reg behavior if buffer isn't big enough
  526. szDocument[OLEUI_CCHLABELMAX -1] = OLESTR('\0');
  527. }
  528. _xstrcpy(szLabel, szDocument); // last resort
  529. }
  530. }
  531. // Get the icon, icon index, and path to icon file
  532. hDefIcon = HIconAndSourceFromClass(rclsid, szIconFile, &IconIndex);
  533. if (NULL == hDefIcon) // Use Vanilla Document
  534. {
  535. DWORD dwLen;
  536. dwLen = GetModuleFileName(g_hmodOLE2,
  537. szIconFile,
  538. sizeof(szIconFile) / sizeof(OLECHAR));
  539. if (0 == dwLen)
  540. {
  541. LEDebugOut((DEB_WARN,
  542. "OleGetIconOfClass: GetModuleFileName failed - %ld",
  543. GetLastError()));
  544. goto ErrRtn;
  545. }
  546. IconIndex = ICONINDEX;
  547. hDefIcon = LoadIcon(g_hmodOLE2, MAKEINTRESOURCE(DEFICON));
  548. }
  549. // Create the metafile
  550. hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon, szLabel,
  551. szIconFile, IconIndex);
  552. if(hDefIcon)
  553. bRet = DestroyIcon(hDefIcon);
  554. Win4Assert(bRet && "DestroyIcon failed");
  555. ErrRtn:
  556. LEDebugOut((DEB_TRACE, "%p OUT OleGetIconOfClass( %p )\n",
  557. NULL, hMetaPict ));
  558. OLETRACEOUTEX((API_OleGetIconOfClass, RETURNFMT("%h"), hMetaPict));
  559. return hMetaPict;
  560. }
  561. //+-------------------------------------------------------------------------
  562. //
  563. // Function: HIconAndSourceFromClass
  564. //
  565. // Synopsis:
  566. // Given an object class name, finds an associated executable in the
  567. // registration database and extracts the first icon from that
  568. // executable. If none is available or the class has no associated
  569. // executable, this function returns NULL.
  570. //
  571. // Effects:
  572. //
  573. // Arguments: [rclsid] -- pointer the class id
  574. // [pszSource] -- where to put the source of the icon
  575. // [puIcon] -- where to store the index of the icon
  576. // -- in [pszSource]
  577. //
  578. // Requires:
  579. //
  580. // Returns: HICON -- handle to the extracted icon
  581. //
  582. // Signals:
  583. //
  584. // Modifies:
  585. //
  586. // Algorithm:
  587. //
  588. // History: dd-mmm-yy Author Comment
  589. // 27-Nov-93 alexgo 32bit port
  590. //
  591. // Notes:
  592. //
  593. //--------------------------------------------------------------------------
  594. HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPOLESTR pszSource,
  595. UINT FAR *puIcon)
  596. {
  597. VDATEHEAP();
  598. HICON hIcon = NULL;
  599. UINT IconIndex;
  600. LEDebugOut((DEB_ITRACE, "%p _IN HIconAndSourceFromClass (%p, %p, %p)\n",
  601. NULL, &rclsid, pszSource, puIcon));
  602. if (IsEqualCLSID(CLSID_NULL, rclsid) || NULL==pszSource)
  603. {
  604. goto ErrRtn;
  605. }
  606. if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX, &IconIndex))
  607. {
  608. goto ErrRtn;
  609. }
  610. hIcon = OleExtractIcon(g_hmodOLE2, pszSource, IconIndex);
  611. // REVIEW: What's special about icon handles > 32 ?
  612. if ((HICON)32 > hIcon)
  613. {
  614. // REVIEW: any cleanup or releasing of handle needed before we lose
  615. // the ptr?
  616. hIcon=NULL;
  617. }
  618. else
  619. {
  620. *puIcon= IconIndex;
  621. }
  622. ErrRtn:
  623. LEDebugOut((DEB_ITRACE, "%p OUT HIconAndSourceFromClass( %lx ) [ %d ]\n",
  624. NULL, hIcon, *puIcon));
  625. return hIcon;
  626. }
  627. //+-------------------------------------------------------------------------
  628. //
  629. // Function: ExtractNameAndIndex
  630. //
  631. // Synopsis: from the given string, extract the file name and icon index
  632. //
  633. // Effects:
  634. //
  635. // Arguments: [pszInfo] -- the starting string
  636. // [pszEXE] -- where to put the name (already allocated)
  637. // [cchEXE] -- sizeof pszEXE
  638. // [pIndex] -- where to put the icon index
  639. //
  640. // Requires: pszInfo != NULL
  641. // pszEXE != NULL
  642. // cchEXE != 0
  643. // pIndex != NULL
  644. //
  645. // Returns: BOOL -- TRUE on success, FALSE on error
  646. //
  647. // Signals:
  648. //
  649. // Modifies:
  650. //
  651. // Algorithm: takes strings of the form '"name",index' or 'name,index'
  652. // from the DefaultIcon registry entry
  653. //
  654. // parsing is very simple: if the name is enclosed in quotes,
  655. // take that as the exe name. If any other characters exist,
  656. // they must be a comma followed by digits (for the icon index)
  657. //
  658. // if the name is not enclosed by quotes, assume the name is
  659. // the entire string up until the last comma (if it exists).
  660. //
  661. // History: dd-mmm-yy Author Comment
  662. // 27-Dec-94 alexgo author
  663. //
  664. // Notes: legal filenames in NT and Win95 can include commas, but not
  665. // quotation marks.
  666. //
  667. //--------------------------------------------------------------------------
  668. BOOL ExtractNameAndIndex( LPOLESTR pszInfo, LPOLESTR pszEXE, UINT cchEXE,
  669. UINT *pIndex)
  670. {
  671. BOOL fRet = FALSE;
  672. LPOLESTR pszStart = pszInfo;
  673. LPOLESTR pszIndex = NULL;
  674. LPOLESTR pszDest = pszEXE;
  675. UINT cchName = 0;
  676. DWORD i = 0;
  677. Assert(pszInfo);
  678. Assert(pszEXE);
  679. Assert(cchEXE != 0);
  680. Assert(pIndex);
  681. VDATEHEAP();
  682. LEDebugOut((DEB_ITRACE, "%p _IN ExtractNameAndIndex ( \"%ws\" , \"%ws\" ,"
  683. " %d , %p )\n", NULL, pszInfo, pszEXE, cchEXE, pIndex));
  684. *pIndex = 0;
  685. if( *pszStart == OLESTR('\"') )
  686. {
  687. // name enclosed by quotes; just zoom down til the very last quote
  688. pszStart++;
  689. while( *pszStart != OLESTR('\0') && *pszStart != OLESTR('\"') &&
  690. pszDest < (pszEXE + cchEXE))
  691. {
  692. *pszDest = *pszStart;
  693. pszDest++;
  694. pszStart++;
  695. }
  696. *pszDest = OLESTR('\0');
  697. if( *pszStart == OLESTR('\"') )
  698. {
  699. pszIndex = pszStart + 1;
  700. }
  701. else
  702. {
  703. pszIndex = pszStart;
  704. }
  705. fRet = TRUE;
  706. }
  707. else
  708. {
  709. // find the last comma (if available)
  710. pszIndex = pszStart + _xstrlen(pszStart);
  711. while( *pszIndex != OLESTR(',') && pszIndex > pszStart )
  712. {
  713. pszIndex--;
  714. }
  715. // if no comma was found, just reset the index pointer to the end
  716. if( pszIndex == pszStart )
  717. {
  718. pszIndex = pszStart + _xstrlen(pszStart);
  719. }
  720. cchName = (ULONG) (pszIndex - pszStart)/sizeof(OLECHAR);
  721. if( cchEXE > cchName )
  722. {
  723. while( pszStart < pszIndex )
  724. {
  725. *pszDest = *pszStart;
  726. pszDest++;
  727. pszStart++;
  728. }
  729. *pszDest = OLESTR('\0');
  730. fRet = TRUE;
  731. }
  732. }
  733. // now fetch the index value
  734. if( *pszIndex == OLESTR(',') )
  735. {
  736. pszIndex++;
  737. }
  738. *pIndex = wcstol(pszIndex, NULL, 10);
  739. LEDebugOut((DEB_ITRACE, "%p OUT ExtractNameAndIndex ( %d ) [ \"%ws\" , "
  740. " %d ]\n", NULL, fRet, pszEXE, *pIndex));
  741. return fRet;
  742. }
  743. #if DBG == 1
  744. //+-------------------------------------------------------------------------
  745. //
  746. // Function: VerifyExtractNameAndIndex
  747. //
  748. // Synopsis: verifies the functioning of ExtractNameAndIndex (DEBUG only)
  749. //
  750. // Effects:
  751. //
  752. // Arguments: void
  753. //
  754. // Requires:
  755. //
  756. // Returns: void
  757. //
  758. // Signals:
  759. //
  760. // Modifies:
  761. //
  762. // Algorithm:
  763. //
  764. // History: dd-mmm-yy Author Comment
  765. // 27-Dec-94 alexgo author
  766. //
  767. // Notes:
  768. //
  769. //--------------------------------------------------------------------------
  770. void VerifyExtractNameAndIndex( void )
  771. {
  772. OLECHAR szName[256];
  773. UINT index = 0;
  774. BOOL fRet = FALSE;
  775. VDATEHEAP();
  776. fRet = ExtractNameAndIndex( OLESTR("\"foo,8\",8"), szName, 256, &index);
  777. Assert(fRet);
  778. Assert(_xstrcmp(szName, OLESTR("foo,8")) == 0);
  779. Assert(index == 8);
  780. fRet = ExtractNameAndIndex( OLESTR("foo,8,8,89"), szName, 256, &index);
  781. Assert(fRet);
  782. Assert(_xstrcmp(szName, OLESTR("foo,8,8")) == 0);
  783. Assert(index == 89);
  784. fRet = ExtractNameAndIndex( OLESTR("progman.exe"), szName, 256, &index);
  785. Assert(fRet);
  786. Assert(_xstrcmp(szName, OLESTR("progman.exe")) == 0);
  787. Assert(index == 0);
  788. fRet = ExtractNameAndIndex( OLESTR("\"progman.exe\""), szName, 256,
  789. &index);
  790. Assert(fRet);
  791. Assert(_xstrcmp(szName, OLESTR("progman.exe")) == 0);
  792. Assert(index == 0);
  793. VDATEHEAP();
  794. }
  795. #endif // DBG == 1
  796. LONG RegReadDefValue(HKEY hKey, LPOLESTR pszKey, LPOLESTR *ppszValue)
  797. {
  798. HKEY hSubKey = NULL;
  799. DWORD dw = 0;
  800. LONG lRet;
  801. LPOLESTR pszValue = NULL;
  802. lRet = RegOpenKeyEx(hKey, pszKey, 0, KEY_READ, &hSubKey);
  803. if(lRet != ERROR_SUCCESS) goto ErrRtn;
  804. lRet = RegQueryValueEx(hSubKey, NULL, NULL, NULL, NULL, &dw);
  805. if(lRet != ERROR_SUCCESS) goto ErrRtn;
  806. pszValue = (LPOLESTR) CoTaskMemAlloc(dw);
  807. if(!pszValue)
  808. {
  809. lRet = ERROR_OUTOFMEMORY;
  810. goto ErrRtn;
  811. }
  812. lRet = RegQueryValueEx(hSubKey, NULL, NULL, NULL, (PBYTE) pszValue, &dw);
  813. ErrRtn:
  814. if(lRet != ERROR_SUCCESS && pszValue)
  815. {
  816. CoTaskMemFree(pszValue);
  817. pszValue = NULL;
  818. }
  819. if(hSubKey)
  820. RegCloseKey(hSubKey);
  821. *ppszValue = pszValue;
  822. return lRet;
  823. }
  824. //+-------------------------------------------------------------------------
  825. //
  826. // Function: FIconFileFromClass, private
  827. //
  828. // Synopsis: Looks up the path to the exectuble that contains the class
  829. // default icon
  830. //
  831. // Effects:
  832. //
  833. // Arguments: [rclsid] -- the class ID to lookup
  834. // [pszEXE] -- where to put the server name
  835. // [cch] -- UINT size of [pszEXE]
  836. // [lpIndex] -- where to put the index of the icon
  837. // in the executable
  838. //
  839. // Requires: pszEXE != NULL
  840. // cch != 0
  841. //
  842. // Returns: TRUE if one or more characters where found for [pszEXE],
  843. // FALSE otherwise
  844. //
  845. // Signals:
  846. //
  847. // Modifies:
  848. //
  849. // Algorithm:
  850. //
  851. // History: dd-mmm-yy Author Comment
  852. // 27-Nov-93 alexgo 32bit port
  853. // 15-Dec-93 alexgo fixed memory allocation bug and
  854. // some UNICODE string manip stuff
  855. // 27-Apr-94 AlexT Tracing, clean up memory allocation
  856. //
  857. // Notes:
  858. //
  859. //--------------------------------------------------------------------------
  860. BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPOLESTR pszEXE,
  861. UINT cch, UINT FAR *lpIndex)
  862. {
  863. VDATEHEAP();
  864. LEDebugOut((DEB_ITRACE, "%p _IN FIconFileFromClass (%p, %p, %d, %p)\n",
  865. NULL, &rclsid, pszEXE, cch, lpIndex));
  866. Win4Assert(NULL != pszEXE && "Bad argument to FIconFileFromClass");
  867. Win4Assert(cch != 0 && "Bad argument to FIconFileFromClass");
  868. BOOL bRet;
  869. LPOLESTR lpBuffer = NULL;
  870. LPOLESTR lpBufferExp = NULL;
  871. LONG dw;
  872. LONG lRet;
  873. HKEY hKey;
  874. LPOLESTR lpIndexString;
  875. if (IsEqualCLSID(CLSID_NULL, rclsid))
  876. {
  877. bRet = FALSE;
  878. goto ErrRtn;
  879. }
  880. //Here, we alloc a buffer (maxpathlen + 8) to
  881. //pass to RegQueryValue. Then, we copy the exe to pszEXE and the
  882. //index to *lpIndex.
  883. if (CoIsOle1Class(rclsid))
  884. {
  885. LPOLESTR lpszProgID;
  886. // we've got an ole 1.0 class on our hands, so we look at
  887. // progID\protocol\stdfileedting\server to get the
  888. // name of the executable.
  889. // REVIEW: could this possibly fail and leave you with an
  890. // invalid ptr passed into regopenkey?
  891. ProgIDFromCLSID(rclsid, &lpszProgID);
  892. //Open up the class key
  893. lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
  894. PubMemFree(lpszProgID);
  895. if (ERROR_SUCCESS != lRet)
  896. {
  897. bRet = FALSE;
  898. goto ErrRtn;
  899. }
  900. // RegQueryValue expects number of *bytes*
  901. lRet = RegReadDefValue(hKey, OLESTR("Protocol\\StdFileEditing\\Server"), &lpBuffer);
  902. RegCloseKey(hKey);
  903. if (ERROR_SUCCESS != lRet)
  904. {
  905. bRet = FALSE;
  906. goto ErrRtn;
  907. }
  908. // Use server and 0 as the icon index
  909. dw = ExpandEnvironmentStringsW(lpBuffer, pszEXE, cch);
  910. if(dw == 0 || dw > (LONG)cch)
  911. {
  912. bRet = FALSE;
  913. goto ErrRtn;
  914. }
  915. // REVIEW: is this internally trusted? No validation...
  916. // (same for rest of writes to it this fn)
  917. *lpIndex = 0;
  918. bRet = TRUE;
  919. goto ErrRtn;
  920. }
  921. /*
  922. * We have to go walking in the registration database under the
  923. * classname, so we first open the classname key and then check
  924. * under "\\DefaultIcon" to get the file that contains the icon.
  925. */
  926. {
  927. LPOLESTR pszClass;
  928. OLECHAR szKey[64];
  929. StringFromCLSID(rclsid, &pszClass);
  930. _xstrcpy(szKey, OLESTR("CLSID\\"));
  931. _xstrcat(szKey, pszClass);
  932. PubMemFree(pszClass);
  933. //Open up the class key
  934. lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
  935. }
  936. if (ERROR_SUCCESS != lRet)
  937. {
  938. bRet = FALSE;
  939. goto ErrRtn;
  940. }
  941. //Get the executable path and icon index.
  942. // RegQueryValue expects number of bytes
  943. lRet = RegReadDefValue(hKey, OLESTR("DefaultIcon"), &lpBuffer);
  944. if (ERROR_SUCCESS != lRet)
  945. {
  946. // no DefaultIcon key...try LocalServer
  947. lRet = RegReadDefValue(hKey, OLESTR("LocalServer32"), &lpBuffer);
  948. }
  949. if (ERROR_SUCCESS != lRet)
  950. {
  951. lRet = RegReadDefValue(hKey, OLESTR("LocalServer"), &lpBuffer);
  952. }
  953. RegCloseKey(hKey);
  954. if (ERROR_SUCCESS != lRet)
  955. {
  956. // no LocalServer entry either...they're outta luck.
  957. bRet = FALSE;
  958. goto ErrRtn;
  959. }
  960. // Nt #335548
  961. dw = ExpandEnvironmentStringsW(lpBuffer, NULL, 0);
  962. if(dw)
  963. {
  964. lpBufferExp = (LPOLESTR) CoTaskMemAlloc(dw * sizeof(OLECHAR));
  965. dw = ExpandEnvironmentStringsW(lpBuffer, lpBufferExp, dw);
  966. }
  967. if(!dw)
  968. {
  969. LEDebugOut((DEB_WARN, "ExpandEnvStrings failure!"));
  970. bRet = FALSE;
  971. goto ErrRtn;
  972. }
  973. // lpBuffer contains a string that looks like
  974. // "<pathtoexe>,<iconindex>",
  975. // so we need to separate the path and the icon index.
  976. bRet = ExtractNameAndIndex(lpBufferExp, pszEXE, cch, lpIndex);
  977. #if DBG == 1
  978. // do some quick checking while we're at it.
  979. VerifyExtractNameAndIndex();
  980. #endif // DBG == 1
  981. ErrRtn:
  982. if(lpBuffer)
  983. CoTaskMemFree(lpBuffer);
  984. if(lpBufferExp)
  985. CoTaskMemFree(lpBufferExp);
  986. LEDebugOut((DEB_ITRACE, "%p OUT FIconFileFromClass ( %d ) [%d]\n",
  987. NULL, bRet, *lpIndex));
  988. return bRet;
  989. }
  990. //+-------------------------------------------------------------------------
  991. //
  992. // Function: OleMetafilePictFromIconAndLabel (public)
  993. //
  994. // Synopsis:
  995. // Creates a METAFILEPICT structure that container a metafile in which
  996. // the icon and label are drawn. A comment record is inserted between
  997. // the icon and the label code so our special draw function can stop
  998. // playing before the label.
  999. //
  1000. // Effects:
  1001. //
  1002. // Arguments: [hIcon] -- icon to draw into the metafile
  1003. // [pszLabel] -- the label string
  1004. // [pszSourceFile] -- local pathname of the icon
  1005. // [iIcon] -- index into [pszSourceFile] for the icon
  1006. //
  1007. // Requires:
  1008. //
  1009. // Returns: HGLOBAL to a METAFILEPICT structure (using MM_ANISOTROPIC
  1010. // mapping mode)
  1011. //
  1012. // Signals:
  1013. //
  1014. // Modifies:
  1015. //
  1016. // Algorithm:
  1017. //
  1018. // History: dd-mmm-yy Author Comment
  1019. // 27-Nov-93 alexgo first 32bit port
  1020. // 15-Dec-93 alexgo fixed bugs with UNICODE strings
  1021. // 09-Mar-94 AlexT Make this backwards compatible
  1022. //
  1023. // Notes: REVIEW32:: need to fix font grabbing etc, to be international
  1024. // friendly, see comments below
  1025. //
  1026. //--------------------------------------------------------------------------
  1027. STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon,
  1028. LPOLESTR pwcsLabel, LPOLESTR pwcsSourceFile, UINT iIcon)
  1029. {
  1030. OLETRACEIN((API_OleMetafilePictFromIconAndLabel,
  1031. PARAMFMT("hIcon= %h, pwcsLabel= %ws, pwcsSourceFile= %ws, iIcon= %d"),
  1032. hIcon, pwcsLabel, pwcsSourceFile, iIcon));
  1033. VDATEHEAP();
  1034. LEDebugOut((DEB_TRACE, "%p _IN OleMetafilePictFromIconAndLabel (%p, %p, %p, %d)\n",
  1035. NULL, hIcon, pwcsLabel, pwcsSourceFile, iIcon));
  1036. //Where to stop to exclude label (explicitly ANSI)
  1037. static char szIconOnly[] = "IconOnly";
  1038. static char szIconLabelNext[] = "OLE: Icon label next (Unicode)";
  1039. static char szIconSourceNext[] = "OLE: Icon source next (Unicode)";
  1040. static char szDefaultChar[] = "?";
  1041. // REVIEW: Mein Got! This is a huge fn, could it be broken up?
  1042. HGLOBAL hMem = NULL;
  1043. HDC hDC, hDCScreen = NULL;
  1044. HMETAFILE hMF;
  1045. LPMETAFILEPICT pMF;
  1046. OLECHAR wszIconLabel[OLEUI_CCHLABELMAX + 1];
  1047. char szIconLabel[OLEUI_CCHLABELMAX + 1];
  1048. UINT cchLabelW;
  1049. UINT cchLabelA;
  1050. UINT cchIndex;
  1051. BOOL bUsedDefaultChar;
  1052. TEXTMETRICA textMetric;
  1053. UINT cxIcon, cyIcon;
  1054. UINT cxText, cyText;
  1055. UINT cx, cy;
  1056. HFONT hFont, hSysFont, hFontT;
  1057. int cyFont;
  1058. char szIndex[10];
  1059. RECT TextRect;
  1060. char * pszSourceFile;
  1061. UINT cchSourceFile;
  1062. int iRet;
  1063. BOOL bWriteUnicodeLabel;
  1064. BOOL bWriteUnicodeSource;
  1065. LOGFONT logfont;
  1066. if (NULL == hIcon) // null icon is valid
  1067. {
  1068. goto ErrRtn;
  1069. }
  1070. //Need to use the screen DC for these operations
  1071. hDCScreen = GetDC(NULL);
  1072. if (!hDCScreen)
  1073. goto ErrRtn;
  1074. // REVIEW: ptr validation on IN params?
  1075. bWriteUnicodeSource = FALSE;
  1076. pszSourceFile = NULL;
  1077. if (NULL != pwcsSourceFile)
  1078. {
  1079. // Prepare source file string
  1080. cchSourceFile = _xstrlen(pwcsSourceFile) + 1;
  1081. #if defined(WIN32)
  1082. pszSourceFile = (char *) PrivMemAlloc(cchSourceFile * sizeof(WCHAR));
  1083. #else
  1084. pszSourceFile = (char *) PrivMemAlloc(cchSourceFile);
  1085. #endif // WIN32
  1086. if (NULL == pszSourceFile)
  1087. {
  1088. LEDebugOut((DEB_WARN, "PrivMemAlloc(%d) failed\n",
  1089. cchSourceFile));
  1090. goto ErrRtn;
  1091. }
  1092. #if defined(WIN32)
  1093. iRet = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
  1094. pwcsSourceFile, cchSourceFile,
  1095. pszSourceFile, cchSourceFile * sizeof(WCHAR),
  1096. szDefaultChar, &bUsedDefaultChar);
  1097. #else
  1098. iRet = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
  1099. pwcsSourceFile, cchSourceFile,
  1100. pszSourceFile, cchSourceFile,
  1101. szDefaultChar, &bUsedDefaultChar);
  1102. #endif // WIN32
  1103. bWriteUnicodeSource = bUsedDefaultChar;
  1104. if (0 == iRet)
  1105. {
  1106. // Unexpected failure, since at worst we should have
  1107. // just filled in pszSourceFile with default characters.
  1108. LEDebugOut((DEB_WARN, "WideCharToMultiByte failed - %lx\n",
  1109. GetLastError()));
  1110. }
  1111. }
  1112. // Create a memory metafile. We explicitly make it an ANSI metafile for
  1113. // backwards compatibility.
  1114. #ifdef WIN32
  1115. hDC = CreateMetaFileA(NULL);
  1116. #else
  1117. hDC = CreateMetaFile(NULL);
  1118. #endif
  1119. if (NULL == hDC)
  1120. {
  1121. LEDebugOut((DEB_WARN, "CreateMetaFile failed - %lx\n",
  1122. GetLastError()));
  1123. PrivMemFree(pszSourceFile);
  1124. goto ErrRtn;
  1125. }
  1126. //Allocate the metafilepict
  1127. hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
  1128. if (NULL == hMem)
  1129. {
  1130. LEDebugOut((DEB_WARN, "GlobalAlloc failed - %lx\n",
  1131. GetLastError()));
  1132. hMF = CloseMetaFile(hDC);
  1133. DeleteMetaFile(hMF);
  1134. PrivMemFree(pszSourceFile);
  1135. goto ErrRtn;
  1136. }
  1137. // Prepare ANSI label
  1138. szIconLabel[0] = '\0';
  1139. cchLabelW = 0;
  1140. cchLabelA = 0;
  1141. // REVIEW: don't follow the logic here: you conditionally set it above
  1142. // and explicity clear it here?
  1143. bWriteUnicodeLabel = FALSE;
  1144. if (NULL != pwcsLabel)
  1145. {
  1146. cchLabelW = _xstrlen(pwcsLabel) + 1;
  1147. if (OLEUI_CCHLABELMAX < cchLabelW)
  1148. {
  1149. //REVIEW: would it be worth warning of the truncation in debug builds?
  1150. // or is this a common case?
  1151. LSTRCPYN(wszIconLabel, pwcsLabel, OLEUI_CCHLABELMAX);
  1152. wszIconLabel[OLEUI_CCHLABELMAX] = L'\0';
  1153. pwcsLabel = wszIconLabel;
  1154. cchLabelW = OLEUI_CCHLABELMAX;
  1155. }
  1156. #if defined(WIN32)
  1157. cchLabelA = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
  1158. pwcsLabel, cchLabelW,
  1159. szIconLabel, 0,
  1160. NULL, NULL);
  1161. #else
  1162. cchLabelA = cchLabelW;
  1163. #endif // WIN32
  1164. // We have a label - translate it to ANSI for the TextOut's...
  1165. iRet = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
  1166. pwcsLabel, cchLabelW,
  1167. szIconLabel, sizeof(szIconLabel),
  1168. szDefaultChar, &bUsedDefaultChar);
  1169. if (0 == iRet)
  1170. {
  1171. // Unexpected failure, since at worst we should have
  1172. // just filled in pszSourceFile with default characters.
  1173. LEDebugOut((DEB_WARN, "WideCharToMultiByte failed - %lx\n",
  1174. GetLastError()));
  1175. }
  1176. bWriteUnicodeLabel = bUsedDefaultChar;
  1177. }
  1178. LOGFONT lf;
  1179. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  1180. hFont = CreateFontIndirect(&lf);
  1181. hFontT= (HFONT) SelectObject(hDCScreen, hFont);
  1182. GetTextMetricsA(hDCScreen, &textMetric);
  1183. // We use double the height to provide some margin space
  1184. cyText = textMetric.tmHeight*3; //max 2 lines & some space
  1185. SelectObject(hDCScreen, hFontT);
  1186. cxIcon = GetSystemMetrics(SM_CXICON);
  1187. cyIcon = GetSystemMetrics(SM_CYICON);
  1188. cxText = cxIcon*3; //extent of text based upon icon width causes
  1189. //the label to look nice and proportionate.
  1190. // If we have no label, then we want the metafile to be the width of
  1191. // the icon (plus margin), not the width of the fattest string.
  1192. if ('\0' == szIconLabel[0])
  1193. {
  1194. cx = cxIcon + cxIcon / 4;
  1195. }
  1196. else
  1197. {
  1198. cx = max(cxText, cxIcon);
  1199. }
  1200. cy = cyIcon + cyText + 4; // Why 4?
  1201. //Set the metafile size to fit the icon and label
  1202. SetMapMode(hDC, MM_ANISOTROPIC);
  1203. SetWindowOrgEx(hDC, 0, 0, NULL);
  1204. SetWindowExtEx(hDC, cx, cy, NULL);
  1205. //Set up rectangle to pass to IconLabelTextOut
  1206. SetRectEmpty(&TextRect);
  1207. TextRect.right = cx;
  1208. TextRect.bottom = cy;
  1209. //Draw the icon and the text, centered with respect to each other.
  1210. DrawIcon(hDC, (cx - cxIcon) / 2, 0, hIcon);
  1211. //String that indicates where to stop if we're only doing icons
  1212. Escape(hDC, MFCOMMENT, sizeof(szIconOnly), szIconOnly, NULL);
  1213. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  1214. SetBkMode(hDC, TRANSPARENT);
  1215. IconLabelTextOut(hDC, hFont, 0, cy - cyText, ETO_CLIPPED,
  1216. &TextRect, szIconLabel, cchLabelA);
  1217. // Write comments containing the icon source file and index.
  1218. if (NULL != pwcsSourceFile)
  1219. {
  1220. AssertSz(pszSourceFile != NULL, "Unicode source existed");
  1221. //Escape wants number of *bytes*
  1222. Escape(hDC, MFCOMMENT,
  1223. cchSourceFile, pszSourceFile, NULL);
  1224. cchIndex = wsprintfA(szIndex, "%u", iIcon);
  1225. // Escape wants number of *bytes*
  1226. Escape(hDC, MFCOMMENT, cchIndex + 1, szIndex, NULL);
  1227. }
  1228. else if (bWriteUnicodeLabel || bWriteUnicodeSource)
  1229. {
  1230. // We're going to write out comment records for the Unicode
  1231. // strings, so we need to emit dummy ANSI source comments.
  1232. //Escape wants number of *bytes*
  1233. Escape(hDC, MFCOMMENT, sizeof(""), "", NULL);
  1234. // Escape wants number of *bytes*
  1235. Escape(hDC, MFCOMMENT, sizeof("0"), "0", NULL);
  1236. }
  1237. if (bWriteUnicodeLabel)
  1238. {
  1239. // Now write out the UNICODE label
  1240. Escape(hDC, MFCOMMENT,
  1241. sizeof(szIconLabelNext), szIconLabelNext, NULL);
  1242. Escape(hDC, MFCOMMENT,
  1243. cchLabelW * sizeof(OLECHAR), (LPSTR) pwcsLabel,
  1244. NULL);
  1245. }
  1246. if (bWriteUnicodeSource)
  1247. {
  1248. // Now write out the UNICODE label
  1249. Escape(hDC, MFCOMMENT,
  1250. sizeof(szIconSourceNext), szIconSourceNext, NULL);
  1251. Escape(hDC, MFCOMMENT,
  1252. cchSourceFile * sizeof(OLECHAR), (LPSTR) pwcsSourceFile,
  1253. NULL);
  1254. }
  1255. //All done with the metafile, now stuff it all into a METAFILEPICT.
  1256. hMF = CloseMetaFile(hDC);
  1257. if (NULL==hMF)
  1258. {
  1259. GlobalFree(hMem);
  1260. hMem = NULL;
  1261. goto ErrRtn;
  1262. }
  1263. pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  1264. //Transform to HIMETRICS
  1265. cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
  1266. cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
  1267. pMF->mm=MM_ANISOTROPIC;
  1268. pMF->xExt=cx;
  1269. pMF->yExt=cy;
  1270. pMF->hMF=hMF;
  1271. GlobalUnlock(hMem);
  1272. if(hFont)
  1273. DeleteObject(hFont);
  1274. PrivMemFree(pszSourceFile);
  1275. // REVIEW: any need to release the font resource?
  1276. ErrRtn:
  1277. if(hDCScreen)
  1278. ReleaseDC(NULL, hDCScreen);
  1279. LEDebugOut((DEB_TRACE, "%p OUT OleMetafilePictFromIconAndLabel ( %p )\n",
  1280. NULL, hMem));
  1281. OLETRACEOUTEX((API_OleMetafilePictFromIconAndLabel,
  1282. RETURNFMT("%h"), hMem));
  1283. return hMem;
  1284. }
  1285. //+-------------------------------------------------------------------------
  1286. //
  1287. // Function: IconLabelTextOut (internal)
  1288. //
  1289. // Synopsis:
  1290. // Replacement for DrawText to be used in the "Display as Icon" metafile.
  1291. // Uses ExtTextOutA to output a string center on (at most) two lines.
  1292. // Uses a very simple word wrap algorithm to split the lines.
  1293. //
  1294. // Effects:
  1295. //
  1296. // Arguments: [hDC] -- device context (cannot be NULL)
  1297. // [hFont] -- font to use
  1298. // [nXStart] -- x-coordinate of starting position
  1299. // [nYStart] -- y-coordinate of starting position
  1300. // [fuOptions] -- rectangle type
  1301. // [lpRect] -- rect far * containing rectangle to draw
  1302. // text in.
  1303. // [lpszString] -- string to draw
  1304. // [cchString] -- length of string (truncated if over
  1305. // OLEUI_CCHLABELMAX), including terminating
  1306. // NULL
  1307. //
  1308. // Requires:
  1309. //
  1310. // Signals:
  1311. //
  1312. // Modifies:
  1313. //
  1314. // Algorithm:
  1315. //
  1316. // History: dd-mmm-yy Author Comment
  1317. // 28-Nov-93 alexgo initial 32bit port
  1318. // 09-Mar-94 AlexT Use ANSI strings
  1319. //
  1320. // Notes:
  1321. //
  1322. //--------------------------------------------------------------------------
  1323. // POSTPPC: The parameter 'cchString' is superfluous since lpszString
  1324. // is guaranteed to be null terminated
  1325. void IconLabelTextOut(HDC hDC, HFONT hFont, int nXStart, int nYStart,
  1326. UINT fuOptions, RECT FAR * lpRect, LPCSTR lpszString,
  1327. UINT cchString)
  1328. {
  1329. VDATEHEAP();
  1330. LEDebugOut((DEB_ITRACE, "%p _IN IconLabelTextOut (%lx, %lx, %d, %d, %d, %p, %p, %d)\n",
  1331. NULL, hDC, hFont,
  1332. nXStart, nYStart, fuOptions, lpRect, lpszString, cchString));
  1333. AssertSz(hDC != NULL, "Bad arg to IconLabelTextOut");
  1334. AssertSz(lpszString != NULL, "Bad arg to IconLabelTextOut");
  1335. AssertSz(strlen(lpszString) < OLEUI_CCHLABELMAX,
  1336. "Bad arg to IconLabelTextOut");
  1337. // REVIEW: does our compiler have to initialize static function scoped
  1338. // data? I know old versions did...
  1339. static char szSeparators[] = " \t\\/!:";
  1340. static char szTempBuff[OLEUI_CCHLABELMAX];
  1341. HDC hDCScreen;
  1342. int cxString, cyString, cxMaxString;
  1343. int cxFirstLine, cyFirstLine, cxSecondLine;
  1344. int index;
  1345. char chKeep;
  1346. LPSTR lpszSecondLine;
  1347. LPSTR lpstrLast;
  1348. HFONT hFontT;
  1349. SIZE size;
  1350. int cch = strlen(lpszString);
  1351. UINT uiAlign = GDI_ERROR;
  1352. // Initialization stuff...
  1353. strcpy(szTempBuff, lpszString);
  1354. // set maximum width
  1355. cxMaxString = lpRect->right - lpRect->left;
  1356. // get screen DC to do text size calculations
  1357. hDCScreen = GetDC(NULL);
  1358. if(!hDCScreen)
  1359. return;
  1360. hFontT= (HFONT)SelectObject(hDCScreen, hFont);
  1361. // get the extent of our label
  1362. GetTextExtentPointA(hDCScreen, szTempBuff, cch, &size);
  1363. cxString = size.cx;
  1364. cyString = size.cy;
  1365. // Select in the font we want to use
  1366. SelectObject(hDC, hFont);
  1367. // Center the string
  1368. uiAlign = SetTextAlign(hDC, TA_CENTER);
  1369. // String is smaller than max string - just center, ETO, and return.
  1370. if (cxString <= cxMaxString)
  1371. {
  1372. ExtTextOutA(hDC,
  1373. nXStart + lpRect->right / 2,
  1374. nYStart,
  1375. fuOptions,
  1376. lpRect,
  1377. szTempBuff,
  1378. cch,
  1379. NULL);
  1380. goto CleanupAndLeave;
  1381. }
  1382. // String is too long...we've got to word-wrap it.
  1383. // Are there any spaces, slashes, tabs, or bangs in string?
  1384. if (strlen(szTempBuff) != strcspn(szTempBuff, szSeparators))
  1385. {
  1386. // Yep, we've got spaces, so we'll try to find the largest
  1387. // space-terminated string that will fit on the first line.
  1388. index = cch;
  1389. while (index >= 0)
  1390. {
  1391. // scan the string backwards for spaces, slashes,
  1392. // tabs, or bangs
  1393. // REVIEW: scary. Could this result in a negative
  1394. // index, or is it guarnateed to hit a separator
  1395. // before that?
  1396. while (!IS_SEPARATOR(szTempBuff[index]) )
  1397. {
  1398. index--;
  1399. }
  1400. if (index <= 0)
  1401. {
  1402. break;
  1403. }
  1404. // remember what char was there
  1405. chKeep = szTempBuff[index];
  1406. szTempBuff[index] = '\0'; // just for now
  1407. GetTextExtentPointA(hDCScreen, szTempBuff,
  1408. index,&size);
  1409. cxFirstLine = size.cx;
  1410. cyFirstLine = size.cy;
  1411. // REVIEW: but chKeep is NOT an OLECHAR
  1412. // put the right OLECHAR back
  1413. szTempBuff[index] = chKeep;
  1414. if (cxFirstLine <= cxMaxString)
  1415. {
  1416. ExtTextOutA(hDC,
  1417. nXStart + lpRect->right / 2,
  1418. nYStart,
  1419. fuOptions,
  1420. lpRect,
  1421. szTempBuff,
  1422. index + 1,
  1423. NULL);
  1424. lpszSecondLine = szTempBuff;
  1425. lpszSecondLine += index + 1;
  1426. GetTextExtentPointA(hDCScreen,
  1427. lpszSecondLine,
  1428. strlen(lpszSecondLine),
  1429. &size);
  1430. // If the second line is wider than the
  1431. // rectangle, we just want to clip the text.
  1432. cxSecondLine = min(size.cx, cxMaxString);
  1433. ExtTextOutA(hDC,
  1434. nXStart + lpRect->right / 2,
  1435. nYStart + cyFirstLine,
  1436. fuOptions,
  1437. lpRect,
  1438. lpszSecondLine,
  1439. strlen(lpszSecondLine),
  1440. NULL);
  1441. goto CleanupAndLeave;
  1442. } // end if
  1443. index--;
  1444. } // end while
  1445. } // end if
  1446. // Here, there are either no spaces in the string
  1447. // (strchr(szTempBuff, ' ') returned NULL), or there spaces in the
  1448. // string, but they are positioned so that the first space
  1449. // terminated string is still longer than one line.
  1450. // So, we walk backwards from the end of the string until we
  1451. // find the largest string that will fit on the first
  1452. // line , and then we just clip the second line.
  1453. // We allow 40 characters in the label, but the metafile is
  1454. // only as wide as 10 W's (for aesthetics - 20 W's wide looked
  1455. // dumb. This means that if we split a long string in half (in
  1456. // terms of characters), then we could still be wider than the
  1457. // metafile. So, if this is the case, we just step backwards
  1458. // from the halfway point until we get something that will fit.
  1459. // Since we just let ETO clip the second line
  1460. cch = strlen(szTempBuff);
  1461. lpstrLast = &szTempBuff[cch];
  1462. chKeep = *lpstrLast;
  1463. *lpstrLast = '\0';
  1464. GetTextExtentPointA(hDCScreen, szTempBuff, cch, &size);
  1465. cxFirstLine = size.cx;
  1466. cyFirstLine = size.cy;
  1467. while (cxFirstLine > cxMaxString)
  1468. {
  1469. *lpstrLast = chKeep;
  1470. // The string is always ansi, so always use CharPrevA.
  1471. lpstrLast = CharPrevA(szTempBuff, lpstrLast);
  1472. if (szTempBuff == lpstrLast)
  1473. {
  1474. goto CleanupAndLeave;
  1475. }
  1476. chKeep = *lpstrLast;
  1477. *lpstrLast = '\0';
  1478. // need to calculate the new length of the string
  1479. cch = strlen(szTempBuff);
  1480. GetTextExtentPointA(hDCScreen, szTempBuff,
  1481. cch, &size);
  1482. cxFirstLine = size.cx;
  1483. }
  1484. ExtTextOutA(hDC,
  1485. nXStart + lpRect->right / 2,
  1486. nYStart,
  1487. fuOptions,
  1488. lpRect,
  1489. szTempBuff,
  1490. strlen(szTempBuff),
  1491. NULL);
  1492. szTempBuff[cch] = chKeep;
  1493. lpszSecondLine = szTempBuff;
  1494. lpszSecondLine += cch;
  1495. GetTextExtentPointA(hDCScreen, lpszSecondLine,
  1496. strlen(lpszSecondLine), &size);
  1497. // If the second line is wider than the rectangle, we
  1498. // just want to clip the text.
  1499. cxSecondLine = min(size.cx, cxMaxString);
  1500. ExtTextOutA(hDC,
  1501. nXStart + lpRect->right / 2,
  1502. nYStart + cyFirstLine,
  1503. fuOptions,
  1504. lpRect,
  1505. lpszSecondLine,
  1506. strlen(lpszSecondLine),
  1507. NULL);
  1508. CleanupAndLeave:
  1509. // If we changed the alignment we restore it here
  1510. if (uiAlign != GDI_ERROR)
  1511. {
  1512. SetTextAlign(hDC, uiAlign);
  1513. }
  1514. SelectObject(hDCScreen, hFontT);
  1515. ReleaseDC(NULL, hDCScreen);
  1516. LEDebugOut((DEB_ITRACE, "%p OUT IconLabelTextOut ()\n"));
  1517. }
  1518. //+-------------------------------------------------------------------------
  1519. //
  1520. // Function: OleStdGetUserTypeOfClass, private
  1521. //
  1522. // Synopsis: Returns the user type info of the specified class
  1523. //
  1524. // Effects:
  1525. //
  1526. // Arguments: [rclsid] -- the class ID in question
  1527. // [lpszUserType] -- where to put the user type string
  1528. // [cch] -- the length of [lpszUserType] (in
  1529. // *characters*, not bytes)
  1530. // [hKey] -- handle to the reg db (may be NULL)
  1531. //
  1532. // Requires:
  1533. //
  1534. // Returns: UINT -- the number of characters put into the return string
  1535. //
  1536. // Signals:
  1537. //
  1538. // Modifies:
  1539. //
  1540. // Algorithm:
  1541. //
  1542. // History: dd-mmm-yy Author Comment
  1543. // 29-Nov-93 alexgo 32bit port
  1544. //
  1545. // Notes:
  1546. //
  1547. //--------------------------------------------------------------------------
  1548. STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPOLESTR lpszUserType, UINT cch, HKEY hKey)
  1549. {
  1550. VDATEHEAP();
  1551. LEDebugOut((DEB_ITRACE, "%p _IN OleStdGetUserTypeOfClass (%p, %p, %d, %lx)\n",
  1552. NULL, &rclsid, lpszUserType, cch, hKey));
  1553. LONG dw = 0;
  1554. LONG lRet;
  1555. // REVIEW: would make more sense to set this when the reg is opened
  1556. BOOL bCloseRegDB = FALSE;
  1557. if (hKey == NULL)
  1558. {
  1559. //Open up the root key.
  1560. lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
  1561. if ((LONG)ERROR_SUCCESS!=lRet)
  1562. {
  1563. goto ErrRtn;
  1564. }
  1565. bCloseRegDB = TRUE;
  1566. }
  1567. // Get a string containing the class name
  1568. {
  1569. LPOLESTR lpszCLSID;
  1570. OLECHAR szKey[128];
  1571. StringFromCLSID(rclsid, &lpszCLSID);
  1572. _xstrcpy(szKey, OLESTR("CLSID\\"));
  1573. _xstrcat(szKey, lpszCLSID);
  1574. PubMemFree((LPVOID)lpszCLSID);
  1575. dw = cch * sizeof(OLECHAR);
  1576. lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw);
  1577. dw = dw / sizeof(OLECHAR);
  1578. }
  1579. if ((LONG)ERROR_SUCCESS!=lRet)
  1580. {
  1581. dw = 0;
  1582. }
  1583. if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) )
  1584. {
  1585. LPOLESTR lpszProgID;
  1586. // We've got an OLE 1.0 class, so let's try to get the user
  1587. // type name from the ProgID entry.
  1588. ProgIDFromCLSID(rclsid, &lpszProgID);
  1589. // REVIEW: will progidfromclsid always set your ptr for you?
  1590. dw = cch * sizeof(OLECHAR);
  1591. lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw);
  1592. dw = dw / sizeof(OLECHAR);
  1593. PubMemFree((LPVOID)lpszProgID);
  1594. if ((LONG)ERROR_SUCCESS != lRet)
  1595. {
  1596. dw = 0;
  1597. }
  1598. }
  1599. if (bCloseRegDB)
  1600. {
  1601. RegCloseKey(hKey);
  1602. }
  1603. ErrRtn:
  1604. LEDebugOut((DEB_ITRACE, "%p OUT OleStdGetUserTypeOfClass ( %d )\n",
  1605. NULL, dw));
  1606. return (UINT)dw;
  1607. }
  1608. //+-------------------------------------------------------------------------
  1609. //
  1610. // Function: OleStdGetAuxUserType, private
  1611. //
  1612. // Synopsis: Returns the specified AuxUserType from the reg db
  1613. //
  1614. // Effects:
  1615. //
  1616. // Arguments: [rclsid] -- the class ID in question
  1617. // [hKey] -- handle to the reg db root (may be NULL)
  1618. // [wAuxUserType] -- which field to look for (name, exe, etc)
  1619. // [lpszUserType] -- where to put the returned string
  1620. // [cch] -- size of [lpszUserType] in *characters*
  1621. //
  1622. // Requires:
  1623. //
  1624. // Returns: UINT -- number of characters in returned string.
  1625. //
  1626. // Signals:
  1627. //
  1628. // Modifies:
  1629. //
  1630. // Algorithm:
  1631. //
  1632. // History: dd-mmm-yy Author Comment
  1633. // 29-Nov-93 alexgo 32bit port
  1634. // 27-Apr-94 AlexT Tracing, clean up
  1635. //
  1636. // Notes:
  1637. //
  1638. //--------------------------------------------------------------------------
  1639. STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
  1640. WORD wAuxUserType,
  1641. LPOLESTR lpszAuxUserType,
  1642. int cch,
  1643. HKEY hKey)
  1644. {
  1645. VDATEHEAP();
  1646. LEDebugOut((DEB_ITRACE, "%p _IN OleStdGetAuxUserType (%p, %hu, %p, %d, %lx)\n",
  1647. NULL, &rclsid, wAuxUserType, lpszAuxUserType, cch, hKey));
  1648. LONG dw = 0;
  1649. HKEY hThisKey;
  1650. BOOL bCloseRegDB = FALSE;
  1651. LRESULT lRet;
  1652. LPOLESTR lpszCLSID;
  1653. OLECHAR szKey[OLEUI_CCHKEYMAX];
  1654. OLECHAR szTemp[32];
  1655. lpszAuxUserType[0] = OLESTR('\0');
  1656. if (NULL == hKey)
  1657. {
  1658. lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey);
  1659. if (ERROR_SUCCESS != lRet)
  1660. {
  1661. goto ErrRtn;
  1662. }
  1663. bCloseRegDB = TRUE;
  1664. }
  1665. else
  1666. {
  1667. hThisKey = hKey;
  1668. }
  1669. StringFromCLSID(rclsid, &lpszCLSID);
  1670. _xstrcpy(szKey, OLESTR("CLSID\\"));
  1671. _xstrcat(szKey, lpszCLSID);
  1672. wsprintf(szTemp, OLESTR("\\AuxUserType\\%d"), wAuxUserType);
  1673. _xstrcat(szKey, szTemp);
  1674. PubMemFree(lpszCLSID);
  1675. dw = cch * sizeof(OLECHAR);
  1676. lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);
  1677. // Convert dw from byte count to OLECHAR count
  1678. dw = dw / sizeof(OLECHAR);
  1679. if (ERROR_SUCCESS != lRet)
  1680. {
  1681. dw = 0;
  1682. lpszAuxUserType[0] = '\0';
  1683. }
  1684. if (bCloseRegDB)
  1685. {
  1686. RegCloseKey(hThisKey);
  1687. }
  1688. ErrRtn:
  1689. // dw is
  1690. LEDebugOut((DEB_ITRACE, "%p OUT OleStdGetAuxUserType ( %d )\n",
  1691. NULL, dw));
  1692. return (UINT)dw;
  1693. }
  1694. //REVIEW: these seem redundant, could the fns be mereged creatively?
  1695. //+-------------------------------------------------------------------------
  1696. //
  1697. // Function:
  1698. // XformWidthInPixelsToHimetric
  1699. // XformWidthInHimetricToPixels
  1700. // XformHeightInPixelsToHimetric
  1701. // XformHeightInHimetricToPixels
  1702. //
  1703. // Synopsis:
  1704. // Functions to convert an int between a device coordinate system and
  1705. // logical HiMetric units.
  1706. //
  1707. // Effects:
  1708. //
  1709. // Arguments:
  1710. //
  1711. // [hDC] HDC providing reference to the pixel mapping. If
  1712. // NULL, a screen DC is used.
  1713. //
  1714. // Size Functions:
  1715. // [lpSizeSrc] LPSIZEL providing the structure to convert. This
  1716. // contains pixels in XformSizeInPixelsToHimetric and
  1717. // logical HiMetric units in the complement function.
  1718. // [lpSizeDst] LPSIZEL providing the structure to receive converted
  1719. // units. This contains pixels in
  1720. // XformSizeInPixelsToHimetric and logical HiMetric
  1721. // units in the complement function.
  1722. //
  1723. // Width Functions:
  1724. // [iWidth] int containing the value to convert.
  1725. //
  1726. // Requires:
  1727. //
  1728. // Returns:
  1729. // Size Functions: None
  1730. // Width Functions: Converted value of the input parameters.
  1731. //
  1732. // Signals:
  1733. //
  1734. // Modifies:
  1735. //
  1736. // Algorithm:
  1737. //
  1738. // History: dd-mmm-yy Author Comment
  1739. // 29-Nov-93 alexgo 32bit port (initial)
  1740. //
  1741. // Notes:
  1742. //
  1743. // When displaying on the screen, Window apps display everything enlarged
  1744. // from its actual size so that it is easier to read. For example, if an
  1745. // app wants to display a 1in. horizontal line, that when printed is
  1746. // actually a 1in. line on the printed page, then it will display the line
  1747. // on the screen physically larger than 1in. This is described as a line
  1748. // that is "logically" 1in. along the display width. Windows maintains as
  1749. // part of the device-specific information about a given display device:
  1750. // LOGPIXELSX -- no. of pixels per logical in along the display width
  1751. // LOGPIXELSY -- no. of pixels per logical in along the display height
  1752. //
  1753. // The following formula converts a distance in pixels into its equivalent
  1754. // logical HIMETRIC units:
  1755. //
  1756. // DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
  1757. // -------------------------------
  1758. // PIXELS_PER_LOGICAL_IN
  1759. //
  1760. //
  1761. // REVIEW32:: merge all these functions into one, as they all do
  1762. // basically the same thing
  1763. //
  1764. //--------------------------------------------------------------------------
  1765. STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix)
  1766. {
  1767. VDATEHEAP();
  1768. LEDebugOut((DEB_ITRACE, "%p _IN XformWidthInPixelsToHimetric (%lx, %d)\n",
  1769. NULL, hDC, iWidthInPix));
  1770. int iXppli; // Pixels per logical inch along width
  1771. int iWidthInHiMetric;
  1772. BOOL fSystemDC=FALSE;
  1773. if (NULL==hDC)
  1774. {
  1775. hDC=GetDC(NULL);
  1776. fSystemDC=TRUE;
  1777. if(!hDC)
  1778. return 0;
  1779. }
  1780. iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
  1781. // We got pixel units, convert them to logical HIMETRIC along
  1782. // the display
  1783. iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli);
  1784. if (fSystemDC)
  1785. {
  1786. ReleaseDC(NULL, hDC);
  1787. }
  1788. LEDebugOut((DEB_ITRACE, "%p OUT XformWidthInPixelsToHimetric (%d)\n",
  1789. NULL, iWidthInHiMetric));
  1790. return iWidthInHiMetric;
  1791. }
  1792. //+-------------------------------------------------------------------------
  1793. //
  1794. // Function: XformWidthInHimetricToPixels
  1795. //
  1796. // Synopsis: see XformWidthInPixelsToHimetric
  1797. //
  1798. // Effects:
  1799. //
  1800. // Arguments:
  1801. //
  1802. // Requires:
  1803. //
  1804. // Returns:
  1805. //
  1806. // Signals:
  1807. //
  1808. // Modifies:
  1809. //
  1810. // Algorithm:
  1811. //
  1812. // History: dd-mmm-yy Author Comment
  1813. // 29-Nov-93 alexgo 32bit port
  1814. //
  1815. // Notes:
  1816. //
  1817. //--------------------------------------------------------------------------
  1818. STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric)
  1819. {
  1820. VDATEHEAP();
  1821. LEDebugOut((DEB_ITRACE, "%p _IN XformWidthInHimetricToPixels (%lx, %d)\n",
  1822. NULL, hDC, iWidthInHiMetric));
  1823. int iXppli; //Pixels per logical inch along width
  1824. int iWidthInPix;
  1825. BOOL fSystemDC=FALSE;
  1826. if (NULL==hDC)
  1827. {
  1828. hDC=GetDC(NULL);
  1829. fSystemDC=TRUE;
  1830. if(!hDC)
  1831. return 0;
  1832. }
  1833. iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
  1834. // We got logical HIMETRIC along the display, convert them to
  1835. // pixel units
  1836. iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli);
  1837. if (fSystemDC)
  1838. {
  1839. ReleaseDC(NULL, hDC);
  1840. }
  1841. LEDebugOut((DEB_ITRACE, "%p OUT XformWidthInHimetricToPixels (%d)\n",
  1842. NULL, iWidthInPix));
  1843. return iWidthInPix;
  1844. }
  1845. //+-------------------------------------------------------------------------
  1846. //
  1847. // Function: XformHeightInPixelsToHimetric
  1848. //
  1849. // Synopsis: see XformWidthInPixelsToHimetric
  1850. //
  1851. // Effects:
  1852. //
  1853. // Arguments:
  1854. //
  1855. // Requires:
  1856. //
  1857. // Returns:
  1858. //
  1859. // Signals:
  1860. //
  1861. // Modifies:
  1862. //
  1863. // Algorithm:
  1864. //
  1865. // History: dd-mmm-yy Author Comment
  1866. // 29-Nov-93 alexgo 32bit port
  1867. //
  1868. // Notes:
  1869. //
  1870. //--------------------------------------------------------------------------
  1871. STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix)
  1872. {
  1873. VDATEHEAP();
  1874. LEDebugOut((DEB_ITRACE, "%p _IN XformHeightInPixelsToHimetric (%lx, %d)\n",
  1875. NULL, hDC, iHeightInPix));
  1876. int iYppli; //Pixels per logical inch along height
  1877. int iHeightInHiMetric;
  1878. BOOL fSystemDC=FALSE;
  1879. if (NULL==hDC)
  1880. {
  1881. hDC=GetDC(NULL);
  1882. fSystemDC=TRUE;
  1883. if(!hDC)
  1884. return 0;
  1885. }
  1886. iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
  1887. // We got pixel units, convert them to logical HIMETRIC along the
  1888. // display
  1889. iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli);
  1890. if (fSystemDC)
  1891. {
  1892. ReleaseDC(NULL, hDC);
  1893. }
  1894. LEDebugOut((DEB_ITRACE, "%p OUT XformHeightInPixelsToHimetric (%d)\n",
  1895. NULL, hDC, iHeightInHiMetric));
  1896. return iHeightInHiMetric;
  1897. }
  1898. //+-------------------------------------------------------------------------
  1899. //
  1900. // Function: XformHeightInHimetricToPixels
  1901. //
  1902. // Synopsis: see XformWidthInPixelsToHimetric
  1903. //
  1904. // Effects:
  1905. //
  1906. // Arguments:
  1907. //
  1908. // Requires:
  1909. //
  1910. // Returns:
  1911. //
  1912. // Signals:
  1913. //
  1914. // Modifies:
  1915. //
  1916. // Algorithm:
  1917. //
  1918. // History: dd-mmm-yy Author Comment
  1919. // 29-Nov-93 alexgo 32bit port
  1920. //
  1921. // Notes:
  1922. //
  1923. //--------------------------------------------------------------------------
  1924. STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric)
  1925. {
  1926. VDATEHEAP();
  1927. LEDebugOut((DEB_ITRACE, "%p _IN XformHeightInHimetricToPixels (%lx, %d)\n",
  1928. NULL, hDC, iHeightInHiMetric));
  1929. int iYppli; //Pixels per logical inch along height
  1930. int iHeightInPix;
  1931. BOOL fSystemDC=FALSE;
  1932. if (NULL==hDC)
  1933. {
  1934. hDC=GetDC(NULL);
  1935. fSystemDC=TRUE;
  1936. if(!hDC)
  1937. return 0;
  1938. }
  1939. iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
  1940. // We got logical HIMETRIC along the display, convert them to pixel
  1941. // units
  1942. iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli);
  1943. if (fSystemDC)
  1944. {
  1945. ReleaseDC(NULL, hDC);
  1946. }
  1947. LEDebugOut((DEB_ITRACE, "%p OUT XformHeightInHimetricToPixels (%d)\n",
  1948. NULL, hDC, iHeightInPix));
  1949. return iHeightInPix;
  1950. }