Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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