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.

1934 lines
49 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. feclient.cpp
  5. Abstract:
  6. This module implements stubs to call EFS Api
  7. Author:
  8. Robert Reichel (RobertRe)
  9. Robert Gu (RobertG)
  10. Revision History:
  11. --*/
  12. //
  13. // Turn off lean and mean so we get wincrypt.h and winefs.h included
  14. //
  15. #undef WIN32_LEAN_AND_MEAN
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <feclient.h>
  21. #include <efsstruc.h>
  22. #include <userenv.h>
  23. #include <overflow.h>
  24. //
  25. // Constants used in export\import file
  26. //
  27. #define INISECTIONNAME L"Encryption"
  28. #define INIKEYNAME L"Disable"
  29. #define INIFILENAME L"\\Desktop.ini"
  30. #define TRUSTEDPEOPLE L"TrustedPeople"
  31. #define BASIC_KEY_INFO 1
  32. #define UPDATE_KEY_USED 0x100
  33. #if DBG
  34. ULONG DebugLevel = 0;
  35. #endif
  36. LPSTR EfsOidlpstr = szOID_KP_EFS;
  37. //
  38. // External prototypes
  39. //
  40. extern "C" {
  41. DWORD
  42. EfsReadFileRawRPCClient(
  43. IN PFE_EXPORT_FUNC ExportCallback,
  44. IN PVOID CallbackContext,
  45. IN PVOID Context
  46. );
  47. DWORD
  48. EfsWriteFileRawRPCClient(
  49. IN PFE_IMPORT_FUNC ImportCallback,
  50. IN PVOID CallbackContext,
  51. IN PVOID Context
  52. );
  53. DWORD
  54. EfsAddUsersRPCClient(
  55. IN LPCWSTR lpFileName,
  56. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  57. );
  58. DWORD
  59. EfsRemoveUsersRPCClient(
  60. IN LPCWSTR lpFileName,
  61. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  62. );
  63. DWORD
  64. EfsQueryRecoveryAgentsRPCClient(
  65. IN LPCWSTR lpFileName,
  66. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  67. );
  68. DWORD
  69. EfsQueryUsersRPCClient(
  70. IN LPCWSTR lpFileName,
  71. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  72. );
  73. DWORD
  74. EfsSetEncryptionKeyRPCClient(
  75. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  76. );
  77. DWORD
  78. EfsDuplicateEncryptionInfoRPCClient(
  79. IN LPCWSTR lpSrcFileName,
  80. IN LPCWSTR lpDestFileName,
  81. IN DWORD dwCreationDistribution,
  82. IN DWORD dwAttributes,
  83. IN PEFS_RPC_BLOB pRelativeSD,
  84. IN BOOL bInheritHandle
  85. );
  86. DWORD
  87. EfsFileKeyInfoRPCClient(
  88. IN LPCWSTR lpFileName,
  89. IN DWORD InfoClass,
  90. OUT PEFS_RPC_BLOB *KeyInfo
  91. );
  92. }
  93. //
  94. // Exported function prototypes
  95. //
  96. DWORD
  97. EfsClientEncryptFile(
  98. IN LPCWSTR FileName
  99. );
  100. DWORD
  101. EfsClientDecryptFile(
  102. IN LPCWSTR FileName,
  103. IN DWORD Recovery
  104. );
  105. BOOL
  106. EfsClientFileEncryptionStatus(
  107. IN LPCWSTR FileName,
  108. OUT LPDWORD lpStatus
  109. );
  110. DWORD
  111. EfsClientOpenFileRaw(
  112. IN LPCWSTR lpFileName,
  113. IN ULONG Flags,
  114. OUT PVOID * Context
  115. );
  116. DWORD
  117. EfsClientReadFileRaw(
  118. IN PFE_EXPORT_FUNC ExportCallback,
  119. IN PVOID CallbackContext,
  120. IN PVOID Context
  121. );
  122. DWORD
  123. EfsClientWriteFileRaw(
  124. IN PFE_IMPORT_FUNC ImportCallback,
  125. IN PVOID CallbackContext,
  126. IN PVOID Context
  127. );
  128. VOID
  129. EfsClientCloseFileRaw(
  130. IN PVOID Context
  131. );
  132. DWORD
  133. EfsClientAddUsers(
  134. IN LPCTSTR lpFileName,
  135. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  136. );
  137. DWORD
  138. EfsClientRemoveUsers(
  139. IN LPCTSTR lpFileName,
  140. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  141. );
  142. DWORD
  143. EfsClientQueryRecoveryAgents(
  144. IN LPCTSTR lpFileName,
  145. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  146. );
  147. DWORD
  148. EfsClientQueryUsers(
  149. IN LPCTSTR lpFileName,
  150. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  151. );
  152. DWORD
  153. EfsClientSetEncryptionKey(
  154. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  155. );
  156. VOID
  157. EfsClientFreeHashList(
  158. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashList
  159. );
  160. DWORD
  161. EfsClientDuplicateEncryptionInfo(
  162. IN LPCWSTR lpSrcFile,
  163. IN LPCWSTR lpDestFile,
  164. IN DWORD dwCreationDistribution,
  165. IN DWORD dwAttributes,
  166. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  167. );
  168. BOOL
  169. EfsClientEncryptionDisable(
  170. IN LPCWSTR DirPath,
  171. IN BOOL Disable
  172. );
  173. DWORD
  174. EfsClientFileKeyInfo(
  175. IN LPCWSTR lpFileName,
  176. IN DWORD InfoClass,
  177. OUT PEFS_RPC_BLOB *KeyInfo
  178. );
  179. VOID
  180. EfsClientFreeKeyInfo(
  181. IN PEFS_RPC_BLOB pKeyInfo
  182. );
  183. FE_CLIENT_DISPATCH_TABLE DispatchTable = { EfsClientEncryptFile,
  184. EfsClientDecryptFile,
  185. EfsClientFileEncryptionStatus,
  186. EfsClientOpenFileRaw,
  187. EfsClientReadFileRaw,
  188. EfsClientWriteFileRaw,
  189. EfsClientCloseFileRaw,
  190. EfsClientAddUsers,
  191. EfsClientRemoveUsers,
  192. EfsClientQueryRecoveryAgents,
  193. EfsClientQueryUsers,
  194. EfsClientSetEncryptionKey,
  195. EfsClientFreeHashList,
  196. EfsClientDuplicateEncryptionInfo,
  197. EfsClientEncryptionDisable,
  198. EfsClientFileKeyInfo,
  199. EfsClientFreeKeyInfo
  200. };
  201. FE_CLIENT_INFO ClientInfo = {
  202. FE_REVISION_1_0,
  203. &DispatchTable
  204. };
  205. //
  206. // Internal function prototypes
  207. //
  208. BOOL
  209. TranslateFileName(
  210. IN LPCWSTR FileName,
  211. OUT PUNICODE_STRING FullFileNameU
  212. );
  213. BOOL
  214. RemoteFile(
  215. IN LPCWSTR FileName
  216. );
  217. extern "C"
  218. BOOL
  219. EfsClientInit(
  220. IN PVOID hmod,
  221. IN ULONG Reason,
  222. IN PCONTEXT Context
  223. )
  224. {
  225. return( TRUE );
  226. }
  227. extern "C"
  228. BOOL
  229. FeClientInitialize(
  230. IN DWORD dwFeRevision,
  231. OUT LPFE_CLIENT_INFO *lpFeInfo
  232. )
  233. /*++
  234. Routine Description:
  235. description-of-function.
  236. Arguments:
  237. dwFeRevision - Is the revision of the current FEAPI interface.
  238. lpFeInfo - On successful return, must contain a pointer to a structure
  239. describing the FE Client Interface. Once returned, the FE Client
  240. must assume that the caller will continue to reference this table until
  241. an unload call has been made. Any changes to this information, or
  242. deallocation of the memory containing the information may result in
  243. system corruptions.
  244. Return Value:
  245. TRUE - Indicates the Client DLL successfully initialized.
  246. FALSE - Indicates the client DLL has not loaded. More information may be
  247. obtained by calling GetLastError().
  248. --*/
  249. {
  250. *lpFeInfo = &ClientInfo;
  251. return( TRUE );
  252. }
  253. BOOL
  254. TranslateFileName(
  255. IN LPCWSTR FileName,
  256. OUT PUNICODE_STRING FullFileNameU
  257. )
  258. /*++
  259. Routine Description:
  260. This routine takes the filename passed by the user and converts
  261. it to a fully qualified pathname in the passed Unicode string.
  262. Arguments:
  263. FileName - Supplies the user-supplied file name.
  264. FullFileNameU - Returns the fully qualified pathname of the passed file.
  265. The buffer in this string is allocated out of heap memory and
  266. must be freed by the caller.
  267. Return Value:
  268. TRUE on success, FALSE otherwise.
  269. --*/
  270. //
  271. // Note: need to free the buffer of the returned string
  272. //
  273. {
  274. UNICODE_STRING FileNameU;
  275. LPWSTR SrcFileName = (LPWSTR)FileName;
  276. if (0 == FileName[0]) {
  277. SetLastError(ERROR_INVALID_PARAMETER);
  278. return FALSE;
  279. }
  280. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, MAX_PATH * sizeof( WCHAR ));
  281. if (!FullFileNameU->Buffer) {
  282. SetLastError(ERROR_OUTOFMEMORY);
  283. return FALSE;
  284. }
  285. FullFileNameU->MaximumLength = MAX_PATH * sizeof( WCHAR );
  286. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  287. SrcFileName,
  288. FullFileNameU->MaximumLength,
  289. FullFileNameU->Buffer,
  290. NULL
  291. );
  292. //
  293. // The return value is supposed to be the length of the filename, without counting
  294. // the trailing NULL character. MAX_PATH is supposed be long enough to contain
  295. // the length of the file name and the trailing NULL, so what we get back had
  296. // better be less than MAX_PATH wchars.
  297. //
  298. if ( FullFileNameU->Length >= FullFileNameU->MaximumLength ){
  299. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  300. FullFileNameU->Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FullFileNameU->Length + sizeof(WCHAR));
  301. if (FullFileNameU->Buffer == NULL) {
  302. return( FALSE );
  303. }
  304. FullFileNameU->MaximumLength = FullFileNameU->Length + sizeof(WCHAR);
  305. FullFileNameU->Length = (USHORT)RtlGetFullPathName_U(
  306. SrcFileName,
  307. FullFileNameU->MaximumLength,
  308. FullFileNameU->Buffer,
  309. NULL
  310. );
  311. }
  312. if (FullFileNameU->Length == 0) {
  313. //
  314. // We failed for some reason
  315. //
  316. RtlFreeHeap( RtlProcessHeap(), 0, FullFileNameU->Buffer );
  317. return( FALSE );
  318. }
  319. return( TRUE );
  320. }
  321. BOOL
  322. WriteEfsIni(
  323. IN LPCWSTR SectionName,
  324. IN LPCWSTR KeyName,
  325. IN LPCWSTR WriteValue,
  326. IN LPCWSTR IniFileName
  327. )
  328. /*++
  329. Routine Description:
  330. This routine writes to the ini file. A wrap of WritePrivateProfileString
  331. Arguments:
  332. SectionName - Section name (Encryption).
  333. KeyName - Key name (Disable).
  334. WriteValue - The value to be write (1).
  335. IniFileName - The path for ini file (dir\desktop.ini).
  336. Return Value:
  337. TRUE on success
  338. --*/
  339. {
  340. BOOL bRet;
  341. bRet = WritePrivateProfileString(
  342. SectionName,
  343. KeyName,
  344. WriteValue,
  345. IniFileName
  346. );
  347. //
  348. // If SetFileAttributes fails, life should go on.
  349. //
  350. SetFileAttributes(IniFileName, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN );
  351. return bRet;
  352. }
  353. BOOL
  354. EfsClientEncryptionDisable(
  355. IN LPCWSTR DirPath,
  356. IN BOOL Disable
  357. )
  358. /*++
  359. Routine Description:
  360. This routine disable and enable EFS in the directory DirPath.
  361. Arguments:
  362. DirPath - Directory path.
  363. Disable - TRUE to disable
  364. Return Value:
  365. TRUE for SUCCESS
  366. --*/
  367. {
  368. LPWSTR IniFilePath;
  369. WCHAR WriteValue[2];
  370. BOOL bRet = FALSE;
  371. if (DirPath) {
  372. IniFilePath = (LPWSTR)RtlAllocateHeap(
  373. RtlProcessHeap(),
  374. 0,
  375. (wcslen(DirPath)+1+wcslen(INIFILENAME))*sizeof(WCHAR)
  376. );
  377. if (IniFilePath) {
  378. if (Disable) {
  379. wcscpy(WriteValue, L"1");
  380. } else {
  381. wcscpy(WriteValue, L"0");
  382. }
  383. wcscpy(IniFilePath, DirPath);
  384. wcscat(IniFilePath, INIFILENAME);
  385. bRet = WriteEfsIni(INISECTIONNAME, INIKEYNAME, WriteValue, IniFilePath);
  386. RtlFreeHeap( RtlProcessHeap(), 0, IniFilePath );
  387. }
  388. } else {
  389. SetLastError(ERROR_INVALID_PARAMETER);
  390. }
  391. return bRet;
  392. }
  393. BOOL
  394. EfsDisabled(
  395. IN LPCWSTR SectionName,
  396. IN LPCWSTR KeyName,
  397. IN LPCWSTR IniFileName
  398. )
  399. /*++
  400. Routine Description:
  401. This routine checks if the encryption has been turned off for the ini file.
  402. Arguments:
  403. SectionName - Section name (Encryption).
  404. KeyName - Key name (Disable).
  405. IniFileName - The path for ini file (dir\desktop.ini).
  406. Return Value:
  407. TRUE for disabled
  408. --*/
  409. {
  410. DWORD ValueLength;
  411. WCHAR ResultString[4];
  412. memset( ResultString, 0, sizeof(ResultString) );
  413. ValueLength = GetPrivateProfileString(
  414. SectionName,
  415. KeyName,
  416. L"0",
  417. ResultString,
  418. sizeof(ResultString)/sizeof(WCHAR),
  419. IniFileName
  420. );
  421. //
  422. // If GetPrivateProfileString failed, EFS will be enabled
  423. //
  424. return (!wcscmp(L"1", ResultString));
  425. }
  426. BOOL
  427. DirEfsDisabled(
  428. IN LPCWSTR DirName
  429. )
  430. /*++
  431. Routine Description:
  432. This routine checks if the encryption has been turned off for the dir.
  433. Arguments:
  434. SectionName - Section name (Encryption).
  435. KeyName - Key name (Disable).
  436. IniFileName - The path for ini file (dir\desktop.ini).
  437. Return Value:
  438. TRUE for disabled
  439. --*/
  440. {
  441. LPWSTR FileName;
  442. DWORD FileLength = (wcslen(INIFILENAME)+wcslen(DirName)+1)*sizeof (WCHAR);
  443. BOOL bRet = FALSE;
  444. FileName = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, FileLength );
  445. if (FileName) {
  446. wcscpy( FileName, DirName );
  447. wcscat( FileName, INIFILENAME );
  448. bRet = EfsDisabled( INISECTIONNAME, INIKEYNAME, FileName );
  449. RtlFreeHeap( RtlProcessHeap(), 0, FileName );
  450. }
  451. return bRet;
  452. }
  453. BOOL
  454. RemoteFile(
  455. IN LPCWSTR FileName
  456. )
  457. /*++
  458. Routine Description:
  459. This routine checks if the file is a local file.
  460. If a UNC name is passed in, it assumes a remote file. A loopback operation will occur.
  461. Arguments:
  462. FileName - Supplies the user-supplied file name.
  463. Return Value:
  464. TRUE for remote file.
  465. --*/
  466. {
  467. if ( FileName[1] == L':' ){
  468. WCHAR DriveLetter[3];
  469. DWORD BufferLength = 3;
  470. DWORD RetCode = ERROR_SUCCESS;
  471. DriveLetter[0] = FileName[0];
  472. DriveLetter[1] = FileName[1];
  473. DriveLetter[2] = 0;
  474. RetCode = WNetGetConnectionW(
  475. DriveLetter,
  476. DriveLetter,
  477. &BufferLength
  478. );
  479. if (RetCode == ERROR_NOT_CONNECTED) {
  480. return FALSE;
  481. } else {
  482. return TRUE;
  483. }
  484. } else {
  485. return TRUE;
  486. }
  487. }
  488. DWORD
  489. EfsClientEncryptFile(
  490. IN LPCWSTR FileName
  491. )
  492. {
  493. DWORD rc;
  494. BOOL Result;
  495. UNICODE_STRING FullFileNameU;
  496. if (NULL == FileName) {
  497. return ERROR_INVALID_PARAMETER;
  498. }
  499. Result = TranslateFileName( FileName, &FullFileNameU );
  500. if (Result) {
  501. //
  502. // Call the server
  503. //
  504. rc = EfsEncryptFileRPCClient( &FullFileNameU );
  505. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  506. } else {
  507. rc = GetLastError();
  508. }
  509. return( rc );
  510. }
  511. DWORD
  512. EfsClientDecryptFile(
  513. IN LPCWSTR FileName,
  514. IN DWORD dwRecovery
  515. )
  516. {
  517. DWORD rc;
  518. BOOL Result;
  519. UNICODE_STRING FullFileNameU;
  520. if (NULL == FileName) {
  521. return ERROR_INVALID_PARAMETER;
  522. }
  523. Result = TranslateFileName( FileName, &FullFileNameU );
  524. if (Result) {
  525. //
  526. // Call the server
  527. //
  528. rc = EfsDecryptFileRPCClient( &FullFileNameU, dwRecovery );
  529. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  530. } else {
  531. rc = GetLastError();
  532. }
  533. return( rc );
  534. }
  535. BOOL
  536. EfsClientFileEncryptionStatus(
  537. IN LPCWSTR FileName,
  538. OUT LPDWORD lpStatus
  539. )
  540. /*++
  541. Routine Description:
  542. This routine checks if a file is encryptable or not.
  543. We do not test the NTFS Volume 5 for the reason of performance.
  544. This means we might return a file encryptable (on FAT at etc.), but
  545. actually it could not be encrypted. This should be OK. This is a best effort
  546. API. We have the same problem with network file. Any way, a file could fail
  547. to be encrypted for many reasons, delegation, disk space and etc.
  548. We disable the encryption from %windir% down.
  549. We might change these features later.
  550. Arguments:
  551. FileName - The file to be checked.
  552. lpStatus - The encryption status of the file. Error code if the return value is
  553. FALSE.
  554. Return Value:
  555. TRUE on success, FALSE otherwise.
  556. --*/
  557. {
  558. BOOL Result;
  559. DWORD FileAttributes;
  560. UNICODE_STRING FullFileNameU;
  561. if ((NULL == FileName) || ( NULL == lpStatus)) {
  562. SetLastError(ERROR_INVALID_PARAMETER);
  563. return FALSE;
  564. }
  565. //
  566. // GetFileAttributes should use the name before TanslateFileName
  567. // in case the passed in name is longer than MAX_PATH and using the
  568. // format \\?\
  569. //
  570. FileAttributes = GetFileAttributes( FileName );
  571. if (FileAttributes == -1){
  572. *lpStatus = GetLastError();
  573. return FALSE;
  574. }
  575. Result = TranslateFileName( FileName, &FullFileNameU );
  576. //
  577. // FullFileNameU.Length does not include the ending 0. The data returned from TranslateFileName does have the ending 0.
  578. //
  579. ASSERT(FullFileNameU.Buffer[FullFileNameU.Length / 2] == 0);
  580. if (Result) {
  581. if ( (FileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ||
  582. (FileAttributes & FILE_ATTRIBUTE_SYSTEM) ) {
  583. //
  584. // File not encryptable. Either it is encypted or a system file.
  585. //
  586. if ( FileAttributes & FILE_ATTRIBUTE_ENCRYPTED ){
  587. *lpStatus = FILE_IS_ENCRYPTED;
  588. } else {
  589. *lpStatus = FILE_SYSTEM_ATTR ;
  590. }
  591. } else {
  592. LPWSTR TmpBuffer;
  593. LPWSTR FullPathName;
  594. UINT TmpBuffLen;
  595. UINT FullPathLen;
  596. UINT PathLength;
  597. BOOL GotRoot;
  598. BOOL EfsDisabled = FALSE;
  599. //
  600. // Check if it is the root.
  601. //
  602. if ( FullFileNameU.Length >= MAX_PATH * sizeof(WCHAR)){
  603. //
  604. // We need to put back the \\?\ or \\?\UNC\ to use the
  605. // Win 32 API. The extra max bytes needed is 7. ( \\?\UNC + NULL - \)
  606. //
  607. FullPathLen = FullFileNameU.Length + 7 * sizeof(WCHAR);
  608. TmpBuffLen = FullPathLen;
  609. FullPathName = (LPWSTR)RtlAllocateHeap(
  610. RtlProcessHeap(),
  611. 0,
  612. FullPathLen
  613. );
  614. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  615. RtlProcessHeap(),
  616. 0,
  617. TmpBuffLen
  618. );
  619. if ((FullPathName == NULL) || (TmpBuffer == NULL)){
  620. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  621. if (FullPathName){
  622. RtlFreeHeap(RtlProcessHeap(), 0, FullPathName);
  623. }
  624. if (TmpBuffer){
  625. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  626. }
  627. *lpStatus = ERROR_OUTOFMEMORY;
  628. return FALSE;
  629. }
  630. if ( FullFileNameU.Buffer[0] == L'\\' ){
  631. //
  632. // Put back the \\?\UNC\
  633. //
  634. wcscpy(FullPathName, L"\\\\?\\UNC");
  635. wcscat(FullPathName, &(FullFileNameU.Buffer[1]));
  636. FullPathLen = FullFileNameU.Length + 6 * sizeof(WCHAR);
  637. } else {
  638. //
  639. // Put back the \\?\
  640. //
  641. wcscpy(FullPathName, L"\\\\?\\");
  642. wcscat(FullPathName, FullFileNameU.Buffer);
  643. FullPathLen = FullFileNameU.Length + 4 * sizeof(WCHAR);
  644. }
  645. } else {
  646. TmpBuffLen = MAX_PATH * sizeof(WCHAR);
  647. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  648. RtlProcessHeap(),
  649. 0,
  650. TmpBuffLen
  651. );
  652. if (TmpBuffer == NULL){
  653. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  654. *lpStatus = ERROR_OUTOFMEMORY;
  655. return FALSE;
  656. }
  657. FullPathName = FullFileNameU.Buffer;
  658. FullPathLen = FullFileNameU.Length;
  659. }
  660. //
  661. // Check desktop.ini here
  662. //
  663. wcscpy(TmpBuffer, FullFileNameU.Buffer);
  664. if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  665. //
  666. // This is a file. Get the DIR path
  667. //
  668. int ii;
  669. ii = wcslen(TmpBuffer) - 1;
  670. while ((ii >= 0) && (TmpBuffer[ii] != L'\\')) {
  671. ii--;
  672. }
  673. if (ii>=0) {
  674. TmpBuffer[ii] = 0;
  675. }
  676. }
  677. EfsDisabled = DirEfsDisabled( TmpBuffer );
  678. if (EfsDisabled) {
  679. *lpStatus = FILE_DIR_DISALLOWED;
  680. } else if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FileAttributes & FILE_ATTRIBUTE_READONLY)){
  681. //
  682. // Read only file
  683. //
  684. *lpStatus = FILE_READ_ONLY;
  685. } else {
  686. GotRoot = GetVolumePathName(
  687. FullPathName,
  688. TmpBuffer,
  689. TmpBuffLen
  690. );
  691. if ( GotRoot ){
  692. DWORD RootLength = wcslen(TmpBuffer) - 1;
  693. TmpBuffer[RootLength] = NULL;
  694. if ( (FullPathLen == RootLength * sizeof (WCHAR))
  695. && !wcscmp(TmpBuffer, FullPathName)){
  696. //
  697. // It is the root
  698. //
  699. *lpStatus = FILE_ROOT_DIR;
  700. } else {
  701. //
  702. // Check if it is the Windows\system32 directories
  703. //
  704. PathLength = GetSystemWindowsDirectory( TmpBuffer, TmpBuffLen );
  705. //PathLength = GetWindowsDirectory( TmpBuffer, TmpBuffLen );
  706. //PathLength = GetSystemDirectory( TmpBuffer, TmpBuffLen );
  707. ASSERT(PathLength <= TmpBuffLen);
  708. if ( PathLength > TmpBuffLen ) {
  709. //
  710. // This is unlikely. Not sure who will ever have the length
  711. // of %windir%\system32 longer than MAXPATH in the real world.
  712. // Even this happen, user could still encrypt the file. FILE_UNKNOWN
  713. // does not mean file could\or couldn't be encrypted.
  714. //
  715. *lpStatus = FILE_UNKNOWN ;
  716. } else {
  717. if ( ( FullFileNameU.Length < PathLength * sizeof (WCHAR) ) ||
  718. ( ( FullFileNameU.Buffer[PathLength] ) &&
  719. ( FullFileNameU.Buffer[PathLength] != L'\\') )){
  720. //
  721. // Check if a remote file
  722. //
  723. if ( RemoteFile( FullFileNameU.Buffer ) ){
  724. *lpStatus = FILE_UNKNOWN;
  725. } else {
  726. *lpStatus = FILE_ENCRYPTABLE;
  727. }
  728. } else {
  729. if ( _wcsnicmp(TmpBuffer, FullFileNameU.Buffer, PathLength)){
  730. //
  731. // Not under %SystemRoot%
  732. //
  733. if ( RemoteFile( FullFileNameU.Buffer ) ){
  734. *lpStatus = FILE_UNKNOWN;
  735. } else {
  736. *lpStatus = FILE_ENCRYPTABLE;
  737. }
  738. } else {
  739. //
  740. // In windows root directory. WINNT
  741. //
  742. BOOL bRet;
  743. DWORD allowPathLen;
  744. //
  745. // Check for allow lists
  746. //
  747. allowPathLen = (DWORD) TmpBuffLen;
  748. bRet = GetProfilesDirectory(TmpBuffer, &allowPathLen);
  749. if (!bRet){
  750. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  751. TmpBuffer = (LPWSTR)RtlAllocateHeap(
  752. RtlProcessHeap(),
  753. 0,
  754. allowPathLen
  755. );
  756. if (TmpBuffer){
  757. bRet = GetProfilesDirectory(TmpBuffer, &allowPathLen);
  758. } else {
  759. *lpStatus = ERROR_OUTOFMEMORY;
  760. Result = FALSE;
  761. }
  762. }
  763. if (bRet){
  764. //
  765. // Check for Profiles directory. allowPathLen including NULL.
  766. //
  767. if ((FullFileNameU.Length >= ((allowPathLen-1) * sizeof (WCHAR)) ) &&
  768. !_wcsnicmp(TmpBuffer, FullFileNameU.Buffer, allowPathLen - 1)){
  769. *lpStatus = FILE_ENCRYPTABLE;
  770. } else {
  771. //
  772. // Under %windir% but not profiles
  773. //
  774. *lpStatus = FILE_SYSTEM_DIR;
  775. }
  776. } else {
  777. if ( *lpStatus != ERROR_OUTOFMEMORY){
  778. //
  779. // This should not happen, unless a bug in GetProfilesDirectoryEx()
  780. //
  781. ASSERT(FALSE);
  782. *lpStatus = FILE_UNKNOWN;
  783. }
  784. }
  785. }
  786. }
  787. }
  788. }
  789. } else {
  790. //
  791. // Cannot get the root. The reason might very well be out of memory.
  792. // Return FILE_UNKNOWN and let other codes dealing with the memory
  793. // problem.
  794. //
  795. *lpStatus = FILE_UNKNOWN ;
  796. }
  797. }
  798. if ((FullPathName != FullFileNameU.Buffer) && FullPathName){
  799. RtlFreeHeap(RtlProcessHeap(), 0, FullPathName);
  800. }
  801. if (TmpBuffer){
  802. RtlFreeHeap(RtlProcessHeap(), 0, TmpBuffer);
  803. }
  804. }
  805. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  806. } else {
  807. *lpStatus = GetLastError();
  808. }
  809. return Result;
  810. }
  811. DWORD
  812. EfsClientOpenFileRaw(
  813. IN LPCWSTR FileName,
  814. IN ULONG Flags,
  815. OUT PVOID * Context
  816. )
  817. /*++
  818. Routine Description:
  819. This routine is used to open an encrypted file. It opens the file and
  820. prepares the necessary context to be used in ReadRaw data and WriteRaw
  821. data.
  822. Arguments:
  823. FileName -- File name of the file to be exported
  824. Flags -- Indicating if open for export or import; for directory or file.
  825. Context - Export context to be used by READ operation later. Caller should
  826. pass this back in ReadRaw().
  827. Return Value:
  828. Result of the operation.
  829. --*/
  830. {
  831. DWORD rc;
  832. BOOL Result;
  833. UNICODE_STRING FullFileNameU;
  834. if ((NULL == FileName) || ( NULL == Context)) {
  835. return ERROR_INVALID_PARAMETER;
  836. }
  837. Result = TranslateFileName( FileName, &FullFileNameU );
  838. if (Result) {
  839. rc = (EfsOpenFileRawRPCClient(
  840. FullFileNameU.Buffer,
  841. Flags,
  842. Context
  843. )
  844. );
  845. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  846. } else {
  847. rc = GetLastError();
  848. }
  849. return rc;
  850. }
  851. DWORD
  852. EfsClientReadFileRaw(
  853. IN PFE_EXPORT_FUNC ExportCallback,
  854. IN PVOID CallbackContext,
  855. IN PVOID Context
  856. )
  857. /*++
  858. Routine Description:
  859. This routine is used to read encrypted file's raw data. It uses
  860. NTFS FSCTL to get the data.
  861. Arguments:
  862. ExportCallback -- Caller supplied callback function to process the
  863. raw data.
  864. CallbackContext -- Caller's context passed back in ExportCallback.
  865. Context - Export context created in the CreateRaw.
  866. Return Value:
  867. Result of the operation.
  868. --*/
  869. {
  870. return ( EfsReadFileRawRPCClient(
  871. ExportCallback,
  872. CallbackContext,
  873. Context
  874. ));
  875. }
  876. DWORD
  877. EfsClientWriteFileRaw(
  878. IN PFE_IMPORT_FUNC ImportCallback,
  879. IN PVOID CallbackContext,
  880. IN PVOID Context
  881. )
  882. /*++
  883. Routine Description:
  884. This routine is used to write encrypted file's raw data. It uses
  885. NTFS FSCTL to write the data.
  886. Arguments:
  887. ImportCallback -- Caller supplied callback function to provide the
  888. raw data.
  889. CallbackContext -- Caller's context passed back in ImportCallback.
  890. Context - Import context created in the CreateRaw.
  891. Return Value:
  892. Result of the operation.
  893. --*/
  894. {
  895. return ( EfsWriteFileRawRPCClient(
  896. ImportCallback,
  897. CallbackContext,
  898. Context
  899. ));
  900. }
  901. VOID
  902. EfsClientCloseFileRaw(
  903. IN PVOID Context
  904. )
  905. /*++
  906. Routine Description:
  907. This routine frees the resources allocated by the CreateRaw
  908. Arguments:
  909. Context - Created by the CreateRaw.
  910. Return Value:
  911. NO.
  912. --*/
  913. {
  914. if ( !Context ){
  915. return;
  916. }
  917. EfsCloseFileRawRPCClient( Context );
  918. }
  919. //
  920. // Beta 2 API
  921. //
  922. DWORD
  923. EfsClientAddUsers(
  924. IN LPCWSTR lpFileName,
  925. IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
  926. )
  927. /*++
  928. Routine Description:
  929. Calls client stub for AddUsersToFile EFS API.
  930. Arguments:
  931. lpFileName - Supplies the name of the file to be modified.
  932. nUsers - Supplies the number of entries in teh pEncryptionCertificates array
  933. pEncryptionCertificates - Supplies an array of pointers to PENCRYPTION_CERTIFICATE
  934. structures. Length of array is given in nUsers parameter.
  935. Return Value:
  936. --*/
  937. {
  938. DWORD rc = ERROR_SUCCESS;
  939. UNICODE_STRING FullFileNameU;
  940. DWORD ii = 0;
  941. CERT_CHAIN_PARA CertChainPara;
  942. if ((NULL == lpFileName) || (NULL == pEncryptionCertificates)) {
  943. return ERROR_INVALID_PARAMETER;
  944. }
  945. //
  946. // Let's check to see if the certs are good or not.
  947. //
  948. CertChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  949. CertChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  950. CertChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  951. CertChainPara.RequestedUsage.Usage.rgpszUsageIdentifier=&EfsOidlpstr;
  952. while ((ERROR_SUCCESS == rc) && (ii < pEncryptionCertificates->nUsers)) {
  953. PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
  954. X509_ASN_ENCODING,
  955. pEncryptionCertificates->pUsers[ii]->pCertBlob->pbData,
  956. pEncryptionCertificates->pUsers[ii]->pCertBlob->cbData
  957. );
  958. if (pCertContext != NULL) {
  959. PCCERT_CHAIN_CONTEXT pChainContext;
  960. //
  961. // Do the chain validation
  962. //
  963. if (CertGetCertificateChain (
  964. HCCE_CURRENT_USER,
  965. pCertContext,
  966. NULL,
  967. NULL,
  968. &CertChainPara,
  969. 0,
  970. NULL,
  971. &pChainContext
  972. )) {
  973. //
  974. // Let's check the chain
  975. //
  976. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[ 0 ];
  977. PCERT_CHAIN_ELEMENT pElement = pChain->rgpElement[ 0 ];
  978. BOOL bSelfSigned = pElement->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED;
  979. DWORD dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;
  980. if (dwErrorStatus) {
  981. if ((dwErrorStatus == CERT_TRUST_IS_UNTRUSTED_ROOT) && bSelfSigned ){
  982. //
  983. // Self signed. Check if it is in the my trusted store
  984. //
  985. HCERTSTORE trustedStore;
  986. PCCERT_CONTEXT pCert=NULL;
  987. trustedStore = CertOpenStore(
  988. CERT_STORE_PROV_SYSTEM_W,
  989. 0, // dwEncodingType
  990. 0, // hCryptProv,
  991. CERT_SYSTEM_STORE_CURRENT_USER,
  992. TRUSTEDPEOPLE
  993. );
  994. if (trustedStore) {
  995. pCert = CertFindCertificateInStore(
  996. trustedStore,
  997. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  998. 0,
  999. CERT_FIND_EXISTING,
  1000. pCertContext,
  1001. pCert
  1002. );
  1003. if (pCert) {
  1004. //
  1005. // We found it.
  1006. //
  1007. CertFreeCertificateContext(pCert);
  1008. } else {
  1009. //
  1010. // Not trusted self-signed cert
  1011. //
  1012. rc = CERT_E_UNTRUSTEDROOT;
  1013. }
  1014. CertCloseStore( trustedStore, 0 );
  1015. } else {
  1016. rc = GetLastError();
  1017. }
  1018. } else {
  1019. //
  1020. // Other chain build error
  1021. // Let's get the error code of the chain building.
  1022. //
  1023. CERT_CHAIN_POLICY_PARA PolicyPara;
  1024. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1025. RtlZeroMemory(&PolicyPara, sizeof(CERT_CHAIN_POLICY_PARA));
  1026. RtlZeroMemory(&PolicyStatus, sizeof(CERT_CHAIN_POLICY_STATUS));
  1027. PolicyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  1028. PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
  1029. if (!CertVerifyCertificateChainPolicy(
  1030. CERT_CHAIN_POLICY_BASE,
  1031. pChainContext,
  1032. &PolicyPara,
  1033. &PolicyStatus
  1034. )) {
  1035. rc = PolicyStatus.dwError;
  1036. }
  1037. }
  1038. }
  1039. CertFreeCertificateChain( pChainContext );
  1040. } else {
  1041. rc = GetLastError();
  1042. }
  1043. CertFreeCertificateContext(pCertContext);
  1044. } else {
  1045. rc = GetLastError();
  1046. }
  1047. ii++;
  1048. }
  1049. if (ERROR_SUCCESS == rc) {
  1050. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1051. rc = EfsAddUsersRPCClient( FullFileNameU.Buffer, pEncryptionCertificates );
  1052. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1053. } else {
  1054. rc = GetLastError();
  1055. }
  1056. }
  1057. return rc;
  1058. }
  1059. DWORD
  1060. EfsClientRemoveUsers(
  1061. IN LPCWSTR lpFileName,
  1062. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Calls client stub for RemoveUsersFromFile EFS API
  1067. Arguments:
  1068. lpFileName - Supplies the name of the file to be modified.
  1069. pHashes - Supplies a structure containing a list of PENCRYPTION_CERTIFICATE_HASH
  1070. structures, each of which represents a user to remove from the specified file.
  1071. Return Value:
  1072. --*/
  1073. {
  1074. DWORD rc;
  1075. UNICODE_STRING FullFileNameU;
  1076. if ((NULL == lpFileName) || (NULL == pHashes) || (pHashes->pUsers == NULL)) {
  1077. return ERROR_INVALID_PARAMETER;
  1078. }
  1079. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1080. rc = EfsRemoveUsersRPCClient( FullFileNameU.Buffer, pHashes );
  1081. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1082. } else {
  1083. rc = GetLastError();
  1084. }
  1085. return rc;
  1086. }
  1087. DWORD
  1088. EfsClientQueryRecoveryAgents(
  1089. IN LPCWSTR lpFileName,
  1090. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. Calls client stub for QueryRecoveryAgents EFS API
  1095. Arguments:
  1096. lpFileName - Supplies the name of the file to be modified.
  1097. pRecoveryAgents - Returns a pointer to a structure containing a list
  1098. of PENCRYPTION_CERTIFICATE_HASH structures, each of which represents
  1099. a recovery agent on the file.
  1100. Return Value:
  1101. --*/
  1102. {
  1103. DWORD rc;
  1104. UNICODE_STRING FullFileNameU;
  1105. if ((NULL == lpFileName) || (NULL == pRecoveryAgents)) {
  1106. return ERROR_INVALID_PARAMETER;
  1107. }
  1108. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1109. rc = EfsQueryRecoveryAgentsRPCClient( FullFileNameU.Buffer, pRecoveryAgents );
  1110. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1111. } else {
  1112. rc = GetLastError();
  1113. }
  1114. return rc;
  1115. }
  1116. DWORD
  1117. EfsClientQueryUsers(
  1118. IN LPCWSTR lpFileName,
  1119. OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Calls client stub for QueryUsersOnFile EFS API
  1124. Arguments:
  1125. lpFileName - Supplies the name of the file to be modified.
  1126. pUsers - Returns a pointer to a structure containing a list
  1127. of PENCRYPTION_CERTIFICATE_HASH structures, each of which represents
  1128. a user of this file (that is, someone who can decrypt the file).
  1129. Return Value:
  1130. --*/
  1131. {
  1132. DWORD rc;
  1133. UNICODE_STRING FullFileNameU;
  1134. if ((NULL == lpFileName) || (NULL == pUsers)) {
  1135. return ERROR_INVALID_PARAMETER;
  1136. }
  1137. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1138. rc = EfsQueryUsersRPCClient( FullFileNameU.Buffer, pUsers );
  1139. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1140. } else {
  1141. rc = GetLastError();
  1142. }
  1143. return rc;
  1144. }
  1145. DWORD
  1146. EfsClientSetEncryptionKey(
  1147. IN PENCRYPTION_CERTIFICATE pEncryptionCertificate
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. Calls client stub for SetFileEncryptionKey EFS API
  1152. Arguments:
  1153. pEncryptionCertificate - Supplies a pointer to an EFS certificate
  1154. representing the public key to use for future encryption operations.
  1155. Return Value:
  1156. --*/
  1157. {
  1158. /*
  1159. if ((NULL == pEncryptionCertificate) || ( NULL == pEncryptionCertificate->pCertBlob)) {
  1160. return ERROR_INVALID_PARAMETER;
  1161. }
  1162. */
  1163. if ( pEncryptionCertificate && ( NULL == pEncryptionCertificate->pCertBlob)) {
  1164. return ERROR_INVALID_PARAMETER;
  1165. }
  1166. DWORD rc = EfsSetEncryptionKeyRPCClient( pEncryptionCertificate );
  1167. return( rc );
  1168. }
  1169. VOID
  1170. EfsClientFreeHashList(
  1171. IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashList
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. This routine frees the memory allocated by a call to
  1176. QueryUsersOnEncryptedFile and QueryRecoveryAgentsOnEncryptedFile
  1177. Arguments:
  1178. pHashList - Supplies the hash list to be freed.
  1179. Return Value:
  1180. None. Faults in user's context if passed bogus data.
  1181. --*/
  1182. {
  1183. if (NULL == pHashList) {
  1184. SetLastError(ERROR_INVALID_PARAMETER);
  1185. return;
  1186. }
  1187. for (DWORD i=0; i<pHashList->nCert_Hash ; i++) {
  1188. PENCRYPTION_CERTIFICATE_HASH pHash = pHashList->pUsers[i];
  1189. if (pHash->lpDisplayInformation) {
  1190. MIDL_user_free( pHash->lpDisplayInformation );
  1191. }
  1192. if (pHash->pUserSid) {
  1193. MIDL_user_free( pHash->pUserSid );
  1194. }
  1195. MIDL_user_free( pHash->pHash->pbData );
  1196. MIDL_user_free( pHash->pHash );
  1197. MIDL_user_free( pHash );
  1198. }
  1199. MIDL_user_free( pHashList->pUsers );
  1200. MIDL_user_free( pHashList );
  1201. return;
  1202. }
  1203. DWORD
  1204. EfsGetMySDRpcBlob(
  1205. IN PSECURITY_DESCRIPTOR pInSD,
  1206. OUT PEFS_RPC_BLOB *pOutSDRpcBlob
  1207. )
  1208. {
  1209. DWORD rc = ERROR_SUCCESS;
  1210. PSECURITY_DESCRIPTOR pRelativeSD;
  1211. ULONG SDLength = 0;
  1212. if ( (pInSD == NULL) || !RtlValidSecurityDescriptor(pInSD) ) {
  1213. return(ERROR_INVALID_PARAMETER);
  1214. }
  1215. if ( ((PISECURITY_DESCRIPTOR)pInSD)->Control & SE_SELF_RELATIVE) {
  1216. //
  1217. // The input SD is already RELATIVE
  1218. // Just fill EFS_RPC_BLOB
  1219. //
  1220. *pOutSDRpcBlob = (PEFS_RPC_BLOB) RtlAllocateHeap(
  1221. RtlProcessHeap(),
  1222. 0,
  1223. sizeof(EFS_RPC_BLOB)
  1224. );
  1225. if (*pOutSDRpcBlob) {
  1226. (*pOutSDRpcBlob)->cbData = RtlLengthSecurityDescriptor (
  1227. pInSD
  1228. );
  1229. (*pOutSDRpcBlob)->pbData = (PBYTE) pInSD;
  1230. } else {
  1231. return(ERROR_NOT_ENOUGH_MEMORY);
  1232. }
  1233. } else {
  1234. //
  1235. // get the length
  1236. //
  1237. RtlMakeSelfRelativeSD( pInSD,
  1238. NULL,
  1239. &SDLength
  1240. );
  1241. if ( SDLength > 0 ) {
  1242. *pOutSDRpcBlob = (PEFS_RPC_BLOB) RtlAllocateHeap(
  1243. RtlProcessHeap(),
  1244. 0,
  1245. SDLength + sizeof(EFS_RPC_BLOB)
  1246. );
  1247. if ( !(*pOutSDRpcBlob) ) {
  1248. return(ERROR_NOT_ENOUGH_MEMORY);
  1249. }
  1250. pRelativeSD = (PSECURITY_DESCRIPTOR)(*pOutSDRpcBlob + 1);
  1251. (*pOutSDRpcBlob)->cbData = SDLength;
  1252. (*pOutSDRpcBlob)->pbData = (PBYTE) pRelativeSD;
  1253. rc = RtlNtStatusToDosError(
  1254. RtlMakeSelfRelativeSD( pInSD,
  1255. pRelativeSD,
  1256. &SDLength
  1257. ));
  1258. if ( rc != ERROR_SUCCESS ) {
  1259. RtlFreeHeap(RtlProcessHeap(), 0, *pOutSDRpcBlob);
  1260. *pOutSDRpcBlob = NULL;
  1261. return(rc);
  1262. }
  1263. } else {
  1264. //
  1265. // something is wrong with the SD
  1266. //
  1267. return(ERROR_INVALID_PARAMETER);
  1268. }
  1269. }
  1270. return(rc);
  1271. }
  1272. DWORD
  1273. EfsClientDuplicateEncryptionInfo(
  1274. IN LPCWSTR lpSrcFile,
  1275. IN LPCWSTR lpDestFile,
  1276. IN DWORD dwCreationDistribution,
  1277. IN DWORD dwAttributes,
  1278. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  1279. )
  1280. {
  1281. DWORD rc = ERROR_SUCCESS;
  1282. UNICODE_STRING SrcFullFileNameU;
  1283. UNICODE_STRING DestFullFileNameU;
  1284. if (TranslateFileName( lpSrcFile, &SrcFullFileNameU )) {
  1285. if (TranslateFileName( lpDestFile, &DestFullFileNameU )) {
  1286. PEFS_RPC_BLOB pRpcBlob = NULL;
  1287. BOOL bInheritHandle = FALSE;
  1288. if (lpSecurityAttributes) {
  1289. rc = EfsGetMySDRpcBlob(lpSecurityAttributes->lpSecurityDescriptor, &pRpcBlob);
  1290. bInheritHandle = lpSecurityAttributes->bInheritHandle;
  1291. }
  1292. if (ERROR_SUCCESS == rc) {
  1293. rc = EfsDuplicateEncryptionInfoRPCClient(
  1294. SrcFullFileNameU.Buffer,
  1295. DestFullFileNameU.Buffer,
  1296. dwCreationDistribution,
  1297. dwAttributes,
  1298. pRpcBlob,
  1299. bInheritHandle
  1300. );
  1301. if (pRpcBlob) {
  1302. RtlFreeHeap(RtlProcessHeap(), 0, pRpcBlob);
  1303. }
  1304. }
  1305. RtlFreeHeap(RtlProcessHeap(), 0, DestFullFileNameU.Buffer);
  1306. } else {
  1307. rc = GetLastError();
  1308. }
  1309. RtlFreeHeap(RtlProcessHeap(), 0, SrcFullFileNameU.Buffer);
  1310. } else {
  1311. rc = GetLastError();
  1312. }
  1313. return( rc );
  1314. }
  1315. DWORD
  1316. EfsClientFileKeyInfo(
  1317. IN LPCWSTR lpFileName,
  1318. IN DWORD InfoClass,
  1319. OUT PEFS_RPC_BLOB *KeyInfo
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. Calls client stub for EncryptedFileKeyInfo EFS API
  1324. Arguments:
  1325. lpFileName - Supplies the name of the file.
  1326. KeyInfo - Returns a pointer to a structure containing key info.
  1327. Return Value:
  1328. --*/
  1329. {
  1330. DWORD rc;
  1331. UNICODE_STRING FullFileNameU;
  1332. DWORD FileAttributes;
  1333. if ((NULL == lpFileName) || (NULL == KeyInfo)) {
  1334. return ERROR_INVALID_PARAMETER;
  1335. }
  1336. if ((InfoClass != BASIC_KEY_INFO) && (InfoClass != UPDATE_KEY_USED)) {
  1337. return ERROR_INVALID_PARAMETER;
  1338. }
  1339. if ( InfoClass == UPDATE_KEY_USED) {
  1340. FileAttributes = GetFileAttributes( lpFileName );
  1341. if ( (FileAttributes == -1) || !(FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  1342. return ERROR_INVALID_PARAMETER;
  1343. }
  1344. }
  1345. if (TranslateFileName( lpFileName, &FullFileNameU )) {
  1346. rc = EfsFileKeyInfoRPCClient( FullFileNameU.Buffer, InfoClass, KeyInfo );
  1347. RtlFreeHeap(RtlProcessHeap(), 0, FullFileNameU.Buffer);
  1348. } else {
  1349. rc = GetLastError();
  1350. }
  1351. return rc;
  1352. }
  1353. VOID
  1354. EfsClientFreeKeyInfo(
  1355. IN PEFS_RPC_BLOB pKeyInfo
  1356. )
  1357. /*++
  1358. Routine Description:
  1359. This routine frees the memory allocated by a call to
  1360. EfsClientFileKeyInfo
  1361. Arguments:
  1362. pKeyInfo - Supplies the memory pointer to be freed.
  1363. Return Value:
  1364. None. Faults in user's context if passed bogus data.
  1365. --*/
  1366. {
  1367. if (NULL == pKeyInfo) {
  1368. SetLastError(ERROR_INVALID_PARAMETER);
  1369. return;
  1370. }
  1371. if (pKeyInfo->pbData) {
  1372. MIDL_user_free( pKeyInfo->pbData );
  1373. }
  1374. MIDL_user_free( pKeyInfo );
  1375. return;
  1376. }