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.

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