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.

578 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. svcfile.c
  5. Abstract:
  6. This module contains routines for supporting the file APIs in the
  7. server service, SrvNetFileClose, SrvNetFileEnum, and
  8. SrvNetFileGetInfo,
  9. Author:
  10. David Treadwell (davidtr) 31-Jan-1991
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "svcfile.tmh"
  15. #pragma hdrstop
  16. #define BugCheckFileId SRV_FILE_SVCFILE
  17. //
  18. // Forward declarations.
  19. //
  20. VOID
  21. FillFileInfoBuffer (
  22. IN PSERVER_REQUEST_PACKET Srp,
  23. IN PVOID Block,
  24. IN OUT PVOID *FixedStructure,
  25. IN LPWSTR *EndOfVariableData
  26. );
  27. BOOLEAN
  28. FilterFiles (
  29. IN PSERVER_REQUEST_PACKET Srp,
  30. IN PVOID Block
  31. );
  32. ULONG
  33. SizeFiles (
  34. IN PSERVER_REQUEST_PACKET Srp,
  35. IN PVOID Block
  36. );
  37. #ifdef ALLOC_PRAGMA
  38. #pragma alloc_text( PAGE, SrvNetFileClose )
  39. #pragma alloc_text( PAGE, SrvNetFileEnum )
  40. #pragma alloc_text( PAGE, FillFileInfoBuffer )
  41. #pragma alloc_text( PAGE, FilterFiles )
  42. #pragma alloc_text( PAGE, SizeFiles )
  43. #endif
  44. //
  45. // Macros to determine the size an RFCB would take up at one of the
  46. // levels of file information.
  47. //
  48. // *** Note that the zero terminator on the path name is accounted for by
  49. // the leading backslash, which is not returned.
  50. //
  51. #define TOTAL_SIZE_OF_FILE(lfcb,level, user) \
  52. ( (level) == 2 ? sizeof(FILE_INFO_2) : \
  53. sizeof(FILE_INFO_3) + \
  54. SrvLengthOfStringInApiBuffer( \
  55. &(lfcb)->Mfcb->FileName) + \
  56. SrvLengthOfStringInApiBuffer( user ) )
  57. #define FIXED_SIZE_OF_FILE(level) \
  58. ( (level) == 2 ? sizeof(FILE_INFO_2) : \
  59. sizeof(FILE_INFO_3) )
  60. NTSTATUS
  61. SrvNetFileClose (
  62. IN PSERVER_REQUEST_PACKET Srp,
  63. IN PVOID Buffer,
  64. IN ULONG BufferLength
  65. )
  66. /*++
  67. Routine Description:
  68. This routine processes the NetFileClose API in the server.
  69. Arguments:
  70. Srp - a pointer to the server request packet that contains all
  71. the information necessary to satisfy the request. This includes:
  72. INPUT:
  73. Parameters.Get.ResumeHandle - the file ID to close.
  74. OUTPUT:
  75. None.
  76. Buffer - unused.
  77. BufferLength - unused.
  78. Return Value:
  79. NTSTATUS - result of operation to return to the server service.
  80. --*/
  81. {
  82. PRFCB rfcb;
  83. PAGED_CODE( );
  84. Buffer, BufferLength;
  85. //
  86. // Try to find a file that matches the file ID. Only an exact
  87. // match will work.
  88. //
  89. rfcb = SrvFindEntryInOrderedList(
  90. &SrvRfcbList,
  91. NULL,
  92. NULL,
  93. Srp->Parameters.Get.ResumeHandle,
  94. TRUE,
  95. NULL
  96. );
  97. if ( rfcb == NULL ) {
  98. Srp->ErrorCode = NERR_FileIdNotFound;
  99. return STATUS_SUCCESS;
  100. }
  101. //
  102. // Close this RFCB.
  103. //
  104. SrvCloseRfcb( rfcb );
  105. //
  106. // SrvFindEntryInOrderedList referenced the RFCB; dereference it
  107. // now.
  108. //
  109. SrvDereferenceRfcb( rfcb );
  110. return STATUS_SUCCESS;
  111. } // SrvNetFileClose
  112. NTSTATUS
  113. SrvNetFileEnum (
  114. IN PSERVER_REQUEST_PACKET Srp,
  115. IN PVOID Buffer,
  116. IN ULONG BufferLength
  117. )
  118. /*++
  119. Routine Description:
  120. This routine processes the NetFileEnum API in the server.
  121. Arguments:
  122. Srp - a pointer to the server request packet that contains all
  123. the information necessary to satisfy the request. This includes:
  124. INPUT:
  125. Name1 - basename for limiting search--only files whose path name
  126. begin with this string are returned.
  127. Level - level of information to return, 2 or 3.
  128. Flags - if SRP_RETURN_SINGLE_ENTRY is set, then this is a
  129. NetFileGetInfo, so behave accordingly.
  130. Parameters.Get.ResumeHandle - a handle to the last file that was
  131. returned, or 0 if this is the first call.
  132. OUTPUT:
  133. Parameters.Get.EntriesRead - the number of entries that fit in
  134. the output buffer.
  135. Parameters.Get.TotalEntries - the total number of entries that
  136. would be returned with a large enough buffer.
  137. Parameters.Get.TotalBytesNeeded - the buffer size that would be
  138. required to hold all the entries.
  139. Parameters.Get.ResumeHandle - a handle to the last file
  140. returned.
  141. Buffer - a pointer to the buffer for results.
  142. BufferLength - the length of this buffer.
  143. Return Value:
  144. NTSTATUS - result of operation to return to the server service.
  145. --*/
  146. {
  147. PAGED_CODE( );
  148. //
  149. // If this is a GetInfo API, we really want to start with the file
  150. // corresponding to the resume handle, not the one after it.
  151. // Decrement the resume handle.
  152. //
  153. if ( (Srp->Flags & SRP_RETURN_SINGLE_ENTRY) != 0 ) {
  154. Srp->Parameters.Get.ResumeHandle--;
  155. }
  156. return SrvEnumApiHandler(
  157. Srp,
  158. Buffer,
  159. BufferLength,
  160. &SrvRfcbList,
  161. FilterFiles,
  162. SizeFiles,
  163. FillFileInfoBuffer
  164. );
  165. } // SrvNetFileEnum
  166. VOID
  167. FillFileInfoBuffer (
  168. IN PSERVER_REQUEST_PACKET Srp,
  169. IN PVOID Block,
  170. IN OUT PVOID *FixedStructure,
  171. IN LPWSTR *EndOfVariableData
  172. )
  173. /*++
  174. Routine Description:
  175. This routine puts a single fixed file structure and associated
  176. variable data, into a buffer. Fixed data goes at the beginning of
  177. the buffer, variable data at the end.
  178. *** This routine assumes that ALL the data, both fixed and variable,
  179. will fit.
  180. Arguments:
  181. Srp - a pointer to the SRP for the operation. Only the Level
  182. field is used.
  183. Block - the RFCB from which to get information.
  184. FixedStructure - where the ine buffer to place the fixed structure.
  185. This pointer is updated to point to the next available
  186. position for a fixed structure.
  187. EndOfVariableData - the last position on the buffer that variable
  188. data for this structure can occupy. The actual variable data
  189. is written before this position as long as it won't overwrite
  190. fixed structures. It is would overwrite fixed structures, it
  191. is not written.
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. PFILE_INFO_3 fi3 = *FixedStructure;
  197. PRFCB rfcb;
  198. PLFCB lfcb;
  199. UNICODE_STRING userName;
  200. PAGED_CODE( );
  201. //
  202. // Update FixedStructure to point to the next structure location.
  203. //
  204. *FixedStructure = (PCHAR)*FixedStructure + FIXED_SIZE_OF_FILE( Srp->Level );
  205. ASSERT( (ULONG_PTR)*EndOfVariableData >= (ULONG_PTR)*FixedStructure );
  206. rfcb = Block;
  207. lfcb = rfcb->Lfcb;
  208. //
  209. // Case on the level to fill in the fixed structure appropriately.
  210. // We fill in actual pointers in the output structure. This is
  211. // possible because we are in the server FSD, hence the server
  212. // service's process and address space.
  213. //
  214. // *** Using the switch statement in this fashion relies on the fact
  215. // that the first fields on the different file structures are
  216. // identical.
  217. //
  218. switch( Srp->Level ) {
  219. case 3:
  220. //
  221. // Set level 3 specific fields in the buffer. Convert the
  222. // permissions (granted access) stored in the LFCB to the format
  223. // expected by the API.
  224. //
  225. fi3->fi3_permissions = 0;
  226. if ( (lfcb->GrantedAccess & FILE_READ_DATA) != 0 ) {
  227. fi3->fi3_permissions |= ACCESS_READ;
  228. }
  229. if ( (lfcb->GrantedAccess & FILE_WRITE_DATA) != 0 ) {
  230. fi3->fi3_permissions |= ACCESS_WRITE;
  231. }
  232. if ( (lfcb->GrantedAccess & FILE_EXECUTE) != 0 ) {
  233. fi3->fi3_permissions |= ACCESS_EXEC;
  234. }
  235. if ( (lfcb->GrantedAccess & DELETE) != 0 ) {
  236. fi3->fi3_permissions |= ACCESS_DELETE;
  237. }
  238. if ( (lfcb->GrantedAccess & FILE_WRITE_ATTRIBUTES) != 0 ) {
  239. fi3->fi3_permissions |= ACCESS_ATRIB;
  240. }
  241. if ( (lfcb->GrantedAccess & WRITE_DAC) != 0 ) {
  242. fi3->fi3_permissions |= ACCESS_PERM;
  243. }
  244. //
  245. // Set count of locks on the RFCB.
  246. //
  247. fi3->fi3_num_locks = rfcb->NumberOfLocks;
  248. //
  249. // Set up the pathname and username of the RFCB. Note that we
  250. // don't return the leading backslash on file names.
  251. //
  252. SrvCopyUnicodeStringToBuffer(
  253. &lfcb->Mfcb->FileName,
  254. *FixedStructure,
  255. EndOfVariableData,
  256. &fi3->fi3_pathname
  257. );
  258. ASSERT( fi3->fi3_pathname != NULL );
  259. SrvGetUserAndDomainName( lfcb->Session, &userName, NULL );
  260. SrvCopyUnicodeStringToBuffer(
  261. &userName,
  262. *FixedStructure,
  263. EndOfVariableData,
  264. &fi3->fi3_username
  265. );
  266. if( userName.Buffer ) {
  267. SrvReleaseUserAndDomainName( lfcb->Session, &userName, NULL );
  268. }
  269. //ASSERT( fi3->fi3_username != NULL );
  270. // *** Lack of break is intentional!
  271. case 2:
  272. //
  273. // Set up the file ID. Note that it is the same value as is
  274. // used for the resume handle, so it is possible to use this
  275. // value for rewindability.
  276. //
  277. fi3->fi3_id = rfcb->GlobalRfcbListEntry.ResumeHandle;
  278. break;
  279. default:
  280. //
  281. // This should never happen. The server service should have
  282. // checked for an invalid level.
  283. //
  284. INTERNAL_ERROR(
  285. ERROR_LEVEL_UNEXPECTED,
  286. "FillFileInfoBuffer: invalid level number: %ld",
  287. Srp->Level,
  288. NULL
  289. );
  290. return;
  291. }
  292. return;
  293. } // FillFileInfoBuffer
  294. BOOLEAN
  295. FilterFiles (
  296. IN PSERVER_REQUEST_PACKET Srp,
  297. IN PVOID Block
  298. )
  299. /*++
  300. Routine Description:
  301. This routine is intended to be called by SrvEnumApiHandler to check
  302. whether a particular RFCB should be returned.
  303. Arguments:
  304. Srp - a pointer to the SRP for the operation. ResumeHandle is
  305. used if this is a NetFileGetInfo; Name1 is used as the path
  306. name and Name2 is used as the user name if this is a
  307. NetFileEnum.
  308. Block - a pointer to the RFCB to check.
  309. Return Value:
  310. TRUE if the block should be placed in the output buffer, FALSE
  311. if it should be passed over.
  312. --*/
  313. {
  314. PRFCB rfcb = Block;
  315. PLFCB lfcb = rfcb->Lfcb;
  316. PMFCB mfcb = lfcb->Mfcb;
  317. UNICODE_STRING pathName;
  318. UNICODE_STRING userName;
  319. PAGED_CODE( );
  320. //
  321. // Check if this is an Enum or GetInfo command. The SRP_RETURN_SINGLE_ENTRY
  322. // flag is set if this is a get info.
  323. //
  324. if ( (Srp->Flags & SRP_RETURN_SINGLE_ENTRY) == 0 ) {
  325. //
  326. // If a user name was specified, the user name on the session
  327. // must match the user name in the SRP exactly.
  328. //
  329. if ( Srp->Name2.Length != 0 ) {
  330. //
  331. // Get the user name for the owning session
  332. //
  333. SrvGetUserAndDomainName( lfcb->Session, &userName, NULL );
  334. if( userName.Buffer == NULL ) {
  335. //
  336. // Since we don't know who owns the session, we can't match
  337. // the username
  338. //
  339. return FALSE;
  340. }
  341. if ( !RtlEqualUnicodeString(
  342. &Srp->Name2,
  343. &userName,
  344. TRUE ) ) {
  345. //
  346. // The names don't match. Don't put this RFCB in the
  347. // output buffer.
  348. //
  349. SrvReleaseUserAndDomainName( lfcb->Session, &userName, NULL );
  350. return FALSE;
  351. }
  352. SrvReleaseUserAndDomainName( lfcb->Session, &userName, NULL );
  353. }
  354. //
  355. // See if the names match to as many digits of precision as are in
  356. // the specified base name. Note that if no base name was
  357. // specified, then the length = 0 and the file path will always
  358. // match. Also note that the path name stored in the MFCB has a
  359. // leading backslash, while the passed-in path name will never have
  360. // this leading slash, hence the increment of the MFCB file name
  361. // buffer.
  362. //
  363. pathName.Buffer = mfcb->FileName.Buffer;
  364. pathName.Length =
  365. MIN( Srp->Name1.Length, mfcb->FileName.Length );
  366. pathName.MaximumLength = mfcb->FileName.MaximumLength;
  367. return RtlEqualUnicodeString(
  368. &Srp->Name1,
  369. &pathName,
  370. TRUE
  371. );
  372. }
  373. //
  374. // It's a GetInfo, so just see if the ResumeHandle in the SRP
  375. // matches the ResumeHandle on the RFCB. We increment the value in
  376. // the SRP because it was decremented before calling
  377. // SrvEnumApiHandler.
  378. //
  379. return (BOOLEAN)( Srp->Parameters.Get.ResumeHandle + 1==
  380. SrvGetResumeHandle( &SrvRfcbList, rfcb ) );
  381. } // FilterFiles
  382. ULONG
  383. SizeFiles (
  384. IN PSERVER_REQUEST_PACKET Srp,
  385. IN PVOID Block
  386. )
  387. /*++
  388. Routine Description:
  389. This routine returns the size the passed-in RFCB would take up
  390. in an API output buffer.
  391. Arguments:
  392. Srp - a pointer to the SRP for the operation. Only the level
  393. parameter is used.
  394. Block - a pointer to the RFCB to size.
  395. Return Value:
  396. ULONG - The number of bytes the file would take up in the output
  397. buffer.
  398. --*/
  399. {
  400. PRFCB rfcb = Block;
  401. UNICODE_STRING userName;
  402. ULONG size;
  403. PAGED_CODE( );
  404. SrvGetUserAndDomainName( rfcb->Lfcb->Session, &userName, NULL );
  405. size = TOTAL_SIZE_OF_FILE( rfcb->Lfcb, Srp->Level, &userName );
  406. SrvReleaseUserAndDomainName( rfcb->Lfcb->Session, &userName, NULL );
  407. return size;
  408. } // SizeFiles