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.

596 lines
21 KiB

  1. /******************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. SystemRestore.CPP -- WMI provider class implementation
  4. Generated by Microsoft WMI Code Generation Engine
  5. TO DO: - See individual function headers
  6. - When linking, make sure you link to framedyd.lib &
  7. msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).
  8. Description:
  9. ******************************************************************/
  10. #include <fwcommon.h> // This must be the first include.
  11. #include "SystemRestore.h"
  12. #include "srdefs.h"
  13. #include "srrestoreptapi.h"
  14. #include "srrpcapi.h"
  15. #include "enumlogs.h"
  16. #include "utils.h"
  17. #include "srshell.h"
  18. // TO DO: Replace "NameSpace" with the appropriate namespace for your
  19. // provider instance. For instance: "root\\default or "root\\cimv2".
  20. //===================================================================
  21. CSystemRestore MySystemRestoreSet (PROVIDER_NAME_SYSTEMRESTORE, L"root\\default") ;
  22. // Property names
  23. //===============
  24. const static WCHAR* pName = L"Description" ;
  25. const static WCHAR* pNumber = L"SequenceNumber" ;
  26. const static WCHAR* pType = L"RestorePointType" ;
  27. const static WCHAR* pEventType = L"EventType" ;
  28. const static WCHAR* pTime = L"CreationTime" ;
  29. /*****************************************************************************
  30. *
  31. * FUNCTION : CSystemRestore::CSystemRestore
  32. *
  33. * DESCRIPTION : Constructor
  34. *
  35. * INPUTS : none
  36. *
  37. * RETURNS : nothing
  38. *
  39. * COMMENTS : Calls the Provider constructor.
  40. *
  41. *****************************************************************************/
  42. CSystemRestore::CSystemRestore (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) :
  43. Provider(lpwszName, lpwszNameSpace)
  44. {
  45. }
  46. /*****************************************************************************
  47. *
  48. * FUNCTION : CSystemRestore::~CSystemRestore
  49. *
  50. * DESCRIPTION : Destructor
  51. *
  52. * INPUTS : none
  53. *
  54. * RETURNS : nothing
  55. *
  56. * COMMENTS :
  57. *
  58. *****************************************************************************/
  59. CSystemRestore::~CSystemRestore ()
  60. {
  61. }
  62. /*****************************************************************************
  63. *
  64. * FUNCTION : CSystemRestore::EnumerateInstances
  65. *
  66. * DESCRIPTION : Returns all the instances of this class.
  67. *
  68. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  69. * A long that contains the flags described in
  70. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  71. * flags are handled by (and filtered out by) WinMgmt:
  72. * WBEM_FLAG_DEEP
  73. * WBEM_FLAG_SHALLOW
  74. * WBEM_FLAG_RETURN_IMMEDIATELY
  75. * WBEM_FLAG_FORWARD_ONLY
  76. * WBEM_FLAG_BIDIRECTIONAL
  77. *
  78. * RETURNS : WBEM_S_NO_ERROR if successful
  79. *
  80. * COMMENTS : TO DO: All instances on the machine should be returned here and
  81. * all properties that this class knows how to populate must
  82. * be filled in. If there are no instances, return
  83. * WBEM_S_NO_ERROR. It is not an error to have no instances.
  84. * If you are implementing a 'method only' provider, you
  85. * should remove this method.
  86. *
  87. *****************************************************************************/
  88. HRESULT CSystemRestore::EnumerateInstances ( MethodContext* pMethodContext, long lFlags )
  89. {
  90. HRESULT hRes = WBEM_S_NO_ERROR;
  91. // TO DO: The following commented lines contain the 'set' methods for the
  92. // properties entered for this class. They are commented because they
  93. // will NOT compile in their current form. Each <Property Value> should be
  94. // replaced with the appropriate value. Also, consider creating a new
  95. // method and moving these set statements and the ones from GetObject
  96. // into that routine. See the framework sample (ReindeerProv.cpp) for
  97. // an example of how this might be done.
  98. //
  99. // If the expectation is that there is more than one instance on the machine
  100. // EnumerateInstances should loop through the instances and fill them accordingly.
  101. //
  102. // Note that you must ALWAYS set ALL the key properties. See the docs for
  103. // further details.
  104. ///////////////////////////////////////////////////////////////////////////////
  105. WCHAR szDrive[MAX_PATH]=L"";
  106. GetSystemDrive(szDrive);
  107. CRestorePointEnum RPEnum(szDrive, TRUE, FALSE);
  108. CRestorePoint RP;
  109. DWORD dwRc;
  110. FILETIME *pft = NULL;
  111. if (!IsAdminOrSystem())
  112. {
  113. return (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED));
  114. }
  115. dwRc = RPEnum.FindFirstRestorePoint(RP);
  116. while (dwRc == ERROR_SUCCESS)
  117. {
  118. CInstance* pInstance = CreateNewInstance(pMethodContext);
  119. if (! pInstance)
  120. {
  121. hRes = WBEM_E_OUT_OF_MEMORY;
  122. break;
  123. }
  124. pInstance->SetCHString(pName, RP.GetName());
  125. pInstance->SetDWORD(pNumber, RP.GetNum());
  126. pInstance->SetDWORD(pType, RP.GetType());
  127. pInstance->SetDWORD(pEventType, RP.GetEventType());
  128. if (pft = RP.GetTime())
  129. {
  130. WBEMTime wbt(*pft);
  131. BSTR bstrTime;
  132. if (bstrTime = wbt.GetBSTR())
  133. {
  134. pInstance->SetCHString(pTime, bstrTime);
  135. SysFreeString(bstrTime);
  136. }
  137. }
  138. hRes = pInstance->Commit();
  139. pInstance->Release();
  140. dwRc = RPEnum.FindNextRestorePoint(RP);
  141. }
  142. RPEnum.FindClose();
  143. return hRes ;
  144. }
  145. /*****************************************************************************
  146. *
  147. * FUNCTION : CSystemRestore::GetObject
  148. *
  149. * DESCRIPTION : Find a single instance based on the key properties for the
  150. * class.
  151. *
  152. * INPUTS : A pointer to a CInstance object containing the key properties.
  153. * A long that contains the flags described in
  154. * IWbemServices::GetObjectAsync.
  155. *
  156. * RETURNS : WBEM_S_NO_ERROR if the instance can be found
  157. * WBEM_E_NOT_FOUND if the instance described by the key properties
  158. * could not be found
  159. * WBEM_E_FAILED if the instance could be found but another error
  160. * occurred.
  161. *
  162. * COMMENTS : If you are implementing a 'method only' provider, you should
  163. * remove this method.
  164. *
  165. *****************************************************************************/
  166. HRESULT CSystemRestore::GetObject ( CInstance* pInstance, long lFlags )
  167. {
  168. // TO DO: The GetObject function is used to search for an instance of this
  169. // class on the machine based on the key properties. Unlike
  170. // EnumerateInstances which finds all instances on the machine, GetObject
  171. // uses the key properties to find the matching single instance and
  172. // returns that instance.
  173. //
  174. // Use the CInstance Get functions (for example, call
  175. // GetCHString(L"Name", sTemp)) against pInstance to see the key values
  176. // the client requested.
  177. HRESULT hr = WBEM_E_NOT_FOUND;
  178. // if (<InstanceExists>)
  179. // {
  180. // TO DO: The following commented lines contain the 'set' methods for the
  181. // properties entered for this class. They are commented because they
  182. // will NOT compile in their current form. Each <Property Value> should be
  183. // replaced with the appropriate value.
  184. //
  185. // pInstance->SetCHString(pName, <Property Value>);
  186. // pInstance->SetVariant(pNumber, <Property Value>);
  187. // pInstance->SetVariant(pType, <Property Value>);
  188. //
  189. // hr = WBEM_S_NO_ERROR;
  190. // }
  191. return hr ;
  192. }
  193. /*****************************************************************************
  194. *
  195. * FUNCTION : CSystemRestore::ExecQuery
  196. *
  197. * DESCRIPTION : You are passed a method context to use in the creation of
  198. * instances that satisfy the query, and a CFrameworkQuery
  199. * which describes the query. Create and populate all
  200. * instances which satisfy the query. You may return more
  201. * instances or more properties than are requested and WinMgmt
  202. * will post filter out any that do not apply.
  203. *
  204. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  205. * A query object describing the query to satisfy.
  206. * A long that contains the flags described in
  207. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  208. * flags are handled by (and filtered out by) WinMgmt:
  209. * WBEM_FLAG_FORWARD_ONLY
  210. * WBEM_FLAG_BIDIRECTIONAL
  211. * WBEM_FLAG_ENSURE_LOCATABLE
  212. *
  213. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for
  214. * this class or if the query is too complex for this class
  215. * to interpret. The framework will call the EnumerateInstances
  216. * function instead and let Winmgmt post filter.
  217. * WBEM_E_FAILED if the query failed
  218. * WBEM_S_NO_ERROR if query was successful
  219. *
  220. * COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt
  221. * will call your enumerate function to get all the instances and perform the
  222. * filtering for you. Unless you expect SIGNIFICANT savings from implementing
  223. * queries, you should remove this method. You should also remove this method
  224. * if you are implementing a 'method only' provider.
  225. *
  226. *****************************************************************************/
  227. HRESULT CSystemRestore::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
  228. {
  229. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  230. }
  231. /*****************************************************************************
  232. *
  233. * FUNCTION : CSystemRestore::PutInstance
  234. *
  235. * DESCRIPTION : PutInstance should be used in provider classes that can
  236. * write instance information back to the hardware or
  237. * software. For example: Win32_Environment will allow a
  238. * PutInstance to create or update an environment variable.
  239. * However, a class like MotherboardDevice will not allow
  240. * editing of the number of slots, since it is difficult for
  241. * a provider to affect that number.
  242. *
  243. * INPUTS : A pointer to a CInstance object containing the key properties.
  244. * A long that contains the flags described in
  245. * IWbemServices::PutInstanceAsync.
  246. *
  247. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
  248. * WBEM_E_FAILED if there is an error delivering the instance
  249. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  250. * are incorrect.
  251. * WBEM_S_NO_ERROR if instance is properly delivered
  252. *
  253. * COMMENTS : TO DO: If you don't intend to support writing to your provider,
  254. * or are creating a 'method only' provider, remove this
  255. * method.
  256. *
  257. *****************************************************************************/
  258. HRESULT CSystemRestore::PutInstance ( const CInstance &Instance, long lFlags)
  259. {
  260. // Use the CInstance Get functions (for example, call
  261. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  262. // the client requested.
  263. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  264. }
  265. /*****************************************************************************
  266. *
  267. * FUNCTION : CSystemRestore::DeleteInstance
  268. *
  269. * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information
  270. * to the software or hardware. For most hardware devices,
  271. * DeleteInstance should not be implemented, but for software
  272. * configuration, DeleteInstance implementation is plausible.
  273. *
  274. * INPUTS : A pointer to a CInstance object containing the key properties.
  275. * A long that contains the flags described in
  276. * IWbemServices::DeleteInstanceAsync.
  277. *
  278. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
  279. * WBEM_E_FAILED if there is an error deleting the instance.
  280. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  281. * are incorrect.
  282. * WBEM_S_NO_ERROR if instance is properly deleted.
  283. *
  284. * COMMENTS : TO DO: If you don't intend to support deleting instances or are
  285. * creating a 'method only' provider, remove this method.
  286. *
  287. *****************************************************************************/
  288. HRESULT CSystemRestore::DeleteInstance ( const CInstance &Instance, long lFlags )
  289. {
  290. // Use the CInstance Get functions (for example, call
  291. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  292. // the client requested.
  293. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  294. }
  295. /*****************************************************************************
  296. *
  297. * FUNCTION : CSystemRestore::ExecMethod
  298. *
  299. * DESCRIPTION : Override this function to provide support for methods.
  300. * A method is an entry point for the user of your provider
  301. * to request your class perform some function above and
  302. * beyond a change of state. (A change of state should be
  303. * handled by PutInstance() )
  304. *
  305. * INPUTS : A pointer to a CInstance containing the instance the method was executed against.
  306. * A string containing the method name
  307. * A pointer to the CInstance which contains the IN parameters.
  308. * A pointer to the CInstance to contain the OUT parameters.
  309. * A set of specialized method flags
  310. *
  311. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
  312. * WBEM_S_NO_ERROR if method executes successfully
  313. * WBEM_E_FAILED if error occurs executing method
  314. *
  315. * COMMENTS : TO DO: If you don't intend to support Methods, remove this method.
  316. *
  317. *****************************************************************************/
  318. HRESULT CSystemRestore::ExecMethod ( const CInstance& Instance,
  319. const BSTR bstrMethodName,
  320. CInstance *pInParams,
  321. CInstance *pOutParams,
  322. long lFlags)
  323. {
  324. // For non-static methods, use the CInstance Get functions (for example,
  325. // call GetCHString(L"Name", sTemp)) against Instance to see the key
  326. // values the client requested.
  327. HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
  328. if (lstrcmpi(bstrMethodName, L"CreateRestorePoint") == 0)
  329. {
  330. hresult = CreateRestorePoint(pInParams, pOutParams);
  331. }
  332. else if (lstrcmpi(bstrMethodName, L"Enable") == 0)
  333. {
  334. hresult = Enable(pInParams, pOutParams);
  335. }
  336. else if (lstrcmpi(bstrMethodName, L"Disable") == 0)
  337. {
  338. hresult = Disable(pInParams, pOutParams);
  339. }
  340. else if (lstrcmpi(bstrMethodName, L"Restore") == 0)
  341. {
  342. hresult = Restore(pInParams, pOutParams);
  343. }
  344. else if (lstrcmpi(bstrMethodName, L"GetLastRestoreStatus") == 0)
  345. {
  346. hresult = GetLastRestoreStatus(pInParams, pOutParams);
  347. }
  348. return hresult;
  349. }
  350. HRESULT CSystemRestore::CreateRestorePoint(
  351. CInstance *pInParams,
  352. CInstance *pOutParams)
  353. {
  354. LPWSTR pwszName = NULL;
  355. HRESULT hr = WBEM_S_NO_ERROR;
  356. RESTOREPOINTINFOW rpi;
  357. STATEMGRSTATUS ss;
  358. ss.nStatus = ERROR_INVALID_PARAMETER;
  359. pInParams->GetWCHAR(L"Description", &pwszName);
  360. if (pwszName)
  361. {
  362. pInParams->GetDWORD(L"RestorePointType", rpi.dwRestorePtType);
  363. pInParams->GetDWORD(L"EventType", rpi.dwEventType);
  364. lstrcpy(rpi.szDescription, pwszName);
  365. // cannot create a RESTORE type restore point from WMI
  366. if (rpi.dwRestorePtType == RESTORE)
  367. {
  368. goto done;
  369. }
  370. ::SRSetRestorePoint(&rpi, &ss);
  371. free(pwszName);
  372. }
  373. done:
  374. pOutParams->SetDWORD(L"ReturnValue", ss.nStatus);
  375. return hr;
  376. }
  377. HRESULT CSystemRestore::Enable(
  378. CInstance *pInParams,
  379. CInstance *pOutParams)
  380. {
  381. LPWSTR pwszDrive = NULL;
  382. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  383. bool fWait = 0;
  384. DWORD dwRc;
  385. pInParams->GetWCHAR(L"Drive", &pwszDrive);
  386. pInParams->Getbool(L"WaitTillEnabled", fWait);
  387. if (pwszDrive)
  388. {
  389. if (0 == lstrcmpi(pwszDrive, L""))
  390. dwRc = ::EnableSREx(NULL, (BOOL) fWait);
  391. else
  392. dwRc = ::EnableSREx(pwszDrive, (BOOL) fWait);
  393. pOutParams->SetDWORD(L"ReturnValue", dwRc);
  394. if (pwszDrive) free(pwszDrive);
  395. hr = WBEM_S_NO_ERROR;
  396. }
  397. return hr;
  398. }
  399. HRESULT CSystemRestore::Disable(
  400. CInstance *pInParams,
  401. CInstance *pOutParams)
  402. {
  403. LPWSTR pwszDrive = NULL;
  404. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  405. DWORD dwRc;
  406. pInParams->GetWCHAR(L"Drive", &pwszDrive);
  407. if (pwszDrive)
  408. {
  409. if (0 == lstrcmpi(pwszDrive, L""))
  410. dwRc = ::DisableSR(NULL);
  411. else
  412. dwRc = ::DisableSR(pwszDrive);
  413. pOutParams->SetDWORD(L"ReturnValue", dwRc);
  414. if (pwszDrive) free(pwszDrive);
  415. hr = WBEM_S_NO_ERROR;
  416. }
  417. return hr;
  418. }
  419. HRESULT CSystemRestore::Restore(
  420. CInstance *pInParams,
  421. CInstance *pOutParams)
  422. {
  423. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  424. DWORD dwRp = 0, dwRpNew;
  425. IRestoreContext *pCtx = NULL;
  426. DWORD dwErr = ERROR_INTERNAL_ERROR;
  427. HMODULE hModule = NULL;
  428. CRestorePoint rp;
  429. WCHAR szRp[MAX_RP_PATH];
  430. pInParams->GetDWORD(L"SequenceNumber", dwRp);
  431. if (dwRp == 0)
  432. goto Err;
  433. hr = WBEM_S_NO_ERROR;
  434. // validate the restore point first
  435. wsprintf( szRp, L"%s%ld", s_cszRPDir, dwRp );
  436. rp.SetDir(szRp);
  437. dwErr = rp.ReadLog();
  438. if (dwErr != ERROR_SUCCESS) // it doesn't exist
  439. {
  440. goto Err;
  441. }
  442. if (rp.GetType() == CANCELLED_OPERATION) // cannot restore to it
  443. {
  444. dwErr = ERROR_INVALID_PARAMETER;
  445. goto Err;
  446. }
  447. hModule = ::LoadLibraryW (L"srrstr.dll");
  448. if (hModule != NULL)
  449. {
  450. INITFUNC pInit = NULL;
  451. PREPFUNC pPrep = (PREPFUNC) GetProcAddress (hModule, "PrepareRestore");
  452. if (pPrep != NULL)
  453. {
  454. if (FALSE == (*pPrep) ((int) dwRp, &pCtx))
  455. {
  456. goto Err;
  457. }
  458. }
  459. else
  460. {
  461. dwErr = GetLastError();
  462. goto Err;
  463. }
  464. //
  465. // make this a silent restore - no result page
  466. //
  467. pCtx->SetSilent();
  468. pInit = (INITFUNC) GetProcAddress (hModule, "InitiateRestore");
  469. if (pInit != NULL)
  470. {
  471. if (FALSE == (*pInit) (pCtx, &dwRpNew))
  472. {
  473. goto Err;
  474. }
  475. else
  476. {
  477. dwErr = ERROR_SUCCESS;
  478. }
  479. }
  480. else
  481. {
  482. dwErr = GetLastError();
  483. goto Err;
  484. }
  485. }
  486. else dwErr = GetLastError();
  487. Err:
  488. pOutParams->SetDWORD(L"ReturnValue", dwErr);
  489. if (hModule != NULL)
  490. ::FreeLibrary (hModule);
  491. return hr;
  492. }
  493. HRESULT
  494. CSystemRestore::GetLastRestoreStatus(
  495. CInstance *pInParams,
  496. CInstance *pOutParams)
  497. {
  498. HRESULT hr = WBEM_S_NO_ERROR;
  499. DWORD dwStatus = 0;
  500. HKEY hkey = NULL;
  501. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, s_cszSRRegKey, &hkey))
  502. {
  503. RegReadDWORD(hkey, s_cszRestoreStatus, &dwStatus);
  504. RegCloseKey(hkey);
  505. }
  506. else
  507. {
  508. dwStatus = 0xFFFFFFFF;
  509. }
  510. pOutParams->SetDWORD(L"ReturnValue", dwStatus);
  511. return hr;
  512. }