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.

1389 lines
45 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: dir.c
  7. //
  8. // Description: This module contains support routines for the diretory
  9. // category API's for the AFP server service. These routines
  10. // are called by the RPC runtime.
  11. //
  12. // History:
  13. // June 11,1992. NarenG Created original version.
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <ntlsa.h>
  18. #include <nturtl.h> // needed for winbase.h
  19. #include "afpsvcp.h"
  20. //**
  21. //
  22. // Call: AfpDirConvertSidsToNames
  23. //
  24. // Returns: NO_ERROR
  25. // error return codes from LsaOpenPolicy and LsaLookupSids
  26. //
  27. // Description: Will convert the directory structure returned by the FSD
  28. // which contains pointers to owner and groups SIDS to their
  29. // respective names. The caller is responsible for freeing up
  30. // the memory allocated to hold the converted dir structure.
  31. //
  32. DWORD
  33. AfpDirConvertSidsToNames(
  34. IN PAFP_DIRECTORY_INFO pAfpDirInfo,
  35. OUT PAFP_DIRECTORY_INFO* ppAfpConvertedDirInfo
  36. )
  37. {
  38. LSA_HANDLE hLsa = NULL;
  39. NTSTATUS ntStatus;
  40. PLSA_REFERENCED_DOMAIN_LIST pDomainList = NULL;
  41. PLSA_TRANSLATED_NAME pNames = NULL;
  42. PSID pSidArray[2];
  43. SECURITY_QUALITY_OF_SERVICE QOS;
  44. OBJECT_ATTRIBUTES ObjectAttributes;
  45. DWORD dwRetCode = NO_ERROR;
  46. PAFP_DIRECTORY_INFO pOutputBuf = NULL;
  47. DWORD cbOutputBuf;
  48. LPBYTE pbVariableData;
  49. DWORD dwIndex;
  50. WCHAR * pWchar;
  51. BOOL fUseUnknownAccount = FALSE;
  52. DWORD dwUse, dwCount = 0;
  53. SID AfpBuiltInSid = { 1, 1, SECURITY_NT_AUTHORITY,
  54. SECURITY_BUILTIN_DOMAIN_RID };
  55. // First open the LSA and obtain a handle to it.
  56. //
  57. QOS.Length = sizeof( QOS );
  58. QOS.ImpersonationLevel = SecurityImpersonation;
  59. QOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  60. QOS.EffectiveOnly = FALSE;
  61. InitializeObjectAttributes( &ObjectAttributes,
  62. NULL,
  63. 0L,
  64. NULL,
  65. NULL );
  66. ObjectAttributes.SecurityQualityOfService = &QOS;
  67. ntStatus = LsaOpenPolicy( NULL,
  68. &ObjectAttributes,
  69. POLICY_LOOKUP_NAMES,
  70. &hLsa );
  71. if ( !NT_SUCCESS( ntStatus ))
  72. return( RtlNtStatusToDosError( ntStatus ) );
  73. // This is not a loop
  74. //
  75. do {
  76. // Set up the owner and group sid into the array.
  77. //
  78. if ((PSID)(pAfpDirInfo->afpdir_owner) != NULL)
  79. {
  80. pSidArray[dwCount++] = (PSID)(pAfpDirInfo->afpdir_owner);
  81. }
  82. if ((PSID)(pAfpDirInfo->afpdir_group) != NULL)
  83. {
  84. pSidArray[dwCount++] = (PSID)(pAfpDirInfo->afpdir_group);
  85. }
  86. // Try to get the names of the owner and primary group.
  87. //
  88. if (dwCount > 0)
  89. {
  90. ntStatus = LsaLookupSids( hLsa, dwCount, pSidArray, &pDomainList, &pNames );
  91. if ( !NT_SUCCESS( ntStatus ) ) {
  92. if ( ntStatus == STATUS_NONE_MAPPED ) {
  93. fUseUnknownAccount = TRUE;
  94. dwRetCode = NO_ERROR;
  95. }
  96. else {
  97. dwRetCode = RtlNtStatusToDosError( ntStatus );
  98. AFP_PRINT(( "SFMSVC: AfpDirConvertSidsToNames, LsaLookupSids failed with error (%ld)\n", dwRetCode));
  99. break;
  100. }
  101. }
  102. }
  103. // We need to calculate the length of the buffer we need to allocate.
  104. //
  105. for( dwIndex = 0,
  106. dwRetCode = NO_ERROR,
  107. cbOutputBuf = sizeof( AFP_DIRECTORY_INFO );
  108. dwIndex < dwCount;
  109. dwIndex++ ) {
  110. if ( fUseUnknownAccount )
  111. dwUse = SidTypeUnknown;
  112. else
  113. dwUse = pNames[dwIndex].Use;
  114. switch( dwUse ) {
  115. case SidTypeInvalid:
  116. cbOutputBuf += ((wcslen((LPWSTR)(AfpGlobals.wchInvalid))+1)
  117. * sizeof(WCHAR));
  118. break;
  119. case SidTypeDeletedAccount:
  120. cbOutputBuf += ((wcslen((LPWSTR)(AfpGlobals.wchDeleted))+1)
  121. * sizeof(WCHAR));
  122. break;
  123. case SidTypeUnknown:
  124. cbOutputBuf += ((wcslen((LPWSTR)(AfpGlobals.wchUnknown))+1)
  125. * sizeof(WCHAR));
  126. break;
  127. case SidTypeWellKnownGroup:
  128. cbOutputBuf += (pNames[dwIndex].Name.Length+sizeof(WCHAR));
  129. break;
  130. case SidTypeDomain:
  131. cbOutputBuf +=
  132. ((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name.Length + sizeof(WCHAR) );
  133. break;
  134. default:
  135. if ( ( pNames[dwIndex].DomainIndex != -1 ) &&
  136. ( pNames[dwIndex].Name.Buffer != NULL ) ) {
  137. PSID pDomainSid;
  138. PUNICODE_STRING pDomain;
  139. pDomain =
  140. &((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name);
  141. pDomainSid =
  142. (pDomainList->Domains[pNames[dwIndex].DomainIndex]).Sid;
  143. if ( !RtlEqualSid( &AfpBuiltInSid, pDomainSid ))
  144. cbOutputBuf += ( pDomain->Length + sizeof( TEXT('\\')));
  145. cbOutputBuf += (pNames[dwIndex].Name.Length+sizeof(WCHAR));
  146. }
  147. else
  148. dwRetCode = ERROR_NONE_MAPPED;
  149. break;
  150. }
  151. }
  152. pOutputBuf = (PAFP_DIRECTORY_INFO)MIDL_user_allocate( cbOutputBuf );
  153. if ( pOutputBuf == NULL ) {
  154. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  155. AFP_PRINT(( "SFMSVC: AfpDirConvertSidsToNames, MIDL_user_allocate 1 failed with error (%ld)\n", dwRetCode));
  156. break;
  157. }
  158. ZeroMemory( (LPBYTE)pOutputBuf, cbOutputBuf );
  159. // Copy the fixed part of the structure.
  160. //
  161. CopyMemory( (LPBYTE)pOutputBuf,
  162. (LPBYTE)pAfpDirInfo,
  163. sizeof(AFP_DIRECTORY_INFO) );
  164. // Now we need to copy the names
  165. //
  166. for( dwIndex = 0,
  167. pbVariableData = (LPBYTE)((ULONG_PTR)pOutputBuf + cbOutputBuf);
  168. dwIndex < dwCount;
  169. dwIndex++ ) {
  170. if ( fUseUnknownAccount )
  171. dwUse = SidTypeUnknown;
  172. else
  173. dwUse = pNames[dwIndex].Use;
  174. switch( dwUse ) {
  175. case SidTypeInvalid:
  176. pbVariableData -= ((wcslen(AfpGlobals.wchInvalid)+1)
  177. * sizeof(WCHAR));
  178. wcscpy( (LPWSTR)pbVariableData, AfpGlobals.wchInvalid );
  179. break;
  180. case SidTypeDeletedAccount:
  181. pbVariableData -= ((wcslen(AfpGlobals.wchDeleted)+1)
  182. * sizeof(WCHAR));
  183. wcscpy( (LPWSTR)pbVariableData, AfpGlobals.wchDeleted );
  184. break;
  185. case SidTypeUnknown:
  186. pbVariableData -= ((wcslen(AfpGlobals.wchUnknown)+1)
  187. * sizeof(WCHAR));
  188. wcscpy( (LPWSTR)pbVariableData, AfpGlobals.wchUnknown );
  189. break;
  190. case SidTypeWellKnownGroup:
  191. pbVariableData -= (pNames[dwIndex].Name.Length+sizeof(WCHAR));
  192. CopyMemory( pbVariableData,
  193. pNames[dwIndex].Name.Buffer,
  194. pNames[dwIndex].Name.Length );
  195. break;
  196. case SidTypeDomain:
  197. cbOutputBuf +=
  198. ((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name.Length);
  199. CopyMemory( pbVariableData,
  200. ((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name.Buffer),
  201. ((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name.Length));
  202. break;
  203. default:
  204. {
  205. PSID pDomainSid;
  206. PUNICODE_STRING pDomain;
  207. pDomain =
  208. &((pDomainList->Domains[pNames[dwIndex].DomainIndex]).Name);
  209. pDomainSid =
  210. (pDomainList->Domains[pNames[dwIndex].DomainIndex]).Sid;
  211. pbVariableData -= ((pNames[dwIndex].Name.Length+sizeof(WCHAR)));
  212. pWchar = (WCHAR*)pbVariableData;
  213. // Copy the domain name if it is not BUILTIN
  214. //
  215. if ( !RtlEqualSid( &AfpBuiltInSid, pDomainSid ) ) {
  216. pbVariableData -= ( pDomain->Length + sizeof( TEXT('\\')));
  217. CopyMemory(pbVariableData,pDomain->Buffer,pDomain->Length);
  218. wcscat((LPWSTR)pbVariableData, (LPWSTR)TEXT("\\"));
  219. pWchar = (WCHAR*)pbVariableData;
  220. pWchar += wcslen( (LPWSTR)pbVariableData );
  221. }
  222. CopyMemory( pWchar,
  223. pNames[dwIndex].Name.Buffer,
  224. pNames[dwIndex].Name.Length );
  225. }
  226. }
  227. // If this is the first time this loop executes then set the
  228. // owner.
  229. //
  230. if ( (dwIndex == 0) && (pAfpDirInfo->afpdir_owner != NULL) )
  231. pOutputBuf->afpdir_owner = (LPWSTR)pbVariableData;
  232. else
  233. pOutputBuf->afpdir_group = (LPWSTR)pbVariableData;
  234. }
  235. } while( FALSE );
  236. if ( pNames != NULL )
  237. LsaFreeMemory( pNames );
  238. if ( pDomainList != NULL )
  239. LsaFreeMemory( pDomainList );
  240. if ( hLsa != NULL )
  241. LsaClose( hLsa );
  242. if ( dwRetCode != NO_ERROR ) {
  243. AFP_PRINT(( "SFMSVC: AfpDirConvertSidsToNames, failed, error = (%ld)\n"
  244. , dwRetCode));
  245. if ( pOutputBuf != NULL )
  246. MIDL_user_free( pOutputBuf );
  247. }
  248. else
  249. {
  250. *ppAfpConvertedDirInfo = pOutputBuf;
  251. }
  252. return( dwRetCode );
  253. }
  254. //**
  255. //
  256. // Call: AfpGetDirInfo
  257. //
  258. // Returns: NO_ERROR - success
  259. // ERROR_NOT_ENOUGH_MEMORY
  260. // Non-zero returns from NtOpenFile, NtQuerySecurityObject,
  261. // NtQueryInformationFile.
  262. //
  263. // Description: Read the security descriptor for this directory and obtain the
  264. // SIDs for Owner and Primary group. Finally obtain Owner, Group
  265. // and World permissions.
  266. DWORD
  267. AfpGetDirInfo(
  268. LPWSTR lpwsDirPath,
  269. PAFP_DIRECTORY_INFO * lppDirInfo
  270. )
  271. {
  272. NTSTATUS ntStatus;
  273. DWORD dwSizeNeeded;
  274. PBYTE pBuffer = NULL;
  275. PBYTE pAbsBuffer = NULL;
  276. PISECURITY_DESCRIPTOR pSecDesc;
  277. PBYTE pAbsSecDesc = NULL; // Used in conversion of
  278. // sec descriptor to
  279. // absolute format
  280. BOOL fSawOwnerAce = FALSE;
  281. BOOL fSawGroupAce = FALSE;
  282. BYTE bOwnerRights = 0;
  283. BYTE bGroupRights = 0;
  284. BYTE bWorldRights = 0;
  285. FILE_BASIC_INFORMATION FileBasicInfo;
  286. IO_STATUS_BLOCK IOStatusBlock;
  287. OBJECT_ATTRIBUTES ObjectAttributes;
  288. UNICODE_STRING DirectoryName;
  289. HANDLE hDirectory;
  290. PAFP_DIRECTORY_INFO pAfpDir;
  291. DWORD dwAlignedSizeAfpDirInfo = sizeof (AFP_DIRECTORY_INFO);
  292. LPWSTR pDirPath;
  293. SID AfpSidNull = { 1, 1, SECURITY_NULL_SID_AUTHORITY,
  294. SECURITY_NULL_RID };
  295. SID AfpSidWorld = { 1, 1, SECURITY_WORLD_SID_AUTHORITY,
  296. SECURITY_WORLD_RID };
  297. pDirPath = (LPWSTR)LocalAlloc( LPTR,
  298. ( STRLEN(lpwsDirPath) +
  299. STRLEN(TEXT("\\DOSDEVICES\\"))+1)
  300. * sizeof( WCHAR ) );
  301. if ( pDirPath == NULL )
  302. return( ERROR_NOT_ENOUGH_MEMORY );
  303. STRCPY( pDirPath, TEXT("\\DOSDEVICES\\") );
  304. STRCAT( pDirPath, lpwsDirPath );
  305. RtlInitUnicodeString( &DirectoryName, pDirPath );
  306. InitializeObjectAttributes( &ObjectAttributes,
  307. &DirectoryName,
  308. OBJ_CASE_INSENSITIVE,
  309. NULL,
  310. NULL );
  311. ntStatus = NtOpenFile( &hDirectory,
  312. GENERIC_READ | READ_CONTROL | SYNCHRONIZE,
  313. &ObjectAttributes,
  314. &IOStatusBlock,
  315. FILE_SHARE_READ |
  316. FILE_SHARE_WRITE |
  317. FILE_SHARE_DELETE,
  318. FILE_DIRECTORY_FILE |
  319. FILE_SYNCHRONOUS_IO_NONALERT );
  320. LocalFree( pDirPath );
  321. if ( !NT_SUCCESS( ntStatus ) )
  322. return( RtlNtStatusToDosError( ntStatus ) );
  323. // Read the security descriptor for this directory. First get the owner
  324. // and group security descriptors. We want to optimize on how much memory
  325. // we need to read this in. Its a pain to make a call just to get that.
  326. // So just make a guess. If that turns out to be short then do the exact
  327. // allocation.
  328. //
  329. dwSizeNeeded = 2048;
  330. do {
  331. if ( pBuffer != NULL )
  332. MIDL_user_free( pBuffer );
  333. if ((pBuffer = MIDL_user_allocate( dwSizeNeeded +
  334. dwAlignedSizeAfpDirInfo ))==NULL)
  335. return( ERROR_NOT_ENOUGH_MEMORY );
  336. ZeroMemory( pBuffer, dwSizeNeeded + dwAlignedSizeAfpDirInfo );
  337. pSecDesc = (PSECURITY_DESCRIPTOR)(pBuffer + dwAlignedSizeAfpDirInfo);
  338. ntStatus = NtQuerySecurityObject( hDirectory,
  339. OWNER_SECURITY_INFORMATION |
  340. GROUP_SECURITY_INFORMATION |
  341. DACL_SECURITY_INFORMATION,
  342. pSecDesc,
  343. dwSizeNeeded,
  344. &dwSizeNeeded);
  345. } while ((ntStatus != STATUS_SUCCESS) &&
  346. ((ntStatus == STATUS_BUFFER_OVERFLOW) ||
  347. (ntStatus == STATUS_BUFFER_TOO_SMALL) ||
  348. (ntStatus == STATUS_MORE_ENTRIES)));
  349. if (!NT_SUCCESS(ntStatus)) {
  350. NtClose( hDirectory );
  351. MIDL_user_free( pBuffer );
  352. return( RtlNtStatusToDosError( ntStatus ) );
  353. }
  354. pSecDesc = (PISECURITY_DESCRIPTOR)((PBYTE)pSecDesc);
  355. // If the security descriptor is in self-relative form, convert to absolute
  356. //
  357. if (pSecDesc->Control & SE_SELF_RELATIVE)
  358. {
  359. NTSTATUS Status;
  360. DWORD dwAbsoluteSizeNeeded;
  361. AFP_PRINT (("AfpGetDirInfo: SE_SELF_RELATIVE security desc\n"));
  362. // An absolute SD is not necessarily the same size as a relative
  363. // SD, so an in-place conversion may not be possible.
  364. dwAbsoluteSizeNeeded = dwSizeNeeded;
  365. Status = RtlSelfRelativeToAbsoluteSD2(pSecDesc, &dwAbsoluteSizeNeeded);
  366. // Buffer will be small only for 64-bit
  367. if (Status == STATUS_BUFFER_TOO_SMALL)
  368. {
  369. // Allocate a new buffer in which to store the absolute
  370. // security descriptor, copy the contents of the relative
  371. // descriptor in and try again
  372. if ((pAbsBuffer = MIDL_user_allocate( dwAbsoluteSizeNeeded +
  373. dwAlignedSizeAfpDirInfo ))==NULL)
  374. {
  375. Status = STATUS_NO_MEMORY;
  376. AFP_PRINT (("AfpGetDirInfo: MIDL_user_allocate failed for pAbsBuffer\n"));
  377. }
  378. else
  379. {
  380. ZeroMemory( pAbsBuffer, dwAbsoluteSizeNeeded + dwAlignedSizeAfpDirInfo );
  381. memcpy (pAbsBuffer, pBuffer, sizeof(AFP_DIRECTORY_INFO));
  382. pAbsSecDesc = (PSECURITY_DESCRIPTOR)(pAbsBuffer + dwAlignedSizeAfpDirInfo);
  383. RtlCopyMemory((VOID *)pAbsSecDesc, (VOID *)pSecDesc, dwSizeNeeded);
  384. // All operations hereon will be performed on
  385. // pAbsBuffer. Free earlier memory
  386. MIDL_user_free(pBuffer);
  387. pBuffer = NULL;
  388. pBuffer = pAbsBuffer;
  389. Status = RtlSelfRelativeToAbsoluteSD2 (pAbsSecDesc,
  390. &dwAbsoluteSizeNeeded);
  391. if (NT_SUCCESS(Status))
  392. {
  393. // We don't need relative form anymore,
  394. // we will work with the Absolute form
  395. pSecDesc = (PISECURITY_DESCRIPTOR)pAbsSecDesc;
  396. }
  397. else
  398. {
  399. AFP_PRINT (("AfpGetDirInfo: RtlSelfRelativeToAbsoluteSD2 2 failed with error %ld\n", Status));
  400. }
  401. }
  402. }
  403. else
  404. {
  405. AFP_PRINT (("AfpGetDirInfo: RtlSelfRelativeToAbsoluteSD2 failed with error %ld\n", Status));
  406. }
  407. if (!NT_SUCCESS(Status))
  408. {
  409. AFP_PRINT (("AfpGetDirInfo: RtlSelfRelativeToAbsoluteSD2: returned error %lx\n", Status));
  410. if (pBuffer != NULL)
  411. {
  412. MIDL_user_free( pBuffer );
  413. pBuffer = NULL;
  414. }
  415. NtClose( hDirectory );
  416. return( RtlNtStatusToDosError( ntStatus ));
  417. }
  418. }
  419. pAfpDir = (PAFP_DIRECTORY_INFO)pBuffer;
  420. // Walk through the ACL list and determine Owner/Group and World
  421. // permissions. For Owner and Group, if the specific ace's are not
  422. // present then they inherit the world permissions.
  423. //
  424. // A NULL Acl => All rights to everyone. An empty Acl on the other
  425. // hand => no access for anyone.
  426. //
  427. // Should we be checking for creater owner/creater group well-defined
  428. // sids or the Owner and Group fields in the security descriptor ?
  429. //
  430. bWorldRights = DIR_ACCESS_ALL;
  431. if (pSecDesc->Control & SE_DACL_PRESENT)
  432. bWorldRights = 0;
  433. if (pSecDesc->Dacl != NULL ) {
  434. DWORD dwCount;
  435. PSID pSid;
  436. PACL pAcl;
  437. PACCESS_ALLOWED_ACE pAce;
  438. bWorldRights = 0;
  439. pAcl = pSecDesc->Dacl;
  440. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAcl + sizeof(ACL));
  441. for ( dwCount = 0; dwCount < pSecDesc->Dacl->AceCount; dwCount++) {
  442. pSid = (PSID)(&pAce->SidStart);
  443. if ( (pSecDesc->Owner != NULL) &&
  444. RtlEqualSid(pSid, pSecDesc->Owner ) ){
  445. AfpAccessMaskToAfpPermissions( bOwnerRights,
  446. pAce->Mask,
  447. pAce->Header.AceType);
  448. fSawOwnerAce = TRUE;
  449. }
  450. if ( ( pSecDesc->Group != NULL ) &&
  451. RtlEqualSid(pSid, pSecDesc->Group)){
  452. AfpAccessMaskToAfpPermissions( bGroupRights,
  453. pAce->Mask,
  454. pAce->Header.AceType);
  455. fSawGroupAce = TRUE;
  456. }
  457. if (RtlEqualSid(pSid, (PSID)&AfpSidWorld)) {
  458. AfpAccessMaskToAfpPermissions( bWorldRights,
  459. pAce->Mask,
  460. pAce->Header.AceType);
  461. }
  462. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAce + pAce->Header.AceSize);
  463. }
  464. }
  465. if (!fSawOwnerAce)
  466. bOwnerRights = bWorldRights;
  467. if (!fSawGroupAce)
  468. bGroupRights = bWorldRights;
  469. if (RtlEqualSid(pSecDesc->Group, &AfpSidNull) ||
  470. ((AfpGlobals.NtProductType != NtProductLanManNt) &&
  471. RtlEqualSid(pSecDesc->Group, AfpGlobals.pSidNone)))
  472. {
  473. bGroupRights = 0;
  474. pSecDesc->Group = NULL;
  475. }
  476. ntStatus = NtQueryInformationFile( hDirectory,
  477. &IOStatusBlock,
  478. &FileBasicInfo,
  479. sizeof( FileBasicInfo ),
  480. FileBasicInformation );
  481. NtClose( hDirectory );
  482. if ( !NT_SUCCESS( ntStatus ) ) {
  483. MIDL_user_free( pBuffer );
  484. return( RtlNtStatusToDosError( ntStatus ) );
  485. }
  486. pAfpDir->afpdir_perms = (bOwnerRights << OWNER_RIGHTS_SHIFT) +
  487. (bGroupRights << GROUP_RIGHTS_SHIFT) +
  488. (bWorldRights << WORLD_RIGHTS_SHIFT);
  489. if ( FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_READONLY )
  490. pAfpDir->afpdir_perms |= AFP_PERM_INHIBIT_MOVE_DELETE;
  491. pAfpDir->afpdir_owner = pSecDesc->Owner;
  492. pAfpDir->afpdir_group = pSecDesc->Group;
  493. *lppDirInfo = pAfpDir;
  494. return( NO_ERROR );
  495. }
  496. //**
  497. //
  498. // Call: AfpValidatePartition
  499. //
  500. // Returns: NO_ERROR
  501. // non-zero returns from GetVolumeInformation.
  502. // AFPERR_UnsupportedFS
  503. //
  504. //
  505. // Description: Will check to see if the directory is in an NTFS/CDFS
  506. // partition not.
  507. //
  508. DWORD
  509. AfpValidatePartition(
  510. IN LPWSTR lpwsPath
  511. )
  512. {
  513. WCHAR wchDrive[5];
  514. DWORD dwMaxCompSize;
  515. DWORD dwFlags;
  516. WCHAR wchFileSystem[10];
  517. // Get the drive letter, : and backslash
  518. //
  519. ZeroMemory( wchDrive, sizeof( wchDrive ) );
  520. STRNCPY( wchDrive, lpwsPath, 3 );
  521. if ( !( GetVolumeInformation( (LPWSTR)wchDrive,
  522. NULL,
  523. 0,
  524. NULL,
  525. &dwMaxCompSize,
  526. &dwFlags,
  527. (LPWSTR)wchFileSystem,
  528. sizeof( wchFileSystem ) ) ) ){
  529. return GetLastError();
  530. }
  531. if ( STRICMP( wchFileSystem, TEXT("CDFS") ) == 0 )
  532. return( (DWORD)AFPERR_SecurityNotSupported );
  533. if ( STRICMP( wchFileSystem, TEXT("NTFS") ) == 0 )
  534. return( NO_ERROR );
  535. else
  536. return( (DWORD)AFPERR_UnsupportedFS );
  537. }
  538. //**
  539. //
  540. // Call: AfpAdminrDirectoryGetInfo
  541. //
  542. // Returns: NO_ERROR
  543. // ERROR_ACCESS_DENIED
  544. // non-zero retunrs from I_DirectoryGetInfo
  545. //
  546. // Description: This routine communicates with the AFP FSD to implement
  547. // the AfpAdminDirectoryGetInfo function. The real work is done
  548. // by I_DirectoryGetInfo
  549. //
  550. DWORD
  551. AfpAdminrDirectoryGetInfo(
  552. IN AFP_SERVER_HANDLE hServer,
  553. IN LPWSTR lpwsPath,
  554. OUT PAFP_DIRECTORY_INFO* ppAfpDirectoryInfo
  555. )
  556. {
  557. DWORD dwRetCode=0;
  558. DWORD dwAccessStatus=0;
  559. // Check if caller has access
  560. //
  561. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  562. {
  563. AFP_PRINT(( "SFMSVC: AfpAdminrDirectoryGetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  564. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  565. dwRetCode, EVENTLOG_ERROR_TYPE );
  566. return( ERROR_ACCESS_DENIED );
  567. }
  568. if ( dwAccessStatus )
  569. {
  570. AFP_PRINT(( "SFMSVC: AfpAdminrDirectoryGetInfo, AfpSecObjAccessCheck returned error (%ld)\n",dwAccessStatus));
  571. return( ERROR_ACCESS_DENIED );
  572. }
  573. dwRetCode = I_DirectoryGetInfo( lpwsPath, ppAfpDirectoryInfo );
  574. return( dwRetCode );
  575. }
  576. //**
  577. //
  578. // Call: I_DirectoryGetInfo
  579. //
  580. // Returns: NO_ERROR
  581. //
  582. // Description: This does the real work to get the directory information.
  583. // The reason for this worker routine is so that it may be
  584. // called without the RPC handle and access checking by
  585. // AfpAdminVolumeAdd API.
  586. //
  587. DWORD
  588. I_DirectoryGetInfo(
  589. IN LPWSTR lpwsPath,
  590. OUT PAFP_DIRECTORY_INFO * ppAfpDirectoryInfo
  591. )
  592. {
  593. DWORD dwRetCode;
  594. AFP_REQUEST_PACKET AfpSrp;
  595. AFP_DIRECTORY_INFO AfpDirInfo;
  596. PAFP_DIRECTORY_INFO pAfpDirInfoSR;
  597. PAFP_DIRECTORY_INFO pAfpDirInfo;
  598. DWORD cbAfpDirInfoSRSize;
  599. // The FSD expects AFP_VOLUME_INFO structure with only the dir path field
  600. // filled in.
  601. //
  602. AfpDirInfo.afpdir_path = lpwsPath;
  603. AfpDirInfo.afpdir_owner = NULL;
  604. AfpDirInfo.afpdir_group = NULL;
  605. // Make buffer self relative.
  606. //
  607. if ( dwRetCode = AfpBufMakeFSDRequest( (LPBYTE)&AfpDirInfo,
  608. 0,
  609. AFP_DIRECTORY_STRUCT,
  610. (LPBYTE*)&pAfpDirInfoSR,
  611. &cbAfpDirInfoSRSize ) )
  612. return( dwRetCode );
  613. // Make IOCTL to get info
  614. //
  615. AfpSrp.dwRequestCode = OP_DIRECTORY_GET_INFO;
  616. AfpSrp.dwApiType = AFP_API_TYPE_GETINFO;
  617. AfpSrp.Type.GetInfo.pInputBuf = pAfpDirInfoSR;
  618. AfpSrp.Type.GetInfo.cbInputBufSize = cbAfpDirInfoSRSize;
  619. dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp );
  620. LocalFree( pAfpDirInfoSR );
  621. if ( ( dwRetCode != ERROR_MORE_DATA ) &&
  622. ( dwRetCode != NO_ERROR ) &&
  623. ( dwRetCode != AFPERR_DirectoryNotInVolume ) )
  624. return( dwRetCode );
  625. // If the directory is not part of a volume, then there server does not
  626. // return any information back. So we have to do the work here.
  627. //
  628. if ( dwRetCode == AFPERR_DirectoryNotInVolume ) {
  629. // First check to see if the directory is in an NTFS/CDFS partition
  630. //
  631. if ( ( dwRetCode = AfpValidatePartition( AfpDirInfo.afpdir_path ))
  632. != NO_ERROR )
  633. return( dwRetCode );
  634. if ( ( dwRetCode = AfpGetDirInfo( AfpDirInfo.afpdir_path,
  635. &pAfpDirInfo ) ) != NO_ERROR )
  636. return( dwRetCode );
  637. pAfpDirInfo->afpdir_in_volume = FALSE;
  638. }
  639. else {
  640. pAfpDirInfo = AfpSrp.Type.GetInfo.pOutputBuf;
  641. // Convert all offsets to pointers
  642. //
  643. AfpBufOffsetToPointer( (LPBYTE)pAfpDirInfo, 1, AFP_DIRECTORY_STRUCT );
  644. pAfpDirInfo->afpdir_in_volume = TRUE;
  645. }
  646. // Now convert the owner and group SIDs to names
  647. //
  648. dwRetCode = AfpDirConvertSidsToNames( pAfpDirInfo, ppAfpDirectoryInfo );
  649. MIDL_user_free( pAfpDirInfo );
  650. return( dwRetCode );
  651. }
  652. //**
  653. //
  654. // Call: AfpDirMakeFSDRequest
  655. //
  656. // Returns: NO_ERROR
  657. // non-zero returnd from LsaLookupNames
  658. // ERROR_NOT_ENOUGH_MEMORY
  659. //
  660. // Description: Given a AFP_DIRECTORY_INFO structure, will create a
  661. // self-relative buffer that is used to IOCTL the directory
  662. // information down to the FSD. If there are any SIDs names
  663. // (owner or group) they will be converted to their
  664. // SIDs.
  665. //
  666. DWORD
  667. AfpDirMakeFSDRequest(
  668. IN PAFP_DIRECTORY_INFO pAfpDirectoryInfo,
  669. IN DWORD dwParmNum,
  670. IN OUT PAFP_DIRECTORY_INFO * ppAfpDirInfoSR,
  671. OUT LPDWORD pcbAfpDirInfoSRSize )
  672. {
  673. UNICODE_STRING Names[2];
  674. DWORD dwIndex = 0;
  675. DWORD dwCount = 0;
  676. PLSA_REFERENCED_DOMAIN_LIST pDomainList = NULL;
  677. PLSA_TRANSLATED_SID pSids = NULL;
  678. LPBYTE pbVariableData;
  679. NTSTATUS ntStatus;
  680. LSA_HANDLE hLsa = NULL;
  681. SECURITY_QUALITY_OF_SERVICE QOS;
  682. OBJECT_ATTRIBUTES ObjectAttributes;
  683. PSID pDomainSid;
  684. DWORD AuthCount;
  685. PAFP_DIRECTORY_INFO pAfpDirInfo;
  686. *pcbAfpDirInfoSRSize = (DWORD)(sizeof( SETINFOREQPKT ) +
  687. sizeof( AFP_DIRECTORY_INFO ) +
  688. (( wcslen( pAfpDirectoryInfo->afpdir_path ) + 1 )
  689. * sizeof(WCHAR)));
  690. // If the client wants to set the owner or the group
  691. // then we need to translate the names to sids
  692. //
  693. if ( ( dwParmNum & AFP_DIR_PARMNUM_OWNER ) ||
  694. ( dwParmNum & AFP_DIR_PARMNUM_GROUP ) )
  695. {
  696. // First open the LSA and obtain a handle to it.
  697. //
  698. QOS.Length = sizeof( QOS );
  699. QOS.ImpersonationLevel = SecurityImpersonation;
  700. QOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  701. QOS.EffectiveOnly = FALSE;
  702. InitializeObjectAttributes( &ObjectAttributes,
  703. NULL,
  704. 0L,
  705. NULL,
  706. NULL );
  707. ObjectAttributes.SecurityQualityOfService = &QOS;
  708. ntStatus = LsaOpenPolicy( NULL,
  709. &ObjectAttributes,
  710. POLICY_LOOKUP_NAMES,
  711. &hLsa );
  712. if ( !NT_SUCCESS( ntStatus ))
  713. {
  714. return( RtlNtStatusToDosError( ntStatus ) );
  715. }
  716. //
  717. // Translate the owner
  718. //
  719. if ( dwParmNum & AFP_DIR_PARMNUM_OWNER )
  720. {
  721. RtlInitUnicodeString( &(Names[dwCount++]),
  722. pAfpDirectoryInfo->afpdir_owner );
  723. }
  724. //
  725. // Translate the group
  726. //
  727. if ( dwParmNum & AFP_DIR_PARMNUM_GROUP )
  728. {
  729. RtlInitUnicodeString( &(Names[dwCount++]),
  730. pAfpDirectoryInfo->afpdir_group );
  731. }
  732. ntStatus = LsaLookupNames(hLsa, dwCount, Names, &pDomainList, &pSids);
  733. if ( !NT_SUCCESS( ntStatus ) )
  734. {
  735. LsaClose( hLsa );
  736. if ( ntStatus == STATUS_NONE_MAPPED )
  737. {
  738. return( (DWORD)AFPERR_NoSuchUserGroup );
  739. }
  740. else
  741. {
  742. return( RtlNtStatusToDosError( ntStatus ) );
  743. }
  744. }
  745. for ( dwIndex = 0; dwIndex < dwCount; dwIndex++ )
  746. {
  747. if ( ( pSids[dwIndex].Use == SidTypeInvalid ) ||
  748. ( pSids[dwIndex].Use == SidTypeUnknown ) ||
  749. ( pSids[dwIndex].Use == SidTypeDomain ) ||
  750. ( pSids[dwIndex].DomainIndex == -1 ) )
  751. {
  752. LsaFreeMemory( pDomainList );
  753. LsaClose( hLsa );
  754. if ( ( pSids[dwIndex].Use == SidTypeUnknown ) ||
  755. ( pSids[dwIndex].Use == SidTypeInvalid ) )
  756. {
  757. LsaFreeMemory( pSids );
  758. if ((dwParmNum & AFP_DIR_PARMNUM_OWNER)&&(dwIndex == 0 ))
  759. {
  760. return( (DWORD)AFPERR_NoSuchUser );
  761. }
  762. else
  763. {
  764. return( (DWORD)AFPERR_NoSuchGroup );
  765. }
  766. }
  767. else
  768. {
  769. LsaFreeMemory( pSids );
  770. return( (DWORD)AFPERR_NoSuchUserGroup );
  771. }
  772. }
  773. pDomainSid = pDomainList->Domains[pSids[dwIndex].DomainIndex].Sid;
  774. AuthCount = *RtlSubAuthorityCountSid( pDomainSid ) + 1;
  775. *pcbAfpDirInfoSRSize += RtlLengthRequiredSid(AuthCount);
  776. }
  777. }
  778. *ppAfpDirInfoSR=(PAFP_DIRECTORY_INFO)LocalAlloc(LPTR,*pcbAfpDirInfoSRSize);
  779. if ( *ppAfpDirInfoSR == NULL )
  780. {
  781. LsaFreeMemory( pDomainList );
  782. LsaFreeMemory( pSids );
  783. LsaClose( hLsa );
  784. return( ERROR_NOT_ENOUGH_MEMORY );
  785. }
  786. pbVariableData = (LPBYTE)((ULONG_PTR)(*ppAfpDirInfoSR) + *pcbAfpDirInfoSRSize);
  787. pAfpDirInfo = (PAFP_DIRECTORY_INFO)((ULONG_PTR)( *ppAfpDirInfoSR) +
  788. sizeof( SETINFOREQPKT ));
  789. // First copy the fixed part
  790. //
  791. CopyMemory( pAfpDirInfo, pAfpDirectoryInfo, sizeof(AFP_DIRECTORY_INFO) );
  792. // Now copy the path
  793. //
  794. pbVariableData-=((wcslen(pAfpDirectoryInfo->afpdir_path)+1)*sizeof(WCHAR));
  795. wcscpy( (LPWSTR)pbVariableData, pAfpDirectoryInfo->afpdir_path );
  796. pAfpDirInfo->afpdir_path = (LPWSTR)pbVariableData;
  797. POINTER_TO_OFFSET( pAfpDirInfo->afpdir_path, pAfpDirInfo );
  798. // Now copy the SIDs if there are any to be copied
  799. //
  800. dwCount = 0;
  801. if ( dwParmNum & AFP_DIR_PARMNUM_OWNER )
  802. {
  803. pDomainSid = pDomainList->Domains[pSids[dwCount].DomainIndex].Sid;
  804. AuthCount = *RtlSubAuthorityCountSid( pDomainSid ) + 1;
  805. pbVariableData -= RtlLengthRequiredSid(AuthCount);
  806. // Copy the Domain Sid.
  807. //
  808. RtlCopySid( RtlLengthRequiredSid(AuthCount),
  809. (PSID)pbVariableData,
  810. pDomainSid );
  811. // Append the Relative Id.
  812. //
  813. *RtlSubAuthorityCountSid( (PSID)pbVariableData ) += 1;
  814. *RtlSubAuthoritySid( (PSID)(pbVariableData), AuthCount - 1) =
  815. pSids[dwCount].RelativeId;
  816. pAfpDirInfo->afpdir_owner = (LPWSTR)pbVariableData;
  817. POINTER_TO_OFFSET( pAfpDirInfo->afpdir_owner, pAfpDirInfo );
  818. dwCount++;
  819. }
  820. if ( dwParmNum & AFP_DIR_PARMNUM_GROUP )
  821. {
  822. pDomainSid = pDomainList->Domains[pSids[dwCount].DomainIndex].Sid;
  823. AuthCount = *RtlSubAuthorityCountSid( pDomainSid ) + 1;
  824. pbVariableData -= RtlLengthRequiredSid(AuthCount);
  825. // Copy the Domain Sid.
  826. //
  827. RtlCopySid( RtlLengthRequiredSid(AuthCount),
  828. (PSID)pbVariableData,
  829. pDomainSid );
  830. // Append the Relative Id.
  831. //
  832. *RtlSubAuthorityCountSid( (PSID)pbVariableData ) += 1;
  833. *RtlSubAuthoritySid( (PSID)(pbVariableData), AuthCount - 1) =
  834. pSids[dwCount].RelativeId;
  835. pAfpDirInfo->afpdir_group = (LPWSTR)pbVariableData;
  836. POINTER_TO_OFFSET( pAfpDirInfo->afpdir_group, pAfpDirInfo );
  837. }
  838. LsaFreeMemory( pDomainList );
  839. LsaFreeMemory( pSids );
  840. LsaClose( hLsa );
  841. return( NO_ERROR );
  842. }
  843. //**
  844. //
  845. // Call: AfpSetDirPermission
  846. //
  847. // Returns: NO_ERROR
  848. // non-zero returns from AfpserverIOCtrl.
  849. //
  850. // Description: Given a directory path, will try to set permissions on it
  851. //
  852. DWORD
  853. AfpSetDirPermission(
  854. IN LPWSTR lpwsDirPath,
  855. IN PAFP_DIRECTORY_INFO pAfpDirInfo,
  856. IN DWORD dwParmNum
  857. )
  858. {
  859. AFP_REQUEST_PACKET AfpSrp;
  860. PAFP_DIRECTORY_INFO pAfpDirInfoSR;
  861. DWORD cbAfpDirInfoSRSize;
  862. DWORD dwRetCode;
  863. pAfpDirInfo->afpdir_path = lpwsDirPath;
  864. // Make a self relative buffer and translate any names to SIDs
  865. //
  866. if ( dwRetCode = AfpDirMakeFSDRequest( pAfpDirInfo,
  867. dwParmNum,
  868. &pAfpDirInfoSR,
  869. &cbAfpDirInfoSRSize ) )
  870. return( dwRetCode );
  871. // Make IOCTL to set info
  872. //
  873. AfpSrp.dwRequestCode = OP_DIRECTORY_SET_INFO;
  874. AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
  875. AfpSrp.Type.SetInfo.pInputBuf = pAfpDirInfoSR;
  876. AfpSrp.Type.SetInfo.cbInputBufSize = cbAfpDirInfoSRSize;
  877. AfpSrp.Type.SetInfo.dwParmNum = dwParmNum;
  878. dwRetCode = AfpServerIOCtrl( &AfpSrp );
  879. LocalFree( pAfpDirInfoSR );
  880. return( dwRetCode );
  881. }
  882. //**
  883. //
  884. // Call: AfpRecursePermissions
  885. //
  886. // Returns: NO_ERROR
  887. // non-zero returns from FindFirstFile and FindNextFile.
  888. // non-zero returns from AfpSetDirPermissions
  889. // ERROR_NOT_ENOUGH_MEMORY.
  890. //
  891. // Description: Will recursively set permissions on a given directory.
  892. //
  893. DWORD
  894. AfpRecursePermissions(
  895. IN HANDLE hFile,
  896. IN LPWSTR lpwsDirPath,
  897. IN PAFP_DIRECTORY_INFO pAfpDirInfo,
  898. IN DWORD dwParmNum
  899. )
  900. {
  901. WIN32_FIND_DATA FileInfo;
  902. DWORD dwRetCode = NO_ERROR;
  903. LPWSTR lpwsPath;
  904. WCHAR * pwchPath;
  905. DWORD dwRetryCount;
  906. do {
  907. lpwsPath = LocalAlloc(LPTR,
  908. (STRLEN(lpwsDirPath)+MAX_PATH)*sizeof(WCHAR));
  909. if ( lpwsPath == NULL ) {
  910. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  911. break;
  912. }
  913. STRCPY( lpwsPath, lpwsDirPath );
  914. if ( hFile != INVALID_HANDLE_VALUE ) {
  915. // Search for the next sub-directory
  916. //
  917. do {
  918. if ( !FindNextFile( hFile, &FileInfo ) ) {
  919. dwRetCode = GetLastError();
  920. AFP_PRINT( ( "AFPSVC_dir: Closing handle %x\n", hFile ) );
  921. FindClose( hFile );
  922. break;
  923. }
  924. if ( ( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
  925. (!( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM )) &&
  926. (!( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN )) &&
  927. ( STRCMP( FileInfo.cFileName, TEXT(".") ) != 0 ) &&
  928. ( STRCMP( FileInfo.cFileName, TEXT("..") ) != 0 ) )
  929. break;
  930. } while( TRUE );
  931. if ( dwRetCode != NO_ERROR )
  932. break;
  933. pwchPath = wcsrchr( lpwsPath, TEXT('\\') );
  934. STRCPY( pwchPath+1, FileInfo.cFileName );
  935. }else{
  936. STRCAT( lpwsPath, TEXT("\\*") );
  937. hFile = FindFirstFile( lpwsPath, &FileInfo );
  938. // If there are no more files, we return to the previous
  939. // level in the recursion.
  940. //
  941. if ( hFile == INVALID_HANDLE_VALUE ){
  942. dwRetCode = GetLastError();
  943. break;
  944. }
  945. // Search for the first sub-directory
  946. //
  947. do {
  948. if ( ( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
  949. (!( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM )) &&
  950. (!( FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN )) &&
  951. ( STRCMP( FileInfo.cFileName, TEXT(".") ) != 0 ) &&
  952. ( STRCMP( FileInfo.cFileName, TEXT("..") ) != 0 ) )
  953. break;
  954. if ( !FindNextFile( hFile, &FileInfo ) ) {
  955. dwRetCode = GetLastError();
  956. AFP_PRINT( ( "AFPSVC_dir: Closing handle %x\n", hFile ) );
  957. FindClose( hFile );
  958. break;
  959. }
  960. } while( TRUE );
  961. if ( dwRetCode != NO_ERROR )
  962. break;
  963. pwchPath = lpwsPath + STRLEN(lpwsDirPath) + 1;
  964. STRCPY( pwchPath, FileInfo.cFileName );
  965. }
  966. // Don't send the \\?\ down to the server
  967. pwchPath = lpwsPath + 4;
  968. // Set the information
  969. //
  970. dwRetryCount = 0;
  971. do
  972. {
  973. dwRetCode = AfpSetDirPermission( pwchPath, pAfpDirInfo, dwParmNum );
  974. if ( dwRetCode != ERROR_PATH_NOT_FOUND )
  975. break;
  976. Sleep( 1000 );
  977. } while( ++dwRetryCount < 4 );
  978. if ( dwRetCode != NO_ERROR )
  979. break;
  980. // Recurse on the directory
  981. //
  982. dwRetCode = AfpRecursePermissions( hFile,
  983. lpwsPath,
  984. pAfpDirInfo,
  985. dwParmNum );
  986. if ( dwRetCode != NO_ERROR )
  987. break;
  988. // Recurse on the sub-directory
  989. //
  990. dwRetCode = AfpRecursePermissions( INVALID_HANDLE_VALUE,
  991. lpwsPath,
  992. pAfpDirInfo,
  993. dwParmNum );
  994. break;
  995. if ( dwRetCode != NO_ERROR )
  996. break;
  997. } while( FALSE );
  998. if ( lpwsPath != (LPWSTR)NULL )
  999. {
  1000. LocalFree( lpwsPath );
  1001. }
  1002. if ( dwRetCode == ERROR_NO_MORE_FILES )
  1003. {
  1004. dwRetCode = NO_ERROR;
  1005. }
  1006. return( dwRetCode );
  1007. }
  1008. //**
  1009. //
  1010. // Call: AfpAdminrDirectorySetInfo
  1011. //
  1012. // Returns: NO_ERROR
  1013. // ERROR_ACCESS_DENIED
  1014. // non-zero retunrs from I_DirectorySetInfo.
  1015. //
  1016. // Description: This routine communicates with the AFP FSD to implement
  1017. // the AfpAdminDirectorySetInfo function. The real work is done
  1018. // by I_DirectorySetInfo
  1019. //
  1020. DWORD
  1021. AfpAdminrDirectorySetInfo(
  1022. IN AFP_SERVER_HANDLE hServer,
  1023. IN PAFP_DIRECTORY_INFO pAfpDirectoryInfo,
  1024. IN DWORD dwParmNum
  1025. )
  1026. {
  1027. DWORD dwRetCode=0;
  1028. DWORD dwAccessStatus=0;
  1029. // Check if caller has access
  1030. //
  1031. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  1032. {
  1033. AFP_PRINT(( "SFMSVC: AfpAdminrDirectorySetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  1034. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  1035. dwRetCode, EVENTLOG_ERROR_TYPE );
  1036. return( ERROR_ACCESS_DENIED );
  1037. }
  1038. if ( dwAccessStatus )
  1039. {
  1040. AFP_PRINT(( "SFMSVC: AfpAdminrDirectorySetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  1041. return( ERROR_ACCESS_DENIED );
  1042. }
  1043. dwRetCode = I_DirectorySetInfo( pAfpDirectoryInfo, dwParmNum );
  1044. return( dwRetCode );
  1045. }
  1046. //**
  1047. //
  1048. // Call: I_DirectorySetInfo
  1049. //
  1050. // Returns: NO_ERROR
  1051. //
  1052. //
  1053. // Description: This routine does the real work. The existance of this
  1054. // worker is so that it may be called from the AfpAfdminVolmeAdd
  1055. // API without the RPC handle and access checking.
  1056. //
  1057. DWORD
  1058. I_DirectorySetInfo(
  1059. IN PAFP_DIRECTORY_INFO pAfpDirectoryInfo,
  1060. IN DWORD dwParmNum
  1061. )
  1062. {
  1063. DWORD dwRetCode;
  1064. if (pAfpDirectoryInfo->afpdir_path == NULL)
  1065. {
  1066. AFP_PRINT(( "SFMSVC: I_DirectorySetInfo, pAfpDirectoryInfo->afpdir_path == NULL\n"));
  1067. return ERROR_INVALID_DATA;
  1068. }
  1069. // Set the permissions on the directory
  1070. //
  1071. if ( ( dwRetCode = AfpSetDirPermission( pAfpDirectoryInfo->afpdir_path,
  1072. pAfpDirectoryInfo,
  1073. dwParmNum ) ) != NO_ERROR )
  1074. return( dwRetCode );
  1075. // If the user wants to set these permissions recursively
  1076. //
  1077. if ( pAfpDirectoryInfo->afpdir_perms & AFP_PERM_SET_SUBDIRS )
  1078. {
  1079. LPWSTR NTDirName;
  1080. // We must use the \\?\ notation for the path in order to bypass
  1081. // the Win32 path length limitation of 260 chars
  1082. NTDirName = LocalAlloc( LPTR,
  1083. (STRLEN(pAfpDirectoryInfo->afpdir_path) + 4 + 1)
  1084. * sizeof(WCHAR));
  1085. if (NTDirName == NULL)
  1086. return( ERROR_NOT_ENOUGH_MEMORY );
  1087. STRCPY( NTDirName, TEXT("\\\\?\\"));
  1088. STRCAT( NTDirName, pAfpDirectoryInfo->afpdir_path);
  1089. dwRetCode = AfpRecursePermissions( INVALID_HANDLE_VALUE,
  1090. NTDirName,
  1091. pAfpDirectoryInfo,
  1092. dwParmNum );
  1093. LocalFree( NTDirName );
  1094. }
  1095. return( dwRetCode );
  1096. }