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.

190 lines
5.8 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include <regstr.h>
  4. #include <olectl.h>
  5. #include <tlhelp32.h>
  6. class CSystemRestoreCleaner : public IFileSystemRestoreDialog
  7. {
  8. private:
  9. LONG _cRef;
  10. public:
  11. CSystemRestoreCleaner(void);
  12. ~CSystemRestoreCleaner(void);
  13. STDMETHODIMP ShowProperties(HWND hwnd);
  14. // IUnknown
  15. STDMETHODIMP QueryInterface (REFIID, void **);
  16. STDMETHODIMP_(ULONG) AddRef (void);
  17. STDMETHODIMP_(ULONG) Release (void);
  18. // IFileSystemRestoreDialog interface members
  19. STDMETHODIMP CanShowFileSystemRestoreDialog(void);
  20. STDMETHODIMP ShowFileSystemRestoreDialog(HWND hwnd); //hwnd points to the parent window.
  21. };
  22. CSystemRestoreCleaner::CSystemRestoreCleaner(void)
  23. {
  24. _cRef = 1;
  25. }
  26. CSystemRestoreCleaner::~CSystemRestoreCleaner(void)
  27. {
  28. }
  29. STDMETHODIMP CSystemRestoreCleaner::QueryInterface(REFIID riid, void **ppv)
  30. {
  31. static const QITAB qit[] = {
  32. QITABENT(CSystemRestoreCleaner, IFileSystemRestoreDialog),
  33. QITABENT(CSystemRestoreCleaner, IUnknown),
  34. { 0 },
  35. };
  36. return QISearch(this, qit, riid, ppv);
  37. }
  38. STDMETHODIMP_(ULONG) CSystemRestoreCleaner::AddRef (void)
  39. {
  40. return InterlockedIncrement(&_cRef);
  41. }
  42. STDMETHODIMP_(ULONG) CSystemRestoreCleaner::Release (void)
  43. {
  44. if (InterlockedDecrement(&_cRef))
  45. return _cRef;
  46. delete this;
  47. return 0;
  48. }
  49. STDMETHODIMP CSystemRestoreCleaner::CanShowFileSystemRestoreDialog(void)
  50. {
  51. typedef BOOL (* PFNISSRENABLED)(void);
  52. HRESULT hr = E_FAIL;
  53. HMODULE hMod = LoadLibrary(TEXT("sfc.dll"));
  54. if (hMod)
  55. {
  56. PFNISSRENABLED pfnIsSREnabled = (PFNISSRENABLED)GetProcAddress(hMod, "IsSREnabled");
  57. if (pfnIsSREnabled)
  58. {
  59. if (pfnIsSREnabled())
  60. hr = S_OK;
  61. else
  62. hr = S_FALSE;
  63. }
  64. FreeLibrary(hMod);
  65. }
  66. return hr;
  67. }
  68. STDMETHODIMP CSystemRestoreCleaner::ShowFileSystemRestoreDialog(HWND hwnd)
  69. {
  70. HRESULT hr = E_FAIL;
  71. if ((hwnd != NULL) && (CanShowFileSystemRestoreDialog() == S_OK))
  72. {
  73. hr = ShowProperties(hwnd);
  74. }
  75. return hr;
  76. }
  77. typedef struct
  78. {
  79. int icon;
  80. TCHAR cpl[ CCHPATHMAX ];
  81. TCHAR applet[ MAX_PATH ];
  82. TCHAR *params;
  83. } CPLEXECINFO;
  84. typedef struct
  85. {
  86. ATOM aCPL; // CPL name atom (so we can match requests)
  87. ATOM aApplet; // applet name atom (so we can match requests, may be zero)
  88. HWND hwndStub; // window for this dude (so we can switch to it)
  89. UINT flags; // see PCPLIF_ flags below
  90. } CPLAPPLETID;
  91. STDAPI_(void) CPL_ParseCommandLine(CPLEXECINFO *info, LPTSTR pszCmdLine, BOOL extract_icon);
  92. STDAPI_(BOOL) SHRunDLLThread(HWND hwnd, LPCTSTR pszCmdLine, int nCmdShow);
  93. STDAPI_(BOOL) CPL_Identify( CPLAPPLETID *identity, CPLEXECINFO *info, HWND stub );
  94. STDAPI_(void) CPL_UnIdentify( CPLAPPLETID *identity );
  95. STDAPI_(HWND) FindCPLWindowByStubWindowClassName(LPTSTR pszWndClassName, CPLAPPLETID *target);
  96. STDMETHODIMP CSystemRestoreCleaner::ShowProperties(HWND hwnd)
  97. {
  98. HRESULT hr = E_FAIL;
  99. CPLEXECINFO info;
  100. CPL_ParseCommandLine( &info, TEXT("sysdm.cpl"), FALSE );
  101. if (PathFindOnPath( info.cpl, NULL ))
  102. {
  103. CPLAPPLETID identity;
  104. if (CPL_Identify( &identity, &info, NULL ))
  105. {
  106. //explorer launches sysdm.cpl control panel on a new process Rundll32 with window name as RunDLL.
  107. HWND hwndTarget = FindCPLWindowByStubWindowClassName(TEXT("RunDLL"), &identity);
  108. if (hwndTarget == NULL)
  109. {
  110. if (SHRunDLLThread(hwnd, TEXT("shell32.dll,Control_RunDLL sysdm.cpl"), SW_SHOWNORMAL))
  111. {
  112. //HACK - We need to wait till the new thread SetProp's the atom to the newly created
  113. //window. Other wise the FindCPLWindowByStubWindowClassName will not find the window.
  114. //Ideally we need to synchronize with the new created thread when it is done SetProp's the
  115. //atom for this Control panel - Look in
  116. int nRetryCount = 0;
  117. while ((NULL == hwndTarget) && nRetryCount < 10)
  118. {
  119. hwndTarget = FindCPLWindowByStubWindowClassName((LPTSTR) c_szStubWindowClass, &identity);
  120. Sleep(50);
  121. ++nRetryCount;
  122. }
  123. }
  124. }
  125. //Even if we don't get the Control's panels hwnd, we would have atleast launched the Property sheet
  126. //for the control panel.
  127. if (hwndTarget && IsWindow(hwndTarget))
  128. {
  129. //If we get the window handle, we switch to the correct tab for the Performance Page and
  130. //emulate File System button click.
  131. // try to find a CPL window on top of it
  132. HWND hDialogWnd = GetLastActivePopup(hwndTarget);
  133. if (hDialogWnd && IsWindow(hDialogWnd))
  134. {
  135. SetForegroundWindow(hDialogWnd);
  136. PropSheet_SetCurSel(hDialogWnd, NULL, 3);
  137. //HACK - Need to simulate a button click on the CPL Dialog. Since it is a 16bit code, we
  138. //can't call the do this hack. 2603 is the ID For the FileSystem button in sysdm.cpl.
  139. PostMessage(hDialogWnd, WM_COMMAND, BN_CLICKED<<16 | 2603, 0 );
  140. hr = S_OK;
  141. }
  142. }
  143. CPL_UnIdentify(&identity);
  144. }
  145. }
  146. return hr;
  147. }
  148. STDAPI CSystemRestoreCleaner_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  149. {
  150. HRESULT hr;
  151. CSystemRestoreCleaner* pdt = new CSystemRestoreCleaner();
  152. if (pdt)
  153. {
  154. hr = pdt->QueryInterface(riid, ppv);
  155. pdt->Release();
  156. }
  157. else
  158. {
  159. *ppv = NULL;
  160. hr = E_OUTOFMEMORY;
  161. }
  162. return hr;
  163. }