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.

1476 lines
32 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. srrpcc.cpp
  5. Abstract:
  6. implements functions exported in srclient.DLL
  7. Exported API:
  8. SRSetRestorePoint / SRRemoveRestorePoint
  9. DisableSR / EnableSR
  10. DisableFIFO / EnableFIFO
  11. Revision History:
  12. Brijesh Krishnaswami (brijeshk) - 04/10/00 - Created
  13. ********************************************************************/
  14. #include "stdafx.h"
  15. #ifdef THIS_FILE
  16. #undef THIS_FILE
  17. #endif
  18. static char __szTraceSourceFile[] = __FILE__;
  19. #define THIS_FILE __szTraceSourceFile
  20. //
  21. // function to check if SR configuration is disabled
  22. // via group policy
  23. //
  24. DWORD
  25. CheckPolicy()
  26. {
  27. DWORD dwPolicyEnabled = 0;
  28. DWORD dwErr = ERROR_SUCCESS;
  29. HKEY hKey = NULL;
  30. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  31. s_cszGroupPolicy,
  32. 0,
  33. KEY_READ,
  34. &hKey))
  35. {
  36. // if this value exists,
  37. // then config policy is either enabled or disabled
  38. // we need to disable access in both cases
  39. if (ERROR_SUCCESS == RegReadDWORD(hKey, s_cszDisableConfig, &dwPolicyEnabled))
  40. dwErr = ERROR_ACCESS_DENIED;
  41. RegCloseKey(hKey);
  42. }
  43. return dwErr;
  44. }
  45. // bind handle to endpoint
  46. DWORD
  47. SRRPCInit(
  48. RPC_IF_HANDLE * pIfHandle,
  49. BOOL fVerifyRights)
  50. {
  51. RPC_STATUS status;
  52. LPWSTR pszStringBinding = NULL;
  53. DWORD dwRc = ERROR_SUCCESS;
  54. InitAsyncTrace();
  55. TENTER("SRRPCInit");
  56. //
  57. // if admin rights are required
  58. //
  59. if (fVerifyRights && ! IsAdminOrSystem())
  60. {
  61. TRACE(0, "Caller does not have admin or localsystem rights");
  62. dwRc = ERROR_ACCESS_DENIED;
  63. goto exit;
  64. }
  65. //
  66. // check if the service is stopping
  67. // if it is, then we don't want to accept any more rpc calls
  68. //
  69. if (IsStopSignalled(NULL))
  70. {
  71. TRACE(0, "Service shut down - not accepting rpc call");
  72. dwRc = ERROR_SERVICE_DISABLED;
  73. goto exit;
  74. }
  75. // compose string to pass to binding api
  76. dwRc = (DWORD) RpcStringBindingCompose(NULL,
  77. s_cszRPCProtocol,
  78. NULL,
  79. s_cszRPCEndPoint,
  80. NULL,
  81. &pszStringBinding);
  82. if (dwRc != ERROR_SUCCESS)
  83. {
  84. TRACE(0, "RPCStringBindingCompose: error=%ld", dwRc);
  85. goto exit;
  86. }
  87. // set the binding handle that will be used to bind to the server.
  88. dwRc = (DWORD) RpcBindingFromStringBinding(pszStringBinding,
  89. pIfHandle);
  90. if (dwRc != ERROR_SUCCESS)
  91. {
  92. TRACE(0, "RPCBindingFromStringBinding: error=%ld", dwRc);
  93. }
  94. // free string
  95. RpcStringFree(&pszStringBinding);
  96. if (dwRc != ERROR_SUCCESS)
  97. goto exit;
  98. RPC_SECURITY_QOS qos;
  99. qos.Version = RPC_C_SECURITY_QOS_VERSION;
  100. qos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; // Important!!!
  101. qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  102. qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  103. dwRc = RpcBindingSetAuthInfoEx(*pIfHandle,
  104. L"NT AUTHORITY\\SYSTEM",
  105. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,
  106. RPC_C_AUTHN_WINNT,
  107. 0,
  108. 0,
  109. &qos);
  110. exit:
  111. TLEAVE();
  112. return dwRc;
  113. }
  114. // free binding handle
  115. DWORD
  116. SRRPCTerm(
  117. RPC_IF_HANDLE * pIfHandle)
  118. {
  119. RPC_STATUS status;
  120. TENTER("SRRPCTerm");
  121. // free binding handle
  122. if (pIfHandle && *pIfHandle)
  123. status = RpcBindingFree(pIfHandle);
  124. TLEAVE();
  125. TermAsyncTrace();
  126. return (DWORD) status;
  127. }
  128. // API to disable System Restore
  129. extern "C" DWORD WINAPI
  130. DisableSR(LPCWSTR pszDrive)
  131. {
  132. DWORD dwRc = ERROR_INTERNAL_ERROR;
  133. handle_t srrpc_IfHandle = NULL;
  134. TENTER("DisableSR");
  135. //
  136. // check if sr config is disabled via group policy
  137. //
  138. dwRc = CheckPolicy();
  139. if (dwRc != ERROR_SUCCESS)
  140. {
  141. goto exit;
  142. }
  143. // initialize
  144. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  145. if (dwRc != ERROR_SUCCESS)
  146. {
  147. goto exit;
  148. }
  149. // call remote procedure
  150. RpcTryExcept
  151. {
  152. dwRc = DisableSRS(srrpc_IfHandle, pszDrive);
  153. }
  154. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  155. {
  156. dwRc = RpcExceptionCode();
  157. TRACE(0, "DisableSRS threw exception: error=%ld", dwRc);
  158. }
  159. RpcEndExcept
  160. // terminate
  161. SRRPCTerm(&srrpc_IfHandle);
  162. exit:
  163. TLEAVE();
  164. return dwRc;
  165. }
  166. // private function to start the SR service
  167. // fWait - if TRUE : function is synchronous - waits till service is started completely
  168. // if FALSE : function is asynchronous - does not wait for service to complete starting
  169. DWORD
  170. StartSRService(BOOL fWait)
  171. {
  172. DWORD dwRc = ERROR_SUCCESS;
  173. SC_HANDLE hSCM = ::OpenSCManager(NULL,
  174. NULL,
  175. SC_MANAGER_ALL_ACCESS);
  176. SERVICE_STATUS Status;
  177. if (hSCM)
  178. {
  179. SC_HANDLE hSR = OpenService(hSCM,
  180. s_cszServiceName,
  181. SERVICE_ALL_ACCESS);
  182. if (hSR)
  183. {
  184. if (FALSE == StartService(hSR, 0, NULL))
  185. {
  186. dwRc = GetLastError();
  187. if (dwRc == ERROR_SERVICE_ALREADY_RUNNING)
  188. {
  189. goto done;
  190. }
  191. if (FALSE == QueryServiceStatus(hSR, &Status))
  192. {
  193. goto done;
  194. }
  195. else
  196. {
  197. dwRc = Status.dwWin32ExitCode;
  198. goto done;
  199. }
  200. }
  201. if (fWait)
  202. {
  203. //
  204. // query the service until it starts or stops
  205. // try thrice
  206. //
  207. for (int i = 0; i < 3; i++)
  208. {
  209. Sleep(2000);
  210. if (FALSE == QueryServiceStatus(hSR, &Status))
  211. {
  212. goto done;
  213. }
  214. if (Status.dwCurrentState == SERVICE_STOPPED)
  215. {
  216. dwRc = Status.dwWin32ExitCode;
  217. if (dwRc == ERROR_SUCCESS)
  218. {
  219. //
  220. // service masks DISABLED error code
  221. // to avoid unnecessary event log messages
  222. //
  223. dwRc = ERROR_SERVICE_DISABLED;
  224. }
  225. goto done;
  226. }
  227. if (Status.dwCurrentState == SERVICE_RUNNING)
  228. {
  229. //
  230. // wait on init event
  231. //
  232. HANDLE hInit = OpenEvent(SYNCHRONIZE, FALSE, s_cszSRInitEvent);
  233. if (hInit)
  234. {
  235. dwRc = WaitForSingleObject(hInit, 120000); // wait for 2 minutes
  236. CloseHandle(hInit);
  237. if (dwRc == WAIT_OBJECT_0)
  238. {
  239. dwRc = ERROR_SUCCESS;
  240. goto done;
  241. }
  242. else
  243. {
  244. dwRc = ERROR_TIMEOUT;
  245. goto done;
  246. }
  247. }
  248. }
  249. }
  250. }
  251. CloseServiceHandle(hSR);
  252. }
  253. else
  254. {
  255. dwRc = GetLastError();
  256. }
  257. CloseServiceHandle(hSCM);
  258. }
  259. else
  260. {
  261. dwRc = GetLastError();
  262. }
  263. done:
  264. return dwRc;
  265. }
  266. DWORD
  267. SetDisableFlag(DWORD dwValue)
  268. {
  269. HKEY hKeySR = NULL;
  270. DWORD dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  271. s_cszSRRegKey,
  272. 0,
  273. KEY_WRITE,
  274. &hKeySR);
  275. if (ERROR_SUCCESS != dwRc)
  276. goto done;
  277. dwRc = RegWriteDWORD(hKeySR, s_cszDisableSR, &dwValue);
  278. if (ERROR_SUCCESS != dwRc)
  279. goto done;
  280. done:
  281. if (hKeySR)
  282. RegCloseKey(hKeySR);
  283. return dwRc;
  284. }
  285. // API to enable System Restore
  286. extern "C" DWORD WINAPI
  287. EnableSR(LPCWSTR pszDrive)
  288. {
  289. DWORD dwRc = ERROR_INTERNAL_ERROR;
  290. handle_t srrpc_IfHandle = NULL;
  291. TENTER("EnableSR");
  292. //
  293. // check if sr config is disabled via group policy
  294. //
  295. dwRc = CheckPolicy();
  296. if (dwRc != ERROR_SUCCESS)
  297. {
  298. goto exit;
  299. }
  300. // if whole of SR is enabled, then
  301. // set the boot mode of service/filter to automatic
  302. // and start the service
  303. if (! pszDrive || IsSystemDrive((LPWSTR) pszDrive))
  304. {
  305. //
  306. // if safe mode, then don't
  307. //
  308. if (0 != GetSystemMetrics(SM_CLEANBOOT))
  309. {
  310. TRACE(0, "This is safemode");
  311. dwRc = ERROR_BAD_ENVIRONMENT;
  312. goto exit;
  313. }
  314. dwRc = SetServiceStartup(s_cszServiceName, SERVICE_AUTO_START);
  315. if (ERROR_SUCCESS != dwRc)
  316. goto exit;
  317. dwRc = SetServiceStartup(s_cszFilterName, SERVICE_BOOT_START);
  318. if (ERROR_SUCCESS != dwRc)
  319. goto exit;
  320. // set the disable flag to false
  321. // BUGBUG - this piece of code is duplicated in the service code as well
  322. // reason is: we need the ability to disable/enable SR from within and outside
  323. // the service
  324. dwRc = SetDisableFlag(FALSE);
  325. if (ERROR_SUCCESS != dwRc)
  326. goto exit;
  327. dwRc = StartSRService(FALSE);
  328. }
  329. else
  330. {
  331. // initialize
  332. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  333. if (dwRc != ERROR_SUCCESS)
  334. {
  335. goto exit;
  336. }
  337. // call remote procedure
  338. RpcTryExcept
  339. {
  340. dwRc = EnableSRS(srrpc_IfHandle, pszDrive);
  341. }
  342. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  343. {
  344. dwRc = RpcExceptionCode();
  345. TRACE(0, "EnableSRS threw exception: error=%ld", dwRc);
  346. }
  347. RpcEndExcept
  348. // terminate
  349. SRRPCTerm(&srrpc_IfHandle);
  350. }
  351. exit:
  352. TLEAVE();
  353. return dwRc;
  354. }
  355. // API to enable System Restore - extended version
  356. extern "C" DWORD WINAPI
  357. EnableSREx(LPCWSTR pszDrive, BOOL fWait)
  358. {
  359. DWORD dwRc = ERROR_INTERNAL_ERROR;
  360. handle_t srrpc_IfHandle = NULL;
  361. TENTER("EnableSREx");
  362. //
  363. // check if sr config is disabled via group policy
  364. //
  365. dwRc = CheckPolicy();
  366. if (dwRc != ERROR_SUCCESS)
  367. {
  368. goto exit;
  369. }
  370. // if whole of SR is enabled, then
  371. // set the boot mode of service/filter to automatic
  372. // and start the service
  373. if (! pszDrive || IsSystemDrive((LPWSTR) pszDrive))
  374. {
  375. //
  376. // if safe mode, then don't
  377. //
  378. if (0 != GetSystemMetrics(SM_CLEANBOOT))
  379. {
  380. TRACE(0, "This is safemode");
  381. dwRc = ERROR_BAD_ENVIRONMENT;
  382. goto exit;
  383. }
  384. dwRc = SetServiceStartup(s_cszServiceName, SERVICE_AUTO_START);
  385. if (ERROR_SUCCESS != dwRc)
  386. goto exit;
  387. dwRc = SetServiceStartup(s_cszFilterName, SERVICE_BOOT_START);
  388. if (ERROR_SUCCESS != dwRc)
  389. goto exit;
  390. // set the disable flag to false
  391. // BUGBUG - this piece of code is duplicated in the service code as well
  392. // reason is: we need the ability to disable/enable SR from within and outside
  393. // the service
  394. dwRc = SetDisableFlag(FALSE);
  395. if (ERROR_SUCCESS != dwRc)
  396. goto exit;
  397. dwRc = StartSRService(fWait);
  398. }
  399. else
  400. {
  401. // initialize
  402. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  403. if (dwRc != ERROR_SUCCESS)
  404. {
  405. goto exit;
  406. }
  407. // call remote procedure
  408. RpcTryExcept
  409. {
  410. dwRc = EnableSRS(srrpc_IfHandle, pszDrive);
  411. }
  412. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  413. {
  414. dwRc = RpcExceptionCode();
  415. TRACE(0, "EnableSRS threw exception: error=%ld", dwRc);
  416. }
  417. RpcEndExcept
  418. // terminate
  419. SRRPCTerm(&srrpc_IfHandle);
  420. }
  421. exit:
  422. TLEAVE();
  423. return dwRc;
  424. }
  425. // API to update the list of protected files - UNICODE version
  426. // pass the fullpath name of the XML file containing the updated list of files
  427. extern "C" DWORD WINAPI
  428. SRUpdateMonitoredListA(
  429. LPCSTR pszXMLFile)
  430. {
  431. DWORD dwRc = ERROR_INTERNAL_ERROR;
  432. LPWSTR pwszXMLFile = NULL;
  433. handle_t srrpc_IfHandle = NULL;
  434. TENTER("SRUpdateMonitoredListA");
  435. pwszXMLFile = ConvertToUnicode((LPSTR) pszXMLFile);
  436. if (! pwszXMLFile)
  437. {
  438. TRACE(0, "ConvertToUnicode");
  439. goto exit;
  440. }
  441. // initialize
  442. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  443. if (dwRc != ERROR_SUCCESS)
  444. {
  445. goto exit;
  446. }
  447. // call remote procedure
  448. RpcTryExcept
  449. {
  450. dwRc = SRUpdateMonitoredListS(srrpc_IfHandle, pwszXMLFile);
  451. }
  452. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  453. {
  454. dwRc = RpcExceptionCode();
  455. TRACE(0, "SRUpdateMonitoredListS threw exception: error=%ld", dwRc);
  456. }
  457. RpcEndExcept
  458. // terminate
  459. SRRPCTerm(&srrpc_IfHandle);
  460. exit:
  461. if (pwszXMLFile)
  462. SRMemFree(pwszXMLFile);
  463. TLEAVE();
  464. return dwRc;
  465. }
  466. // API to update the list of protected files - UNICODE version
  467. // pass the fullpath name of the XML file containing the updated list of files
  468. extern "C" DWORD WINAPI
  469. SRUpdateMonitoredListW(
  470. LPCWSTR pwszXMLFile)
  471. {
  472. DWORD dwRc = ERROR_INTERNAL_ERROR;
  473. handle_t srrpc_IfHandle = NULL;
  474. TENTER("SRUpdateMonitoredListW");
  475. // initialize
  476. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  477. if (dwRc != ERROR_SUCCESS)
  478. {
  479. goto exit;
  480. }
  481. // call remote procedure
  482. RpcTryExcept
  483. {
  484. dwRc = SRUpdateMonitoredListS(srrpc_IfHandle, pwszXMLFile);
  485. }
  486. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  487. {
  488. dwRc = RpcExceptionCode();
  489. TRACE(0, "SRUpdateMonitoredListS threw exception: error=%ld", dwRc);
  490. }
  491. RpcEndExcept
  492. // terminate
  493. SRRPCTerm(&srrpc_IfHandle);
  494. exit:
  495. TLEAVE();
  496. return dwRc;
  497. }
  498. // API to set a restore point - ANSI version
  499. extern "C" BOOL
  500. SRSetRestorePointA(
  501. PRESTOREPOINTINFOA pRPInfoA,
  502. PSTATEMGRSTATUS pSMgrStatus)
  503. {
  504. BOOL fRc = FALSE;
  505. RESTOREPOINTINFOW RPInfoW;
  506. LPWSTR pszDescW = NULL;
  507. handle_t srrpc_IfHandle = NULL;
  508. TENTER("SRSetRestorePointA");
  509. // Initialize return values
  510. if (! pSMgrStatus || ! pRPInfoA)
  511. {
  512. goto exit;
  513. }
  514. pSMgrStatus->llSequenceNumber = 0;
  515. pSMgrStatus->nStatus = ERROR_INTERNAL_ERROR;
  516. // convert struct to unicode
  517. // since the string is the last member of the struct, we can memcpy
  518. // all
  519. memcpy(&RPInfoW, pRPInfoA, sizeof(RESTOREPOINTINFOA));
  520. pszDescW = ConvertToUnicode(pRPInfoA->szDescription);
  521. if (! pszDescW)
  522. {
  523. TRACE(0, "ConvertToUnicode");
  524. goto exit;
  525. }
  526. lstrcpy(RPInfoW.szDescription, pszDescW);
  527. // initialize
  528. // don't need admin rights to call this api
  529. pSMgrStatus->nStatus = SRRPCInit(&srrpc_IfHandle, FALSE);
  530. if (pSMgrStatus->nStatus != ERROR_SUCCESS)
  531. {
  532. goto exit;
  533. }
  534. // call remote procedure
  535. RpcTryExcept
  536. {
  537. fRc = SRSetRestorePointS(srrpc_IfHandle, &RPInfoW, pSMgrStatus);
  538. }
  539. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  540. {
  541. // set right error code if SR is disabled
  542. DWORD dwRc = RpcExceptionCode();
  543. if (RPC_S_SERVER_UNAVAILABLE == dwRc ||
  544. RPC_S_UNKNOWN_IF == dwRc)
  545. {
  546. pSMgrStatus->nStatus = ERROR_SERVICE_DISABLED;
  547. }
  548. else
  549. {
  550. pSMgrStatus->nStatus = dwRc;
  551. }
  552. TRACE(0, "SRSetRestorePointS threw exception: nStatus=%ld", pSMgrStatus->nStatus);
  553. }
  554. RpcEndExcept
  555. // terminate
  556. SRRPCTerm(&srrpc_IfHandle);
  557. exit:
  558. if (pszDescW)
  559. SRMemFree(pszDescW);
  560. TLEAVE();
  561. return fRc;
  562. }
  563. // API to set a restore point - UNICODE version
  564. extern "C" BOOL
  565. SRSetRestorePointW(
  566. PRESTOREPOINTINFOW pRPInfoW,
  567. PSTATEMGRSTATUS pSMgrStatus)
  568. {
  569. BOOL fRc = FALSE;
  570. DWORD dwRc = ERROR_SUCCESS;
  571. handle_t srrpc_IfHandle = NULL;
  572. TENTER("SRSetRestorePointW");
  573. // Initialize return values
  574. if (! pSMgrStatus || ! pRPInfoW)
  575. {
  576. goto exit;
  577. }
  578. pSMgrStatus->llSequenceNumber = 0;
  579. pSMgrStatus->nStatus = ERROR_INTERNAL_ERROR;
  580. // initialize
  581. pSMgrStatus->nStatus = SRRPCInit(&srrpc_IfHandle, FALSE);
  582. if (pSMgrStatus->nStatus != ERROR_SUCCESS)
  583. {
  584. goto exit;
  585. }
  586. // call remote procedure
  587. RpcTryExcept
  588. {
  589. fRc = SRSetRestorePointS(srrpc_IfHandle, pRPInfoW, pSMgrStatus);
  590. }
  591. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  592. {
  593. // set right error code if SR is disabled
  594. DWORD dwRc = RpcExceptionCode();
  595. if (RPC_S_SERVER_UNAVAILABLE == dwRc ||
  596. RPC_S_UNKNOWN_IF == dwRc)
  597. {
  598. pSMgrStatus->nStatus = ERROR_SERVICE_DISABLED;
  599. }
  600. else
  601. {
  602. pSMgrStatus->nStatus = dwRc;
  603. }
  604. TRACE(0, "SRSetRestorePointS threw exception: nStatus=%ld", pSMgrStatus->nStatus);
  605. }
  606. RpcEndExcept
  607. // terminate
  608. SRRPCTerm(&srrpc_IfHandle);
  609. exit:
  610. TLEAVE();
  611. return fRc;
  612. }
  613. // API to remove a restore point
  614. extern "C" DWORD
  615. SRRemoveRestorePoint(
  616. DWORD dwRPNum)
  617. {
  618. DWORD dwRc = ERROR_INTERNAL_ERROR;
  619. handle_t srrpc_IfHandle = NULL;
  620. TENTER("SRRemoveRestorePoint");
  621. // initialize
  622. dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
  623. if (dwRc != ERROR_SUCCESS)
  624. goto exit;
  625. // call remote procedure
  626. RpcTryExcept
  627. {
  628. dwRc = SRRemoveRestorePointS(srrpc_IfHandle, dwRPNum);
  629. }
  630. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  631. {
  632. dwRc = RpcExceptionCode();
  633. TRACE(0, "SRRemoveRestorePointS threw exception: error=%ld", dwRc);
  634. }
  635. RpcEndExcept
  636. // terminate
  637. SRRPCTerm(&srrpc_IfHandle);
  638. exit:
  639. TLEAVE();
  640. return dwRc;
  641. }
  642. // api to disable FIFO
  643. extern "C" DWORD WINAPI
  644. DisableFIFO(
  645. DWORD dwRPNum)
  646. {
  647. DWORD dwRc = ERROR_INTERNAL_ERROR;
  648. handle_t srrpc_IfHandle = NULL;
  649. TENTER("DisableFIFO");
  650. // initialize
  651. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  652. if (dwRc != ERROR_SUCCESS)
  653. {
  654. goto exit;
  655. }
  656. // call remote procedure
  657. RpcTryExcept
  658. {
  659. dwRc = DisableFIFOS(srrpc_IfHandle, dwRPNum);
  660. }
  661. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  662. {
  663. dwRc = RpcExceptionCode();
  664. TRACE(0, "DisableFIFOS threw exception: error=%ld", dwRc);
  665. }
  666. RpcEndExcept
  667. // terminate
  668. SRRPCTerm(&srrpc_IfHandle);
  669. exit:
  670. TLEAVE();
  671. return dwRc;
  672. }
  673. // api to enable FIFO
  674. extern "C" DWORD WINAPI
  675. EnableFIFO()
  676. {
  677. DWORD dwRc = ERROR_INTERNAL_ERROR;
  678. handle_t srrpc_IfHandle = NULL;
  679. TENTER("EnableFIFO");
  680. // initialize
  681. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  682. if (dwRc != ERROR_SUCCESS)
  683. {
  684. goto exit;
  685. }
  686. // call remote procedure
  687. RpcTryExcept
  688. {
  689. dwRc = EnableFIFOS(srrpc_IfHandle);
  690. }
  691. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  692. {
  693. dwRc = RpcExceptionCode();
  694. TRACE(0, "EnableFIFOS threw exception: error=%ld", dwRc);
  695. }
  696. RpcEndExcept
  697. // terminate
  698. SRRPCTerm(&srrpc_IfHandle);
  699. exit:
  700. TLEAVE();
  701. return dwRc;
  702. }
  703. // api to reset SR
  704. extern "C" DWORD WINAPI
  705. ResetSR(
  706. LPCWSTR pszDrive)
  707. {
  708. DWORD dwRc = ERROR_INTERNAL_ERROR;
  709. handle_t srrpc_IfHandle = NULL;
  710. TENTER("ResetSR");
  711. // initialize
  712. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  713. if (dwRc != ERROR_SUCCESS)
  714. {
  715. goto exit;
  716. }
  717. // call remote procedure
  718. RpcTryExcept
  719. {
  720. dwRc = ResetSRS(srrpc_IfHandle, pszDrive);
  721. }
  722. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  723. {
  724. dwRc = RpcExceptionCode();
  725. TRACE(0, "ResetSRS threw exception: error=%ld", dwRc);
  726. }
  727. RpcEndExcept
  728. // terminate
  729. SRRPCTerm(&srrpc_IfHandle);
  730. exit:
  731. TLEAVE();
  732. return dwRc;
  733. }
  734. // api to refresh the drive table from disk
  735. // restore UI will call this - service will update its drivetable in memory
  736. extern "C" DWORD WINAPI
  737. SRUpdateDSSize(LPCWSTR pszDrive, UINT64 ullSizeLimit)
  738. {
  739. DWORD dwRc = ERROR_INTERNAL_ERROR;
  740. handle_t srrpc_IfHandle = NULL;
  741. TENTER("SRUpdateDSSize");
  742. //
  743. // check if sr config is disabled via group policy
  744. //
  745. dwRc = CheckPolicy();
  746. if (dwRc != ERROR_SUCCESS)
  747. {
  748. goto exit;
  749. }
  750. // initialize
  751. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  752. if (dwRc != ERROR_SUCCESS)
  753. {
  754. goto exit;
  755. }
  756. // call remote procedure
  757. RpcTryExcept
  758. {
  759. dwRc = SRUpdateDSSizeS(srrpc_IfHandle, pszDrive, ullSizeLimit);
  760. }
  761. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  762. {
  763. dwRc = RpcExceptionCode();
  764. TRACE(0, "SRUpdateDSSizeS threw exception: error=%ld", dwRc);
  765. }
  766. RpcEndExcept
  767. // terminate
  768. SRRPCTerm(&srrpc_IfHandle);
  769. exit:
  770. TLEAVE();
  771. return dwRc;
  772. }
  773. extern "C" DWORD WINAPI
  774. SRSwitchLog()
  775. {
  776. DWORD dwRc = ERROR_INTERNAL_ERROR;
  777. handle_t srrpc_IfHandle = NULL;
  778. TENTER("SRSwitchLog");
  779. // initialize
  780. dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
  781. if (dwRc != ERROR_SUCCESS)
  782. {
  783. goto exit;
  784. }
  785. // call remote procedure
  786. RpcTryExcept
  787. {
  788. dwRc = SRSwitchLogS(srrpc_IfHandle);
  789. }
  790. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  791. {
  792. dwRc = RpcExceptionCode();
  793. TRACE(0, "SRSwitchLogS threw exception: error=%ld", dwRc);
  794. }
  795. RpcEndExcept
  796. // terminate
  797. SRRPCTerm(&srrpc_IfHandle);
  798. exit:
  799. TLEAVE();
  800. return dwRc;
  801. }
  802. extern "C" void WINAPI
  803. SRNotify(LPCWSTR pszDrive, DWORD dwFreeSpaceInMB, BOOL fImproving)
  804. {
  805. DWORD dwRc = ERROR_INTERNAL_ERROR;
  806. handle_t srrpc_IfHandle = NULL;
  807. TENTER("SRNotify");
  808. // initialize
  809. dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
  810. if (dwRc != ERROR_SUCCESS)
  811. {
  812. goto exit;
  813. }
  814. // call remote procedure
  815. RpcTryExcept
  816. {
  817. SRNotifyS(srrpc_IfHandle, pszDrive, dwFreeSpaceInMB, fImproving);
  818. }
  819. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  820. {
  821. dwRc = RpcExceptionCode();
  822. TRACE(0, "SRNotifyS threw exception: error=%ld", dwRc);
  823. }
  824. RpcEndExcept
  825. // terminate
  826. SRRPCTerm(&srrpc_IfHandle);
  827. exit:
  828. TLEAVE();
  829. return;
  830. }
  831. extern "C" void WINAPI
  832. SRPrintState()
  833. {
  834. DWORD dwRc = ERROR_INTERNAL_ERROR;
  835. handle_t srrpc_IfHandle = NULL;
  836. TENTER("SRPrintState");
  837. // initialize
  838. dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
  839. if (dwRc != ERROR_SUCCESS)
  840. {
  841. goto exit;
  842. }
  843. // call remote procedure
  844. RpcTryExcept
  845. {
  846. SRPrintStateS(srrpc_IfHandle);
  847. }
  848. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  849. {
  850. dwRc = RpcExceptionCode();
  851. TRACE(0, "SRPrintStateS threw exception: error=%ld", dwRc);
  852. }
  853. RpcEndExcept
  854. // terminate
  855. SRRPCTerm(&srrpc_IfHandle);
  856. exit:
  857. TLEAVE();
  858. return;
  859. }
  860. extern "C" DWORD WINAPI
  861. SRFifo(LPCWSTR pszDrive, DWORD dwTargetRp, int nPercent, BOOL fIncludeCurrentRp, BOOL fFifoAtleastOneRp)
  862. {
  863. DWORD dwRc = ERROR_INTERNAL_ERROR;
  864. handle_t srrpc_IfHandle = NULL;
  865. TENTER("Fifo");
  866. // initialize
  867. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  868. if (dwRc != ERROR_SUCCESS)
  869. {
  870. goto exit;
  871. }
  872. // call remote procedure
  873. RpcTryExcept
  874. {
  875. dwRc = FifoS(srrpc_IfHandle, pszDrive, dwTargetRp, nPercent, fIncludeCurrentRp, fFifoAtleastOneRp);
  876. }
  877. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  878. {
  879. dwRc = RpcExceptionCode();
  880. TRACE(0, "Fifo threw exception: error=%ld", dwRc);
  881. }
  882. RpcEndExcept
  883. // terminate
  884. SRRPCTerm(&srrpc_IfHandle);
  885. exit:
  886. TLEAVE();
  887. return dwRc;
  888. }
  889. extern "C" DWORD WINAPI
  890. SRCompress(LPCWSTR pszDrive)
  891. {
  892. DWORD dwRc = ERROR_INTERNAL_ERROR;
  893. handle_t srrpc_IfHandle = NULL;
  894. TENTER("Compress");
  895. // initialize
  896. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  897. if (dwRc != ERROR_SUCCESS)
  898. {
  899. goto exit;
  900. }
  901. // call remote procedure
  902. RpcTryExcept
  903. {
  904. dwRc = CompressS(srrpc_IfHandle, pszDrive);
  905. }
  906. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  907. {
  908. dwRc = RpcExceptionCode();
  909. TRACE(0, "Compress threw exception: error=%ld", dwRc);
  910. }
  911. RpcEndExcept
  912. // terminate
  913. SRRPCTerm(&srrpc_IfHandle);
  914. exit:
  915. TLEAVE();
  916. return dwRc;
  917. }
  918. extern "C" DWORD WINAPI
  919. SRFreeze(LPCWSTR pszDrive)
  920. {
  921. DWORD dwRc = ERROR_INTERNAL_ERROR;
  922. handle_t srrpc_IfHandle = NULL;
  923. TENTER("Freeze");
  924. // initialize
  925. dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
  926. if (dwRc != ERROR_SUCCESS)
  927. {
  928. goto exit;
  929. }
  930. // call remote procedure
  931. RpcTryExcept
  932. {
  933. dwRc = FreezeS(srrpc_IfHandle, pszDrive);
  934. }
  935. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  936. {
  937. dwRc = RpcExceptionCode();
  938. TRACE(0, "Freeze threw exception: error=%ld", dwRc);
  939. }
  940. RpcEndExcept
  941. // terminate
  942. SRRPCTerm(&srrpc_IfHandle);
  943. exit:
  944. TLEAVE();
  945. return dwRc;
  946. }
  947. // registration of callback method for third-parties to
  948. // do their own snapshotting and restoration for their components
  949. // clients will call this method with the full path of their dll.
  950. // system restore will call "CreateSnapshot" and "RestoreSnapshot"
  951. // methods in the registered dll when creating a restore point and
  952. // when restoring respectively
  953. extern "C" DWORD WINAPI
  954. SRRegisterSnapshotCallback(
  955. LPCWSTR pszDllPath)
  956. {
  957. DWORD dwErr = ERROR_SUCCESS;
  958. HKEY hKey = NULL;
  959. LPWSTR pszDllName = NULL;
  960. WCHAR szKey[MAX_PATH];
  961. DWORD dwDisposition;
  962. TENTER("RegisterSnapshotCallback");
  963. //
  964. // allow this only if admin or system
  965. //
  966. if (! IsAdminOrSystem())
  967. {
  968. dwErr = ERROR_ACCESS_DENIED;
  969. trace(0, "Not admin or system");
  970. goto Err;
  971. }
  972. if (pszDllPath == NULL)
  973. {
  974. dwErr = ERROR_INVALID_PARAMETER;
  975. trace(0, "pszDllPath = NULL");
  976. goto Err;
  977. }
  978. //
  979. // add the dll to Software\...\SystemRestore\SnapshotCallbacks
  980. // each dll will be a value
  981. // value name : name of dll, value: fullpath of dll
  982. // this way, the registration is idempotent
  983. //
  984. //
  985. // create/open the key
  986. //
  987. lstrcpy(szKey, s_cszSRRegKey);
  988. lstrcat(szKey, L"\\");
  989. lstrcat(szKey, s_cszCallbacksRegKey);
  990. CHECKERR( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  991. szKey,
  992. 0,
  993. NULL,
  994. 0,
  995. KEY_ALL_ACCESS,
  996. NULL,
  997. &hKey,
  998. &dwDisposition),
  999. L"RegCreateKeyEx" );
  1000. //
  1001. // get the dll name from the path
  1002. // if the path is not specified, this is same as input param
  1003. //
  1004. pszDllName = wcsrchr(pszDllPath, L'\\');
  1005. if (pszDllName == NULL)
  1006. {
  1007. pszDllName = (LPWSTR) pszDllPath;
  1008. }
  1009. else
  1010. {
  1011. pszDllName++; // skip the '\'
  1012. }
  1013. //
  1014. // if the value already exists
  1015. // bail
  1016. //
  1017. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1018. pszDllName,
  1019. 0,
  1020. NULL,
  1021. NULL,
  1022. NULL))
  1023. {
  1024. trace(0, "Dll is already registered");
  1025. dwErr = ERROR_ALREADY_EXISTS;
  1026. goto Err;
  1027. }
  1028. //
  1029. // add the value
  1030. //
  1031. CHECKERR(RegSetValueEx(hKey,
  1032. pszDllName,
  1033. 0,
  1034. REG_SZ,
  1035. (BYTE *) pszDllPath,
  1036. (lstrlen(pszDllPath)+1)*sizeof(WCHAR)),
  1037. L"RegSetValueEx");
  1038. trace(0, "Added %S as snapshot callback", pszDllPath);
  1039. Err:
  1040. if (hKey)
  1041. {
  1042. RegCloseKey(hKey);
  1043. }
  1044. TLEAVE();
  1045. return dwErr;
  1046. }
  1047. // corresponding unregistration function to above function
  1048. // clients can call this to unregister any snapshot callbacks
  1049. // they have already registered
  1050. extern "C" DWORD WINAPI
  1051. SRUnregisterSnapshotCallback(
  1052. LPCWSTR pszDllPath)
  1053. {
  1054. DWORD dwErr = ERROR_SUCCESS;
  1055. HKEY hKey = NULL;
  1056. LPWSTR pszDllName = NULL;
  1057. WCHAR szKey[MAX_PATH];
  1058. TENTER("SRUnregisterSnapshotCallback");
  1059. //
  1060. // allow this only if admin or system
  1061. //
  1062. if (! IsAdminOrSystem())
  1063. {
  1064. dwErr = ERROR_ACCESS_DENIED;
  1065. trace(0, "Not admin or system");
  1066. goto Err;
  1067. }
  1068. if (pszDllPath == NULL)
  1069. {
  1070. dwErr = ERROR_INVALID_PARAMETER;
  1071. trace(0, "pszDllPath = NULL");
  1072. goto Err;
  1073. }
  1074. //
  1075. // add the dll to Software\...\SystemRestore\SnapshotCallbacks
  1076. // each dll will be a value
  1077. // value name : name of dll, value: fullpath of dll
  1078. // this way, the registration is idempotent
  1079. //
  1080. //
  1081. // open the key
  1082. //
  1083. lstrcpy(szKey, s_cszSRRegKey);
  1084. lstrcat(szKey, L"\\");
  1085. lstrcat(szKey, s_cszCallbacksRegKey);
  1086. CHECKERR( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1087. szKey,
  1088. 0,
  1089. KEY_ALL_ACCESS,
  1090. &hKey),
  1091. L"RegOpenKeyEx" );
  1092. //
  1093. // get the dll name from the path
  1094. // if the path is not specified, this is same as input param
  1095. //
  1096. pszDllName = wcsrchr(pszDllPath, L'\\');
  1097. if (pszDllName == NULL)
  1098. {
  1099. pszDllName = (LPWSTR) pszDllPath;
  1100. }
  1101. else
  1102. {
  1103. pszDllName++; // skip the '\'
  1104. }
  1105. //
  1106. // remove the value
  1107. //
  1108. CHECKERR(RegDeleteValue(hKey,
  1109. pszDllName),
  1110. L"RegDeleteValue");
  1111. trace(0, "Removed %S from snapshot callback", pszDllPath);
  1112. Err:
  1113. if (hKey)
  1114. {
  1115. RegCloseKey(hKey);
  1116. }
  1117. TLEAVE();
  1118. return dwErr;
  1119. }
  1120. //
  1121. // test functions for snapshot callbacks
  1122. //
  1123. extern "C" DWORD WINAPI
  1124. CreateSnapshot(LPCWSTR pszSnapshotDir)
  1125. {
  1126. TENTER("CreateSnapshot");
  1127. WCHAR szFile[MAX_PATH];
  1128. wsprintf(szFile, L"%s\\srclient.txt", pszSnapshotDir);
  1129. DebugTrace(0, "Callback createsnapshot");
  1130. if (FALSE == CopyFile(L"c:\\srclient.txt", szFile, FALSE))
  1131. {
  1132. trace(0, "! CopyFile");
  1133. }
  1134. TLEAVE();
  1135. return ERROR_SUCCESS;
  1136. }
  1137. extern "C" DWORD WINAPI
  1138. RestoreSnapshot(LPCWSTR pszSnapshotDir)
  1139. {
  1140. TENTER("RestoreSnapshot");
  1141. WCHAR szFile[MAX_PATH];
  1142. wsprintf(szFile, L"%s\\srclient.txt", pszSnapshotDir);
  1143. DebugTrace(0, "Callback restoresnapshot");
  1144. if (FALSE == CopyFile(szFile, L"c:\\restored.txt", FALSE))
  1145. {
  1146. trace(0, "! CopyFile");
  1147. }
  1148. TLEAVE();
  1149. return ERROR_SUCCESS;
  1150. }
  1151. // alloc/dealloc functions for midl compiler
  1152. void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
  1153. {
  1154. return(SRMemAlloc((DWORD) len));
  1155. }
  1156. void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
  1157. {
  1158. SRMemFree(ptr);
  1159. }