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.

894 lines
22 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdriver.c
  5. Abstract:
  6. Device-driver interface routines for text setup.
  7. Author:
  8. Ted Miller (tedm) 11-August-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. #include "spcmdcon.h"
  14. PSETUP_COMMUNICATION CommunicationParams;
  15. PVOID RequestReadyEventObjectBody;
  16. PVOID RequestReadyEventWaitObjectBody;
  17. PVOID RequestServicedEventObjectBody;
  18. PVOID RequestServicedEventWaitObjectBody;
  19. PEPROCESS UsetupProcess;
  20. PAUTOCHK_MSG_PROCESSING_ROUTINE pAutochkCallbackRoutine;
  21. SYSTEM_BASIC_INFORMATION SystemBasicInfo;
  22. BOOLEAN AutochkRunning = FALSE;
  23. BOOLEAN AutofrmtRunning = FALSE;
  24. NTSTATUS
  25. SetupOpenCreate(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp
  28. );
  29. NTSTATUS
  30. SetupClose(
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PIRP Irp
  33. );
  34. NTSTATUS
  35. SetupDeviceControl(
  36. IN PDEVICE_OBJECT DeviceObject,
  37. IN PIRP Irp
  38. );
  39. VOID
  40. SetupUnload(
  41. IN PDRIVER_OBJECT DriverObject
  42. );
  43. NTSTATUS
  44. SpInitialize0(
  45. IN PDRIVER_OBJECT DriverObject
  46. );
  47. BOOLEAN
  48. pSpVerifyEventWaitable(
  49. IN HANDLE hEvent,
  50. OUT PVOID *EventObjectBody,
  51. OUT PVOID *EventWaitObjectBody
  52. );
  53. ULONG
  54. DriverEntry(
  55. IN PDRIVER_OBJECT DriverObject,
  56. IN PUNICODE_STRING RegistryPath
  57. )
  58. /*++
  59. Routine Description:
  60. This routine initializes the setup driver.
  61. Arguments:
  62. DriverObject - Pointer to driver object created by system.
  63. RegistryPath - Pointer to the Unicode name of the registry path
  64. for this driver.
  65. Return Value:
  66. The function value is the final status from the initialization operation.
  67. --*/
  68. {
  69. NTSTATUS status;
  70. UNICODE_STRING unicodeString;
  71. PDEVICE_OBJECT deviceObject;
  72. //
  73. // Create exclusive device object.
  74. //
  75. RtlInitUnicodeString(&unicodeString,DD_SETUP_DEVICE_NAME_U);
  76. status = IoCreateDevice(
  77. DriverObject,
  78. 0,
  79. &unicodeString,
  80. FILE_DEVICE_UNKNOWN,
  81. 0,
  82. FALSE,
  83. &deviceObject
  84. );
  85. if(!NT_SUCCESS(status)) {
  86. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to create device object (%lx)\n",status));
  87. return(status);
  88. }
  89. //
  90. // Set up device driver entry points.
  91. //
  92. //DriverObject->DriverStartIo = NULL;
  93. DriverObject->DriverUnload = SetupUnload;
  94. DriverObject->MajorFunction[IRP_MJ_CREATE] = SetupOpenCreate;
  95. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SetupClose;
  96. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SetupDeviceControl;
  97. //DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NULL;
  98. return((ULONG)SpInitialize0(DriverObject));
  99. }
  100. VOID
  101. SetupUnload(
  102. IN PDRIVER_OBJECT DriverObject
  103. )
  104. /*++
  105. Routine Description:
  106. This routine is the setup driver unload routine.
  107. Arguments:
  108. DriverObject - Pointer to driver object.
  109. Return Value:
  110. None.
  111. --*/
  112. {
  113. //
  114. // Delete the device object.
  115. //
  116. IoDeleteDevice(DriverObject->DeviceObject);
  117. return;
  118. }
  119. NTSTATUS
  120. SetupOpenCreate(
  121. IN PDEVICE_OBJECT DeviceObject,
  122. IN PIRP Irp
  123. )
  124. /*++
  125. Routine Description:
  126. This routine is the dispatch routine for open/create.
  127. When the setup device is opened, text setup begins.
  128. The open/create does not complete until text setup is done.
  129. Arguments:
  130. DeviceObject - Pointer to class device object.
  131. Irp - Pointer to the request packet.
  132. Return Value:
  133. Status is returned.
  134. --*/
  135. {
  136. Irp->IoStatus.Status = STATUS_SUCCESS;
  137. Irp->IoStatus.Information = FILE_OPENED;
  138. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  139. return(STATUS_SUCCESS);
  140. }
  141. NTSTATUS
  142. SetupClose(
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN PIRP Irp
  145. )
  146. /*++
  147. Routine Description:
  148. This routine is the dispatch routine for close.
  149. Close requests are completed here.
  150. Arguments:
  151. DeviceObject - Pointer to class device object.
  152. Irp - Pointer to the request packet.
  153. Return Value:
  154. Status is returned.
  155. --*/
  156. {
  157. //
  158. // Complete the request and return status.
  159. //
  160. Irp->IoStatus.Status = STATUS_SUCCESS;
  161. Irp->IoStatus.Information = 0;
  162. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  163. return(STATUS_SUCCESS);
  164. }
  165. NTSTATUS
  166. SetupDeviceControl(
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN PIRP Irp
  169. )
  170. {
  171. PIO_STACK_LOCATION IrpSp;
  172. NTSTATUS Status;
  173. PSETUP_START_INFO SetupStartInfo;
  174. BOOLEAN b;
  175. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  176. switch(IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  177. case IOCTL_SETUP_START:
  178. //
  179. // Make sure we've been passed a suitable input buffer.
  180. //
  181. if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SETUP_START_INFO)) {
  182. Status = STATUS_INVALID_PARAMETER;
  183. } else {
  184. //
  185. // Save away relevent fields in the setup information
  186. // parameters.
  187. //
  188. SetupStartInfo = (PSETUP_START_INFO)Irp->AssociatedIrp.SystemBuffer;
  189. ResourceImageBase = SetupStartInfo->UserModeImageBase;
  190. CommunicationParams = SetupStartInfo->Communication;
  191. UsetupProcess = PsGetCurrentProcess();
  192. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: usetup process = %lx \n", UsetupProcess));
  193. b = pSpVerifyEventWaitable(
  194. SetupStartInfo->RequestReadyEvent,
  195. &RequestReadyEventObjectBody,
  196. &RequestReadyEventWaitObjectBody
  197. );
  198. if(!b) {
  199. Status = STATUS_INVALID_HANDLE;
  200. break;
  201. }
  202. b = pSpVerifyEventWaitable(
  203. SetupStartInfo->RequestServicedEvent,
  204. &RequestServicedEventObjectBody,
  205. &RequestServicedEventWaitObjectBody
  206. );
  207. if(!b) {
  208. Status = STATUS_INVALID_HANDLE;
  209. ObDereferenceObject(RequestReadyEventObjectBody);
  210. break;
  211. }
  212. SystemBasicInfo = SetupStartInfo->SystemBasicInfo;
  213. //
  214. // Start Setup going.
  215. //
  216. SpStartSetup();
  217. ObDereferenceObject(RequestReadyEventObjectBody);
  218. ObDereferenceObject(RequestServicedEventObjectBody);
  219. Status = STATUS_SUCCESS;
  220. }
  221. break;
  222. case IOCTL_SETUP_FMIFS_MESSAGE:
  223. //
  224. // Make sure that we were not called by usetup.exe.
  225. // Make sure we've been passed a suitable input buffer.
  226. //
  227. if( (UsetupProcess == PsGetCurrentProcess()) ||
  228. (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SETUP_FMIFS_MESSAGE)) ) {
  229. ASSERT( UsetupProcess != PsGetCurrentProcess() );
  230. Status = STATUS_INVALID_PARAMETER;
  231. } else {
  232. PSETUP_FMIFS_MESSAGE SetupFmifsMessage;
  233. SetupFmifsMessage = (PSETUP_FMIFS_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
  234. Status = STATUS_SUCCESS;
  235. //
  236. // If there's a callback override specified, use it.
  237. //
  238. if(pAutochkCallbackRoutine) {
  239. Status = pAutochkCallbackRoutine(SetupFmifsMessage);
  240. break;
  241. }
  242. //
  243. // If there is a gauge defined, then process the message.
  244. // Otherwise, don't bother processing it.
  245. //
  246. if( UserModeGauge != NULL ) {
  247. //
  248. // Save away relevent fields in the setup information
  249. // parameters.
  250. //
  251. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: caller process = %lx \n", PsGetCurrentProcess()));
  252. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: FmIfsPacketType = %d \n", SetupFmifsMessage->FmifsPacketType));
  253. //
  254. // Find out if the FmIfs packet is one of those that we care about
  255. //
  256. if( SetupFmifsMessage->FmifsPacketType == FmIfsPercentCompleted ) {
  257. ULONG PercentCompleted;
  258. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: PercentCompleted = %d \n", ((PFMIFS_PERCENT_COMPLETE_INFORMATION)SetupFmifsMessage->FmifsPacket)->PercentCompleted ));
  259. //
  260. // Save the percentage in a local variable, before we attach to
  261. // usetup address space
  262. //
  263. PercentCompleted = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)SetupFmifsMessage->FmifsPacket)->PercentCompleted;
  264. //
  265. // We need to adjust the percentage, depending on the partition
  266. // (System or NT partition) that is currently being accessed.
  267. // We use this because we want to use only one gauge to display
  268. // the progress on both System and NT partitions.
  269. // When autochk is running, 50% of the gauge will be used to
  270. // display the progress on the system partition, and the remaining
  271. // 50% will be used for the NT partition.
  272. // Note that when there are two partitions, the range of the
  273. // gauge is initialized as 200. When there is only one partition
  274. // the range is initialized as 100.
  275. // Note also that when autofmt is running, we always set CurrentDiskIndex
  276. // to 0.
  277. //
  278. ASSERT( CurrentDiskIndex <= 1 );
  279. PercentCompleted += 100*CurrentDiskIndex;
  280. //
  281. // Attach to usetup.exe address space
  282. //
  283. KeAttachProcess( (PKPROCESS)UsetupProcess );
  284. //
  285. // Call the function that processes FmIfsPackets
  286. //
  287. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Calling ProcessFmIfsPacket \n"));
  288. // Status = ProcessFmIfsPacket( SetupFmifsMessage );
  289. SpFillGauge( UserModeGauge, PercentCompleted );
  290. if (AutochkRunning) {
  291. SendSetupProgressEvent(PartitioningEvent, ValidatePartitionEvent, &PercentCompleted);
  292. } else if (AutofrmtRunning) {
  293. SendSetupProgressEvent(PartitioningEvent, FormatPartitionEvent, &PercentCompleted);
  294. }
  295. //
  296. // Now that the message was processed, detach from usetup.exe
  297. // address space
  298. //
  299. KeDetachProcess();
  300. } else {
  301. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: FmIfsPacketType = %d \n", SetupFmifsMessage->FmifsPacketType));
  302. }
  303. }
  304. }
  305. break;
  306. default:
  307. Status = STATUS_INVALID_PARAMETER;
  308. break;
  309. }
  310. Irp->IoStatus.Status = Status;
  311. Irp->IoStatus.Information = 0;
  312. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  313. return(Status);
  314. }
  315. VOID
  316. SpSetAutochkCallback(
  317. IN PAUTOCHK_MSG_PROCESSING_ROUTINE AutochkCallbackRoutine
  318. )
  319. {
  320. pAutochkCallbackRoutine = AutochkCallbackRoutine;
  321. }
  322. BOOLEAN
  323. pSpVerifyEventWaitable(
  324. IN HANDLE hEvent,
  325. OUT PVOID *EventObjectBody,
  326. OUT PVOID *EventWaitObjectBody
  327. )
  328. {
  329. POBJECT_HEADER ObjectHeader;
  330. NTSTATUS Status;
  331. //
  332. // Reference the event and verify that it is waitable.
  333. //
  334. Status = ObReferenceObjectByHandle(
  335. hEvent,
  336. EVENT_ALL_ACCESS,
  337. NULL,
  338. KernelMode,
  339. EventObjectBody,
  340. NULL
  341. );
  342. if(!NT_SUCCESS(Status)) {
  343. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to reference event object (%lx)\n",Status));
  344. return(FALSE);
  345. }
  346. ObjectHeader = OBJECT_TO_OBJECT_HEADER(*EventObjectBody);
  347. if(!ObjectHeader->Type->TypeInfo.UseDefaultObject) {
  348. *EventWaitObjectBody = (PVOID)((PCHAR)(*EventObjectBody) +
  349. (ULONG_PTR)ObjectHeader->Type->DefaultObject);
  350. } else {
  351. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: event object not waitable!\n"));
  352. ObDereferenceObject(*EventObjectBody);
  353. return(FALSE);
  354. }
  355. return(TRUE);
  356. }
  357. NTSTATUS
  358. SpInvokeUserModeService(
  359. VOID
  360. )
  361. {
  362. NTSTATUS Status;
  363. //
  364. // Set the event indicating that the communication buffer is
  365. // ready for the user-mode process. Because this is a synchronization
  366. // event, it automatically resets after releasing the waiting
  367. // user-mode thread. Note that we specify WaitNext to prevent the
  368. // race condition between setting this synchronization event and
  369. // waiting on the next one.
  370. //
  371. KeSetEvent(RequestReadyEventObjectBody,EVENT_INCREMENT,TRUE);
  372. //
  373. // Wait for the user-mode process to indicate that it is done
  374. // processing the request. We wait in user mode so that we can be
  375. // interrupted if necessary -- say, by an exit APC.
  376. //
  377. Status = KeWaitForSingleObject(
  378. RequestServicedEventWaitObjectBody,
  379. Executive,
  380. UserMode,
  381. FALSE,
  382. NULL
  383. );
  384. if(!NT_SUCCESS(Status)) {
  385. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: KeWaitForSingleObject returns %lx\n",Status));
  386. return(Status);
  387. }
  388. //
  389. // Return the status returned by the user mode process.
  390. //
  391. return(CommunicationParams->u.Status);
  392. }
  393. NTSTATUS
  394. SpExecuteImage(
  395. IN PWSTR ImagePath,
  396. OUT PULONG ReturnStatus, OPTIONAL
  397. IN ULONG ArgumentCount,
  398. ...
  399. )
  400. {
  401. va_list arglist;
  402. ULONG i;
  403. PSERVICE_EXECUTE RequestBuffer;
  404. NTSTATUS Status;
  405. //
  406. // Locate the request buffer and set up the request number.
  407. //
  408. CommunicationParams->u.RequestNumber = SetupServiceExecute;
  409. RequestBuffer = (PSERVICE_EXECUTE)&CommunicationParams->Buffer;
  410. //
  411. // Determine the lcoations of the two strings that get copied
  412. // into the request buffer for this service.
  413. //
  414. RequestBuffer->FullImagePath = RequestBuffer->Buffer;
  415. RequestBuffer->CommandLine = RequestBuffer->FullImagePath + wcslen(ImagePath) + 1;
  416. //
  417. // Copy the image path into the request buffer.
  418. //
  419. wcscpy(RequestBuffer->FullImagePath,ImagePath);
  420. //
  421. // Move the arguments into the request buffer one by one
  422. // starting with the image path.
  423. //
  424. wcscpy(RequestBuffer->CommandLine,ImagePath);
  425. va_start(arglist,ArgumentCount);
  426. for(i=0; i<ArgumentCount; i++) {
  427. wcscat(RequestBuffer->CommandLine,L" ");
  428. wcscat(RequestBuffer->CommandLine,va_arg(arglist,PWSTR));
  429. }
  430. va_end(arglist);
  431. //
  432. // Invoke the service.
  433. //
  434. Status = SpInvokeUserModeService();
  435. //
  436. // Set process's return status (if required)
  437. //
  438. if(NT_SUCCESS(Status) && ReturnStatus) {
  439. *ReturnStatus = RequestBuffer->ReturnStatus;
  440. }
  441. return Status;
  442. }
  443. NTSTATUS
  444. SpLoadUnloadKey(
  445. IN HANDLE TargetKeyRootDirectory, OPTIONAL
  446. IN HANDLE SourceFileRootDirectory, OPTIONAL
  447. IN PWSTR TargetKeyName,
  448. IN PWSTR SourceFileName OPTIONAL
  449. )
  450. {
  451. //
  452. // This was once a user-mode service but now the relevent apis
  453. // are exported from the kernel so don't bother.
  454. //
  455. UNICODE_STRING KeyName,FileName;
  456. OBJECT_ATTRIBUTES ObjaKey,ObjaFile;
  457. NTSTATUS Status;
  458. BOOLEAN Loading;
  459. BOOLEAN bFileExists = FALSE;
  460. //
  461. // Loading if we have a source filename, otherwise unloading.
  462. //
  463. Loading = (BOOLEAN)(SourceFileName != NULL);
  464. INIT_OBJA(&ObjaKey,&KeyName,TargetKeyName);
  465. ObjaKey.RootDirectory = TargetKeyRootDirectory;
  466. if(Loading) {
  467. INIT_OBJA(&ObjaFile,&FileName,SourceFileName);
  468. ObjaFile.RootDirectory = SourceFileRootDirectory;
  469. //
  470. // NOTE:ZwLoadKey(...) creates the file if does not exist
  471. // so we need to check for the existence of the file
  472. //
  473. if (SpFileExists(SourceFileName, FALSE))
  474. Status = ZwLoadKey(&ObjaKey,&ObjaFile);
  475. else
  476. Status = STATUS_NO_SUCH_FILE;
  477. } else {
  478. Status = ZwUnloadKey(&ObjaKey);
  479. }
  480. if(!NT_SUCCESS(Status)) {
  481. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  482. "SETUP: %wskey of %ws failed (%lx)\n",
  483. Loading ? L"load" : L"unload",
  484. TargetKeyName,
  485. Status
  486. ));
  487. }
  488. return(Status);
  489. }
  490. NTSTATUS
  491. SpDeleteKey(
  492. IN HANDLE KeyRootDirectory, OPTIONAL
  493. IN PWSTR Key
  494. )
  495. {
  496. PSERVICE_DELETE_KEY RequestBuffer;
  497. //
  498. // Locate the request buffer and set up the request number.
  499. //
  500. CommunicationParams->u.RequestNumber = SetupServiceDeleteKey;
  501. RequestBuffer = (PSERVICE_DELETE_KEY)&CommunicationParams->Buffer;
  502. //
  503. // Determine the lcoation of the strings that get copied
  504. // into the request buffer for this service.
  505. //
  506. RequestBuffer->Key = RequestBuffer->Buffer;
  507. //
  508. // Copy the string into the request buffer.
  509. //
  510. wcscpy(RequestBuffer->Buffer,Key);
  511. //
  512. // Initialize the root directory fields.
  513. //
  514. RequestBuffer->KeyRootDirectory = KeyRootDirectory;
  515. //
  516. // Invoke the service.
  517. //
  518. return(SpInvokeUserModeService());
  519. }
  520. NTSTATUS
  521. SpQueryDirectoryObject(
  522. IN HANDLE DirectoryHandle,
  523. IN BOOLEAN RestartScan,
  524. IN OUT PULONG Context
  525. )
  526. {
  527. PSERVICE_QUERY_DIRECTORY_OBJECT RequestBuffer;
  528. NTSTATUS Status;
  529. CommunicationParams->u.RequestNumber = SetupServiceQueryDirectoryObject;
  530. RequestBuffer = (PSERVICE_QUERY_DIRECTORY_OBJECT)&CommunicationParams->Buffer;
  531. RequestBuffer->DirectoryHandle = DirectoryHandle;
  532. RequestBuffer->Context = *Context;
  533. RequestBuffer->RestartScan = RestartScan;
  534. Status = SpInvokeUserModeService();
  535. if(NT_SUCCESS(Status)) {
  536. *Context = RequestBuffer->Context;
  537. }
  538. return(Status);
  539. }
  540. NTSTATUS
  541. SpFlushVirtualMemory(
  542. IN PVOID BaseAddress,
  543. IN ULONG RangeLength
  544. )
  545. {
  546. PSERVICE_FLUSH_VIRTUAL_MEMORY RequestBuffer;
  547. CommunicationParams->u.RequestNumber = SetupServiceFlushVirtualMemory;
  548. RequestBuffer = (PSERVICE_FLUSH_VIRTUAL_MEMORY)&CommunicationParams->Buffer;
  549. RequestBuffer->BaseAddress = BaseAddress;
  550. RequestBuffer->RangeLength = RangeLength;
  551. return(SpInvokeUserModeService());
  552. }
  553. VOID
  554. SpShutdownSystem(
  555. VOID
  556. )
  557. {
  558. SendSetupProgressEvent(SetupCompletedEvent, ShutdownEvent, NULL);
  559. CommunicationParams->u.RequestNumber = SetupServiceShutdownSystem;
  560. SpInvokeUserModeService();
  561. //
  562. // Shouldn't get here, but just in case...
  563. //
  564. HalReturnToFirmware(HalRebootRoutine);
  565. }
  566. NTSTATUS
  567. SpLoadKbdLayoutDll(
  568. IN PWSTR Directory,
  569. IN PWSTR DllName,
  570. OUT PVOID *TableAddress
  571. )
  572. {
  573. PSERVICE_LOAD_KBD_LAYOUT_DLL RequestBuffer;
  574. NTSTATUS Status;
  575. CommunicationParams->u.RequestNumber = SetupServiceLoadKbdLayoutDll;
  576. RequestBuffer = (PSERVICE_LOAD_KBD_LAYOUT_DLL)&CommunicationParams->Buffer;
  577. wcscpy(RequestBuffer->DllName,Directory);
  578. SpConcatenatePaths(RequestBuffer->DllName,DllName);
  579. Status = SpInvokeUserModeService();
  580. if(NT_SUCCESS(Status)) {
  581. *TableAddress = RequestBuffer->TableAddress;
  582. }
  583. return(Status);
  584. }
  585. NTSTATUS
  586. SpLockUnlockVolume(
  587. IN HANDLE Handle,
  588. IN BOOLEAN LockVolume
  589. )
  590. {
  591. PSERVICE_LOCK_UNLOCK_VOLUME RequestBuffer;
  592. CommunicationParams->u.RequestNumber = (LockVolume)? SetupServiceLockVolume :
  593. SetupServiceUnlockVolume;
  594. RequestBuffer = (PSERVICE_LOCK_UNLOCK_VOLUME)&CommunicationParams->Buffer;
  595. RequestBuffer->Handle = Handle;
  596. return(SpInvokeUserModeService());
  597. }
  598. NTSTATUS
  599. SpDismountVolume(
  600. IN HANDLE Handle
  601. )
  602. {
  603. PSERVICE_DISMOUNT_VOLUME RequestBuffer;
  604. CommunicationParams->u.RequestNumber = SetupServiceDismountVolume;
  605. RequestBuffer = (PSERVICE_DISMOUNT_VOLUME)&CommunicationParams->Buffer;
  606. RequestBuffer->Handle = Handle;
  607. return(SpInvokeUserModeService());
  608. }
  609. NTSTATUS
  610. SpSetDefaultFileSecurity(
  611. IN PWSTR FileName
  612. )
  613. {
  614. PSERVICE_DEFAULT_FILE_SECURITY RequestBuffer;
  615. CommunicationParams->u.RequestNumber = SetupServiceSetDefaultFileSecurity;
  616. RequestBuffer = (PSERVICE_DEFAULT_FILE_SECURITY)&CommunicationParams->Buffer;
  617. wcscpy( RequestBuffer->FileName, FileName );
  618. return(SpInvokeUserModeService());
  619. }
  620. NTSTATUS
  621. SpVerifyFileAccess(
  622. IN PWSTR FileName,
  623. IN ACCESS_MASK DesiredAccess
  624. )
  625. {
  626. PSERVICE_VERIFY_FILE_ACCESS RequestBuffer;
  627. CommunicationParams->u.RequestNumber = SetupServiceVerifyFileAccess;
  628. RequestBuffer = (PSERVICE_VERIFY_FILE_ACCESS)&CommunicationParams->Buffer;
  629. wcscpy( RequestBuffer->FileName, FileName );
  630. RequestBuffer->DesiredAccess = DesiredAccess;
  631. return(SpInvokeUserModeService());
  632. }
  633. NTSTATUS
  634. SpCreatePageFile(
  635. IN PWSTR FileName,
  636. IN ULONG MinSize,
  637. IN ULONG MaxSize
  638. )
  639. {
  640. PSERVICE_CREATE_PAGEFILE RequestBuffer;
  641. CommunicationParams->u.RequestNumber = SetupServiceCreatePageFile;
  642. RequestBuffer = (PSERVICE_CREATE_PAGEFILE)&CommunicationParams->Buffer;
  643. wcscpy(RequestBuffer->FileName,FileName);
  644. RequestBuffer->MinSize.HighPart = 0;
  645. RequestBuffer->MinSize.LowPart = MinSize;
  646. RequestBuffer->MaxSize.HighPart = 0;
  647. RequestBuffer->MaxSize.LowPart = MaxSize;
  648. return(SpInvokeUserModeService());
  649. }
  650. NTSTATUS
  651. SpGetFullPathName(
  652. IN OUT PWSTR FileName
  653. )
  654. {
  655. PSERVICE_GETFULLPATHNAME RequestBuffer;
  656. NTSTATUS Status;
  657. CommunicationParams->u.RequestNumber = SetupServiceGetFullPathName;
  658. RequestBuffer = (PSERVICE_GETFULLPATHNAME)&CommunicationParams->Buffer;
  659. wcscpy(RequestBuffer->FileName,FileName);
  660. Status = SpInvokeUserModeService();
  661. if(NT_SUCCESS(Status)) {
  662. wcscpy(FileName,RequestBuffer->NameOut);
  663. }
  664. return(Status);
  665. }