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.

1134 lines
30 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. apisrv.c
  5. Abstract:
  6. Windows File Protection server side APIs. Note that these server side APIs
  7. all run in the context of the winlogon process, so special care must be
  8. taken to validate all parameters.
  9. Author:
  10. Wesley Witt (wesw) 27-May-1999
  11. Revision History:
  12. Andrew Ritz (andrewr) 5-Jul-1999 : added comments
  13. --*/
  14. #include "sfcp.h"
  15. #pragma hdrstop
  16. DWORD
  17. WINAPI
  18. SfcSrv_FileException(
  19. IN HANDLE RpcHandle,
  20. IN PCWSTR FileName,
  21. IN DWORD ExpectedChangeType
  22. )
  23. /*++
  24. Routine Description:
  25. Routine to exempt a given file from the specified file change. This
  26. routine is used by certain clients to allow files to be deleted from
  27. the system, etc. Server side counterpart to SfcFileException API.
  28. Arguments:
  29. RpcHandle - RPC binding handle to the SFC server
  30. FileName - NULL terminated unicode string specifying full
  31. filename of the file to be exempted
  32. ExpectedChangeType - SFC_ACTION_* mask listing the file changes to exempt
  33. Return Value:
  34. Win32 error code indicating outcome.
  35. --*/
  36. {
  37. #define BUFSZ (MAX_PATH*2)
  38. PNAME_NODE Node;
  39. PSFC_REGISTRY_VALUE RegVal;
  40. WCHAR Buffer[BUFSZ];
  41. DWORD sz;
  42. DWORD retval;
  43. //
  44. // do an access check to make sure the caller is allowed to perform this
  45. // action.
  46. //
  47. retval = SfcRpcPriviledgeCheck( RpcHandle );
  48. if (retval != ERROR_SUCCESS) {
  49. goto exit;
  50. }
  51. //
  52. // expand any environment variables...this also serves to probe the client
  53. // buffer
  54. //
  55. if (FileName == NULL) {
  56. retval = ERROR_INVALID_PARAMETER;
  57. } else {
  58. sz = ExpandEnvironmentStrings( FileName, Buffer, UnicodeChars(Buffer) );
  59. if (sz == 0) {
  60. retval = GetLastError();
  61. } else if(sz > UnicodeChars(Buffer)) {
  62. retval = ERROR_BUFFER_OVERFLOW;
  63. }
  64. }
  65. if (retval != ERROR_SUCCESS) {
  66. return(retval);
  67. }
  68. //
  69. // our internal structures all assume the strings are in lower case. we
  70. // must convert our search string to lowercase as well.
  71. //
  72. MyLowerString( Buffer, wcslen(Buffer) );
  73. DebugPrint2( LVL_MINIMAL, L"S_FE: [%ws], [%d]", Buffer, ExpectedChangeType );
  74. //
  75. // search for the file in our list.
  76. //
  77. Node = SfcFindProtectedFile( Buffer, UnicodeLen(Buffer) );
  78. if (Node == NULL) {
  79. retval = ERROR_FILE_NOT_FOUND;
  80. goto exit;
  81. }
  82. //
  83. // get pointer to file registry value for file
  84. //
  85. RegVal = (PSFC_REGISTRY_VALUE)Node->Context;
  86. RtlEnterCriticalSection( &ErrorCs );
  87. //
  88. // If the exemption flags are not valid anymore, reset them all
  89. //
  90. if(!SfcAreExemptionFlagsValid(TRUE)) {
  91. ZeroMemory(IgnoreNextChange, SfcProtectedDllCount * sizeof(ULONG));
  92. }
  93. //
  94. // OR the new flags into the current ones
  95. //
  96. SfcSetExemptionFlags(RegVal, ExpectedChangeType);
  97. RtlLeaveCriticalSection( &ErrorCs );
  98. exit:
  99. return(retval);
  100. }
  101. DWORD
  102. WINAPI
  103. SfcSrv_InitiateScan(
  104. IN HANDLE hBinding,
  105. IN DWORD ScanWhen
  106. )
  107. /*++
  108. Routine Description:
  109. Routine to start some sort scan on the system.
  110. Arguments:
  111. RpcHandle - RPC binding handle to the SFC server
  112. ScanWhen - flag indicating when to scan.
  113. Return Value:
  114. Win32 error code indicating outcome.
  115. --*/
  116. {
  117. HANDLE hThread;
  118. PSCAN_PARAMS ScanParams;
  119. DWORD retval = ERROR_SUCCESS;
  120. //
  121. // do an access check to make sure the caller is allowed to perform this
  122. // action.
  123. //
  124. retval = SfcRpcPriviledgeCheck( hBinding );
  125. if (retval != ERROR_SUCCESS) {
  126. goto exit;
  127. }
  128. switch( ScanWhen ) {
  129. case SFC_SCAN_NORMAL:
  130. case SFC_SCAN_ALWAYS:
  131. case SFC_SCAN_ONCE:
  132. retval = SfcWriteRegDword( REGKEY_WINLOGON, REGVAL_SFCSCAN, ScanWhen );
  133. break;
  134. case SFC_SCAN_IMMEDIATE:
  135. //
  136. // a user must be logged on for this API to be called since it can bring up
  137. // UI (if the user need to insert media to restore files, etc.) we could
  138. // succeed this and let the SfcScanProtectedDlls thread wait for a user to
  139. // log on if we wanted to.
  140. //
  141. if (!UserLoggedOn) {
  142. DebugPrint( LVL_MINIMAL, L"SfcSrv_InitiateScan: User not logged on" );
  143. retval = ERROR_NOT_LOGGED_ON;
  144. goto exit;
  145. }
  146. ScanParams = MemAlloc( sizeof(SCAN_PARAMS) );
  147. if (!ScanParams) {
  148. retval = ERROR_NOT_ENOUGH_MEMORY;
  149. goto exit;
  150. }
  151. //
  152. // set the progress window to null so we force ourselves to show UI
  153. //
  154. ScanParams->ProgressWindow = NULL;
  155. ScanParams->AllowUI = !SFCNoPopUps;
  156. ScanParams->FreeMemory = TRUE;
  157. //
  158. // start off another thread to do the scan.
  159. //
  160. hThread = CreateThread(
  161. NULL,
  162. 0,
  163. (LPTHREAD_START_ROUTINE)SfcScanProtectedDlls,
  164. ScanParams,
  165. 0,
  166. NULL
  167. );
  168. if (hThread) {
  169. CloseHandle( hThread );
  170. } else {
  171. MemFree(ScanParams);
  172. retval = GetLastError();
  173. }
  174. break;
  175. default:
  176. retval = ERROR_INVALID_PARAMETER;
  177. break;
  178. }
  179. exit:
  180. return(retval);
  181. }
  182. DWORD
  183. WINAPI
  184. SfcSrv_InstallProtectedFiles(
  185. IN HANDLE hBinding,
  186. IN const LPBYTE FileNamesBuffer,
  187. IN DWORD FileNamesSize,
  188. OUT LPBYTE *InstallStatusBuffer,
  189. OUT LPDWORD InstallStatusBufferSize,
  190. OUT LPDWORD InstallStatusCount,
  191. IN BOOL AllowUI,
  192. IN PCWSTR ClassName,
  193. IN PCWSTR WindowName
  194. )
  195. /*++
  196. Routine Description:
  197. Routine to install one or more protected system files onto the system at
  198. the protected location. A client can use this API to request that WFP
  199. install the specified operating system files as appropriate (instead of the
  200. client redistributing the operating system files!)
  201. The routine works by building up a file queue of the files specified by the
  202. caller, then it commits the queue.
  203. Arguments:
  204. RpcHandle - RPC binding handle to the SFC server
  205. FileNamesBuffer - a list of NULL seperated unicode strings, terminated by
  206. two NULL characters.
  207. FileNamesSize - DWORD indicating the size of the string buffer above.
  208. InstallStatusBuffer - receives an array of FILEINSTALL_STATUS structures
  209. InstallStatusBufferSize - receives the size of InstallStatusBuffer
  210. InstallStatusCount - receives the number of files processed
  211. AllowUI - a BOOL indicating whether UI is allowed or not. If this value
  212. is TRUE, then any prompts for UI cause the API call to fail.
  213. ClassName - NULL terminated unicode string indicating the window classname
  214. for the parent window
  215. WindowName - NULL terminated unicode string indicating the window name for
  216. the parent window for any UI that may be displayed
  217. Return Value:
  218. Win32 error code indicating outcome.
  219. --*/
  220. {
  221. WCHAR buf[MAX_PATH*2];
  222. HSPFILEQ hFileQ = INVALID_HANDLE_VALUE;
  223. PVOID MsgHandlerContext = NULL;
  224. DWORD rVal = ERROR_SUCCESS;
  225. NTSTATUS Status;
  226. DWORD ScanResult;
  227. FILE_COPY_INFO fci;
  228. PSFC_REGISTRY_VALUE RegVal;
  229. PWSTR fname;
  230. PNAME_NODE Node;
  231. ULONG cnt = 0,tmpcnt;
  232. ULONG sz = 0;
  233. PFILEINSTALL_STATUS cs = NULL;
  234. BOOL b;
  235. PWSTR s;
  236. PSOURCE_INFO si = NULL;
  237. PWSTR FileNamesScratchBuffer = NULL, FileNamesScratchBufferStart;
  238. PWSTR ClientBufferCopy = NULL;
  239. HCATADMIN hCatAdmin = NULL;
  240. UNREFERENCED_PARAMETER( hBinding );
  241. UNREFERENCED_PARAMETER( FileNamesSize );
  242. //
  243. // do an access check to make sure the caller is allowed to perform this
  244. // action.
  245. //
  246. rVal = SfcRpcPriviledgeCheck( hBinding );
  247. if (rVal != ERROR_SUCCESS) {
  248. return rVal;
  249. }
  250. if(NULL == FileNamesBuffer || 0 == FileNamesSize || NULL == InstallStatusBuffer)
  251. {
  252. return ERROR_INVALID_PARAMETER;
  253. }
  254. if(*InstallStatusBuffer != NULL || *InstallStatusBufferSize != 0)
  255. {
  256. return ERROR_INVALID_DATA;
  257. }
  258. ZeroMemory( &fci, sizeof(FILE_COPY_INFO) );
  259. if (ClassName && *ClassName && WindowName && *WindowName) {
  260. fci.hWnd = FindWindow( ClassName, WindowName );
  261. }
  262. fci.AllowUI = AllowUI;
  263. //
  264. // create the file queue
  265. //
  266. hFileQ = SetupOpenFileQueue();
  267. if (hFileQ == INVALID_HANDLE_VALUE) {
  268. rVal = GetLastError();
  269. DebugPrint1( LVL_VERBOSE, L"SetupOpenFileQueue failed, ec=%d", rVal );
  270. goto exit;
  271. }
  272. //
  273. // find out how much space we'll need for the FILEINSTALL_STATUS array
  274. //
  275. try {
  276. ClientBufferCopy = MemAlloc( FileNamesSize );
  277. if (ClientBufferCopy) {
  278. RtlCopyMemory( ClientBufferCopy, FileNamesBuffer, FileNamesSize );
  279. fname = ClientBufferCopy;
  280. while (*fname) {
  281. DWORD dwSize = ExpandEnvironmentStrings( fname, buf, UnicodeChars(buf) );
  282. if(0 == dwSize) {
  283. rVal = GetLastError();
  284. break;
  285. }
  286. if(dwSize > UnicodeChars(buf)) {
  287. rVal = ERROR_BUFFER_OVERFLOW;
  288. break;
  289. }
  290. DebugPrint1(LVL_VERBOSE, L"S_IPF [%ws]", buf);
  291. //
  292. // size = old size
  293. // + 8 (unicode null + slop)
  294. // + size of current string
  295. // + size of FILEINSTALL_STATUS for this entry
  296. //
  297. sz = sz + 8 + UnicodeLen(buf) + sizeof(FILEINSTALL_STATUS);
  298. cnt += 1;
  299. fname += (wcslen(fname) + 1);
  300. }
  301. } else {
  302. rVal = ERROR_NOT_ENOUGH_MEMORY;
  303. }
  304. } except (EXCEPTION_EXECUTE_HANDLER) {
  305. rVal = RtlNtStatusToDosError(GetExceptionCode());
  306. DebugPrint1(LVL_VERBOSE, L"S_IPF: exception occured while parsing client file buffer, ec=0x%08x", rVal);
  307. }
  308. if (rVal != ERROR_SUCCESS) {
  309. goto exit;
  310. }
  311. //
  312. // extra unicode NULL to size for termination is included in slop above
  313. //
  314. //
  315. // allocate and zero out the memory for the array
  316. //
  317. cs = (PFILEINSTALL_STATUS) midl_user_allocate( sz );
  318. if (cs == NULL) {
  319. rVal = ERROR_OUTOFMEMORY;
  320. goto exit;
  321. }
  322. ZeroMemory( cs, sz );
  323. *InstallStatusBuffer = (LPBYTE) cs;
  324. *InstallStatusBufferSize = sz;
  325. *InstallStatusCount = cnt;
  326. //
  327. // also create a scratch buffer for our files for later
  328. //
  329. FileNamesScratchBufferStart
  330. = FileNamesScratchBuffer
  331. = (PWSTR) MemAlloc(cnt * MAX_PATH * 2 * sizeof(WCHAR));
  332. if (!FileNamesScratchBuffer) {
  333. rVal = GetLastError();
  334. DebugPrint1( LVL_VERBOSE,
  335. L"S_IPF: MemAlloc (%d) failed",
  336. FileNamesSize );
  337. goto exit;
  338. }
  339. //
  340. // create an array of sourceinfo pointers (and an array of source_info
  341. // structures) so that the commital callback routine can find out about
  342. // the status of each file
  343. //
  344. fci.CopyStatus = cs;
  345. fci.FileCount = cnt;
  346. fci.si = (PSOURCE_INFO *)MemAlloc( cnt * sizeof(PSOURCE_INFO) );
  347. if (!fci.si) {
  348. DebugPrint1( LVL_VERBOSE,
  349. L"S_IPF: MemAlloc (%d) failed",
  350. cnt* sizeof(PSOURCE_INFO) );
  351. rVal = ERROR_OUTOFMEMORY;
  352. goto exit;
  353. }
  354. si = MemAlloc( cnt * sizeof(SOURCE_INFO) );
  355. if (!si) {
  356. DebugPrint1( LVL_VERBOSE,
  357. L"S_IPF: MemAlloc (%d) failed",
  358. cnt* sizeof(SOURCE_INFO) );
  359. rVal = ERROR_OUTOFMEMORY;
  360. goto exit;
  361. }
  362. fname = ClientBufferCopy;
  363. //
  364. // now build up the FILEINSTALL_STATUS array
  365. //
  366. //
  367. // First set a string pointer to the end of the FILEINSTALL_STATUS
  368. // array. We will later copy strings after the array of structures.
  369. //
  370. s = (PWSTR)((LPBYTE)cs + (cnt * sizeof(FILEINSTALL_STATUS)));
  371. tmpcnt = 0;
  372. //
  373. // Second, for each member in the caller supplied list,
  374. // - copy the filename to the end of the array
  375. // - save off the pointer to the filename in the proper FILEINSTALL_STATUS
  376. // member
  377. // - point to the next file in the list
  378. //
  379. while (*fname) {
  380. DWORD StringLength;
  381. StringLength = ExpandEnvironmentStrings( fname, buf, UnicodeChars(buf) );
  382. if(0 == StringLength) {
  383. rVal = GetLastError();
  384. goto exit;
  385. }
  386. //
  387. // We validated the length once so we don't do that again here
  388. //
  389. StringLength = wcslen(buf);
  390. MyLowerString(buf, StringLength);
  391. wcsncpy(&FileNamesScratchBuffer[MAX_PATH*2*tmpcnt],buf,MAX_PATH);
  392. cs->FileName = s;
  393. wcscpy( s, &FileNamesScratchBuffer[MAX_PATH*2*tmpcnt] );
  394. s += StringLength + 1;
  395. cs += 1;
  396. tmpcnt += 1;
  397. fname += (wcslen(fname) + 1);
  398. ASSERT(tmpcnt <= cnt);
  399. }
  400. //
  401. // we're finally ready to queue files
  402. // - determine where the file comes from
  403. // - add the file to the queue using the appropriate filename if the file
  404. // is renamed
  405. //
  406. cs = fci.CopyStatus;
  407. FileNamesScratchBuffer = FileNamesScratchBufferStart;
  408. //
  409. //initialize crypto
  410. //
  411. Status = LoadCrypto();
  412. if(!NT_SUCCESS(Status))
  413. {
  414. rVal = RtlNtStatusToDosError(Status);
  415. goto exit;
  416. }
  417. if(!CryptCATAdminAcquireContext(&hCatAdmin, &DriverVerifyGuid, 0)) {
  418. rVal = GetLastError();
  419. DebugPrint1( LVL_MINIMAL, L"CCAAC() failed, ec = 0x%08x", rVal);
  420. goto exit;
  421. }
  422. //
  423. // Flush the Cache once before we start any Crypto operations
  424. //
  425. SfcFlushCryptoCache();
  426. //
  427. // Refresh exception packages info
  428. //
  429. SfcRefreshExceptionInfo();
  430. tmpcnt=0;
  431. while (tmpcnt < cnt) {
  432. Node = SfcFindProtectedFile( (PWSTR)&FileNamesScratchBuffer[MAX_PATH*2*tmpcnt], UnicodeLen(&FileNamesScratchBuffer[MAX_PATH*2*tmpcnt]) );
  433. if (Node) {
  434. HANDLE FileHandle;
  435. BOOL QueuedFromCache;
  436. IMAGE_VALIDATION_DATA SignatureData;
  437. UNICODE_STRING tmpPath;
  438. WCHAR InfFileName[MAX_PATH];
  439. BOOL ExcepPackFile;
  440. RegVal = (PSFC_REGISTRY_VALUE)Node->Context;
  441. ASSERT(RegVal != NULL);
  442. //
  443. // get the inf name here
  444. //
  445. ExcepPackFile = SfcGetInfName(RegVal, InfFileName);
  446. //
  447. // Setup the SOURCE_INFO structure so we can record where each file in
  448. // the list is coming from (ie., golden media, driver cabinet,
  449. // service pack, etc.)
  450. //
  451. fci.si[tmpcnt] = &si[tmpcnt];
  452. if (!SfcGetSourceInformation( RegVal->SourceFileName.Length ? RegVal->SourceFileName.Buffer : RegVal->FileName.Buffer, InfFileName, ExcepPackFile, &si[tmpcnt] )) {
  453. rVal = GetLastError();
  454. DebugPrint2(LVL_VERBOSE, L"S_IPF failed SfcGetSourceInformation() on %ws, ec = %x",
  455. RegVal->SourceFileName.Length ? RegVal->SourceFileName.Buffer : RegVal->FileName.Buffer,
  456. rVal
  457. );
  458. goto exit;
  459. }
  460. //
  461. // If the file is in the dllcache and it's valid, then queue up the
  462. // file to be copied from the dllcache instead of the installation
  463. // source.
  464. //
  465. // First we check the signature of the file in the dllcache. Then
  466. // we try to queue up the file from the cache if the signature is
  467. // valid. If anything goes wrong, we just queue from the regular
  468. // install media
  469. //
  470. QueuedFromCache = FALSE;
  471. RtlInitUnicodeString( &tmpPath, FileNameOnMedia( RegVal ) );
  472. if (!SfcGetValidationData(
  473. &tmpPath,
  474. &SfcProtectedDllPath,
  475. SfcProtectedDllFileDirectory,
  476. hCatAdmin,
  477. &SignatureData)) {
  478. DebugPrint1( LVL_MINIMAL,
  479. L"SfcGetValidationData() failed, ec = 0x%08x",
  480. GetLastError() );
  481. } else if (SignatureData.SignatureValid) {
  482. //
  483. // The file is valid, so queue it up.
  484. //
  485. // We have to munge some of the SOURCE_INFO members to make
  486. // this function do what we want. Remember these members
  487. // in case the queuing fails. Then we can at least try to
  488. // queue the files for installation from media.
  489. //
  490. WCHAR SourcePathOld;
  491. SourcePathOld = si[tmpcnt].SourcePath[0];
  492. si[tmpcnt].SourcePath[0] = L'\0';
  493. b = SfcAddFileToQueue(
  494. hFileQ,
  495. RegVal->FileName.Buffer,
  496. RegVal->FileName.Buffer,
  497. RegVal->DirName.Buffer,
  498. FileNameOnMedia( RegVal ),
  499. SfcProtectedDllPath.Buffer,
  500. InfFileName,
  501. ExcepPackFile,
  502. &si[tmpcnt]
  503. );
  504. if (!b) {
  505. //
  506. // put the source path back
  507. //
  508. si[tmpcnt].SourcePath[0] = SourcePathOld;
  509. //
  510. // print out an error but continue.
  511. //
  512. rVal = GetLastError();
  513. DebugPrint2(
  514. LVL_VERBOSE,
  515. L"S_IPF failed SfcAddFileToQueue(DLLCACHE) on %ws, ec = %x",
  516. RegVal->FileName.Buffer,
  517. rVal );
  518. } else {
  519. //
  520. // successfully queued from cache. remember this and continue
  521. //
  522. QueuedFromCache = TRUE;
  523. }
  524. }
  525. //
  526. // add the file to the queue if we haven't already
  527. //
  528. if (!QueuedFromCache) {
  529. b = SfcAddFileToQueue(
  530. hFileQ,
  531. RegVal->FileName.Buffer,
  532. RegVal->FileName.Buffer,
  533. RegVal->DirName.Buffer,
  534. FileNameOnMedia( RegVal ),
  535. NULL,
  536. InfFileName,
  537. ExcepPackFile,
  538. &si[tmpcnt]
  539. );
  540. if (!b) {
  541. rVal = GetLastError();
  542. DebugPrint2(
  543. LVL_VERBOSE,
  544. L"S_IPF failed SfcAddFileToQueue() on %ws, ec = %x",
  545. RegVal->FileName.Buffer,
  546. rVal );
  547. goto exit;
  548. }
  549. }
  550. //
  551. // see if the file is already present so we can save off the file
  552. // version. If we copy in a new file, we will update the file
  553. // version at that time. But if the file is already present and
  554. // signed, we will not copy the file and we must save off the file
  555. // version in that case.
  556. //
  557. Status = SfcOpenFile( &RegVal->FileName, RegVal->DirHandle, SHARE_ALL, &FileHandle);
  558. if (NT_SUCCESS(Status)) {
  559. SfcGetFileVersion( FileHandle, &cs->Version, NULL, NULL);
  560. NtClose( FileHandle );
  561. }
  562. } else {
  563. //
  564. // File is not in protected list. We'll just mark the file as not
  565. // found and continue committing the rest of the files
  566. //
  567. DebugPrint1(LVL_VERBOSE,
  568. L"S_IPF failed to find %ws in protected file list",
  569. &FileNamesScratchBuffer[MAX_PATH*2*tmpcnt] );
  570. cs->Win32Error = ERROR_FILE_NOT_FOUND;
  571. }
  572. cs += 1;
  573. tmpcnt+=1;
  574. }
  575. cs = fci.CopyStatus;
  576. fci.Flags |= FCI_FLAG_INSTALL_PROTECTED;
  577. //
  578. // setup the default queue callback with the popups disabled
  579. //
  580. MsgHandlerContext = SetupInitDefaultQueueCallbackEx( NULL, INVALID_HANDLE_VALUE, 0, 0, 0 );
  581. if (MsgHandlerContext == NULL) {
  582. rVal = GetLastError();
  583. DebugPrint1( LVL_VERBOSE, L"SetupInitDefaultQueueCallbackEx failed, ec=%d", rVal );
  584. goto exit;
  585. }
  586. fci.MsgHandlerContext = MsgHandlerContext;
  587. //
  588. // see if the files in the queue are already present and valid. If they
  589. // are, then we don't have to copy anything
  590. //
  591. b = SetupScanFileQueue(
  592. hFileQ,
  593. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  594. fci.hWnd,
  595. NULL,
  596. NULL,
  597. &ScanResult);
  598. //
  599. // if SetupScanFileQueue succeeds, ScanResult = 1 and we don't have to copy
  600. // anything at all. If it failed (it shouldn't), then we just commit the
  601. // queue anyway.
  602. //
  603. if (!b) {
  604. ScanResult = 0;
  605. }
  606. if (ScanResult == 1) {
  607. b = TRUE;
  608. } else {
  609. //
  610. // commit the file queue
  611. //
  612. b = SetupCommitFileQueue(
  613. NULL,
  614. hFileQ,
  615. SfcQueueCallback,
  616. &fci
  617. );
  618. if (!b) {
  619. DebugPrint1( LVL_VERBOSE, L"SetupCommitFileQueue failed, ec=%d", GetLastError() );
  620. rVal = GetLastError();
  621. goto exit;
  622. }
  623. }
  624. //
  625. // now that the queue is committed, we need to turn the filename pointers
  626. // from actual filename pointers into offsets to the filename so that RPC
  627. // can send the data back to the clients
  628. //
  629. for (sz=0; sz<cnt; sz++) {
  630. cs[sz].FileName = (PWSTR)((DWORD_PTR)cs[sz].FileName - (DWORD_PTR)fci.CopyStatus);
  631. }
  632. exit:
  633. //
  634. // cleanup and exit
  635. //
  636. if (hCatAdmin) {
  637. CryptCATAdminReleaseContext(hCatAdmin,0);
  638. }
  639. if (MsgHandlerContext) {
  640. SetupTermDefaultQueueCallback( MsgHandlerContext );
  641. }
  642. if (hFileQ != INVALID_HANDLE_VALUE) {
  643. SetupCloseFileQueue( hFileQ );
  644. }
  645. if (FileNamesScratchBuffer) {
  646. MemFree(FileNamesScratchBuffer);
  647. }
  648. if (si) {
  649. MemFree( si );
  650. }
  651. if (fci.si) {
  652. MemFree( fci.si );
  653. }
  654. if (ClientBufferCopy) {
  655. MemFree( ClientBufferCopy );
  656. }
  657. if (rVal != ERROR_SUCCESS) {
  658. if(*InstallStatusBuffer != NULL) {
  659. midl_user_free(*InstallStatusBuffer);
  660. }
  661. *InstallStatusBuffer = NULL;
  662. *InstallStatusBufferSize = 0;
  663. *InstallStatusCount = 0;
  664. }
  665. return rVal;
  666. }
  667. DWORD
  668. WINAPI
  669. SfcSrv_GetNextProtectedFile(
  670. IN HANDLE RpcHandle,
  671. IN DWORD FileNumber,
  672. IN LPBYTE *FileName,
  673. IN LPDWORD FileNameSize
  674. )
  675. /*++
  676. Routine Description:
  677. Routine to retrieve the next protected file in the list.
  678. Arguments:
  679. RpcHandle - RPC binding handle to the SFC server
  680. FileNumer - 1-based number of file to be retrieved
  681. FileName - receives file name string
  682. FileNameSize - size of file name string
  683. Return Value:
  684. win32 error code indicating success.
  685. --*/
  686. {
  687. LPWSTR szName;
  688. LPBYTE pBuffer;
  689. DWORD dwSize;
  690. UNREFERENCED_PARAMETER( RpcHandle );
  691. if(NULL == FileName)
  692. {
  693. return ERROR_INVALID_PARAMETER;
  694. }
  695. if(*FileName != NULL || *FileNameSize != 0)
  696. {
  697. return ERROR_INVALID_DATA;
  698. }
  699. //
  700. // The filenumber is zero based, and we return "no more files" to
  701. // signify that they've enumerated all of the files
  702. //
  703. if (FileNumber >= SfcProtectedDllCount) {
  704. return ERROR_NO_MORE_FILES;
  705. }
  706. //
  707. // get the proper file from the list, allocate a buffer, and copy the
  708. // filename into the buffer
  709. //
  710. szName = SfcProtectedDllsList[FileNumber].FullPathName.Buffer;
  711. dwSize = UnicodeLen(szName) + sizeof(WCHAR);
  712. pBuffer = (LPBYTE) midl_user_allocate( dwSize );
  713. if(NULL == pBuffer)
  714. return ERROR_NOT_ENOUGH_MEMORY;
  715. RtlCopyMemory( pBuffer, szName, dwSize);
  716. *FileName = pBuffer;
  717. *FileNameSize = dwSize;
  718. return ERROR_SUCCESS;
  719. }
  720. DWORD
  721. WINAPI
  722. SfcSrv_IsFileProtected(
  723. IN HANDLE RpcHandle,
  724. IN PCWSTR ProtFileName
  725. )
  726. /*++
  727. Routine Description:
  728. Routine to determine if the specified file is protected.
  729. Arguments:
  730. RpcHandle - RPC binding handle to the SFC server
  731. ProtFileName - NULL terminated unicode string indicating fully qualified
  732. filename to query
  733. Return Value:
  734. Win32 error code indicating outcome.
  735. --*/
  736. {
  737. WCHAR buf[MAX_PATH];
  738. DWORD dwSize;
  739. UNREFERENCED_PARAMETER( RpcHandle );
  740. if (!ProtFileName)
  741. return ERROR_INVALID_PARAMETER;
  742. //
  743. // our internal structures all assume the strings are in lower case. we
  744. // must convert our search string to lowercase as well.
  745. //
  746. if (!*ProtFileName)
  747. return ERROR_INVALID_DATA;
  748. dwSize = ExpandEnvironmentStrings( ProtFileName, buf, UnicodeChars(buf));
  749. if(0 == dwSize)
  750. {
  751. DWORD retval = GetLastError();
  752. DebugPrint1( LVL_MINIMAL, L"ExpandEnvironmentStrings failed, ec = 0x%x", retval);
  753. return retval;
  754. }
  755. if(dwSize > UnicodeChars(buf))
  756. {
  757. //
  758. // expandenvironmentstrings must have encountered a buffer that was
  759. // too large
  760. //
  761. DebugPrint(LVL_MINIMAL, L"ExpandEnvironmentStrings failed with STATUS_BUFFER_TOO_SMALL");
  762. return ERROR_INSUFFICIENT_BUFFER;
  763. }
  764. MyLowerString( buf, wcslen(buf) );
  765. if (!SfcFindProtectedFile( buf, UnicodeLen(buf) ))
  766. return ERROR_FILE_NOT_FOUND;
  767. return ERROR_SUCCESS;
  768. }
  769. DWORD
  770. WINAPI
  771. SfcSrv_PurgeCache(
  772. IN HANDLE hBinding
  773. )
  774. /*++
  775. Routine Description:
  776. Routine to purge the contents of the dllcache.
  777. Arguments:
  778. RpcHandle - RPC binding handle to the SFC server
  779. Return Value:
  780. Win32 error code indicating outcome.
  781. --*/
  782. {
  783. DWORD retval = ERROR_SUCCESS, DeleteError = ERROR_SUCCESS;
  784. WCHAR CacheDir[MAX_PATH];
  785. WIN32_FIND_DATA FindFileData;
  786. HANDLE hFind;
  787. PWSTR p;
  788. //
  789. // do an access check to make sure the caller is allowed to perform this
  790. // action.
  791. //
  792. retval = SfcRpcPriviledgeCheck( hBinding );
  793. if (retval != ERROR_SUCCESS) {
  794. goto exit;
  795. }
  796. ASSERT(SfcProtectedDllPath.Buffer != NULL);
  797. wcscpy( CacheDir, SfcProtectedDllPath.Buffer);
  798. pSetupConcatenatePaths( CacheDir, L"*", MAX_PATH, NULL );
  799. //
  800. // save pointer to directory
  801. //
  802. p = wcsrchr( CacheDir, L'\\' );
  803. if (!p) {
  804. ASSERT(FALSE);
  805. retval = ERROR_INVALID_DATA;
  806. goto exit;
  807. }
  808. p += 1;
  809. hFind = FindFirstFile( CacheDir, &FindFileData );
  810. if (hFind == INVALID_HANDLE_VALUE) {
  811. retval = GetLastError();
  812. goto exit;
  813. }
  814. do {
  815. if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  816. wcscpy( p, FindFileData.cFileName );
  817. SetFileAttributes( CacheDir, FILE_ATTRIBUTE_NORMAL );
  818. if (!DeleteFile( CacheDir )) {
  819. DeleteError = GetLastError();
  820. }
  821. }
  822. } while(FindNextFile( hFind, &FindFileData ));
  823. FindClose( hFind );
  824. retval = DeleteError;
  825. exit:
  826. return(retval);
  827. }
  828. DWORD
  829. WINAPI
  830. SfcSrv_SetDisable(
  831. IN HANDLE hBinding,
  832. IN DWORD NewValue
  833. )
  834. /*++
  835. Routine Description:
  836. Routine to set the disable flag in the registry.
  837. Arguments:
  838. RpcHandle - RPC binding handle to the SFC server
  839. NewValue - value of SFCDisable key in registry.
  840. Return Value:
  841. Win32 error code indicating outcome.
  842. --*/
  843. {
  844. DWORD retval = ERROR_SUCCESS;
  845. //
  846. // do an access check to make sure the caller is allowed to perform this
  847. // action.
  848. //
  849. retval = SfcRpcPriviledgeCheck( hBinding );
  850. if (retval != ERROR_SUCCESS) {
  851. goto exit;
  852. }
  853. switch( NewValue ) {
  854. case SFC_DISABLE_SETUP:
  855. case SFC_DISABLE_QUIET:
  856. retval = ERROR_INVALID_PARAMETER;
  857. break;
  858. case SFC_DISABLE_ONCE:
  859. case SFC_DISABLE_NOPOPUPS:
  860. case SFC_DISABLE_ASK:
  861. case SFC_DISABLE_NORMAL:
  862. retval = SfcWriteRegDword( REGKEY_WINLOGON, REGVAL_SFCDISABLE, NewValue );
  863. //
  864. // Issue: it would be nice if we made this "realtime", and shutdown
  865. // WFP if the caller requested.
  866. //
  867. // InterlockedExchange( &SFCDisable, NewValue );
  868. break;
  869. }
  870. exit:
  871. return(retval);
  872. }
  873. DWORD
  874. WINAPI
  875. SfcSrv_SetCacheSize(
  876. IN HANDLE hBinding,
  877. IN DWORD NewValue
  878. )
  879. /*++
  880. Routine Description:
  881. Routine to set the dllcache quota size.
  882. Arguments:
  883. RpcHandle - RPC binding handle to the SFC server
  884. NewValue - value of SFCQuota key in registry.
  885. Return Value:
  886. Win32 error code indicating outcome.
  887. --*/
  888. {
  889. DWORD retval = ERROR_SUCCESS;
  890. ULONGLONG tmp;
  891. //
  892. // do an access check to make sure the caller is allowed to perform this
  893. // action.
  894. //
  895. retval = SfcRpcPriviledgeCheck( hBinding );
  896. if (retval != ERROR_SUCCESS) {
  897. goto exit;
  898. }
  899. if( NewValue == SFC_QUOTA_ALL_FILES ) {
  900. tmp = (ULONGLONG)-1;
  901. } else {
  902. tmp = NewValue * (1024*1024);
  903. }
  904. SFCQuota = tmp;
  905. retval = SfcWriteRegDword( REGKEY_WINLOGON, REGVAL_SFCQUOTA, NewValue );
  906. exit:
  907. return(retval);
  908. }