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.

1141 lines
28 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. usetup.c
  5. Abstract:
  6. User-mode text-setup process.
  7. Author:
  8. Ted Miller (tedm) 29-July-1993
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <ntdddisk.h>
  15. #include <fmifs.h>
  16. #include <setupdd.h>
  17. HANDLE hEventRequestReady,hEventRequestServiced;
  18. SETUP_COMMUNICATION Communication;
  19. //
  20. // Global variables (global to the module) used by the functions
  21. // that set a security descriptor to a file.
  22. //
  23. BOOLEAN _SecurityDescriptorInitialized = FALSE;
  24. SECURITY_DESCRIPTOR _SecurityDescriptor;
  25. PSID _WorldSid;
  26. PSID _SystemSid;
  27. BOOLEAN
  28. uSpInitializeDefaultSecurityDescriptor(
  29. )
  30. /*++
  31. Routine Description:
  32. Build the security descriptor that will be set in the files, that
  33. contain bogus security descriptor.
  34. Arguments:
  35. None
  36. Return Value:
  37. BOOLEAN - Returns TRUE if the security descriptor was successfully
  38. initialized. Returns FALSE otherwise.
  39. --*/
  40. {
  41. NTSTATUS NtStatus;
  42. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  43. CHAR Acl[256]; // 256 is more than big enough
  44. ULONG AclLength=256;
  45. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  46. //
  47. // Create the SIDs for World and System
  48. //
  49. NtStatus = RtlAllocateAndInitializeSid( &WorldSidAuthority,
  50. 1,
  51. SECURITY_WORLD_RID,
  52. 0, 0, 0, 0, 0, 0, 0,
  53. &_WorldSid
  54. );
  55. if ( !NT_SUCCESS( NtStatus )) {
  56. KdPrint(( "uSETUP: Unable to allocate and initialize SID %x \n", NtStatus ));
  57. return( FALSE );
  58. }
  59. NtStatus = RtlAllocateAndInitializeSid( &SystemSidAuthority,
  60. 1,
  61. SECURITY_LOCAL_SYSTEM_RID,
  62. 0, 0, 0, 0, 0, 0, 0,
  63. &_SystemSid
  64. );
  65. if ( !NT_SUCCESS( NtStatus )) {
  66. KdPrint(( "uSETUP: Unable to allocate and initialize SID, status = %x \n", NtStatus ));
  67. RtlFreeSid( _WorldSid );
  68. return( FALSE );
  69. }
  70. //
  71. // Create the ACL
  72. //
  73. NtStatus = RtlCreateAcl( (PACL)Acl,
  74. AclLength,
  75. ACL_REVISION2
  76. );
  77. if ( !NT_SUCCESS( NtStatus )) {
  78. KdPrint(( "uSETUP: Unable to create Acl, status = %x \n", NtStatus ));
  79. RtlFreeSid( _WorldSid );
  80. RtlFreeSid( _SystemSid );
  81. return( FALSE );
  82. }
  83. //
  84. // Copy the World SID into the ACL
  85. //
  86. NtStatus = RtlAddAccessAllowedAce( (PACL)Acl,
  87. ACL_REVISION2,
  88. GENERIC_ALL,
  89. _WorldSid
  90. );
  91. if ( !NT_SUCCESS( NtStatus )) {
  92. KdPrint(( "uSETUP: Unable to add Access Allowed Ace to Acl, status = %x \n", NtStatus ));
  93. RtlFreeSid( _WorldSid );
  94. RtlFreeSid( _SystemSid );
  95. return( FALSE );
  96. }
  97. //
  98. // Sid has been copied into the ACL
  99. //
  100. // RtlFreeSid( WorldSid );
  101. //
  102. // Create and initialize the security descriptor
  103. //
  104. NtStatus = RtlCreateSecurityDescriptor( &_SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  105. if ( !NT_SUCCESS( NtStatus )) {
  106. KdPrint(( "uSETUP: Unable to create security descriptor, status = %x \n", NtStatus ));
  107. RtlFreeSid( _WorldSid );
  108. RtlFreeSid( _SystemSid );
  109. return( FALSE );
  110. }
  111. NtStatus = RtlSetDaclSecurityDescriptor ( &_SecurityDescriptor,
  112. TRUE,
  113. (PACL)Acl,
  114. FALSE
  115. );
  116. if ( !NT_SUCCESS( NtStatus )) {
  117. KdPrint(( "uSETUP: Unable to set Acl to _SecurityDescriptor, status = %x \n", NtStatus ));
  118. RtlFreeSid( _WorldSid );
  119. RtlFreeSid( _SystemSid );
  120. return( FALSE );
  121. }
  122. //
  123. // Copy the owner into the security descriptor
  124. //
  125. NtStatus = RtlSetOwnerSecurityDescriptor( &_SecurityDescriptor,
  126. _SystemSid,
  127. FALSE );
  128. // RtlFreeSid( SystemSid );
  129. if ( !NT_SUCCESS( NtStatus )) {
  130. KdPrint(( "uSETUP: Unable to set Owner to _SecurityDescriptor, status = %x \n", NtStatus ));
  131. RtlFreeSid( _WorldSid );
  132. RtlFreeSid( _SystemSid );
  133. return( FALSE );
  134. }
  135. _SecurityDescriptorInitialized = TRUE;
  136. return( TRUE );
  137. }
  138. NTSTATUS
  139. uSpSetFileSecurity(
  140. PWSTR FileName,
  141. SECURITY_INFORMATION SecurityInformation,
  142. PSECURITY_DESCRIPTOR pSecurityDescriptor
  143. )
  144. /*++
  145. Routine Description:
  146. This function sets the security of a file.
  147. It is based on the Win32 API SetFileSecurity.
  148. This API can be used to set the security of a file or directory
  149. (process, file, event, etc.). This call is only successful if the
  150. following conditions are met:
  151. o If the object's owner or group is to be set, the caller must
  152. have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.
  153. o If the object's DACL is to be set, the caller must have
  154. WRITE_DAC permission or be the object's owner.
  155. o If the object's SACL is to be set, the caller must have
  156. SeSecurityPrivilege.
  157. Arguments:
  158. lpFileName - Supplies the file name of the file whose security
  159. is to be set.
  160. SecurityInformation - A pointer to information describing the
  161. contents of the Security Descriptor.
  162. pSecurityDescriptor - A pointer to a well formed Security
  163. Descriptor.
  164. Return Value:
  165. NTSTATUS - An NT status code indcating the result of the operation.
  166. --*/
  167. {
  168. NTSTATUS Status;
  169. HANDLE FileHandle;
  170. ACCESS_MASK DesiredAccess;
  171. OBJECT_ATTRIBUTES Obja;
  172. UNICODE_STRING UnicodeFileName;
  173. IO_STATUS_BLOCK IoStatusBlock;
  174. DesiredAccess = 0;
  175. if ((SecurityInformation & OWNER_SECURITY_INFORMATION) ||
  176. (SecurityInformation & GROUP_SECURITY_INFORMATION) ) {
  177. DesiredAccess |= WRITE_OWNER;
  178. }
  179. if (SecurityInformation & DACL_SECURITY_INFORMATION) {
  180. DesiredAccess |= WRITE_DAC;
  181. }
  182. if (SecurityInformation & SACL_SECURITY_INFORMATION) {
  183. DesiredAccess |= ACCESS_SYSTEM_SECURITY;
  184. }
  185. RtlInitUnicodeString( &UnicodeFileName,
  186. FileName );
  187. InitializeObjectAttributes(
  188. &Obja,
  189. &UnicodeFileName,
  190. OBJ_CASE_INSENSITIVE,
  191. NULL,
  192. NULL
  193. );
  194. Status = NtOpenFile(
  195. &FileHandle,
  196. DesiredAccess,
  197. &Obja,
  198. &IoStatusBlock,
  199. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  200. 0
  201. );
  202. if ( NT_SUCCESS( Status ) ) {
  203. Status = NtSetSecurityObject(
  204. FileHandle,
  205. SecurityInformation,
  206. pSecurityDescriptor
  207. );
  208. NtClose(FileHandle);
  209. }
  210. return Status;
  211. }
  212. NTSTATUS
  213. uSpSetDefaultFileSecurity(
  214. VOID
  215. )
  216. /*++
  217. Routine Description:
  218. Set a default security descriptor onto a file.
  219. Arguments:
  220. None
  221. Return Value:
  222. NTSTATUS
  223. --*/
  224. {
  225. NTSTATUS Status;
  226. PWSTR FileName;
  227. PSERVICE_DEFAULT_FILE_SECURITY Params = (PSERVICE_DEFAULT_FILE_SECURITY)Communication.Buffer;
  228. FileName = Params->FileName;
  229. if( !_SecurityDescriptorInitialized ) {
  230. Status = uSpInitializeDefaultSecurityDescriptor();
  231. if( !NT_SUCCESS( Status ) ) {
  232. KdPrint(( "uSETUP: Unable to initialize default security descriptor. Status = %x \n", Status ));
  233. return( Status );
  234. }
  235. }
  236. //
  237. // Attempt to write the DACL
  238. //
  239. Status = uSpSetFileSecurity( FileName,
  240. DACL_SECURITY_INFORMATION,
  241. &_SecurityDescriptor );
  242. if( !NT_SUCCESS( Status ) ) {
  243. //
  244. // Make the system the owner of the file
  245. //
  246. Status = uSpSetFileSecurity( FileName,
  247. OWNER_SECURITY_INFORMATION,
  248. &_SecurityDescriptor );
  249. #if DBG
  250. if( !NT_SUCCESS( Status ) ) {
  251. KdPrint(( "uSETUP: Unable to set file OWNER. Status = %x \n", Status ));
  252. }
  253. #endif
  254. if( NT_SUCCESS( Status ) ) {
  255. //
  256. // Write the DACL to the file
  257. //
  258. Status = uSpSetFileSecurity( FileName,
  259. DACL_SECURITY_INFORMATION,
  260. &_SecurityDescriptor );
  261. #if DBG
  262. if( !NT_SUCCESS( Status ) ) {
  263. KdPrint(( "uSETUP: Unable to set file DACL. Status = %x \n", Status ));
  264. }
  265. #endif
  266. }
  267. }
  268. return( Status );
  269. }
  270. NTSTATUS
  271. uSpVerifyFileAccess(
  272. VOID
  273. )
  274. /*++
  275. Routine Description:
  276. Check whether or not the security descriptor set in a file allows
  277. textmode setup to perform some file operation. If textmode setup
  278. is not allowed to open the file for certain accesses, we assume
  279. that the security information in the file is not valid.
  280. Arguments:
  281. FileName - Full path to the file to be examined
  282. Return Value:
  283. NTSTATUS -
  284. --*/
  285. {
  286. ACCESS_MASK DesiredAccess;
  287. HANDLE FileHandle;
  288. OBJECT_ATTRIBUTES ObjectAttributes;
  289. IO_STATUS_BLOCK IoStatusBlock;
  290. NTSTATUS Status;
  291. UNICODE_STRING UnicodeFileName;
  292. PWSTR FileName;
  293. PSERVICE_VERIFY_FILE_ACCESS Params = (PSERVICE_VERIFY_FILE_ACCESS)Communication.Buffer;
  294. FileName = Params->FileName;
  295. DesiredAccess = Params->DesiredAccess;
  296. RtlInitUnicodeString( &UnicodeFileName,
  297. FileName );
  298. InitializeObjectAttributes( &ObjectAttributes,
  299. &UnicodeFileName,
  300. OBJ_CASE_INSENSITIVE,
  301. NULL,
  302. NULL );
  303. Status = NtOpenFile( &FileHandle,
  304. DesiredAccess,
  305. &ObjectAttributes,
  306. &IoStatusBlock,
  307. 0,
  308. FILE_SYNCHRONOUS_IO_NONALERT );
  309. if( NT_SUCCESS( Status ) ) {
  310. NtClose( FileHandle );
  311. }
  312. #if DBG
  313. if( !NT_SUCCESS( Status ) ) {
  314. KdPrint( ("uSETUP: NtOpenFile() failed. File = %ls, Status = %x\n",FileName, Status ) );
  315. }
  316. #endif
  317. return( Status );
  318. }
  319. NTSTATUS
  320. uSpLoadKbdLayoutDll(
  321. VOID
  322. )
  323. {
  324. UNICODE_STRING DllNameU;
  325. PSERVICE_LOAD_KBD_LAYOUT_DLL Params = (PSERVICE_LOAD_KBD_LAYOUT_DLL)Communication.Buffer;
  326. NTSTATUS Status;
  327. PVOID DllBaseAddress;
  328. PVOID (*RoutineAddress)(VOID);
  329. RtlInitUnicodeString(&DllNameU,Params->DllName);
  330. Status = LdrLoadDll(NULL,NULL,&DllNameU,&DllBaseAddress);
  331. if(!NT_SUCCESS(Status)) {
  332. KdPrint(("uSETUP: Unable to load dll %ws (%lx)\n",Params->DllName,Status));
  333. return(Status);
  334. }
  335. Status = LdrGetProcedureAddress(DllBaseAddress,NULL,1,(PVOID)&RoutineAddress);
  336. if(NT_SUCCESS(Status)) {
  337. Params->TableAddress = (*RoutineAddress)();
  338. } else {
  339. KdPrint(("uSETUP: Unable to get address of proc 1 from dll %ws (%lx)\n",Params->DllName,Status));
  340. LdrUnloadDll(DllBaseAddress);
  341. }
  342. return(Status);
  343. }
  344. NTSTATUS
  345. uSpExecuteImage(
  346. VOID
  347. )
  348. {
  349. UNICODE_STRING CommandLineU,ImagePathU,CurrentDirectoryU;
  350. PSERVICE_EXECUTE Params = (PSERVICE_EXECUTE)Communication.Buffer;
  351. NTSTATUS Status;
  352. RTL_USER_PROCESS_INFORMATION ProcessInformation;
  353. PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
  354. WCHAR Env[2] = { 0,0 };
  355. PROCESS_BASIC_INFORMATION BasicInformation;
  356. //
  357. // Initialize unicode strings.
  358. //
  359. RtlInitUnicodeString(&CommandLineU,Params->CommandLine);
  360. RtlInitUnicodeString(&ImagePathU,Params->FullImagePath);
  361. RtlInitUnicodeString(&CurrentDirectoryU,L"\\");
  362. //
  363. // Create process parameters.
  364. //
  365. Status = RtlCreateProcessParameters(
  366. &ProcessParameters,
  367. &ImagePathU,
  368. NULL,
  369. &CurrentDirectoryU,
  370. &CommandLineU,
  371. Env,
  372. NULL,
  373. NULL,
  374. NULL,
  375. NULL
  376. );
  377. if(!NT_SUCCESS(Status)) {
  378. KdPrint(("uSETUP: Unable to create process params for %ws (%lx)\n",Params->FullImagePath,Status));
  379. return(Status);
  380. }
  381. ProcessParameters->DebugFlags = 0;
  382. //
  383. // Create the user process.
  384. //
  385. ProcessInformation.Length = sizeof(RTL_USER_PROCESS_INFORMATION);
  386. Status = RtlCreateUserProcess(
  387. &ImagePathU,
  388. OBJ_CASE_INSENSITIVE,
  389. ProcessParameters,
  390. NULL,
  391. NULL,
  392. NULL,
  393. FALSE,
  394. NULL,
  395. NULL,
  396. &ProcessInformation
  397. );
  398. RtlDestroyProcessParameters(ProcessParameters);
  399. if(!NT_SUCCESS(Status)) {
  400. KdPrint(("uSETUP: Unable to create user process %ws (%lx)\n",Params->FullImagePath,Status));
  401. return(Status);
  402. }
  403. //
  404. // Make sure the image is a native NT image.
  405. //
  406. if(ProcessInformation.ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_NATIVE) {
  407. KdPrint(("uSETUP: %ws is not an NT image\n",Params->FullImagePath));
  408. NtTerminateProcess(ProcessInformation.Process,STATUS_INVALID_IMAGE_FORMAT);
  409. NtWaitForSingleObject(ProcessInformation.Thread,FALSE,NULL);
  410. NtClose(ProcessInformation.Thread);
  411. NtClose(ProcessInformation.Process);
  412. return(STATUS_INVALID_IMAGE_FORMAT);
  413. }
  414. //
  415. // Start the process going.
  416. //
  417. Status = NtResumeThread(ProcessInformation.Thread,NULL);
  418. //
  419. // Wait for the process to finish.
  420. //
  421. NtWaitForSingleObject(ProcessInformation.Process,FALSE,NULL);
  422. //
  423. // Get process return status
  424. //
  425. Status = NtQueryInformationProcess(
  426. ProcessInformation.Process,
  427. ProcessBasicInformation,
  428. &BasicInformation,
  429. sizeof(BasicInformation),
  430. NULL
  431. );
  432. if ( NT_SUCCESS(Status) ) {
  433. Params->ReturnStatus = BasicInformation.ExitStatus;
  434. }
  435. //
  436. // Clean up and return.
  437. //
  438. NtClose(ProcessInformation.Thread);
  439. NtClose(ProcessInformation.Process);
  440. return Status;
  441. }
  442. NTSTATUS
  443. uSpDeleteKey(
  444. VOID
  445. )
  446. {
  447. UNICODE_STRING KeyName;
  448. OBJECT_ATTRIBUTES Obja;
  449. HANDLE hKey;
  450. NTSTATUS Status;
  451. PSERVICE_DELETE_KEY Params = (PSERVICE_DELETE_KEY)Communication.Buffer;
  452. //
  453. // Initialize unicode strings and object attributes.
  454. //
  455. RtlInitUnicodeString(&KeyName,Params->Key);
  456. InitializeObjectAttributes(
  457. &Obja,
  458. &KeyName,
  459. OBJ_CASE_INSENSITIVE,
  460. Params->KeyRootDirectory,
  461. NULL
  462. );
  463. //
  464. // Open the key and delete it
  465. //
  466. Status = NtOpenKey(&hKey,KEY_ALL_ACCESS,&Obja);
  467. if(NT_SUCCESS(Status)) {
  468. Status = NtDeleteKey(hKey);
  469. NtClose(hKey);
  470. }
  471. return(Status);
  472. }
  473. NTSTATUS
  474. uSpQueryDirectoryObject(
  475. VOID
  476. )
  477. {
  478. PSERVICE_QUERY_DIRECTORY_OBJECT Params = (PSERVICE_QUERY_DIRECTORY_OBJECT)Communication.Buffer;
  479. NTSTATUS Status;
  480. Status = NtQueryDirectoryObject(
  481. Params->DirectoryHandle,
  482. Params->Buffer,
  483. sizeof(Params->Buffer),
  484. TRUE, // return single entry
  485. Params->RestartScan,
  486. &Params->Context,
  487. NULL
  488. );
  489. if(!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_ENTRIES)) {
  490. KdPrint(("uSETUP: Unable to query directory object (%lx)\n",Status));
  491. }
  492. return(Status);
  493. }
  494. NTSTATUS
  495. uSpFlushVirtualMemory(
  496. VOID
  497. )
  498. {
  499. PSERVICE_FLUSH_VIRTUAL_MEMORY Params = (PSERVICE_FLUSH_VIRTUAL_MEMORY)Communication.Buffer;
  500. NTSTATUS Status;
  501. IO_STATUS_BLOCK IoStatus;
  502. PVOID BaseAddress;
  503. SIZE_T RangeLength;
  504. BaseAddress = Params->BaseAddress;
  505. RangeLength = Params->RangeLength;
  506. Status = NtFlushVirtualMemory(
  507. NtCurrentProcess(),
  508. &BaseAddress,
  509. &RangeLength,
  510. &IoStatus
  511. );
  512. if(NT_SUCCESS(Status)) {
  513. if(BaseAddress != Params->BaseAddress) {
  514. KdPrint((
  515. "uSETUP: Warning: uSpFlushVirtualMemory: base address %lx changed to %lx\n",
  516. Params->BaseAddress,
  517. BaseAddress
  518. ));
  519. }
  520. } else {
  521. KdPrint((
  522. "uSETUP: Unable to flush virtual memory @%p length %p (%lx)\n",
  523. Params->BaseAddress,
  524. Params->RangeLength,
  525. Status
  526. ));
  527. }
  528. return(Status);
  529. }
  530. NTSTATUS
  531. uSpShutdownSystem(
  532. VOID
  533. )
  534. {
  535. NTSTATUS Status;
  536. Status = NtShutdownSystem(ShutdownReboot);
  537. KdPrint(("uSETUP: NtShutdownSystem returned (%lx)\n",Status));
  538. return(Status);
  539. }
  540. NTSTATUS
  541. uSpLockUnlockVolume(
  542. VOID
  543. )
  544. {
  545. HANDLE Handle;
  546. NTSTATUS Status;
  547. BOOLEAN Locking;
  548. IO_STATUS_BLOCK IoStatusBlock;
  549. PSERVICE_LOCK_UNLOCK_VOLUME Params = (PSERVICE_LOCK_UNLOCK_VOLUME)Communication.Buffer;
  550. Handle = Params->Handle;
  551. Locking = (BOOLEAN)(Communication.u.RequestNumber == SetupServiceLockVolume);
  552. Status = NtFsControlFile( Handle,
  553. NULL,
  554. NULL,
  555. NULL,
  556. &IoStatusBlock,
  557. ( Locking )? FSCTL_LOCK_VOLUME : FSCTL_UNLOCK_VOLUME,
  558. NULL,
  559. 0,
  560. NULL,
  561. 0 );
  562. if( !NT_SUCCESS( Status ) ) {
  563. KdPrint((
  564. "uSETUP: Unable to %ws volume (%lx)\n",
  565. ( Locking )? L"lock" : L"unlock",
  566. Status
  567. ));
  568. }
  569. return(Status);
  570. }
  571. NTSTATUS
  572. uSpDismountVolume(
  573. VOID
  574. )
  575. {
  576. HANDLE Handle;
  577. NTSTATUS Status;
  578. IO_STATUS_BLOCK IoStatusBlock;
  579. PSERVICE_DISMOUNT_VOLUME Params = (PSERVICE_DISMOUNT_VOLUME)Communication.Buffer;
  580. Handle = Params->Handle;
  581. Status = NtFsControlFile( Handle,
  582. NULL,
  583. NULL,
  584. NULL,
  585. &IoStatusBlock,
  586. FSCTL_DISMOUNT_VOLUME,
  587. NULL,
  588. 0,
  589. NULL,
  590. 0 );
  591. if( !NT_SUCCESS( Status ) ) {
  592. KdPrint((
  593. "uSETUP: Unable to dismount volume (%lx)\n",
  594. Status
  595. ));
  596. }
  597. return(Status);
  598. }
  599. NTSTATUS
  600. uSpCreatePageFile(
  601. VOID
  602. )
  603. {
  604. NTSTATUS Status;
  605. UNICODE_STRING UnicodeString;
  606. PSERVICE_CREATE_PAGEFILE Params = (PSERVICE_CREATE_PAGEFILE)Communication.Buffer;
  607. RtlInitUnicodeString(&UnicodeString,Params->FileName);
  608. Status = NtCreatePagingFile(&UnicodeString,&Params->MinSize,&Params->MaxSize,0);
  609. if(!NT_SUCCESS(Status)) {
  610. KdPrint((
  611. "uSETUP: Unable to create pagefile %ws %x-%x (%x)",
  612. Params->FileName,
  613. Params->MinSize.LowPart,
  614. Params->MaxSize.LowPart,
  615. Status
  616. ));
  617. }
  618. return(Status);
  619. }
  620. NTSTATUS
  621. uSpGetFullPathName(
  622. VOID
  623. )
  624. {
  625. ULONG len;
  626. ULONG u;
  627. PSERVICE_GETFULLPATHNAME Params = (PSERVICE_GETFULLPATHNAME)Communication.Buffer;
  628. len = wcslen(Params->FileName);
  629. Params->NameOut = Params->FileName + len + 1;
  630. u = RtlGetFullPathName_U(
  631. Params->FileName,
  632. (sizeof(Communication.Buffer) - ((len+1)*sizeof(WCHAR))) - sizeof(PVOID),
  633. Params->NameOut,
  634. NULL
  635. );
  636. return(u ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
  637. }
  638. NTSTATUS
  639. SpRequestServiceThread(
  640. PVOID ThreadParameter
  641. )
  642. {
  643. NTSTATUS Status;
  644. while(1) {
  645. //
  646. // Wait for the driver to fill the request buffer and indicate
  647. // that a request requires servicing.
  648. //
  649. Status = NtWaitForSingleObject(hEventRequestReady,FALSE,NULL);
  650. if(!NT_SUCCESS(Status)) {
  651. KdPrint(("uSETUP: wait on RequestReady event returned %lx\n",Status));
  652. return(Status);
  653. }
  654. switch(Communication.u.RequestNumber) {
  655. case SetupServiceExecute:
  656. Status = uSpExecuteImage();
  657. break;
  658. case SetupServiceLockVolume:
  659. case SetupServiceUnlockVolume:
  660. Status = uSpLockUnlockVolume();
  661. break;
  662. case SetupServiceDismountVolume:
  663. Status = uSpDismountVolume();
  664. break;
  665. case SetupServiceQueryDirectoryObject:
  666. Status = uSpQueryDirectoryObject();
  667. break;
  668. case SetupServiceFlushVirtualMemory:
  669. Status = uSpFlushVirtualMemory();
  670. break;
  671. case SetupServiceShutdownSystem:
  672. Status = uSpShutdownSystem();
  673. break;
  674. case SetupServiceDeleteKey:
  675. Status = uSpDeleteKey();
  676. break;
  677. case SetupServiceLoadKbdLayoutDll:
  678. Status = uSpLoadKbdLayoutDll();
  679. break;
  680. case SetupServiceDone:
  681. return(STATUS_SUCCESS);
  682. case SetupServiceSetDefaultFileSecurity:
  683. Status = uSpSetDefaultFileSecurity();
  684. break;
  685. case SetupServiceVerifyFileAccess:
  686. Status = uSpVerifyFileAccess();
  687. break;
  688. case SetupServiceCreatePageFile:
  689. Status = uSpCreatePageFile();
  690. break;
  691. case SetupServiceGetFullPathName:
  692. Status = uSpGetFullPathName();
  693. break;
  694. default:
  695. KdPrint(("uSETUP: unknown service %u requested\n",Communication.u.RequestNumber));
  696. Status = STATUS_INVALID_PARAMETER;
  697. break;
  698. }
  699. //
  700. // Store the result status where the driver can get at it.
  701. //
  702. Communication.u.Status = Status;
  703. //
  704. // Inform the driver that we're done servicing the request.
  705. //
  706. Status = NtSetEvent(hEventRequestServiced,NULL);
  707. if(!NT_SUCCESS(Status)) {
  708. KdPrint(("uSETUP: set RequestServiced event returned %lx\n",Status));
  709. return(Status);
  710. }
  711. }
  712. }
  713. void
  714. __cdecl
  715. main(
  716. int argc,
  717. char *argv[],
  718. char *envp[],
  719. ULONG DebugParameter OPTIONAL
  720. )
  721. {
  722. HANDLE handle;
  723. IO_STATUS_BLOCK IoStatusBlock;
  724. UNICODE_STRING UnicodeString;
  725. OBJECT_ATTRIBUTES Attributes;
  726. NTSTATUS Status;
  727. HANDLE hThread;
  728. SETUP_START_INFO SetupStartInfo;
  729. BOOLEAN b;
  730. //
  731. // Enable several privileges that we will need.
  732. //
  733. Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,TRUE,FALSE,&b);
  734. if(!NT_SUCCESS(Status)) {
  735. KdPrint(("uSETUP: Warning: unable to enable backup privilege (%lx)\n",Status));
  736. }
  737. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,TRUE,FALSE,&b);
  738. if(!NT_SUCCESS(Status)) {
  739. KdPrint(("uSETUP: Warning: unable to enable restore privilege (%lx)\n",Status));
  740. }
  741. Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,FALSE,&b);
  742. if(!NT_SUCCESS(Status)) {
  743. KdPrint(("uSETUP: Warning: unable to enable shutdown privilege (%lx)\n",Status));
  744. }
  745. Status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE,TRUE,FALSE,&b);
  746. if(!NT_SUCCESS(Status)) {
  747. KdPrint(("uSETUP: Warning: unable to enable take ownership privilege (%lx)\n",Status));
  748. }
  749. //
  750. // Get the registry going. Pass a flag indicating that this is a setup boot.
  751. //
  752. Status = NtInitializeRegistry(REG_INIT_BOOT_SETUP);
  753. if(!NT_SUCCESS(Status)) {
  754. KdPrint(("uSETUP: Unable to initialize registry (%lx)\n",Status));
  755. goto main0;
  756. }
  757. //
  758. // Query basic system info.
  759. //
  760. Status = NtQuerySystemInformation(
  761. SystemBasicInformation,
  762. &SetupStartInfo.SystemBasicInfo,
  763. sizeof(SYSTEM_BASIC_INFORMATION),
  764. NULL
  765. );
  766. if(!NT_SUCCESS(Status)) {
  767. KdPrint(("uSETUP: Unable to query system basic information (%lx)\n",Status));
  768. goto main0;
  769. }
  770. //
  771. // Create two events for cummunicating with the setup device driver.
  772. // One event indicates that the request buffer is filled (ie, request service)
  773. // and the other indicates that the request has been processed.
  774. // Both events are initially not signalled.
  775. //
  776. Status = NtCreateEvent(
  777. &hEventRequestReady,
  778. EVENT_ALL_ACCESS,
  779. NULL,
  780. SynchronizationEvent,
  781. FALSE
  782. );
  783. if(!NT_SUCCESS(Status)) {
  784. KdPrint(("uSETUP: Unable to create event (%lx)\n",Status));
  785. goto main0;
  786. }
  787. Status = NtCreateEvent(
  788. &hEventRequestServiced,
  789. EVENT_ALL_ACCESS,
  790. NULL,
  791. SynchronizationEvent,
  792. FALSE
  793. );
  794. if(!NT_SUCCESS(Status)) {
  795. KdPrint(("uSETUP: Unable to create event (%lx)\n",Status));
  796. goto main1;
  797. }
  798. //
  799. // Open the setup device.
  800. //
  801. RtlInitUnicodeString(&UnicodeString,DD_SETUP_DEVICE_NAME_U);
  802. InitializeObjectAttributes(
  803. &Attributes,
  804. &UnicodeString,
  805. OBJ_CASE_INSENSITIVE,
  806. NULL,
  807. NULL
  808. );
  809. Status = NtCreateFile(
  810. &handle,
  811. FILE_ALL_ACCESS,
  812. &Attributes,
  813. &IoStatusBlock,
  814. NULL, // allocation size
  815. 0,
  816. FILE_SHARE_READ,
  817. FILE_OPEN,
  818. FILE_SYNCHRONOUS_IO_NONALERT,
  819. NULL, // no EAs
  820. 0
  821. );
  822. if(!NT_SUCCESS(Status)) {
  823. KdPrint(("uSETUP: Unable to open %ws (%lx)\n",DD_SETUP_DEVICE_NAME_U,Status));
  824. goto main2;
  825. }
  826. //
  827. // Create a thread to service requests from the text setup device driver.
  828. //
  829. Status = RtlCreateUserThread(
  830. NtCurrentProcess(),
  831. NULL, // security descriptor
  832. FALSE, // not suspended
  833. 0, // zero bits
  834. 0, // stack reserve
  835. 0, // stack commit
  836. SpRequestServiceThread,
  837. NULL, // parameter
  838. &hThread,
  839. NULL // client id
  840. );
  841. if(!NT_SUCCESS(Status)) {
  842. KdPrint(("uSETUP: Unable to create thread (%lx)\n",Status));
  843. goto main3;
  844. }
  845. //
  846. // Determine the image base of this program.
  847. //
  848. RtlPcToFileHeader(main,&SetupStartInfo.UserModeImageBase);
  849. if(!SetupStartInfo.UserModeImageBase) {
  850. KdPrint(("uSETUP: Unable to get image base\n"));
  851. goto main3;
  852. }
  853. //
  854. // Invoke the setup ioctl to get setup going.
  855. // Note that this is a synchronous call -- so this routine
  856. // will not return until text setup is done.
  857. // However the second thread we started above will be servicing
  858. // requests from the text setup device driver.
  859. //
  860. SetupStartInfo.RequestReadyEvent = hEventRequestReady;
  861. SetupStartInfo.RequestServicedEvent = hEventRequestServiced;
  862. SetupStartInfo.Communication = &Communication;
  863. Status = NtDeviceIoControlFile(
  864. handle,
  865. NULL,
  866. NULL,
  867. NULL,
  868. &IoStatusBlock,
  869. IOCTL_SETUP_START,
  870. &SetupStartInfo,
  871. sizeof(SetupStartInfo),
  872. NULL,
  873. 0
  874. );
  875. if(Status != STATUS_SUCCESS) {
  876. KdPrint(("uSETUP: Warning: start setup ioctl returned %lx\n",Status));
  877. }
  878. //
  879. // Clean up.
  880. //
  881. NtClose(hThread);
  882. main3:
  883. NtClose(handle);
  884. main2:
  885. NtClose(hEventRequestServiced);
  886. main1:
  887. NtClose(hEventRequestReady);
  888. main0:
  889. NtTerminateProcess(NULL,STATUS_SUCCESS);
  890. }