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.

2216 lines
55 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. eclient.c
  5. Abstract:
  6. EFS RPC client code.
  7. Author:
  8. Robert Gu (RobertG) Aug, 1997
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <string.h>
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <ntrpcp.h> // prototypes for MIDL user functions
  18. #include <wincrypt.h>
  19. #include <efsrpc.h>
  20. #include <efsstruc.h>
  21. #include <dfsfsctl.h>
  22. #include <rpcasync.h>
  23. #define DAVHEADER 0x01
  24. //
  25. // Internal prototypes
  26. //
  27. void __RPC_FAR
  28. EfsPipeAlloc(
  29. char __RPC_FAR * State,
  30. unsigned long ReqSize,
  31. unsigned char __RPC_FAR * __RPC_FAR * Buf,
  32. unsigned long __RPC_FAR * RealSize
  33. );
  34. void __RPC_FAR
  35. EfsPipeRead (
  36. char __RPC_FAR * State,
  37. unsigned char __RPC_FAR * DataBuf,
  38. unsigned long ByteCount
  39. );
  40. void __RPC_FAR
  41. EfsPipeWrite (
  42. char __RPC_FAR * State,
  43. unsigned char __RPC_FAR * DataBuf,
  44. unsigned long ByteRequested,
  45. unsigned long *ByteFromCaller
  46. );
  47. DWORD
  48. GetFullName(
  49. LPCWSTR FileName,
  50. LPWSTR *FullName,
  51. LPWSTR *ServerName,
  52. ULONG Flags,
  53. DWORD *dwCreationDistribution,
  54. DWORD dwAttributes,
  55. PSECURITY_DESCRIPTOR pRelativeSD,
  56. BOOL bInheritHandle
  57. );
  58. DWORD
  59. EnablePrivilege(
  60. ULONG Flags,
  61. HANDLE *TokenHandle,
  62. PTOKEN_PRIVILEGES *OldPrivs
  63. );
  64. VOID
  65. RestorePrivilege(
  66. HANDLE *TokenHandle,
  67. PTOKEN_PRIVILEGES *OldPrivs
  68. );
  69. DWORD
  70. EnablePrivilege(
  71. ULONG Flags,
  72. HANDLE *TokenHandle,
  73. PTOKEN_PRIVILEGES *OldPrivs
  74. )
  75. {
  76. TOKEN_PRIVILEGES Privs;
  77. DWORD RetCode = ERROR_SUCCESS;
  78. BOOL b;
  79. DWORD ReturnLength;
  80. *TokenHandle = NULL;
  81. *OldPrivs = NULL;
  82. *OldPrivs = ( TOKEN_PRIVILEGES *) RtlAllocateHeap(
  83. RtlProcessHeap(),
  84. 0,
  85. sizeof( TOKEN_PRIVILEGES )
  86. );
  87. if ( *OldPrivs == NULL ){
  88. return ERROR_NOT_ENOUGH_MEMORY;
  89. }
  90. //
  91. // We're impersonating, use the thread token.
  92. //
  93. b = OpenThreadToken(
  94. GetCurrentThread(),
  95. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  96. FALSE,
  97. TokenHandle
  98. );
  99. if (!b) {
  100. b = OpenProcessToken(
  101. GetCurrentProcess(),
  102. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  103. TokenHandle
  104. );
  105. }
  106. if ( b ) {
  107. //
  108. // We've got a token handle
  109. //
  110. //
  111. // If we're doing a create for import, enable restore privilege,
  112. // otherwise enable backup privilege.
  113. //
  114. Privs.PrivilegeCount = 1;
  115. Privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  116. if ( !(Flags & CREATE_FOR_IMPORT) ){
  117. Privs.Privileges[0].Luid = RtlConvertLongToLuid(SE_BACKUP_PRIVILEGE);
  118. } else {
  119. Privs.Privileges[0].Luid = RtlConvertLongToLuid(SE_RESTORE_PRIVILEGE);
  120. }
  121. ReturnLength = sizeof( TOKEN_PRIVILEGES );
  122. (VOID) AdjustTokenPrivileges (
  123. *TokenHandle,
  124. FALSE,
  125. &Privs,
  126. sizeof( TOKEN_PRIVILEGES ),
  127. *OldPrivs,
  128. &ReturnLength
  129. );
  130. if ( ERROR_SUCCESS != (RetCode = GetLastError()) ) {
  131. //
  132. // Privilege adjust failed
  133. //
  134. CloseHandle( *TokenHandle );
  135. *TokenHandle = NULL;
  136. RtlFreeHeap( RtlProcessHeap(), 0, *OldPrivs );
  137. *OldPrivs = NULL;
  138. }
  139. } else {
  140. *TokenHandle = NULL;
  141. RtlFreeHeap( RtlProcessHeap(), 0, *OldPrivs );
  142. *OldPrivs = NULL;
  143. }
  144. return RetCode;
  145. }
  146. VOID
  147. RestorePrivilege(
  148. HANDLE *TokenHandle,
  149. PTOKEN_PRIVILEGES *OldPrivs
  150. )
  151. {
  152. if (!TokenHandle || !OldPrivs || !(*TokenHandle) || !(*OldPrivs)) {
  153. return;
  154. }
  155. (VOID) AdjustTokenPrivileges (
  156. *TokenHandle,
  157. FALSE,
  158. *OldPrivs,
  159. 0,
  160. NULL,
  161. NULL
  162. );
  163. CloseHandle( *TokenHandle );
  164. *TokenHandle = 0;
  165. RtlFreeHeap( RtlProcessHeap(), 0, *OldPrivs );
  166. *OldPrivs = NULL;
  167. }
  168. DWORD
  169. EfsOpenFileRawRPCClient(
  170. IN LPCWSTR FileName,
  171. IN ULONG Flags,
  172. OUT PVOID * Context
  173. )
  174. /*++
  175. Routine Description:
  176. This routine is the client side of EfsOpenFileRaw. It establishes the
  177. connection to the server. And then call the server to finish the task.
  178. Arguments:
  179. FileName -- File name of the file to be exported
  180. Flags -- Indicating if open for export or import; for directory or file.
  181. Context - Export context to be used by READ operation later. Caller should
  182. pass this back in ReadRaw().
  183. Return Value:
  184. Result of the operation.
  185. --*/
  186. {
  187. DWORD RetCode;
  188. handle_t binding_h;
  189. NTSTATUS Status;
  190. PEXIMPORT_CONTEXT_HANDLE RawContext;
  191. LPWSTR FullName;
  192. LPWSTR Server;
  193. HANDLE TokenHandle;
  194. PTOKEN_PRIVILEGES OldPrivs;
  195. *Context = NULL;
  196. RetCode = GetFullName(
  197. FileName,
  198. &FullName,
  199. &Server,
  200. Flags,
  201. NULL,
  202. 0,
  203. NULL,
  204. FALSE
  205. );
  206. if ( RetCode == ERROR_SUCCESS ){
  207. (VOID) EnablePrivilege(
  208. Flags,
  209. &TokenHandle,
  210. &OldPrivs
  211. );
  212. Status = RpcpBindRpc (
  213. Server,
  214. L"lsarpc",
  215. L"security=Impersonation static true",
  216. &binding_h
  217. );
  218. if (NT_SUCCESS(Status)){
  219. RpcTryExcept {
  220. RetCode = EfsRpcOpenFileRaw(
  221. binding_h,
  222. &RawContext,
  223. FullName,
  224. Flags
  225. );
  226. if ( ERROR_SUCCESS == RetCode ){
  227. //
  228. // Send the context handle back to the user
  229. //
  230. if (RawContext) {
  231. *Context = (PVOID) RawContext;
  232. } else {
  233. //
  234. // The server is hacked?
  235. //
  236. RetCode = ERROR_DEV_NOT_EXIST;
  237. }
  238. }
  239. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  240. RetCode = RpcExceptionCode();
  241. } RpcEndExcept;
  242. //
  243. // Free the binding handle
  244. //
  245. RpcpUnbindRpc( binding_h );
  246. } else {
  247. RetCode = RtlNtStatusToDosError( Status );
  248. }
  249. RestorePrivilege(
  250. &TokenHandle,
  251. &OldPrivs
  252. );
  253. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  254. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  255. }
  256. return RetCode;
  257. }
  258. VOID
  259. EfsCloseFileRawRPCClient(
  260. IN PVOID Context
  261. )
  262. /*++
  263. Routine Description:
  264. This routine is the client side of EfsCloseFileRaw.
  265. Arguments:
  266. Context - Export/Import context used by READ/WRITE raw data.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. PEXIMPORT_CONTEXT_HANDLE phContext;
  272. phContext = (PEXIMPORT_CONTEXT_HANDLE) Context;
  273. RpcTryExcept {
  274. EfsRpcCloseRaw(
  275. &phContext
  276. );
  277. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  278. } RpcEndExcept;
  279. }
  280. DWORD
  281. EfsReadFileRawRPCClient(
  282. IN PFE_EXPORT_FUNC ExportCallback,
  283. IN PVOID CallbackContext,
  284. IN PVOID Context
  285. )
  286. /*++
  287. Routine Description:
  288. This routine is the client side of EfsReadFileRaw.
  289. Arguments:
  290. ExportCallback - Caller provided callback function.
  291. CallbackContext - Caller's context.
  292. Context - Export context used by READ raw data.
  293. Return Value:
  294. None.
  295. */
  296. {
  297. PEXIMPORT_CONTEXT_HANDLE phContext;
  298. EFS_EXIM_STATE Pipe_State;
  299. EFS_EXIM_PIPE ExportPipe;
  300. DWORD RetCode;
  301. if ( NULL == Context){
  302. return ERROR_ACCESS_DENIED;
  303. }
  304. phContext = ( PEXIMPORT_CONTEXT_HANDLE ) Context;
  305. //
  306. // Try to allocate a reasonable size buffer. The size can be fine tuned later, but should
  307. // at least one page plus 4K. FSCTL_OUTPUT_LESS_LENGTH should be n * page size.
  308. // FSCTL_OUTPUT_MIN_LENGTH can be fine tuned later. It should be at least one page
  309. // plus 4K.
  310. //
  311. Pipe_State.BufLength = FSCTL_OUTPUT_INITIAL_LENGTH;
  312. Pipe_State.WorkBuf = NULL;
  313. while ( !Pipe_State.WorkBuf &&
  314. (Pipe_State.BufLength >= FSCTL_OUTPUT_MIN_LENGTH)
  315. ){
  316. Pipe_State.WorkBuf = RtlAllocateHeap(
  317. RtlProcessHeap(),
  318. 0,
  319. Pipe_State.BufLength
  320. );
  321. if ( !Pipe_State.WorkBuf ){
  322. //
  323. // Memory allocation failed.
  324. // Try smaller allocation.
  325. //
  326. Pipe_State.BufLength -= FSCTL_OUTPUT_LESS_LENGTH;
  327. }
  328. }
  329. if (!Pipe_State.WorkBuf){
  330. return ERROR_OUTOFMEMORY;
  331. }
  332. Pipe_State.ExImCallback = (PVOID) ExportCallback;
  333. Pipe_State.CallbackContext = CallbackContext;
  334. Pipe_State.Status = NO_ERROR;
  335. ExportPipe.state = (char *) &Pipe_State;
  336. ExportPipe.alloc = EfsPipeAlloc;
  337. ExportPipe.pull = NULL;
  338. ExportPipe.push = EfsPipeRead;
  339. RpcTryExcept{
  340. RetCode = EfsRpcReadFileRaw(
  341. phContext,
  342. &ExportPipe
  343. );
  344. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  345. if ( NO_ERROR == Pipe_State.Status ){
  346. RetCode = RpcExceptionCode();
  347. } else {
  348. RetCode = Pipe_State.Status;
  349. }
  350. } RpcEndExcept;
  351. RtlFreeHeap( RtlProcessHeap(), 0, Pipe_State.WorkBuf );
  352. return RetCode;
  353. }
  354. DWORD
  355. EfsWriteFileRawRPCClient(
  356. IN PFE_IMPORT_FUNC ImportCallback,
  357. IN PVOID CallbackContext,
  358. IN PVOID Context
  359. )
  360. /*++
  361. Routine Description:
  362. This routine is the client side of EfsWriteFileRaw.
  363. Arguments:
  364. ImportCallback - Caller provided callback function.
  365. CallbackContext - Caller's context.
  366. Context - Import context used by WRITE raw data.
  367. Return Value:
  368. None.
  369. */
  370. {
  371. PEXIMPORT_CONTEXT_HANDLE phContext;
  372. EFS_EXIM_STATE Pipe_State;
  373. EFS_EXIM_PIPE ImportPipe;
  374. DWORD RetCode;
  375. HANDLE TokenHandle;
  376. PTOKEN_PRIVILEGES OldPrivs;
  377. if ( NULL == Context){
  378. return ERROR_ACCESS_DENIED;
  379. }
  380. phContext = ( PEXIMPORT_CONTEXT_HANDLE ) Context;
  381. //
  382. // Try to allocate a reasonable size buffer. The size can be fine tuned later, but should
  383. // at least one page plus 4K. FSCTL_OUTPUT_LESS_LENGTH should be n * page size.
  384. // FSCTL_OUTPUT_MIN_LENGTH can be fine tuned later. It should be at least one page
  385. // plus 4K.
  386. //
  387. Pipe_State.BufLength = FSCTL_OUTPUT_INITIAL_LENGTH;
  388. Pipe_State.WorkBuf = RtlAllocateHeap(
  389. RtlProcessHeap(),
  390. 0,
  391. Pipe_State.BufLength
  392. );
  393. if (!Pipe_State.WorkBuf){
  394. return ERROR_OUTOFMEMORY;
  395. }
  396. Pipe_State.ExImCallback = (PVOID) ImportCallback;
  397. Pipe_State.CallbackContext = CallbackContext;
  398. Pipe_State.Status = NO_ERROR;
  399. ImportPipe.state = (char *) &Pipe_State;
  400. ImportPipe.alloc = EfsPipeAlloc;
  401. ImportPipe.pull = EfsPipeWrite;
  402. ImportPipe.push = NULL;
  403. (VOID) EnablePrivilege(
  404. CREATE_FOR_IMPORT,
  405. &TokenHandle,
  406. &OldPrivs
  407. );
  408. RpcTryExcept{
  409. RetCode = EfsRpcWriteFileRaw(
  410. phContext,
  411. &ImportPipe
  412. );
  413. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  414. if ( NO_ERROR == Pipe_State.Status ){
  415. RetCode = RpcExceptionCode();
  416. } else {
  417. RetCode = Pipe_State.Status;
  418. }
  419. } RpcEndExcept;
  420. RestorePrivilege(
  421. &TokenHandle,
  422. &OldPrivs
  423. );
  424. RtlFreeHeap( RtlProcessHeap(), 0, Pipe_State.WorkBuf );
  425. return RetCode;
  426. }
  427. void __RPC_FAR
  428. EfsPipeAlloc(
  429. char __RPC_FAR * State,
  430. unsigned long ReqSize,
  431. unsigned char __RPC_FAR * __RPC_FAR * Buf,
  432. unsigned long __RPC_FAR * RealSize
  433. )
  434. /*++
  435. Routine Description:
  436. This routine is required by the RPC pipe. It allocates the memory
  437. for the push and pull routines.
  438. Arguments:
  439. State - Pipe status.
  440. ReqSize - Required buffer sixe in bytes.
  441. Buf - Buffer pointer.
  442. RealSize - Size of allocated buffer in bytes.
  443. Return Value:
  444. None.
  445. */
  446. {
  447. PEFS_EXIM_STATE Pipe_State = (PEFS_EXIM_STATE) State;
  448. //
  449. // If error had occured, this is the chance to tell the RPC LIB to
  450. // stop the pipe work.
  451. //
  452. if ( NO_ERROR != Pipe_State->Status){
  453. *RealSize = 0;
  454. *Buf = NULL;
  455. } else {
  456. if ( ReqSize > Pipe_State->BufLength ){
  457. *RealSize = Pipe_State->BufLength;
  458. } else {
  459. *RealSize = ReqSize;
  460. }
  461. *Buf = Pipe_State->WorkBuf;
  462. }
  463. }
  464. void __RPC_FAR
  465. EfsPipeRead (
  466. char __RPC_FAR * State,
  467. unsigned char __RPC_FAR * DataBuf,
  468. unsigned long ByteCount
  469. )
  470. /*++
  471. Routine Description:
  472. This routine is called by the RPC pipe. It send the exported data to the caller.
  473. Arguments:
  474. State - Pipe status.
  475. DataBuf - Buffer pointer.
  476. ByteCount - Number of bytes to be sent out.
  477. Return Value:
  478. None.
  479. */
  480. {
  481. DWORD HResult;
  482. PEFS_EXIM_STATE Pipe_State = (PEFS_EXIM_STATE) State;
  483. PFE_EXPORT_FUNC ExportCallback;
  484. PVOID CallbackContext;
  485. ExportCallback = Pipe_State->ExImCallback;
  486. CallbackContext = Pipe_State->CallbackContext;
  487. HResult = (*ExportCallback)( DataBuf, CallbackContext, ByteCount);
  488. if ( NO_ERROR != HResult ){
  489. Pipe_State->Status = HResult;
  490. }
  491. }
  492. void __RPC_FAR
  493. EfsPipeWrite (
  494. char __RPC_FAR * State,
  495. unsigned char __RPC_FAR * DataBuf,
  496. unsigned long ByteRequested,
  497. unsigned long *ByteFromCaller
  498. )
  499. /*++
  500. Routine Description:
  501. This routine is called by the RPC pipe. It requests the imported data from the caller.
  502. Arguments:
  503. State - Pipe status.
  504. DataBuf - Buffer pointer.
  505. ByteRequested - Number of bytes requested to write to the pipe.
  506. ByteFromCaller - Number of bytes available for writing to the pipe.
  507. Return Value:
  508. None.
  509. */
  510. {
  511. DWORD HResult;
  512. PEFS_EXIM_STATE Pipe_State = (PEFS_EXIM_STATE) State;
  513. PFE_IMPORT_FUNC ImportCallback;
  514. PVOID CallbackContext;
  515. ImportCallback = Pipe_State->ExImCallback;
  516. CallbackContext = Pipe_State->CallbackContext;
  517. *ByteFromCaller = ByteRequested;
  518. HResult = (*ImportCallback)( DataBuf, CallbackContext, ByteFromCaller);
  519. if ( NO_ERROR != HResult ){
  520. Pipe_State->Status = HResult;
  521. }
  522. }
  523. DWORD
  524. EfsEncryptFileRPCClient(
  525. UNICODE_STRING *FullFileNameU
  526. )
  527. /*++
  528. Routine Description:
  529. This routine is the client side of Encryption API. It establishes the
  530. connection to the server. And then call the server to finish the task.
  531. Arguments:
  532. FullFileNameU - Supplies the name of the file to be encrypted.
  533. Return Value:
  534. ERROR_SUCCESS on success, other on failure.
  535. --*/
  536. {
  537. DWORD RetCode;
  538. handle_t binding_h;
  539. NTSTATUS Status;
  540. LPWSTR FullName;
  541. LPWSTR Server;
  542. RetCode = GetFullName(
  543. FullFileNameU->Buffer,
  544. &FullName,
  545. &Server,
  546. 0,
  547. NULL,
  548. 0,
  549. NULL,
  550. FALSE
  551. );
  552. if ( RetCode == ERROR_SUCCESS ){
  553. Status = RpcpBindRpc (
  554. Server,
  555. L"lsarpc",
  556. 0,
  557. &binding_h
  558. );
  559. if (NT_SUCCESS(Status)){
  560. RpcTryExcept {
  561. RetCode = EfsRpcEncryptFileSrv(
  562. binding_h,
  563. FullName
  564. );
  565. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  566. RetCode = RpcExceptionCode();
  567. } RpcEndExcept;
  568. //
  569. // Free the binding handle
  570. //
  571. RpcpUnbindRpc( binding_h );
  572. } else {
  573. RetCode = RtlNtStatusToDosError( Status );
  574. }
  575. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  576. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  577. }
  578. return RetCode;
  579. }
  580. DWORD
  581. EfsDecryptFileRPCClient(
  582. UNICODE_STRING *FullFileNameU,
  583. DWORD dwRecovery
  584. )
  585. /*++
  586. Routine Description:
  587. This routine is the client side of Decryption API. It establishes the
  588. connection to the server. And then call the server to finish the task.
  589. Arguments:
  590. FullFileNameU - Supplies the name of the file to be encrypted.
  591. Return Value:
  592. ERROR_SUCCESS on success, other on failure.
  593. --*/
  594. {
  595. DWORD RetCode;
  596. handle_t binding_h;
  597. NTSTATUS Status;
  598. LPWSTR FullName;
  599. LPWSTR Server;
  600. RetCode = GetFullName(
  601. FullFileNameU->Buffer,
  602. &FullName,
  603. &Server,
  604. 0,
  605. NULL,
  606. 0,
  607. NULL,
  608. FALSE
  609. );
  610. if ( RetCode == ERROR_SUCCESS ){
  611. Status = RpcpBindRpc (
  612. Server,
  613. L"lsarpc",
  614. 0,
  615. &binding_h
  616. );
  617. if (NT_SUCCESS(Status)){
  618. RpcTryExcept {
  619. RetCode = EfsRpcDecryptFileSrv(
  620. binding_h,
  621. FullName,
  622. dwRecovery
  623. );
  624. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  625. RetCode = RpcExceptionCode();
  626. } RpcEndExcept;
  627. //
  628. // Free the binding handle
  629. //
  630. RpcpUnbindRpc( binding_h );
  631. } else {
  632. RetCode = RtlNtStatusToDosError( Status );
  633. }
  634. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  635. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  636. }
  637. return RetCode;
  638. }
  639. DWORD
  640. GetFullName(
  641. LPCWSTR FileName,
  642. LPWSTR *FullName,
  643. LPWSTR *ServerName,
  644. ULONG Flags,
  645. DWORD *dwCreationDistribution,
  646. DWORD dwAttributes,
  647. PSECURITY_DESCRIPTOR pRelativeSD,
  648. BOOL bInheritHandle
  649. )
  650. /*++
  651. Routine Description:
  652. This routine will extract the server name and the file UNC name from the
  653. passed in file name.
  654. Arguments:
  655. FileName - Supplies the name of the file to be parsed.
  656. FullName - File name used on the server.
  657. ServerName - The server machine name where the file lives.
  658. Flags - Indicates if the object is a directory or a file. CREATE_FOR_DIR for directory.
  659. dwCreationDistribution - How the file should be created.
  660. dwAtrributes - The attributes for creating a new object.
  661. pRelativeSD - Security Descriptor.
  662. bInheritHandle - If the file to be created should inherit the security.
  663. Return Value:
  664. ERROR_SUCCESS on success, other on failure.
  665. --*/
  666. {
  667. HANDLE FileHdl = 0;
  668. HANDLE DriverHandle;
  669. UNICODE_STRING DfsDriverName;
  670. DWORD RetCode = ERROR_SUCCESS;
  671. LPWSTR TmpFullName;
  672. DWORD FullNameLength;
  673. DWORD FileNameLength;
  674. OBJECT_ATTRIBUTES Obja;
  675. IO_STATUS_BLOCK IoStatusBlock;
  676. UNICODE_STRING FileNtName;
  677. NTSTATUS NtStatus;
  678. BOOL b = TRUE;
  679. DWORD FileAttributes = 0;
  680. DWORD CreationDistribution = 0;
  681. DWORD CreateOptions = 0;
  682. ULONG ii, jj;
  683. BOOL GotRoot;
  684. WCHAR *PathName;
  685. UINT DriveType;
  686. PFILE_NAME_INFORMATION FileNameInfo;
  687. WCHAR WorkBuffer[MAX_PATH+4];
  688. DWORD BufSize;
  689. DWORD BufferLength;
  690. NETRESOURCEW RemotePathResource;
  691. NETRESOURCEW *pNetInfo;
  692. FileNameLength = wcslen(FileName);
  693. BufferLength = (FileNameLength + 1) <= MAX_PATH ?
  694. (MAX_PATH + 1) * sizeof(WCHAR) : (FileNameLength + 1) * sizeof (WCHAR);
  695. PathName = (WCHAR *) RtlAllocateHeap(
  696. RtlProcessHeap(),
  697. 0,
  698. BufferLength
  699. );
  700. if ( !PathName ) {
  701. return ERROR_NOT_ENOUGH_MEMORY;
  702. }
  703. GotRoot = GetVolumePathNameW(
  704. FileName,
  705. PathName,
  706. BufferLength / sizeof(WCHAR)
  707. );
  708. if (!GotRoot) {
  709. RetCode = GetLastError();
  710. RtlFreeHeap( RtlProcessHeap(), 0, PathName );
  711. return RetCode;
  712. }
  713. DriveType = GetDriveTypeW(PathName);
  714. RtlFreeHeap( RtlProcessHeap(), 0, PathName );
  715. if (DriveType == DRIVE_REMOTE){
  716. if ((Flags & CREATE_FOR_IMPORT) || (dwAttributes !=0) ) {
  717. //
  718. // Called from OpenRaw or DuplicateInfo.
  719. // Use NtCreateFile()
  720. //
  721. FileAttributes = GetFileAttributesW( FileName );
  722. if (dwAttributes) {
  723. //
  724. // From dup
  725. //
  726. if (-1 != FileAttributes) {
  727. //
  728. // File existed
  729. //
  730. if ( dwCreationDistribution && (*dwCreationDistribution == CREATE_NEW) ){
  731. return ERROR_FILE_EXISTS;
  732. }
  733. CreationDistribution = FILE_OPEN;
  734. if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  735. if ((Flags & CREATE_FOR_DIR) == 0) {
  736. return ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH;
  737. }
  738. CreateOptions |= FILE_DIRECTORY_FILE;
  739. }
  740. } else {
  741. //
  742. // Destination not existing
  743. //
  744. CreationDistribution = FILE_CREATE;
  745. if (dwCreationDistribution && (*dwCreationDistribution == CREATE_NEW) ) {
  746. *dwCreationDistribution = CREATE_ALWAYS;
  747. }
  748. if (Flags & CREATE_FOR_DIR) {
  749. CreateOptions |= FILE_DIRECTORY_FILE;
  750. dwAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  751. } else {
  752. CreateOptions |= FILE_NO_COMPRESSION;
  753. }
  754. }
  755. } else {
  756. //
  757. // From OpenRaw import
  758. //
  759. dwAttributes = FILE_ATTRIBUTE_NORMAL;
  760. CreateOptions = FILE_OPEN_FOR_BACKUP_INTENT;
  761. if (-1 == FileAttributes) {
  762. CreationDistribution = FILE_CREATE;
  763. if (Flags & CREATE_FOR_DIR) {
  764. CreateOptions |= FILE_DIRECTORY_FILE;
  765. dwAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  766. } else {
  767. CreateOptions |= FILE_NO_COMPRESSION;
  768. }
  769. } else {
  770. //
  771. // File already existing
  772. //
  773. CreationDistribution = FILE_OPEN;
  774. if (Flags & CREATE_FOR_DIR) {
  775. CreateOptions |= FILE_DIRECTORY_FILE;
  776. dwAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  777. }
  778. }
  779. }
  780. RtlInitUnicodeString(
  781. &FileNtName,
  782. NULL
  783. );
  784. b = RtlDosPathNameToNtPathName_U(
  785. FileName,
  786. &FileNtName,
  787. NULL,
  788. NULL
  789. );
  790. if (b) {
  791. dwAttributes &= ~(FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_READONLY);
  792. InitializeObjectAttributes(
  793. &Obja,
  794. &FileNtName,
  795. bInheritHandle ? OBJ_INHERIT | OBJ_CASE_INSENSITIVE : OBJ_CASE_INSENSITIVE,
  796. 0,
  797. pRelativeSD? ((PEFS_RPC_BLOB)pRelativeSD)->pbData:NULL
  798. );
  799. NtStatus = NtCreateFile(
  800. &FileHdl,
  801. FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
  802. &Obja,
  803. &IoStatusBlock,
  804. NULL,
  805. dwAttributes,
  806. 0,
  807. CreationDistribution,
  808. CreateOptions,
  809. NULL,
  810. 0
  811. );
  812. RtlFreeHeap(
  813. RtlProcessHeap(),
  814. 0,
  815. FileNtName.Buffer
  816. );
  817. if (!NT_SUCCESS(NtStatus)) {
  818. return (RtlNtStatusToDosError( NtStatus ));
  819. }
  820. } else {
  821. return ERROR_PATH_NOT_FOUND;
  822. }
  823. } else {
  824. FileHdl = CreateFileW(
  825. FileName,
  826. FILE_READ_ATTRIBUTES,
  827. FILE_SHARE_READ,
  828. NULL,
  829. OPEN_EXISTING,
  830. FILE_FLAG_BACKUP_SEMANTICS,
  831. NULL
  832. );
  833. if (INVALID_HANDLE_VALUE == FileHdl) {
  834. RetCode = GetLastError();
  835. return RetCode;
  836. }
  837. }
  838. FileNameInfo = (PFILE_NAME_INFORMATION) WorkBuffer;
  839. BufSize = sizeof (WorkBuffer);
  840. do {
  841. NtStatus = NtQueryInformationFile(
  842. FileHdl,
  843. &IoStatusBlock,
  844. FileNameInfo,
  845. BufSize,
  846. FileNameInformation
  847. );
  848. if ( NtStatus == STATUS_BUFFER_OVERFLOW || NtStatus == STATUS_BUFFER_TOO_SMALL ) {
  849. BufSize *= 2;
  850. if (FileNameInfo != (PFILE_NAME_INFORMATION)WorkBuffer) {
  851. RtlFreeHeap( RtlProcessHeap(), 0, FileNameInfo );
  852. }
  853. FileNameInfo = (PFILE_NAME_INFORMATION) RtlAllocateHeap(
  854. RtlProcessHeap(),
  855. 0,
  856. BufSize
  857. );
  858. if (!FileNameInfo) {
  859. CloseHandle(FileHdl);
  860. return ERROR_NOT_ENOUGH_MEMORY;
  861. }
  862. }
  863. } while (NtStatus == STATUS_BUFFER_OVERFLOW || NtStatus == STATUS_BUFFER_TOO_SMALL);
  864. CloseHandle(FileHdl);
  865. if (!NT_SUCCESS(NtStatus)) {
  866. if (FileNameInfo != (PFILE_NAME_INFORMATION)WorkBuffer) {
  867. RtlFreeHeap( RtlProcessHeap(), 0, FileNameInfo );
  868. }
  869. return RtlNtStatusToDosError(NtStatus);
  870. } else {
  871. ASSERT((FileNameInfo->FileName)[ 0 ] == L'\\');
  872. }
  873. //
  874. // We got the UNC name
  875. //
  876. *FullName = RtlAllocateHeap(
  877. RtlProcessHeap(),
  878. 0,
  879. FileNameInfo->FileNameLength+2*sizeof (WCHAR)
  880. );
  881. *ServerName = RtlAllocateHeap(
  882. RtlProcessHeap(),
  883. 0,
  884. ( MAX_PATH + 1) * sizeof (WCHAR)
  885. );
  886. if ( (NULL == *FullName) || (NULL == *ServerName) ){
  887. if ( *FullName ){
  888. RtlFreeHeap( RtlProcessHeap(), 0, *FullName );
  889. *FullName = NULL;
  890. }
  891. if ( *ServerName ){
  892. RtlFreeHeap( RtlProcessHeap(), 0, *ServerName );
  893. *ServerName = NULL;
  894. }
  895. if (FileNameInfo != (PFILE_NAME_INFORMATION)WorkBuffer) {
  896. RtlFreeHeap( RtlProcessHeap(), 0, FileNameInfo );
  897. }
  898. return ERROR_NOT_ENOUGH_MEMORY;
  899. }
  900. } else {
  901. //
  902. // The path is local
  903. //
  904. *FullName = RtlAllocateHeap(
  905. RtlProcessHeap(),
  906. 0,
  907. (FileNameLength + 1) * sizeof (WCHAR)
  908. );
  909. *ServerName = RtlAllocateHeap(
  910. RtlProcessHeap(),
  911. 0,
  912. 8 * sizeof (WCHAR)
  913. );
  914. //
  915. // Use . for local case.
  916. //
  917. if ( (NULL == *FullName) || (NULL == *ServerName) ){
  918. if ( *FullName ){
  919. RtlFreeHeap( RtlProcessHeap(), 0, *FullName );
  920. *FullName = NULL;
  921. }
  922. if ( *ServerName ){
  923. RtlFreeHeap( RtlProcessHeap(), 0, *ServerName );
  924. *ServerName = NULL;
  925. }
  926. return ERROR_NOT_ENOUGH_MEMORY;
  927. }
  928. wcscpy ( *ServerName, L".");
  929. wcscpy ( *FullName, FileName);
  930. return ERROR_SUCCESS;
  931. }
  932. //
  933. // Let's get the UNC server and path name
  934. //
  935. FullNameLength = FileNameInfo->FileNameLength;
  936. ii = jj = 0;
  937. while ( (FileNameInfo->FileName)[ jj ] == L'\\' ) {
  938. jj ++;
  939. }
  940. while ( jj < FullNameLength/sizeof(WCHAR) && ((FileNameInfo->FileName)[ jj ] != L'\\') ){
  941. (*ServerName)[ii++] = (FileNameInfo->FileName)[ jj++ ];
  942. }
  943. (*ServerName)[ii] = 0;
  944. if (FileNameInfo->FileName[0] == L'\\' && FileNameInfo->FileName[1] != L'\\' ) {
  945. //
  946. // NtQueryInformationFile returns \server\share\...
  947. //
  948. (*FullName)[0] = L'\\';
  949. wcsncpy( &((*FullName)[1]), &FileNameInfo->FileName[0], FullNameLength/sizeof(WCHAR) );
  950. (*FullName)[1+FullNameLength/sizeof(WCHAR)] = 0;
  951. } else{
  952. //
  953. // Just in case we get \\server\share\...
  954. //
  955. wcsncpy( &((*FullName)[0]), &FileNameInfo->FileName[0], FullNameLength/sizeof(WCHAR) );
  956. (*FullName)[FullNameLength/sizeof(WCHAR)] = 0;
  957. }
  958. //
  959. // WorkBuffer is freed here. It can be reused from here.
  960. //
  961. if (FileNameInfo != (PFILE_NAME_INFORMATION)WorkBuffer) {
  962. RtlFreeHeap( RtlProcessHeap(), 0, FileNameInfo );
  963. }
  964. //
  965. // This is a workaround to test DFS path.
  966. // Let's see if the path could be a DFS path or not
  967. //
  968. RtlInitUnicodeString(&DfsDriverName, DFS_DRIVER_NAME);
  969. InitializeObjectAttributes(
  970. &Obja,
  971. &DfsDriverName,
  972. OBJ_CASE_INSENSITIVE,
  973. NULL,
  974. NULL
  975. );
  976. NtStatus = NtCreateFile(
  977. &DriverHandle,
  978. SYNCHRONIZE,
  979. &Obja,
  980. &IoStatusBlock,
  981. NULL,
  982. FILE_ATTRIBUTE_NORMAL,
  983. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  984. FILE_OPEN_IF,
  985. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  986. NULL,
  987. 0
  988. );
  989. if ( NT_SUCCESS( NtStatus ) ){
  990. //
  991. // DfsDriver opened successfully
  992. //
  993. TmpFullName = RtlAllocateHeap(
  994. RtlProcessHeap(),
  995. 0,
  996. FullNameLength + 2*sizeof (WCHAR)
  997. );
  998. if (TmpFullName) {
  999. NtStatus = NtFsControlFile(
  1000. DriverHandle,
  1001. NULL,
  1002. NULL,
  1003. NULL,
  1004. &IoStatusBlock,
  1005. FSCTL_DFS_GET_SERVER_NAME,
  1006. *FullName,
  1007. FullNameLength + 2*sizeof (WCHAR) ,
  1008. TmpFullName,
  1009. FullNameLength + 2* sizeof (WCHAR)
  1010. );
  1011. if ( STATUS_BUFFER_OVERFLOW == NtStatus ){
  1012. ULONG OldFullNameLength = FullNameLength;
  1013. FullNameLength = *(ULONG *)TmpFullName + sizeof (WCHAR);
  1014. RtlFreeHeap( RtlProcessHeap(), 0, TmpFullName );
  1015. TmpFullName = RtlAllocateHeap(
  1016. RtlProcessHeap(),
  1017. 0,
  1018. FullNameLength
  1019. );
  1020. if (NULL == TmpFullName){
  1021. //
  1022. // Remember this is just a workaround.
  1023. // Let's assume this is not DFS path. If it is, it will fail later anyway.
  1024. //
  1025. NtClose( DriverHandle );
  1026. DriverHandle = NULL;
  1027. } else {
  1028. NtStatus = NtFsControlFile(
  1029. DriverHandle,
  1030. NULL,
  1031. NULL,
  1032. NULL,
  1033. &IoStatusBlock,
  1034. FSCTL_DFS_GET_SERVER_NAME,
  1035. *FullName,
  1036. OldFullNameLength + 2*sizeof (WCHAR) ,
  1037. TmpFullName,
  1038. FullNameLength
  1039. );
  1040. }
  1041. }
  1042. if (TmpFullName) {
  1043. if ( NT_SUCCESS( NtStatus ) ){
  1044. //
  1045. // The name is a DFS file name. Use the name in the TmpFullName
  1046. //
  1047. RtlFreeHeap( RtlProcessHeap(), 0, *FullName );
  1048. *FullName = TmpFullName;
  1049. //
  1050. // Reset the server name
  1051. //
  1052. ii = jj = 0;
  1053. while ( (*FullName)[ jj ] == L'\\' ) {
  1054. jj ++;
  1055. }
  1056. while ( ((*FullName)[ jj ]) && ((*FullName)[ jj ] != L'\\') ){
  1057. (*ServerName)[ii++] = (*FullName)[ jj++ ];
  1058. }
  1059. (*ServerName)[ii] = 0;
  1060. } else {
  1061. //
  1062. // Not a DFS name
  1063. //
  1064. RtlFreeHeap( RtlProcessHeap(), 0, TmpFullName );
  1065. }
  1066. }
  1067. }
  1068. if (DriverHandle) {
  1069. NtClose( DriverHandle );
  1070. }
  1071. }
  1072. //
  1073. // Let's see if the path is a WEB DAV path or not
  1074. //
  1075. BufSize = 1024; //If not enough, we will allocate more
  1076. pNetInfo = (NETRESOURCEW *) RtlAllocateHeap(
  1077. RtlProcessHeap(),
  1078. 0,
  1079. BufSize
  1080. );
  1081. //
  1082. // If we can't decide if the path is WEBDAV path, we assume not.
  1083. // Error will be returned later if it turns out to be a WEBDAV Share.
  1084. //
  1085. if (pNetInfo) {
  1086. LPWSTR lpSysName;
  1087. RemotePathResource.dwScope = RESOURCE_CONNECTED;
  1088. RemotePathResource.dwType = RESOURCETYPE_DISK;
  1089. RemotePathResource.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
  1090. RemotePathResource.dwUsage = 0;
  1091. RemotePathResource.lpLocalName = NULL;
  1092. RemotePathResource.lpRemoteName = *FullName;
  1093. RemotePathResource.lpComment = NULL;
  1094. RemotePathResource.lpProvider = NULL;
  1095. RetCode = WNetGetResourceInformationW (
  1096. &RemotePathResource, // network resource
  1097. (LPVOID) pNetInfo, // information buffer
  1098. (LPDWORD) &BufSize, // size of information buffer
  1099. &lpSysName
  1100. );
  1101. if (RetCode == ERROR_MORE_DATA) {
  1102. //
  1103. // This is not likely to happen
  1104. //
  1105. RtlFreeHeap( RtlProcessHeap(), 0, pNetInfo );
  1106. pNetInfo = (NETRESOURCEW *) RtlAllocateHeap(
  1107. RtlProcessHeap(),
  1108. 0,
  1109. BufSize
  1110. );
  1111. if (pNetInfo) {
  1112. RetCode = WNetGetResourceInformationW (
  1113. &RemotePathResource, // network resource
  1114. (LPVOID) pNetInfo, // information buffer
  1115. (LPDWORD) &BufSize, // size of information buffer
  1116. &lpSysName
  1117. );
  1118. } else {
  1119. RetCode = ERROR_NOT_ENOUGH_MEMORY;
  1120. }
  1121. }
  1122. if (ERROR_SUCCESS == RetCode) {
  1123. WCHAR *WebDavPath;
  1124. DWORD DavNameLength;
  1125. WebDavPath = WorkBuffer;
  1126. DavNameLength = sizeof(WorkBuffer) / sizeof (WCHAR);
  1127. RetCode = WNetGetProviderNameW(
  1128. WNNC_NET_DAV,
  1129. WebDavPath,
  1130. &DavNameLength
  1131. );
  1132. if (ERROR_SUCCESS != RetCode) {
  1133. if ( ERROR_MORE_DATA == RetCode) {
  1134. WebDavPath = RtlAllocateHeap(
  1135. RtlProcessHeap(),
  1136. 0,
  1137. DavNameLength * sizeof (WCHAR)
  1138. );
  1139. if (WebDavPath) {
  1140. RetCode = WNetGetProviderNameW(
  1141. WNNC_NET_DAV,
  1142. WebDavPath,
  1143. &DavNameLength
  1144. );
  1145. } else {
  1146. RetCode = ERROR_NOT_ENOUGH_MEMORY;
  1147. }
  1148. }
  1149. }
  1150. //
  1151. // Check to see if the provider is WEBDAV
  1152. //
  1153. if ((ERROR_SUCCESS == RetCode) && !wcscmp(WebDavPath, pNetInfo->lpProvider)){
  1154. //
  1155. // This is the WEBDAV. Let's redo the name.
  1156. //
  1157. RtlFreeHeap( RtlProcessHeap(), 0, pNetInfo );
  1158. RtlFreeHeap( RtlProcessHeap(), 0, *FullName );
  1159. if (WebDavPath && (WebDavPath != WorkBuffer)) {
  1160. RtlFreeHeap( RtlProcessHeap(), 0, WebDavPath );
  1161. }
  1162. *FullName = RtlAllocateHeap(
  1163. RtlProcessHeap(),
  1164. 0,
  1165. (FileNameLength + 3) * sizeof (WCHAR)
  1166. );
  1167. //
  1168. // Use . for local case.
  1169. //
  1170. if (*FullName) {
  1171. wcscpy ( *ServerName, L".");
  1172. (*FullName)[0] = DAVHEADER;
  1173. (*FullName)[1] = 0;
  1174. wcscat ( *FullName, FileName);
  1175. return ERROR_SUCCESS;
  1176. } else {
  1177. //
  1178. // Out of memory
  1179. //
  1180. RtlFreeHeap( RtlProcessHeap(), 0, *ServerName );
  1181. *ServerName = NULL;
  1182. return ERROR_NOT_ENOUGH_MEMORY;
  1183. }
  1184. }
  1185. if (WebDavPath && (WebDavPath != WorkBuffer)) {
  1186. RtlFreeHeap( RtlProcessHeap(), 0, WebDavPath );
  1187. }
  1188. }
  1189. if (pNetInfo) {
  1190. RtlFreeHeap( RtlProcessHeap(), 0, pNetInfo );
  1191. }
  1192. }
  1193. return ERROR_SUCCESS;
  1194. }
  1195. //
  1196. // Beta 2 API
  1197. //
  1198. DWORD
  1199. EfsAddUsersRPCClient(
  1200. IN LPCWSTR lpFileName,
  1201. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. description-of-function.
  1206. Arguments:
  1207. argument-name - Supplies | Returns description of argument.
  1208. .
  1209. .
  1210. Return Value:
  1211. return-value - Description of conditions needed to return value. - or -
  1212. None.
  1213. --*/
  1214. {
  1215. DWORD RetCode;
  1216. handle_t binding_h;
  1217. NTSTATUS Status;
  1218. LPWSTR FullName;
  1219. LPWSTR Server;
  1220. RetCode = GetFullName(
  1221. lpFileName,
  1222. &FullName,
  1223. &Server,
  1224. 0,
  1225. NULL,
  1226. 0,
  1227. NULL,
  1228. FALSE
  1229. );
  1230. if ( RetCode == ERROR_SUCCESS ) {
  1231. Status = RpcpBindRpc (
  1232. Server,
  1233. L"lsarpc",
  1234. 0,
  1235. &binding_h
  1236. );
  1237. if (NT_SUCCESS(Status)){
  1238. RpcTryExcept {
  1239. RetCode = EfsRpcAddUsersToFile(
  1240. binding_h,
  1241. FullName,
  1242. pEncryptionCertificates
  1243. );
  1244. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1245. RetCode = RpcExceptionCode();
  1246. } RpcEndExcept;
  1247. //
  1248. // Free the binding handle
  1249. //
  1250. RpcpUnbindRpc( binding_h );
  1251. } else {
  1252. RetCode = RtlNtStatusToDosError( Status );
  1253. }
  1254. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  1255. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  1256. }
  1257. return RetCode;
  1258. }
  1259. DWORD
  1260. EfsRemoveUsersRPCClient(
  1261. IN LPCWSTR lpFileName,
  1262. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  1263. )
  1264. /*++
  1265. Routine Description:
  1266. description-of-function.
  1267. Arguments:
  1268. argument-name - Supplies | Returns description of argument.
  1269. .
  1270. .
  1271. Return Value:
  1272. return-value - Description of conditions needed to return value. - or -
  1273. None.
  1274. --*/
  1275. {
  1276. DWORD RetCode;
  1277. handle_t binding_h;
  1278. NTSTATUS Status;
  1279. LPWSTR FullName;
  1280. LPWSTR Server;
  1281. RetCode = GetFullName(
  1282. lpFileName,
  1283. &FullName,
  1284. &Server,
  1285. 0,
  1286. NULL,
  1287. 0,
  1288. NULL,
  1289. FALSE
  1290. );
  1291. if ( RetCode == ERROR_SUCCESS ){
  1292. Status = RpcpBindRpc (
  1293. Server,
  1294. L"lsarpc",
  1295. 0,
  1296. &binding_h
  1297. );
  1298. if (NT_SUCCESS(Status)){
  1299. RpcTryExcept {
  1300. RetCode = EfsRpcRemoveUsersFromFile(
  1301. binding_h,
  1302. FullName,
  1303. pHashes
  1304. );
  1305. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1306. RetCode = RpcExceptionCode();
  1307. } RpcEndExcept;
  1308. //
  1309. // Free the binding handle
  1310. //
  1311. RpcpUnbindRpc( binding_h );
  1312. } else {
  1313. RetCode = RtlNtStatusToDosError( Status );
  1314. }
  1315. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  1316. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  1317. }
  1318. return RetCode;
  1319. }
  1320. DWORD
  1321. EfsQueryRecoveryAgentsRPCClient(
  1322. IN LPCWSTR lpFileName,
  1323. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  1324. )
  1325. /*++
  1326. Routine Description:
  1327. description-of-function.
  1328. Arguments:
  1329. argument-name - Supplies | Returns description of argument.
  1330. .
  1331. .
  1332. Return Value:
  1333. return-value - Description of conditions needed to return value. - or -
  1334. None.
  1335. --*/
  1336. {
  1337. DWORD RetCode;
  1338. handle_t binding_h;
  1339. NTSTATUS Status;
  1340. LPWSTR FullName;
  1341. LPWSTR Server;
  1342. //
  1343. // Clear out this parameter, or RPC will choke on the server
  1344. // side.
  1345. //
  1346. *pRecoveryAgents = NULL;
  1347. RetCode = GetFullName(
  1348. lpFileName,
  1349. &FullName,
  1350. &Server,
  1351. 0,
  1352. NULL,
  1353. 0,
  1354. NULL,
  1355. FALSE
  1356. );
  1357. if ( RetCode == ERROR_SUCCESS ){
  1358. Status = RpcpBindRpc (
  1359. Server,
  1360. L"lsarpc",
  1361. 0,
  1362. &binding_h
  1363. );
  1364. if (NT_SUCCESS(Status)){
  1365. RpcTryExcept {
  1366. RetCode = EfsRpcQueryRecoveryAgents(
  1367. binding_h,
  1368. FullName,
  1369. pRecoveryAgents
  1370. );
  1371. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1372. RetCode = RpcExceptionCode();
  1373. } RpcEndExcept;
  1374. //
  1375. // Free the binding handle
  1376. //
  1377. RpcpUnbindRpc( binding_h );
  1378. } else {
  1379. RetCode = RtlNtStatusToDosError( Status );
  1380. }
  1381. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  1382. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  1383. }
  1384. return RetCode;
  1385. }
  1386. DWORD
  1387. EfsQueryUsersRPCClient(
  1388. IN LPCWSTR lpFileName,
  1389. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. description-of-function.
  1394. Arguments:
  1395. argument-name - Supplies | Returns description of argument.
  1396. .
  1397. .
  1398. Return Value:
  1399. return-value - Description of conditions needed to return value. - or -
  1400. None.
  1401. --*/
  1402. {
  1403. DWORD RetCode;
  1404. handle_t binding_h;
  1405. NTSTATUS Status;
  1406. LPWSTR FullName;
  1407. LPWSTR Server;
  1408. //
  1409. // Clear out this parameter, or RPC will choke on the server
  1410. // side.
  1411. //
  1412. *pUsers = NULL;
  1413. RetCode = GetFullName(
  1414. lpFileName,
  1415. &FullName,
  1416. &Server,
  1417. 0,
  1418. NULL,
  1419. 0,
  1420. NULL,
  1421. FALSE
  1422. );
  1423. if ( RetCode == ERROR_SUCCESS ){
  1424. Status = RpcpBindRpc (
  1425. Server,
  1426. L"lsarpc",
  1427. 0,
  1428. &binding_h
  1429. );
  1430. if (NT_SUCCESS(Status)){
  1431. RpcTryExcept {
  1432. RetCode = EfsRpcQueryUsersOnFile(
  1433. binding_h,
  1434. FullName,
  1435. pUsers
  1436. );
  1437. if ((ERROR_SUCCESS == RetCode) && !(*pUsers)) {
  1438. //
  1439. // The server is hacked? There should always be one user on the file.
  1440. //
  1441. RetCode = ERROR_DEV_NOT_EXIST;
  1442. }
  1443. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1444. RetCode = RpcExceptionCode();
  1445. } RpcEndExcept;
  1446. //
  1447. // Free the binding handle
  1448. //
  1449. RpcpUnbindRpc( binding_h );
  1450. } else {
  1451. RetCode = RtlNtStatusToDosError( Status );
  1452. }
  1453. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  1454. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  1455. }
  1456. return RetCode;
  1457. }
  1458. DWORD
  1459. EfsSetEncryptionKeyRPCClient(
  1460. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  1461. )
  1462. {
  1463. DWORD RetCode;
  1464. handle_t binding_h;
  1465. NTSTATUS Status;
  1466. WCHAR ServerName[3 ];
  1467. wcscpy(&ServerName[0], L".");
  1468. Status = RpcpBindRpc (
  1469. &ServerName[0],
  1470. L"lsarpc",
  1471. 0,
  1472. &binding_h
  1473. );
  1474. if (NT_SUCCESS(Status)){
  1475. RpcTryExcept {
  1476. RetCode = EfsRpcSetFileEncryptionKey(
  1477. binding_h,
  1478. pEncryptionCertificate
  1479. );
  1480. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1481. RetCode = RpcExceptionCode();
  1482. } RpcEndExcept;
  1483. //
  1484. // Free the binding handle
  1485. //
  1486. RpcpUnbindRpc( binding_h );
  1487. } else {
  1488. RetCode = RtlNtStatusToDosError( Status );
  1489. }
  1490. return RetCode;
  1491. }
  1492. DWORD
  1493. EfsDuplicateEncryptionInfoRPCClient(
  1494. IN LPCWSTR lpSrcFileName,
  1495. IN LPCWSTR lpDestFileName,
  1496. IN DWORD dwCreationDistribution,
  1497. IN DWORD dwAttributes,
  1498. IN PEFS_RPC_BLOB pRelativeSD,
  1499. IN BOOL bInheritHandle
  1500. )
  1501. {
  1502. DWORD RetCode;
  1503. handle_t binding_h;
  1504. NTSTATUS Status;
  1505. LPWSTR SrcServer;
  1506. LPWSTR DestServer;
  1507. LPWSTR FullSrcName;
  1508. LPWSTR FullDestName;
  1509. DWORD FileAttribute;
  1510. DWORD MyCreationDistribution = dwCreationDistribution;
  1511. DWORD Flags = 0;
  1512. RetCode = GetFullName(
  1513. lpSrcFileName,
  1514. &FullSrcName,
  1515. &SrcServer,
  1516. 0,
  1517. NULL,
  1518. 0,
  1519. NULL,
  1520. FALSE
  1521. );
  1522. if (RetCode == ERROR_SUCCESS) {
  1523. FileAttribute = GetFileAttributesW(lpSrcFileName);
  1524. if (-1 != FileAttribute) {
  1525. if (FileAttribute & FILE_ATTRIBUTE_DIRECTORY) {
  1526. Flags = CREATE_FOR_DIR;
  1527. }
  1528. }
  1529. if (dwAttributes == 0) {
  1530. FileAttribute = FILE_ATTRIBUTE_NORMAL;
  1531. } else {
  1532. FileAttribute = dwAttributes;
  1533. }
  1534. RetCode = GetFullName(
  1535. lpDestFileName,
  1536. &FullDestName,
  1537. &DestServer,
  1538. Flags,
  1539. &MyCreationDistribution,
  1540. FileAttribute,
  1541. pRelativeSD,
  1542. bInheritHandle
  1543. );
  1544. if (RetCode == ERROR_SUCCESS) {
  1545. BOOL SamePC = TRUE;
  1546. //
  1547. // Only do this if they're on the same server.
  1548. //
  1549. SamePC = (_wcsicmp( SrcServer, DestServer ) == 0);
  1550. if (!SamePC) {
  1551. //
  1552. // Check loopback case.
  1553. //
  1554. if ((wcscmp( SrcServer, L".") == 0) || (wcscmp( DestServer, L".") == 0)){
  1555. WCHAR MyComputerName[( MAX_COMPUTERNAME_LENGTH + 1) * sizeof (WCHAR)];
  1556. DWORD WorkBufferLength = MAX_COMPUTERNAME_LENGTH + 1;
  1557. BOOL b;
  1558. b = GetComputerNameW(
  1559. MyComputerName,
  1560. &WorkBufferLength
  1561. );
  1562. if (b) {
  1563. if (wcscmp( SrcServer, L".") == 0) {
  1564. SamePC = (_wcsicmp( MyComputerName, DestServer ) == 0);
  1565. } else {
  1566. SamePC = (_wcsicmp( MyComputerName, SrcServer ) == 0);
  1567. }
  1568. }
  1569. }
  1570. }
  1571. if (SamePC) {
  1572. Status = RpcpBindRpc (
  1573. SrcServer,
  1574. L"lsarpc",
  1575. 0,
  1576. &binding_h
  1577. );
  1578. if (NT_SUCCESS(Status)){
  1579. RpcTryExcept {
  1580. RetCode = EfsRpcDuplicateEncryptionInfoFile(
  1581. binding_h,
  1582. FullSrcName,
  1583. FullDestName,
  1584. MyCreationDistribution,
  1585. dwAttributes,
  1586. pRelativeSD,
  1587. bInheritHandle
  1588. );
  1589. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1590. RetCode = RpcExceptionCode();
  1591. } RpcEndExcept;
  1592. //
  1593. // Free the binding handle
  1594. //
  1595. RpcpUnbindRpc( binding_h );
  1596. } else {
  1597. RetCode = RtlNtStatusToDosError( Status );
  1598. }
  1599. } else {
  1600. RetCode = ERROR_INVALID_PARAMETER;
  1601. }
  1602. RtlFreeHeap( RtlProcessHeap(), 0, FullDestName );
  1603. RtlFreeHeap( RtlProcessHeap(), 0, DestServer );
  1604. }
  1605. if ((RetCode != ERROR_SUCCESS) && (RetCode != ERROR_FILE_EXISTS) && (CREATE_NEW == dwCreationDistribution)) {
  1606. //
  1607. // Let's delete the file. This is the best effort. No return code is to be
  1608. // checked.
  1609. //
  1610. DeleteFileW(lpDestFileName);
  1611. }
  1612. RtlFreeHeap( RtlProcessHeap(), 0, FullSrcName );
  1613. RtlFreeHeap( RtlProcessHeap(), 0, SrcServer );
  1614. }
  1615. return RetCode;
  1616. }
  1617. DWORD
  1618. EfsFileKeyInfoRPCClient(
  1619. IN LPCWSTR lpFileName,
  1620. IN DWORD InfoClass,
  1621. OUT PEFS_RPC_BLOB *KeyInfo
  1622. )
  1623. {
  1624. DWORD RetCode;
  1625. handle_t binding_h;
  1626. NTSTATUS Status;
  1627. LPWSTR FullName;
  1628. LPWSTR Server;
  1629. //
  1630. // Clear out this parameter, or RPC will choke on the server
  1631. // side.
  1632. //
  1633. if (KeyInfo) {
  1634. *KeyInfo = NULL;
  1635. }
  1636. RetCode = GetFullName(
  1637. lpFileName,
  1638. &FullName,
  1639. &Server,
  1640. 0,
  1641. NULL,
  1642. 0,
  1643. NULL,
  1644. FALSE
  1645. );
  1646. if ( RetCode == ERROR_SUCCESS ){
  1647. Status = RpcpBindRpc (
  1648. Server,
  1649. L"lsarpc",
  1650. 0,
  1651. &binding_h
  1652. );
  1653. if (NT_SUCCESS(Status)){
  1654. RpcTryExcept {
  1655. RetCode = EfsRpcFileKeyInfo(
  1656. binding_h,
  1657. FullName,
  1658. InfoClass,
  1659. KeyInfo
  1660. );
  1661. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1662. RetCode = RpcExceptionCode();
  1663. } RpcEndExcept;
  1664. //
  1665. // Free the binding handle
  1666. //
  1667. RpcpUnbindRpc( binding_h );
  1668. } else {
  1669. RetCode = RtlNtStatusToDosError( Status );
  1670. }
  1671. RtlFreeHeap( RtlProcessHeap(), 0, FullName );
  1672. RtlFreeHeap( RtlProcessHeap(), 0, Server );
  1673. }
  1674. return RetCode;
  1675. }