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.

1312 lines
33 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. svcshare.c
  5. Abstract:
  6. This module contains routines for supporting the share APIs in the
  7. server service, NetShareAdd, NetShareCheck, NetShareDel,
  8. NetShareEnum, NetShareGetInfo, and NetShareSetInfo.
  9. Author:
  10. David Treadwell (davidtr) 15-Jan-1991
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "svcshare.tmh"
  15. #pragma hdrstop
  16. #define BugCheckFileId SRV_FILE_SVCSHARE
  17. #define DISK_ROOT_NAME_TEMPLATE L"\\DosDevices\\X:\\"
  18. //
  19. // Forward declarations.
  20. //
  21. STATIC
  22. VOID
  23. FillShareInfoBuffer (
  24. IN PSERVER_REQUEST_PACKET Srp,
  25. IN PVOID Block,
  26. IN OUT PVOID *FixedStructure,
  27. IN LPWSTR *EndOfVariableData
  28. );
  29. STATIC
  30. BOOLEAN
  31. FilterShares (
  32. IN PSERVER_REQUEST_PACKET Srp,
  33. IN PVOID Block
  34. );
  35. STATIC
  36. ULONG
  37. SizeShares (
  38. IN PSERVER_REQUEST_PACKET Srp,
  39. IN PVOID Block
  40. );
  41. #ifdef ALLOC_PRAGMA
  42. #pragma alloc_text( PAGE, SrvNetShareAdd )
  43. #pragma alloc_text( PAGE, SrvNetShareDel )
  44. #pragma alloc_text( PAGE, SrvNetShareEnum )
  45. #pragma alloc_text( PAGE, SrvNetShareSetInfo )
  46. #pragma alloc_text( PAGE, FillShareInfoBuffer )
  47. #pragma alloc_text( PAGE, FilterShares )
  48. #pragma alloc_text( PAGE, SizeShares )
  49. #endif
  50. #define FIXED_SIZE_OF_SHARE(level) \
  51. ( (level) == 0 ? sizeof(SHARE_INFO_0) : \
  52. (level) == 1 ? sizeof(SHARE_INFO_1) : \
  53. (level) == 2 ? sizeof(SHARE_INFO_2) : \
  54. (level) == 501 ? sizeof(SHARE_INFO_501) : \
  55. (level) == 502 ? sizeof(SHARE_INFO_502) : \
  56. sizeof(SHARE_INFO_1005) )
  57. NTSTATUS
  58. SrvNetShareAdd (
  59. IN PSERVER_REQUEST_PACKET Srp,
  60. IN PVOID Buffer,
  61. IN ULONG BufferLength
  62. )
  63. /*++
  64. Routine Description:
  65. This routine processes the NetShareAdd API in the server.
  66. Arguments:
  67. Srp - a pointer to the server request packet that contains all
  68. the information necessary to satisfy the request. This includes:
  69. INPUT:
  70. Name1 - the NT path name of the share.
  71. OUTPUT:
  72. Parameters.Set.ErrorParameter - if STATUS_INVALID_PARAMETER is
  73. returned, this contains the index of the parameter in error.
  74. Buffer - a pointer to a SHARE_INFO2 structure for the new share.
  75. BufferLength - total length of this buffer.
  76. Return Value:
  77. NTSTATUS - result of operation to return to the server service.
  78. --*/
  79. {
  80. NTSTATUS status;
  81. PSHARE share;
  82. SHARE_TYPE shareType;
  83. BOOLEAN isSpecial;
  84. BOOLEAN isRemovable;
  85. BOOLEAN isCdrom;
  86. UNICODE_STRING shareName;
  87. UNICODE_STRING ntPath;
  88. UNICODE_STRING dosPath;
  89. UNICODE_STRING remark;
  90. PSHARE_INFO_502 shi502;
  91. PSECURITY_DESCRIPTOR securityDescriptor = NULL;
  92. PSECURITY_DESCRIPTOR fileSecurityDescriptor = NULL;
  93. PAGED_CODE( );
  94. //
  95. // We usually don't return any information about the parameter in
  96. // error.
  97. //
  98. Srp->Parameters.Set.ErrorParameter = 0;
  99. //
  100. // Convert the offsets in the share data structure to pointers. Also
  101. // make sure that all the pointers are within the specified buffer.
  102. //
  103. shi502 = Buffer;
  104. OFFSET_TO_POINTER( shi502->shi502_netname, shi502 );
  105. OFFSET_TO_POINTER( shi502->shi502_remark, shi502 );
  106. OFFSET_TO_POINTER( shi502->shi502_path, shi502 );
  107. OFFSET_TO_POINTER( shi502->shi502_security_descriptor, shi502 );
  108. //
  109. // Construct the security descriptor pointer by hand, because
  110. // shi502_permissions is only 32 bits in width.
  111. //
  112. if( shi502->shi502_permissions ) {
  113. securityDescriptor =
  114. (PSECURITY_DESCRIPTOR)((PCHAR)shi502 + shi502->shi502_permissions);
  115. }
  116. else
  117. {
  118. // Connect securityDescriptor is REQUIRED!
  119. return STATUS_INVALID_PARAMETER;
  120. }
  121. if ( !POINTER_IS_VALID( shi502->shi502_netname, shi502, BufferLength ) ||
  122. !POINTER_IS_VALID( shi502->shi502_remark, shi502, BufferLength ) ||
  123. !POINTER_IS_VALID( shi502->shi502_path, shi502, BufferLength ) ||
  124. !POINTER_IS_VALID( securityDescriptor, shi502, BufferLength ) ||
  125. !POINTER_IS_VALID( shi502->shi502_security_descriptor, shi502, BufferLength ) ) {
  126. return STATUS_ACCESS_VIOLATION;
  127. }
  128. //
  129. // Check the share type
  130. //
  131. isSpecial = (BOOLEAN)((shi502->shi502_type & STYPE_SPECIAL) != 0);
  132. isRemovable = FALSE;
  133. isCdrom = FALSE;
  134. switch ( shi502->shi502_type & ~(STYPE_TEMPORARY|STYPE_SPECIAL) ) {
  135. case STYPE_CDROM:
  136. isCdrom = TRUE; // lack of break is intentional
  137. case STYPE_REMOVABLE:
  138. isRemovable = TRUE; // lack of break is intentional
  139. case STYPE_DISKTREE:
  140. shareType = ShareTypeDisk;
  141. break;
  142. case STYPE_PRINTQ:
  143. shareType = ShareTypePrint;
  144. break;
  145. case STYPE_IPC:
  146. shareType = ShareTypePipe;
  147. break;
  148. default:
  149. //
  150. // An illegal share type was passed in.
  151. //
  152. IF_DEBUG(SMB_ERRORS) {
  153. KdPrint(( "SrvNetShareAdd: illegal share type: %ld\n",
  154. shi502->shi502_type ));
  155. }
  156. Srp->Parameters.Set.ErrorParameter = SHARE_TYPE_PARMNUM;
  157. return STATUS_INVALID_PARAMETER;
  158. }
  159. //
  160. // Get pointers to the share name, path, remark, and security
  161. // descriptor.
  162. //
  163. RtlInitUnicodeString( &shareName, (PWCH)shi502->shi502_netname );
  164. ntPath = Srp->Name1;
  165. RtlInitUnicodeString( &dosPath, (PWCH)shi502->shi502_path );
  166. RtlInitUnicodeString( &remark, (PWCH)shi502->shi502_remark );
  167. //
  168. // If this is level 502, get the file security descriptor
  169. //
  170. if ( Srp->Level == 502 ) {
  171. fileSecurityDescriptor = shi502->shi502_security_descriptor;
  172. //
  173. // if the sd is invalid, quit.
  174. //
  175. if ( fileSecurityDescriptor != NULL &&
  176. !RtlValidSecurityDescriptor( fileSecurityDescriptor) ) {
  177. Srp->Parameters.Set.ErrorParameter = SHARE_FILE_SD_PARMNUM;
  178. return STATUS_INVALID_PARAMETER;
  179. }
  180. }
  181. //
  182. // Allocate a share block.
  183. //
  184. SrvAllocateShare(
  185. &share,
  186. &shareName,
  187. &ntPath,
  188. &dosPath,
  189. &remark,
  190. securityDescriptor,
  191. fileSecurityDescriptor,
  192. shareType
  193. );
  194. if ( share == NULL ) {
  195. DEBUG KdPrint(( "SrvNetShareAdd: unable to allocate share block\n" ));
  196. return STATUS_INSUFF_SERVER_RESOURCES;
  197. }
  198. share->SpecialShare = isSpecial;
  199. share->Removable = isRemovable;
  200. //
  201. // Set the MaxUses field in the share. The CurrentUses field was
  202. // zeroed by SrvAllocateShare.
  203. //
  204. share->MaxUses = shi502->shi502_max_uses;
  205. if ( shareType == ShareTypePrint ) {
  206. status = SrvOpenPrinter((PWCH)shi502->shi502_path,
  207. &share->Type.hPrinter,
  208. &Srp->ErrorCode
  209. );
  210. if ( !NT_SUCCESS(status) ) {
  211. SrvFreeShare( share );
  212. return status;
  213. }
  214. if ( Srp->ErrorCode != NO_ERROR ) {
  215. SrvFreeShare( share );
  216. return STATUS_SUCCESS;
  217. }
  218. }
  219. //
  220. // Mark the share if it is in the DFS
  221. //
  222. SrvIsShareInDfs( share, &share->IsDfs, &share->IsDfsRoot );
  223. //
  224. // Ensure that another share with the same name doesn't already
  225. // exist. Insert the share block in the global share list.
  226. //
  227. ACQUIRE_LOCK( &SrvShareLock );
  228. if ( SrvFindShare( &share->ShareName ) != NULL ) {
  229. //
  230. // A share with the same name exists. Clean up and return an
  231. // error.
  232. //
  233. // *** Note that SrvFindShare ignores existing shares that are
  234. // closing. This allows a new share to be created even if
  235. // and old share with the same name is in the "twilight
  236. // zone" between existence and nonexistence because of a
  237. // stray reference.
  238. //
  239. RELEASE_LOCK( &SrvShareLock );
  240. SrvFreeShare( share );
  241. Srp->ErrorCode = NERR_DuplicateShare;
  242. return STATUS_SUCCESS;
  243. }
  244. //
  245. // Insert the share on the global ordered list.
  246. //
  247. SrvAddShare( share );
  248. RELEASE_LOCK( &SrvShareLock );
  249. //
  250. // Is this is a removable type e.g. Floppy or CDROM, fill up the
  251. // file system name.
  252. //
  253. if ( isRemovable ) {
  254. PWSTR fileSystemName;
  255. ULONG fileSystemNameLength;
  256. if ( isCdrom ) {
  257. //
  258. // uses cdfs
  259. //
  260. fileSystemName = StrFsCdfs;
  261. fileSystemNameLength = sizeof( FS_CDFS ) - sizeof(WCHAR);
  262. } else {
  263. //
  264. // assume it's fat
  265. //
  266. fileSystemName = StrFsFat;
  267. fileSystemNameLength = sizeof( FS_FAT ) - sizeof(WCHAR);
  268. }
  269. SrvFillInFileSystemName(
  270. share,
  271. fileSystemName,
  272. fileSystemNameLength
  273. );
  274. }
  275. //
  276. // If this is an administrative disk share, update SrvDiskConfiguration
  277. // to cause the scavenger thread to check the disk free space. The server
  278. // service has already verified that the format of the pathname is valid
  279. // before it allowed the ShareAdd to get this far.
  280. //
  281. // We want to skip this if its a \\?\ name
  282. //
  283. if( share->SpecialShare && share->ShareType == ShareTypeDisk &&
  284. share->ShareName.Buffer[1] == L'$' &&
  285. share->DosPathName.Buffer[0] != L'\\' ) {
  286. ACQUIRE_LOCK( &SrvConfigurationLock );
  287. SrvDiskConfiguration |= (0x80000000 >> (share->DosPathName.Buffer[0] - L'A'));
  288. RELEASE_LOCK( &SrvConfigurationLock );
  289. }
  290. //
  291. // Dereference the share block, because we're going to forget
  292. // its address. (The initial reference count is 2.)
  293. //
  294. SrvDereferenceShare( share );
  295. return STATUS_SUCCESS;
  296. } // SrvNetShareAdd
  297. NTSTATUS
  298. SrvNetShareDel (
  299. IN PSERVER_REQUEST_PACKET Srp,
  300. IN PVOID Buffer,
  301. IN ULONG BufferLength
  302. )
  303. /*++
  304. Routine Description:
  305. This routine processes the NetShareDel API in the server.
  306. Arguments:
  307. Srp - a pointer to the server request packet that contains all
  308. the information necessary to satisfy the request. This includes:
  309. INPUT:
  310. Name1 - name of the share to delete.
  311. OUTPUT:
  312. None.
  313. Buffer - unused.
  314. BufferLength - unused.
  315. Return Value:
  316. NTSTATUS - result of operation to return to the server service.
  317. --*/
  318. {
  319. PSHARE share;
  320. DWORD AdministrativeDiskBit = 0;
  321. BOOLEAN isPrintShare = FALSE;
  322. PAGED_CODE( );
  323. Buffer, BufferLength;
  324. //
  325. // Find the share with the specified name. Note that if a share
  326. // with the specified name exists but is closing, it will not be
  327. // found.
  328. //
  329. ACQUIRE_LOCK( &SrvShareLock );
  330. share = SrvFindShare( &Srp->Name1 );
  331. if ( share == NULL ) {
  332. //
  333. // No share with the specified name exists. Return an error.
  334. //
  335. RELEASE_LOCK( &SrvShareLock );
  336. Srp->ErrorCode = NERR_NetNameNotFound;
  337. return STATUS_SUCCESS;
  338. }
  339. //
  340. // Make sure the DFS state for this share is accurate
  341. //
  342. SrvIsShareInDfs( share, &share->IsDfs, &share->IsDfsRoot );
  343. //
  344. // If the share really is in the DFS, then do not allow it to be deleted
  345. //
  346. if( share->IsDfs == TRUE ) {
  347. RELEASE_LOCK( &SrvShareLock );
  348. IF_DEBUG( DFS ) {
  349. KdPrint(("NetShareDel attempted on share in DFS!\n" ));
  350. }
  351. Srp->ErrorCode = NERR_IsDfsShare;
  352. return STATUS_SUCCESS;
  353. }
  354. // Don't allow the deletion of IPC$, as behavior is very bad with it gone
  355. // (Named-pipe traffic doesn't work, so NetAPI's and RPC don't work..)
  356. if( share->SpecialShare )
  357. {
  358. UNICODE_STRING Ipc = { 8, 8, L"IPC$" };
  359. if( RtlCompareUnicodeString( &Ipc, &share->ShareName, TRUE ) == 0 )
  360. {
  361. RELEASE_LOCK( &SrvShareLock );
  362. Srp->ErrorCode = ERROR_ACCESS_DENIED;
  363. return STATUS_SUCCESS;
  364. }
  365. }
  366. switch( share->ShareType ) {
  367. case ShareTypePrint:
  368. //
  369. // This is a print share
  370. // Don't close the printer here because we have the ShareLock acquired,
  371. // and it can cause some strange deadlocks because it involves calling up
  372. // to usermode, and then calling over to Spooler, etc. This can take a long time
  373. //
  374. isPrintShare = TRUE;
  375. // Reference the share so it doesn't go away at SrvCloseShare time
  376. SrvReferenceShare( share );
  377. break;
  378. case ShareTypeDisk:
  379. //
  380. // See if this was an administrative disk share
  381. //
  382. if( share->SpecialShare && share->DosPathName.Buffer[1] == L'$' ) {
  383. AdministrativeDiskBit = (0x80000000 >> (share->DosPathName.Buffer[0] - L'A'));
  384. }
  385. break;
  386. }
  387. SrvCloseShare( share );
  388. RELEASE_LOCK( &SrvShareLock );
  389. // If it was a print share, we need to close the printer now that we've released the lock
  390. if( isPrintShare )
  391. {
  392. SrvClosePrinter( share->Type.hPrinter );
  393. SrvDereferenceShare( share );
  394. }
  395. //
  396. // If this was an administrative disk share, update SrvDiskConfiguration
  397. // to cause the scavenger thread to ignore this disk.
  398. //
  399. if( AdministrativeDiskBit ) {
  400. ACQUIRE_LOCK( &SrvConfigurationLock );
  401. SrvDiskConfiguration &= ~AdministrativeDiskBit;
  402. RELEASE_LOCK( &SrvConfigurationLock );
  403. }
  404. return STATUS_SUCCESS;
  405. } // SrvNetShareDel
  406. NTSTATUS
  407. SrvNetShareEnum (
  408. IN PSERVER_REQUEST_PACKET Srp,
  409. IN PVOID Buffer,
  410. IN ULONG BufferLength
  411. )
  412. /*++
  413. Routine Description:
  414. This routine processes the NetShareEnum API in the server.
  415. Arguments:
  416. Srp - a pointer to the server request packet that contains all
  417. the information necessary to satisfy the request. This includes:
  418. INPUT:
  419. Level - level of information to return, 0, 1, or 2.
  420. Parameters.Get.ResumeHandle - share ID to determine where to
  421. start returning info. We start with the first share with an
  422. ID greater than this value.
  423. OUTPUT:
  424. Parameters.Get.EntriesRead - the number of entries that fit in
  425. the output buffer.
  426. Parameters.Get.TotalEntries - the total number of entries that
  427. would be returned with a large enough buffer.
  428. Parameters.Get.TotalBytesNeeded - the buffer size that would be
  429. required to hold all the entries.
  430. Parameters.Get.ResumeHandle - share ID of last share returned.
  431. Buffer - a pointer to the buffer for results.
  432. BufferLength - the length of this buffer.
  433. Return Value:
  434. NTSTATUS - result of operation to return to the server service.
  435. --*/
  436. {
  437. PAGED_CODE( );
  438. return SrvShareEnumApiHandler(
  439. Srp,
  440. Buffer,
  441. BufferLength,
  442. FilterShares,
  443. SizeShares,
  444. FillShareInfoBuffer
  445. );
  446. } // SrvNetShareEnum
  447. NTSTATUS
  448. SrvNetShareSetInfo (
  449. IN PSERVER_REQUEST_PACKET Srp,
  450. IN PVOID Buffer,
  451. IN ULONG BufferLength
  452. )
  453. /*++
  454. Routine Description:
  455. This routine processes the NetShareSetInfo API in the server.
  456. Arguments:
  457. Srp - a pointer to the server request packet that contains all
  458. the information necessary to satisfy the request. This includes:
  459. INPUT:
  460. Name1 - name of the share to set information on.
  461. Parameters.Set.Api.ShareInfo.MaxUses - if not 0, a new maximum
  462. user count. If the current count of users on the share
  463. exceeds the new value, no check is made, but no new
  464. tree connects are allowed.
  465. OUTPUT:
  466. Parameters.Set.ErrorParameter - if ERROR_INVALID_PARAMETER is
  467. returned, this contains the index of the parameter in error.
  468. Buffer - a pointer to a SHARE_INFO_502 structure.
  469. BufferLength - length of this buffer.
  470. Return Value:
  471. NTSTATUS - result of operation to return to the user.
  472. --*/
  473. {
  474. PSHARE share;
  475. UNICODE_STRING remark;
  476. PWCH newRemarkBuffer = NULL;
  477. ULONG maxUses;
  478. ULONG level;
  479. PSHARE_INFO_502 shi502;
  480. PSECURITY_DESCRIPTOR fileSD;
  481. PSECURITY_DESCRIPTOR securityDescriptor = NULL;
  482. PAGED_CODE( );
  483. //
  484. // Convert the offsets in the share data structure to pointers. Also
  485. // make sure that all the pointers are within the specified buffer.
  486. //
  487. level = Srp->Level;
  488. switch( level ) {
  489. default:
  490. shi502 = Buffer;
  491. if( shi502->shi502_permissions ) {
  492. securityDescriptor =
  493. (PSECURITY_DESCRIPTOR)((PCHAR)shi502 + shi502->shi502_permissions);
  494. }
  495. OFFSET_TO_POINTER( shi502->shi502_netname, shi502 );
  496. OFFSET_TO_POINTER( shi502->shi502_remark, shi502 );
  497. OFFSET_TO_POINTER( shi502->shi502_path, shi502 );
  498. OFFSET_TO_POINTER( shi502->shi502_security_descriptor, shi502 );
  499. if ( !POINTER_IS_VALID( shi502->shi502_netname, shi502, BufferLength ) ||
  500. !POINTER_IS_VALID( shi502->shi502_remark, shi502, BufferLength ) ||
  501. !POINTER_IS_VALID( shi502->shi502_path, shi502, BufferLength ) ||
  502. !POINTER_IS_VALID( securityDescriptor, shi502, BufferLength ) ||
  503. !POINTER_IS_VALID( shi502->shi502_security_descriptor, shi502, BufferLength ) ) {
  504. return STATUS_ACCESS_VIOLATION;
  505. }
  506. break;
  507. case 1005:
  508. break;
  509. }
  510. //
  511. // Acquire the lock that protects the share list and attempt to find
  512. // the correct share.
  513. //
  514. ACQUIRE_LOCK( &SrvShareLock );
  515. share = SrvFindShare( &Srp->Name1 );
  516. if ( share == NULL ) {
  517. IF_DEBUG(API_ERRORS) {
  518. KdPrint(( "SrvNetShareSetInfo: share %wZ not found.\n",
  519. &Srp->Name1 ));
  520. }
  521. RELEASE_LOCK( &SrvShareLock );
  522. Srp->ErrorCode = NERR_NetNameNotFound;
  523. return STATUS_SUCCESS;
  524. }
  525. if( level == 1005 ) {
  526. if( share->ShareType != ShareTypeDisk ) {
  527. Srp->Parameters.Set.ErrorParameter = 0;
  528. Srp->ErrorCode = ERROR_BAD_DEV_TYPE;
  529. } else {
  530. PSHARE_INFO_1005 shi1005 = Buffer;
  531. share->CSCState = shi1005->shi1005_flags & CSC_MASK;
  532. share->ShareProperties = (shi1005->shi1005_flags & ~CSC_MASK);
  533. Srp->ErrorCode = 0;
  534. }
  535. RELEASE_LOCK( &SrvShareLock );
  536. return STATUS_SUCCESS;
  537. }
  538. //
  539. // Set up local variables.
  540. //
  541. maxUses = Srp->Parameters.Set.Api.ShareInfo.MaxUses;
  542. //
  543. // If a remark was specified, allocate space for a new remark and
  544. // copy over the remark.
  545. //
  546. if ( ARGUMENT_PRESENT( shi502->shi502_remark ) ) {
  547. RtlInitUnicodeString( &remark, shi502->shi502_remark );
  548. newRemarkBuffer = ALLOCATE_HEAP_COLD(
  549. remark.MaximumLength,
  550. BlockTypeDataBuffer
  551. );
  552. if ( newRemarkBuffer == NULL ) {
  553. RELEASE_LOCK( &SrvShareLock );
  554. INTERNAL_ERROR(
  555. ERROR_LEVEL_EXPECTED,
  556. "SrvNetShareSetInfo: unable to allocate %ld bytes of heap.\n",
  557. remark.MaximumLength,
  558. NULL
  559. );
  560. Srp->Parameters.Set.ErrorParameter = SHARE_REMARK_PARMNUM;
  561. return STATUS_INSUFF_SERVER_RESOURCES;
  562. }
  563. }
  564. //
  565. // If a file security descriptor was specified, allocate space for a
  566. // new SD and copy over the new SD. We do this before setting the
  567. // MaxUses in case the allocation fails and we have to back out.
  568. //
  569. // Don't let a file ACL be specified for admin shares.
  570. //
  571. fileSD = shi502->shi502_security_descriptor;
  572. if ( ((level == 502) || (level == SHARE_FILE_SD_INFOLEVEL)) &&
  573. ARGUMENT_PRESENT( fileSD ) ) {
  574. PSECURITY_DESCRIPTOR newFileSD;
  575. ULONG newFileSDLength;
  576. if ( share->SpecialShare || !RtlValidSecurityDescriptor( fileSD ) ) {
  577. RELEASE_LOCK( &SrvShareLock );
  578. if ( newRemarkBuffer != NULL) {
  579. FREE_HEAP( newRemarkBuffer );
  580. }
  581. Srp->Parameters.Set.ErrorParameter = SHARE_FILE_SD_PARMNUM;
  582. return STATUS_INVALID_PARAMETER;
  583. }
  584. newFileSDLength = RtlLengthSecurityDescriptor( fileSD );
  585. newFileSD = ALLOCATE_HEAP_COLD(
  586. newFileSDLength,
  587. BlockTypeDataBuffer
  588. );
  589. if ( newFileSD == NULL ) {
  590. RELEASE_LOCK( &SrvShareLock );
  591. INTERNAL_ERROR(
  592. ERROR_LEVEL_EXPECTED,
  593. "SrvNetShareSetInfo: unable to allocate %ld bytes of heap.\n",
  594. newFileSDLength,
  595. NULL
  596. );
  597. Srp->Parameters.Set.ErrorParameter = SHARE_FILE_SD_PARMNUM;
  598. //
  599. // Free the remarks buffer allocated
  600. //
  601. if ( newRemarkBuffer != NULL) {
  602. FREE_HEAP( newRemarkBuffer );
  603. }
  604. return STATUS_INSUFF_SERVER_RESOURCES;
  605. }
  606. ACQUIRE_LOCK( share->SecurityDescriptorLock );
  607. //
  608. // Free the old security descriptor
  609. //
  610. if ( share->FileSecurityDescriptor != NULL ) {
  611. FREE_HEAP( share->FileSecurityDescriptor );
  612. }
  613. //
  614. // And set up the new one.
  615. //
  616. share->FileSecurityDescriptor = newFileSD;
  617. RtlCopyMemory(
  618. share->FileSecurityDescriptor,
  619. fileSD,
  620. newFileSDLength
  621. );
  622. RELEASE_LOCK( share->SecurityDescriptorLock );
  623. }
  624. //
  625. // Replace the old remark if a new one was specified.
  626. //
  627. if ( newRemarkBuffer != NULL ) {
  628. //
  629. // Free the old remark buffer.
  630. //
  631. if ( share->Remark.Buffer != NULL ) {
  632. FREE_HEAP( share->Remark.Buffer );
  633. }
  634. //
  635. // And set up the new one.
  636. //
  637. share->Remark.Buffer = newRemarkBuffer;
  638. share->Remark.MaximumLength = remark.MaximumLength;
  639. RtlCopyUnicodeString( &share->Remark, &remark );
  640. }
  641. //
  642. // If MaxUses was specified, set the new value.
  643. //
  644. if ( maxUses != 0 ) {
  645. share->MaxUses = maxUses;
  646. }
  647. //
  648. // Release the share lock.
  649. //
  650. RELEASE_LOCK( &SrvShareLock );
  651. //
  652. // Set up the error parameter to 0 (no error) and return.
  653. //
  654. Srp->Parameters.Set.ErrorParameter = 0;
  655. return STATUS_SUCCESS;
  656. } // SrvNetShareSetInfo
  657. VOID
  658. FillShareInfoBuffer (
  659. IN PSERVER_REQUEST_PACKET Srp,
  660. IN PVOID Block,
  661. IN OUT PVOID *FixedStructure,
  662. IN LPWSTR *EndOfVariableData
  663. )
  664. /*++
  665. Routine Description:
  666. This routine puts a single fixed share structure and, if it fits,
  667. associated variable data, into a buffer. Fixed data goes at the
  668. beginning of the buffer, variable data at the end.
  669. Arguments:
  670. Level - the level of information to copy from the share.
  671. Block - the share from which to get information.
  672. FixedStructure - where the ine buffer to place the fixed structure.
  673. This pointer is updated to point to the next available
  674. position for a fixed structure.
  675. EndOfVariableData - the last position on the buffer that variable
  676. data for this structure can occupy. The actual variable data
  677. is written before this position as long as it won't overwrite
  678. fixed structures. It is would overwrite fixed structures, it
  679. is not written.
  680. Return Value:
  681. None.
  682. --*/
  683. {
  684. PSHARE share = Block;
  685. PSHARE_INFO_501 shi501 = *FixedStructure;
  686. PSHARE_INFO_502 shi502 = *FixedStructure;
  687. PSHARE_INFO_1005 shi1005 = *FixedStructure;
  688. PAGED_CODE( );
  689. //
  690. // Update FixedStructure to point to the next structure
  691. // location.
  692. //
  693. *FixedStructure = (PCHAR)*FixedStructure + FIXED_SIZE_OF_SHARE( Srp->Level );
  694. ASSERT( (ULONG_PTR)*EndOfVariableData >= (ULONG_PTR)*FixedStructure );
  695. //
  696. // Case on the level to fill in the fixed structure appropriately.
  697. // We fill in actual pointers in the output structure. This is
  698. // possible because we are in the server FSD, hence the server
  699. // service's process and address space.
  700. //
  701. // *** This routine assumes that the fixed structure will fit in the
  702. // buffer!
  703. //
  704. // *** Using the switch statement in this fashion relies on the fact
  705. // that the first fields on the different share structures are
  706. // identical.
  707. //
  708. switch( Srp->Level ) {
  709. case 1005:
  710. shi1005->shi1005_flags = 0;
  711. if( share->IsDfs ) {
  712. shi1005->shi1005_flags |= SHI1005_FLAGS_DFS;
  713. }
  714. if( share->IsDfsRoot ) {
  715. shi1005->shi1005_flags |= SHI1005_FLAGS_DFS_ROOT;
  716. }
  717. shi1005->shi1005_flags |= share->ShareProperties;
  718. shi1005->shi1005_flags |= share->CSCState;
  719. break;
  720. case 502:
  721. ACQUIRE_LOCK_SHARED( share->SecurityDescriptorLock );
  722. if ( share->FileSecurityDescriptor != NULL ) {
  723. ULONG fileSDLength;
  724. fileSDLength =
  725. RtlLengthSecurityDescriptor( share->FileSecurityDescriptor );
  726. //
  727. // DWord Align
  728. //
  729. *EndOfVariableData = (LPWSTR) ( (ULONG_PTR) ((PCHAR) *EndOfVariableData -
  730. fileSDLength ) & ~3 );
  731. shi502->shi502_security_descriptor = *EndOfVariableData;
  732. shi502->shi502_reserved = fileSDLength;
  733. RtlCopyMemory(
  734. shi502->shi502_security_descriptor,
  735. share->FileSecurityDescriptor,
  736. fileSDLength
  737. );
  738. } else {
  739. shi502->shi502_security_descriptor = NULL;
  740. shi502->shi502_reserved = 0;
  741. }
  742. RELEASE_LOCK( share->SecurityDescriptorLock );
  743. case 2:
  744. //
  745. // Set level 2 specific fields in the buffer. Since this server
  746. // can only have user-level security, share permissions are
  747. // meaningless.
  748. //
  749. shi502->shi502_permissions = 0;
  750. shi502->shi502_max_uses = share->MaxUses;
  751. shi502->shi502_current_uses = share->CurrentUses;
  752. //
  753. // Copy the DOS path name to the buffer.
  754. //
  755. SrvCopyUnicodeStringToBuffer(
  756. &share->DosPathName,
  757. *FixedStructure,
  758. EndOfVariableData,
  759. &shi502->shi502_path
  760. );
  761. //
  762. // We don't have per-share passwords (share-level security)
  763. // so set the password pointer to NULL.
  764. //
  765. shi502->shi502_passwd = NULL;
  766. // *** Lack of break is intentional!
  767. case 501:
  768. if( Srp->Level == 501 ) {
  769. shi501->shi501_flags = share->CSCState;
  770. }
  771. // *** Lack of break is intentional!
  772. case 1:
  773. //
  774. // Convert the server's internal representation of share types
  775. // to the expected format.
  776. //
  777. switch ( share->ShareType ) {
  778. case ShareTypeDisk:
  779. shi502->shi502_type = STYPE_DISKTREE;
  780. break;
  781. case ShareTypePrint:
  782. shi502->shi502_type = STYPE_PRINTQ;
  783. break;
  784. case ShareTypePipe:
  785. shi502->shi502_type = STYPE_IPC;
  786. break;
  787. default:
  788. //
  789. // This should never happen. It means that somebody
  790. // stomped on the share block.
  791. //
  792. INTERNAL_ERROR(
  793. ERROR_LEVEL_UNEXPECTED,
  794. "FillShareInfoBuffer: invalid share type in share: %ld",
  795. share->ShareType,
  796. NULL
  797. );
  798. shi502->shi502_type = 0;
  799. }
  800. if ( share->SpecialShare ) {
  801. shi502->shi502_type |= STYPE_SPECIAL;
  802. }
  803. //
  804. // Copy the remark to the buffer. The routine will handle the
  805. // case where there is no remark on the share and put a pointer
  806. // to a zero terminator in the buffer.
  807. //
  808. // *** We hold the share lock to keep SrvNetShareSetInfo from
  809. // changing the remark during the copy. (Changing the
  810. // remark can result in different storage being allocated.)
  811. //
  812. SrvCopyUnicodeStringToBuffer(
  813. &share->Remark,
  814. *FixedStructure,
  815. EndOfVariableData,
  816. &shi502->shi502_remark
  817. );
  818. // *** Lack of break is intentional!
  819. case 0:
  820. //
  821. // Copy the share name to the buffer.
  822. //
  823. SrvCopyUnicodeStringToBuffer(
  824. &share->ShareName,
  825. *FixedStructure,
  826. EndOfVariableData,
  827. &shi502->shi502_netname
  828. );
  829. break;
  830. default:
  831. //
  832. // This should never happen. The server service should have
  833. // checked for an invalid level.
  834. //
  835. INTERNAL_ERROR(
  836. ERROR_LEVEL_UNEXPECTED,
  837. "FillShareInfoBuffer: invalid level number: %ld",
  838. Srp->Level,
  839. NULL
  840. );
  841. }
  842. return;
  843. } // FillShareInfoBuffer
  844. BOOLEAN
  845. FilterShares (
  846. IN PSERVER_REQUEST_PACKET Srp,
  847. IN PVOID Block
  848. )
  849. /*++
  850. Routine Description:
  851. This routine is intended to be called by SrvEnumApiHandler to check
  852. whether a particular share should be returned.
  853. Arguments:
  854. Srp - a pointer to the SRP for the operation. Name1 ("netname"
  855. on NetShareGetInfo) is used to do the filtering.
  856. Block - a pointer to the share to check.
  857. Return Value:
  858. TRUE if the block should be placed in the output buffer, FALSE
  859. if it should be passed over.
  860. --*/
  861. {
  862. PSHARE share = Block;
  863. PAGED_CODE( );
  864. //
  865. // If this share is being deleted, than we should not let it be enumerated
  866. //
  867. if( GET_BLOCK_STATE(share) == BlockStateClosing )
  868. {
  869. return FALSE;
  870. }
  871. //
  872. // If this is an Enum, then we definitely want the share. An Enum
  873. // leaves the net name blank; a get info sets the name to the share
  874. // name on which to return info.
  875. //
  876. if ( Srp->Name1.Length == 0 ) {
  877. return TRUE;
  878. }
  879. //
  880. // This is a get info; use the share only if the share name matches
  881. // the Name1 field of the SRP.
  882. //
  883. return RtlEqualUnicodeString(
  884. &Srp->Name1,
  885. &share->ShareName,
  886. TRUE
  887. );
  888. } // FilterShares
  889. ULONG
  890. SizeShares (
  891. IN PSERVER_REQUEST_PACKET Srp,
  892. IN PVOID Block
  893. )
  894. /*++
  895. Routine Description:
  896. This routine returns the size the passed-in share would take up in
  897. an API output buffer.
  898. Arguments:
  899. Srp - a pointer to the SRP for the operation. Only the Level
  900. parameter is used.
  901. Block - a pointer to the share to size.
  902. Return Value:
  903. ULONG - The number of bytes the share would take up in the
  904. output buffer.
  905. --*/
  906. {
  907. PSHARE share = Block;
  908. ULONG shareSize = 0;
  909. PAGED_CODE( );
  910. switch ( Srp->Level ) {
  911. case 502:
  912. ACQUIRE_LOCK_SHARED( share->SecurityDescriptorLock );
  913. if ( share->FileSecurityDescriptor != NULL ) {
  914. //
  915. // add 4 bytes for possible padding
  916. //
  917. shareSize = sizeof( ULONG ) +
  918. RtlLengthSecurityDescriptor( share->FileSecurityDescriptor );
  919. }
  920. RELEASE_LOCK( share->SecurityDescriptorLock );
  921. case 2:
  922. shareSize += SrvLengthOfStringInApiBuffer(&share->DosPathName);
  923. case 501:
  924. case 1:
  925. shareSize += SrvLengthOfStringInApiBuffer(&share->Remark);
  926. case 0:
  927. shareSize += SrvLengthOfStringInApiBuffer(&share->ShareName);
  928. }
  929. return ( shareSize + FIXED_SIZE_OF_SHARE( Srp->Level ) );
  930. } // SizeShares