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.

819 lines
21 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1999
  5. //
  6. // File: util.cpp
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 7/8/1996 RaviR Created
  15. //
  16. //____________________________________________________________________________
  17. #include <objbase.h>
  18. #include <basetyps.h>
  19. #include "dbg.h"
  20. #include "cstr.h"
  21. #include <Atlbase.h>
  22. #include <winnls.h>
  23. #include "tstring.h"
  24. #include "strings.h"
  25. #define MMC_ATL ::ATL
  26. #include <atlbase.h>
  27. using namespace MMC_ATL;
  28. /* define these ourselves until they're defined properly in commctrl.h */
  29. #ifndef ILP_DOWNLEVEL
  30. #define ILP_NORMAL 0 // Writes or reads the stream using new sematics for this version of comctl32
  31. #define ILP_DOWNLEVEL 1 // Write or reads the stream using downlevel sematics.
  32. WINCOMMCTRLAPI HRESULT WINAPI ImageList_ReadEx(DWORD dwFlags, LPSTREAM pstm, REFIID riid, PVOID* ppv);
  33. WINCOMMCTRLAPI HRESULT WINAPI ImageList_WriteEx(HIMAGELIST himl, DWORD dwFlags, LPSTREAM pstm);
  34. #endif
  35. ULONG _ttoul(LPTSTR psz)
  36. {
  37. ULONG ul;
  38. for (ul = 0; *psz != TEXT('\0'); ++psz)
  39. {
  40. ul = ul * 10 + (*psz - TEXT('0'));
  41. }
  42. return ul;
  43. }
  44. WORD I_SplitModuleAndResourceID(LPCTSTR szBuf)
  45. {
  46. WORD wID = (WORD)-1;
  47. // String must be in the form "module, res_id"
  48. for (TCHAR *ptc = (TCHAR *)szBuf;
  49. *ptc != TEXT('\0') && *ptc != TEXT(',');
  50. ptc++);
  51. // If no comma - return
  52. if (*ptc != TEXT(','))
  53. return wID;
  54. *ptc = TEXT('\0');
  55. ++ptc;
  56. while (*ptc == TEXT(' ') && *ptc != TEXT('\0'))
  57. {
  58. ++ptc;
  59. }
  60. // If it does not have a res_id break.
  61. if (*ptc == TEXT('\0'))
  62. return wID;
  63. // Get the res-id
  64. wID = (WORD)_ttoul(ptc);
  65. return wID;
  66. }
  67. BOOL
  68. I_GetStrFromModule(
  69. LPCTSTR pszModule,
  70. ULONG ulMsgNo,
  71. CStr &strBuf)
  72. {
  73. TCHAR szBuf[512];
  74. ULONG cchBuf = 512;
  75. HINSTANCE hinst = LoadLibraryEx(pszModule, NULL,
  76. LOAD_LIBRARY_AS_DATAFILE);
  77. if (hinst)
  78. {
  79. LANGID lidUser = LANGIDFROMLCID(GetUserDefaultLCID());
  80. DWORD cChars = ::FormatMessage(
  81. FORMAT_MESSAGE_FROM_HMODULE |
  82. FORMAT_MESSAGE_IGNORE_INSERTS,
  83. (HMODULE)hinst,
  84. ulMsgNo,
  85. lidUser,
  86. szBuf,
  87. cchBuf,
  88. NULL);
  89. FreeLibrary(hinst);
  90. if (cChars != 0)
  91. {
  92. strBuf = szBuf;
  93. return TRUE;
  94. }
  95. }
  96. //Dbg(DEB_USER1, _T("I_GetStringFromModule failed<%dL>\n"), GetLastError());
  97. return FALSE;
  98. }
  99. HICON I_GetHicon(LPCTSTR pszModule, ULONG ulId)
  100. {
  101. HICON hIcon = NULL;
  102. HINSTANCE hinst = LoadLibraryEx(pszModule, NULL,
  103. LOAD_LIBRARY_AS_DATAFILE);
  104. if (hinst)
  105. {
  106. hIcon = LoadIcon(hinst, MAKEINTRESOURCE(ulId));
  107. FreeLibrary(hinst);
  108. }
  109. return hIcon;
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Function: NewDupString
  114. //
  115. // Synopsis: Allocates memory & duplicates a given string.
  116. //
  117. // Arguments: [lpszIn] -- IN the string to duplicate.
  118. //
  119. // Returns: The duplicated string. Throws exception if out of memory.
  120. //
  121. //+---------------------------------------------------------------------------
  122. LPTSTR NewDupString(LPCTSTR lpszIn)
  123. {
  124. register ULONG len = lstrlen(lpszIn) + 1;
  125. TCHAR * lpszOut = new TCHAR[len];
  126. if (lpszOut == NULL)
  127. return NULL;
  128. CopyMemory(lpszOut, lpszIn, len * sizeof(TCHAR));
  129. return lpszOut;
  130. }
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Function: CoTaskDupString
  134. //
  135. // Synopsis: Allocates memory & duplicates a given string.
  136. //
  137. // Arguments: [lpszIn] -- IN the string to duplicate.
  138. //
  139. // Returns: The duplicated string. Throws exception if out of memory.
  140. //
  141. //+---------------------------------------------------------------------------
  142. // Tony
  143. LPSTR CoTaskDupString(LPCSTR lpszIn)
  144. {
  145. if (lpszIn == NULL)
  146. return NULL;
  147. ULONG cbTemp = (strlen(lpszIn) + 1) * sizeof(*lpszIn);
  148. LPSTR lpszOut = (LPSTR) CoTaskMemAlloc(cbTemp);
  149. if (lpszOut != NULL)
  150. CopyMemory(lpszOut, lpszIn, cbTemp);
  151. return (lpszOut);
  152. }
  153. LPWSTR CoTaskDupString(LPCWSTR lpszIn)
  154. {
  155. if (lpszIn == NULL)
  156. return NULL;
  157. ULONG cbTemp = (wcslen(lpszIn) + 1) * sizeof(*lpszIn);
  158. LPWSTR lpszOut = (LPWSTR) CoTaskMemAlloc(cbTemp);
  159. if (lpszOut != NULL)
  160. CopyMemory(lpszOut, lpszIn, cbTemp);
  161. return (lpszOut);
  162. }
  163. //+---------------------------------------------------------------------------
  164. //
  165. // Function: GUIDToString
  166. // GUIDFromString
  167. //
  168. // Synopsis: Converts between GUID& and CStr
  169. //
  170. // Returns: FALSE for invalid string, or CMemoryException
  171. //
  172. //+---------------------------------------------------------------------------
  173. HRESULT GUIDToCStr(CStr& str, const GUID& guid)
  174. {
  175. LPOLESTR lpolestr = NULL;
  176. HRESULT hr = StringFromIID( guid, &lpolestr );
  177. if (FAILED(hr))
  178. {
  179. //TRACE("GUIDToString error %ld\n", hr);
  180. return hr;
  181. }
  182. else
  183. {
  184. str = lpolestr;
  185. CoTaskMemFree(lpolestr);
  186. }
  187. return hr;
  188. }
  189. HRESULT GUIDFromCStr(const CStr& str, GUID* pguid)
  190. {
  191. USES_CONVERSION;
  192. HRESULT hr = IIDFromString( T2OLE( const_cast<LPTSTR>((LPCTSTR)str) ), pguid );
  193. if (FAILED(hr))
  194. {
  195. //TRACE("GUIDFromString error %ld\n", hr);
  196. }
  197. return hr;
  198. }
  199. //+---------------------------------------------------------------------------
  200. //
  201. // Function: DoesFileExist
  202. //
  203. // Synopsis: Determines if the specified file exists. The file path may
  204. // include environment variables.
  205. //
  206. // Returns: TRUE/FALSE
  207. //
  208. //+---------------------------------------------------------------------------
  209. BOOL DoesFileExist(LPCTSTR pszFilePath)
  210. {
  211. TCHAR szExpandedPath[MAX_PATH];
  212. DWORD dwCnt = ExpandEnvironmentStrings(pszFilePath, szExpandedPath, MAX_PATH);
  213. if (dwCnt == 0 || dwCnt > MAX_PATH)
  214. return FALSE;
  215. return (::GetFileAttributes(szExpandedPath) != 0xffffffff);
  216. }
  217. /*+-------------------------------------------------------------------------*
  218. *
  219. * GetHelpFile
  220. *
  221. * PURPOSE: Returns a path to the help file
  222. *
  223. * RETURNS:
  224. * static LPCTSTR
  225. *
  226. *+-------------------------------------------------------------------------*/
  227. LPCTSTR GetHelpFile()
  228. {
  229. static const TCHAR NEW_HELP_FILE_STR[] = _T("%windir%\\Help\\MMC_DLG.HLP");
  230. static const TCHAR OLD_HELP_FILE_STR[] = _T("%windir%\\Help\\MMC.HLP");
  231. static LPCTSTR pszHelpFile = NULL;
  232. // See if help file is present. Check new name first, then old name.
  233. // This is done because the old help file may be overwritten by
  234. // an MMC 1.0 installation (see NT bug 299590)
  235. if (pszHelpFile == NULL)
  236. {
  237. if (DoesFileExist(NEW_HELP_FILE_STR))
  238. {
  239. pszHelpFile = NEW_HELP_FILE_STR;
  240. }
  241. else if (DoesFileExist(OLD_HELP_FILE_STR))
  242. {
  243. pszHelpFile = OLD_HELP_FILE_STR;
  244. }
  245. else
  246. {
  247. // if neither file is present, then use the new file name.
  248. // This will let WinHelp display an error message indicating
  249. // that the file is missing and needs to be installed.
  250. pszHelpFile = NEW_HELP_FILE_STR;
  251. }
  252. }
  253. return pszHelpFile;
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Function: HelpWmHelp
  258. //
  259. // Synopsis: Calls WinHelp with the ID passed to display help
  260. //
  261. // Returns: none
  262. //
  263. //+---------------------------------------------------------------------------
  264. void HelpWmHelp(LPHELPINFO pHelpInfo, const DWORD* pHelpIDs)
  265. {
  266. if (pHelpInfo != NULL)
  267. {
  268. if (pHelpInfo->iContextType == HELPINFO_WINDOW) // must be for a control
  269. {
  270. ASSERT(pHelpIDs != NULL);
  271. if (pHelpIDs)
  272. {
  273. ::WinHelp((HWND)pHelpInfo->hItemHandle, GetHelpFile(),
  274. HELP_WM_HELP, (ULONG_PTR)(LPVOID)pHelpIDs);
  275. }
  276. }
  277. }
  278. }
  279. /*+-------------------------------------------------------------------------*
  280. *
  281. * HelpContextMenuHelp
  282. *
  283. * PURPOSE: Handle context menu help. Invoked when the user right-clicks
  284. * on a dialog item and selects "What's this?"
  285. *
  286. * PARAMETERS:
  287. * HWND hWnd :
  288. * ULONG_PTR p :
  289. *
  290. * RETURNS:
  291. * void
  292. *
  293. *+-------------------------------------------------------------------------*/
  294. void HelpContextMenuHelp(HWND hWnd, ULONG_PTR p)
  295. {
  296. ::WinHelp (hWnd, GetHelpFile(), HELP_CONTEXTMENU, p);
  297. }
  298. /*+-------------------------------------------------------------------------*
  299. * InflateFont
  300. *
  301. * Inflates a LOGFONT by the a given number of points
  302. *--------------------------------------------------------------------------*/
  303. bool InflateFont (LOGFONT* plf, int nPointsToGrowBy)
  304. {
  305. if (nPointsToGrowBy != 0)
  306. {
  307. HDC hdc = GetWindowDC (NULL);
  308. if (hdc == NULL)
  309. return (FALSE);
  310. int nLogPixelsY = GetDeviceCaps (hdc, LOGPIXELSY);
  311. int nPoints = -MulDiv (plf->lfHeight, 72, nLogPixelsY);
  312. nPoints += nPointsToGrowBy;
  313. plf->lfHeight = -MulDiv (nPoints, nLogPixelsY, 72);
  314. ReleaseDC (NULL, hdc);
  315. }
  316. return (true);
  317. }
  318. //+-------------------------------------------------------------------
  319. //
  320. // Member: GetTBBtnTextAndStatus
  321. //
  322. // Synopsis: Helper routine to get one/two part button text resource.
  323. //
  324. // Arguments: [hInst] - Instance handle.
  325. // [nID] - String resource id.
  326. // [ppszButton] - Button text.
  327. // [ppszToolTip] - Button status text.
  328. //
  329. // Note: Uses MFC CString.
  330. //
  331. // Returns: bool
  332. //
  333. //--------------------------------------------------------------------
  334. bool GetTBBtnTextAndStatus(HINSTANCE hInst, int nID, std::wstring& szButton, std::wstring& szToolTip)
  335. {
  336. USES_CONVERSION;
  337. CStr str;
  338. str.LoadString(hInst, nID);
  339. ASSERT(!str.IsEmpty());
  340. if (str.IsEmpty())
  341. return false;
  342. int iPos = str.Find(_T('\n'));
  343. if (-1 != iPos)
  344. {
  345. // Two strings. First from 0 to iPos-1
  346. // and second from iPos+1 to end.
  347. szButton = T2CW((LPCTSTR)str.Left(iPos));
  348. szToolTip = T2CW((LPCTSTR)str.Right(str.GetLength() - iPos - 1));
  349. }
  350. else
  351. {
  352. // Only one string. Use this for both text and status.
  353. szButton = T2CW((LPCTSTR)str);
  354. szToolTip = szButton;
  355. }
  356. return true;
  357. }
  358. #ifdef DBG
  359. /*+-------------------------------------------------------------------------*
  360. * DrawOnDesktop
  361. *
  362. * Draws a bitmap, icon, or imagelist to a specific location on the desktop.
  363. *--------------------------------------------------------------------------*/
  364. void DrawOnDesktop (HBITMAP hbm, int x, int y)
  365. {
  366. HDC hdcDesktop = GetWindowDC (NULL);
  367. HDC hdcMem = CreateCompatibleDC (NULL);
  368. BITMAP bm;
  369. GetObject ((HGDIOBJ) hbm, sizeof(bm), &bm);
  370. HGDIOBJ hbmOld = SelectObject (hdcMem, (HGDIOBJ) hbm);
  371. BitBlt (hdcDesktop, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
  372. SelectObject (hdcMem, hbmOld);
  373. DeleteDC (hdcMem);
  374. ReleaseDC (NULL, hdcDesktop);
  375. }
  376. void DrawOnDesktop (HICON hIcon, int x, int y)
  377. {
  378. HDC hdcDesktop = GetWindowDC (NULL);
  379. DrawIconEx (hdcDesktop, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
  380. ReleaseDC (NULL, hdcDesktop);
  381. }
  382. void DrawOnDesktop (HIMAGELIST himl, int x, int y, int iImage /*=-1*/)
  383. {
  384. HDC hdcDesktop = GetWindowDC (NULL);
  385. /*
  386. * draw all images?
  387. */
  388. if (iImage == -1)
  389. {
  390. int cImages = ImageList_GetImageCount (himl);
  391. int cxImage, cyImage;
  392. ImageList_GetIconSize (himl, &cxImage, &cyImage);
  393. for (int i = 0; i < cImages; i++, x += cxImage)
  394. {
  395. ImageList_Draw (himl, i, hdcDesktop, x, y, ILD_NORMAL);
  396. }
  397. }
  398. else
  399. {
  400. /*
  401. * draw a specific image
  402. */
  403. ImageList_Draw (himl, iImage, hdcDesktop, x, y, ILD_NORMAL);
  404. }
  405. ReleaseDC (NULL, hdcDesktop);
  406. }
  407. #endif // DBG
  408. /*+-------------------------------------------------------------------------*
  409. * StripTrailingWhitespace
  410. *
  411. * Removes the whitespace at the end of the input string. Returns a pointer
  412. * the the beginning of the string.
  413. *--------------------------------------------------------------------------*/
  414. LPTSTR StripTrailingWhitespace (LPTSTR pszStart)
  415. {
  416. for (LPTSTR pch = pszStart + _tcslen(pszStart) - 1; pch > pszStart; pch--)
  417. {
  418. /*
  419. * if this isn't a whitespace character, terminate just after this position
  420. */
  421. if (!_istspace (*pch))
  422. {
  423. *++pch = 0;
  424. break;
  425. }
  426. }
  427. return (pszStart);
  428. }
  429. /***************************************************************************\
  430. *
  431. * METHOD: PrivateSetLayout
  432. *
  433. * PURPOSE: Wrapper to invoke GDI function when it is available,
  434. * but not to depend on its availability
  435. *
  436. * PARAMETERS:
  437. * HDC hdc
  438. * DWORD dwLayout
  439. *
  440. * RETURNS:
  441. * DWORD - previous layout, GDI_ERROR on error
  442. *
  443. \***************************************************************************/
  444. DWORD PrivateSetLayout( HDC hdc, DWORD dwLayout )
  445. {
  446. // static pointer to function
  447. static BOOL (WINAPI* pfnSetLayout)(HDC, DWORD) = NULL;
  448. static bool bTriedToGetFunction = false;
  449. if ( !bTriedToGetFunction )
  450. {
  451. bTriedToGetFunction = true;
  452. HINSTANCE hmodGdi = GetModuleHandle (_T("Gdi32.dll"));
  453. if (hmodGdi != NULL)
  454. (FARPROC&)pfnSetLayout = GetProcAddress (hmodGdi, "SetLayout");
  455. }
  456. if (pfnSetLayout == NULL)
  457. return GDI_ERROR;
  458. return (*pfnSetLayout)(hdc, dwLayout);
  459. }
  460. /***************************************************************************\
  461. *
  462. * METHOD: PrivateGetLayout
  463. *
  464. * PURPOSE: Wrapper to invoke GDI function when it is available,
  465. * but not to depend on its availability
  466. *
  467. * PARAMETERS:
  468. * HDC hdc
  469. *
  470. * RETURNS:
  471. * DWORD - layout, 0 if function not found
  472. *
  473. \***************************************************************************/
  474. DWORD PrivateGetLayout( HDC hdc )
  475. {
  476. // static pointer to function
  477. static BOOL (WINAPI* pfnGetLayout)(HDC) = NULL;
  478. static bool bTriedToGetFunction = false;
  479. if ( !bTriedToGetFunction )
  480. {
  481. bTriedToGetFunction = true;
  482. HINSTANCE hmodGdi = GetModuleHandle (_T("Gdi32.dll"));
  483. if (hmodGdi != NULL)
  484. (FARPROC&)pfnGetLayout = GetProcAddress (hmodGdi, "GetLayout");
  485. }
  486. if (pfnGetLayout == NULL)
  487. return 0; // at least not LAYOUT_RTL
  488. return (*pfnGetLayout)(hdc);
  489. }
  490. /*+-------------------------------------------------------------------------*
  491. * IsWhistler
  492. *
  493. * Returns true if we're running on Whistler or higher, false otherwise.
  494. *--------------------------------------------------------------------------*/
  495. bool IsWhistler ()
  496. {
  497. static bool fFirstTime = true;
  498. static bool fWhistler = false;
  499. if (fFirstTime)
  500. {
  501. fFirstTime = false;
  502. OSVERSIONINFO vi;
  503. vi.dwOSVersionInfoSize = sizeof(vi);
  504. GetVersionEx (&vi);
  505. fWhistler = (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  506. ((vi.dwMajorVersion > 5) ||
  507. (vi.dwMajorVersion == 5) && (vi.dwMinorVersion >= 1));
  508. }
  509. return (fWhistler);
  510. }
  511. /*+-------------------------------------------------------------------------*
  512. * WriteCompatibleImageList
  513. *
  514. * Writes an imagelist to a stream in a format that's guaranteed to be
  515. * compatible with comctl32 version 5 imagelists.
  516. *--------------------------------------------------------------------------*/
  517. HRESULT WriteCompatibleImageList (HIMAGELIST himl, IStream* pstm)
  518. {
  519. /*
  520. * If we're running on Whistler, we might be trying to write a v6
  521. * imagelist. Try to write it in a v5-compatible format with
  522. * ImageList_WriteEx.
  523. */
  524. if (IsWhistler())
  525. {
  526. /*
  527. * ImageList_WriteEx will return E_NOINTERFACE if we're actually
  528. * writing a v5 imagelist, in which case we want to write with
  529. * ImageList_Write. In any other case (success or failure), we
  530. * just want to return.
  531. */
  532. HRESULT hr = ImageList_WriteEx (himl, ILP_DOWNLEVEL, pstm);
  533. if (hr != E_NOINTERFACE)
  534. return (hr);
  535. }
  536. /*
  537. * if we get here, we have a v5 imagelist -- just write it
  538. */
  539. return (ImageList_Write (himl, pstm));
  540. }
  541. /*+-------------------------------------------------------------------------*
  542. * ReadCompatibleImageList
  543. *
  544. * Reads an imagelist from a stream that's in version 5 format.
  545. *--------------------------------------------------------------------------*/
  546. HRESULT ReadCompatibleImageList (IStream* pstm, HIMAGELIST& himl)
  547. {
  548. HRESULT hr = S_OK;
  549. /*
  550. * init the out parameter
  551. */
  552. himl = NULL;
  553. /*
  554. * If we're running on Whistler, we're trying to create a v6
  555. * imagelist from the stream. Do it in a v5-compatible manner
  556. * with ImageList_ReadEx.
  557. */
  558. if (IsWhistler())
  559. {
  560. /*
  561. * HACK: We have to query ImageList_ReadEx for IID_IImageList -- the
  562. * one defined by the shell, not the one defined by MMC. If we
  563. * just refer to "IID_IImageList" in the code here, we'll get MMC's
  564. * version, not the shell's. The right way to fix it is to rename
  565. * the shell's IImageList interface (since MMC's interface was defined
  566. * and published first), but that's not going to happen.
  567. *
  568. * We'll hardcode the IID's value in a string here and convert it
  569. * to an IID on the fly. Ugh.
  570. */
  571. IID iidShellImageList = {0};
  572. hr = CLSIDFromString (L"{46eb5926-582e-4017-9fdf-e8998daa0950}", &iidShellImageList);
  573. if (FAILED (hr))
  574. return (hr);
  575. /*
  576. * ImageList_ReadEx will return E_NOINTERFACE if we're actually
  577. * writing a v5 imagelist, in which case we want to write with
  578. * ImageList_Write. In any other case (success or failure), we
  579. * just want to return.
  580. */
  581. IUnknownPtr spUnk;
  582. hr = ImageList_ReadEx (ILP_DOWNLEVEL, pstm, iidShellImageList, (void**) &spUnk);
  583. if (FAILED (hr))
  584. return (hr);
  585. /*
  586. * The IUnknown *is* the HIMAGELIST. Don't release it here,
  587. * ImageList_Destroy will take care of it.
  588. */
  589. himl = reinterpret_cast<HIMAGELIST>(spUnk.Detach());
  590. }
  591. else
  592. {
  593. /*
  594. * non-Whistler, just read it normally
  595. */
  596. himl = ImageList_Read (pstm);
  597. /*
  598. * If the read failed, get the last error. Just in case ImageList_Read
  599. * didn't set the last error, make sure we return a failure code.
  600. */
  601. if (himl == NULL)
  602. {
  603. hr = HRESULT_FROM_WIN32 (GetLastError());
  604. if (!FAILED (hr))
  605. hr = E_FAIL;
  606. }
  607. }
  608. return (hr);
  609. }
  610. //+-------------------------------------------------------------------
  611. //
  612. // Member: MmcDownlevelActivateActCtx
  613. //
  614. // Synopsis: Calls ActivateActCtx to set the activation context to V5
  615. // common controls. This is needed before calling into snapins
  616. // so that snapin created windows are not themed accidentally.
  617. //
  618. // The snapin can theme its windows by calling appropriate
  619. // fusion apis while calling create-window.
  620. //
  621. // Description:
  622. // When MMC calls into the snapin if the last winproc which
  623. // received a window message is themed and will result in a
  624. // call to snapin then we will call the snapin in themed
  625. // context. If snapin creates & displays any UI then it will
  626. // be themed. This function is to de-activate the theming
  627. // before calling the snapin.
  628. //
  629. // Arguments:
  630. // [hActCtx] - See ActivateActCtx API details
  631. // [pulCookie] - See ActivateActCtx API details
  632. //
  633. // Returns: BOOL, TRUE if we could de-activate V6 context and switch to V5 context
  634. // or if we are in V5 context (W2K, Win95, Win98...)
  635. // FALSE if ActivateActCtx returns failure.
  636. //
  637. //--------------------------------------------------------------------
  638. BOOL WINAPI MmcDownlevelActivateActCtx(HANDLE hActCtx, ULONG_PTR* pulCookie)
  639. {
  640. typedef BOOL (WINAPI* PFN)(HANDLE hActCtx, ULONG_PTR* pulCookie);
  641. static PFN s_pfn;
  642. static DWORD s_dwError;
  643. if (s_pfn == NULL && s_dwError == 0)
  644. if ((s_pfn = (PFN)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "ActivateActCtx")) == NULL)
  645. s_dwError = (GetLastError() == NO_ERROR) ? ERROR_INTERNAL_ERROR : GetLastError();
  646. if (s_pfn != NULL)
  647. return s_pfn(hActCtx, pulCookie);
  648. SetLastError(s_dwError);
  649. if (s_dwError == ERROR_PROC_NOT_FOUND)
  650. return TRUE;
  651. return FALSE;
  652. }
  653. //+-------------------------------------------------------------------
  654. //
  655. // Member: MmcDownlevelDeactivateActCtx
  656. //
  657. // Synopsis: Calls DeactivateActCtx to restore the activation context.
  658. // This is needed after calling into snapins, so that
  659. // if we called from themed context then it is restored.
  660. //
  661. // Description:
  662. // When MMC calls into the snapin if the last winproc which
  663. // received a window message is themed and will result in a
  664. // call to snapin then we will call the snapin in themed
  665. // context. If snapin creates & displays any UI then it will
  666. // be themed. This function is to de-activate the theming
  667. // before calling the snapin.
  668. //
  669. // Arguments:
  670. // [dwFlags] - See DeactivateActCtx API details
  671. // [ulCookie] - See DeactivateActCtx API details
  672. //
  673. // Returns: None
  674. //
  675. //--------------------------------------------------------------------
  676. VOID WINAPI MmcDownlevelDeactivateActCtx(DWORD dwFlags, ULONG_PTR ulCookie)
  677. {
  678. typedef VOID (WINAPI* PFN)(DWORD dwFlags, ULONG_PTR ulCookie);
  679. static PFN s_pfn;
  680. static BOOL s_fInited;
  681. if (!s_fInited)
  682. s_pfn = (PFN)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "DeactivateActCtx");
  683. s_fInited = TRUE;
  684. if (s_pfn != NULL)
  685. s_pfn(dwFlags, ulCookie);
  686. }