Windows NT 4.0 source code leak
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.

552 lines
13 KiB

4 years ago
  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. #pragma hdrstop
  15. #define BugCheckFileId SRV_FILE_SVCFILE
  16. //
  17. // Forward declarations.
  18. //
  19. VOID
  20. FillFileInfoBuffer (
  21. IN PSERVER_REQUEST_PACKET Srp,
  22. IN PVOID Block,
  23. IN OUT PVOID *FixedStructure,
  24. IN LPTSTR *EndOfVariableData
  25. );
  26. BOOLEAN
  27. FilterFiles (
  28. IN PSERVER_REQUEST_PACKET Srp,
  29. IN PVOID Block
  30. );
  31. ULONG
  32. SizeFiles (
  33. IN PSERVER_REQUEST_PACKET Srp,
  34. IN PVOID Block
  35. );
  36. #ifdef ALLOC_PRAGMA
  37. #pragma alloc_text( PAGE, SrvNetFileClose )
  38. #pragma alloc_text( PAGE, SrvNetFileEnum )
  39. #pragma alloc_text( PAGE, FillFileInfoBuffer )
  40. #pragma alloc_text( PAGE, FilterFiles )
  41. #pragma alloc_text( PAGE, SizeFiles )
  42. #endif
  43. //
  44. // Macros to determine the size an RFCB would take up at one of the
  45. // levels of file information.
  46. //
  47. // *** Note that the zero terminator on the path name is accounted for by
  48. // the leading backslash, which is not returned.
  49. //
  50. #define TOTAL_SIZE_OF_FILE(lfcb,level) \
  51. ( (level) == 2 ? sizeof(FILE_INFO_2) : \
  52. sizeof(FILE_INFO_3) + \
  53. SrvLengthOfStringInApiBuffer( \
  54. &(lfcb)->Mfcb->FileName) + \
  55. SrvLengthOfStringInApiBuffer( \
  56. &(lfcb)->Session->UserName) )
  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 LPTSTR *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. PAGED_CODE( );
  200. //
  201. // Update FixedStructure to point to the next structure location.
  202. //
  203. *FixedStructure = (PCHAR)*FixedStructure + FIXED_SIZE_OF_FILE( Srp->Level );
  204. ASSERT( (ULONG)*EndOfVariableData >= (ULONG)*FixedStructure );
  205. rfcb = Block;
  206. lfcb = rfcb->Lfcb;
  207. //
  208. // Case on the level to fill in the fixed structure appropriately.
  209. // We fill in actual pointers in the output structure. This is
  210. // possible because we are in the server FSD, hence the server
  211. // service's process and address space.
  212. //
  213. // *** Using the switch statement in this fashion relies on the fact
  214. // that the first fields on the different file structures are
  215. // identical.
  216. //
  217. switch( Srp->Level ) {
  218. case 3:
  219. //
  220. // Set level 3 specific fields in the buffer. Convert the
  221. // permissions (granted access) stored in the LFCB to the format
  222. // expected by the API.
  223. //
  224. fi3->fi3_permissions = 0;
  225. if ( (lfcb->GrantedAccess & FILE_READ_DATA) != 0 ) {
  226. fi3->fi3_permissions |= ACCESS_READ;
  227. }
  228. if ( (lfcb->GrantedAccess & FILE_WRITE_DATA) != 0 ) {
  229. fi3->fi3_permissions |= ACCESS_WRITE;
  230. }
  231. if ( (lfcb->GrantedAccess & FILE_EXECUTE) != 0 ) {
  232. fi3->fi3_permissions |= ACCESS_EXEC;
  233. }
  234. if ( (lfcb->GrantedAccess & DELETE) != 0 ) {
  235. fi3->fi3_permissions |= ACCESS_DELETE;
  236. }
  237. if ( (lfcb->GrantedAccess & FILE_WRITE_ATTRIBUTES) != 0 ) {
  238. fi3->fi3_permissions |= ACCESS_ATRIB;
  239. }
  240. if ( (lfcb->GrantedAccess & WRITE_DAC) != 0 ) {
  241. fi3->fi3_permissions |= ACCESS_PERM;
  242. }
  243. //
  244. // Set count of locks on the RFCB.
  245. //
  246. fi3->fi3_num_locks = rfcb->NumberOfLocks;
  247. //
  248. // Set up the pathname and username of the RFCB. Note that we
  249. // don't return the leading backslash on file names.
  250. //
  251. SrvCopyUnicodeStringToBuffer(
  252. &lfcb->Mfcb->FileName,
  253. *FixedStructure,
  254. EndOfVariableData,
  255. &fi3->fi3_pathname
  256. );
  257. ASSERT( fi3->fi3_pathname != NULL );
  258. SrvCopyUnicodeStringToBuffer(
  259. &lfcb->Session->UserName,
  260. *FixedStructure,
  261. EndOfVariableData,
  262. &fi3->fi3_username
  263. );
  264. //ASSERT( fi3->fi3_username != NULL );
  265. // *** Lack of break is intentional!
  266. case 2:
  267. //
  268. // Set up the file ID. Note that it is the same value as is
  269. // used for the resume handle, so it is possible to use this
  270. // value for rewindability.
  271. //
  272. fi3->fi3_id = rfcb->GlobalRfcbListEntry.ResumeHandle;
  273. break;
  274. default:
  275. //
  276. // This should never happen. The server service should have
  277. // checked for an invalid level.
  278. //
  279. INTERNAL_ERROR(
  280. ERROR_LEVEL_UNEXPECTED,
  281. "FillFileInfoBuffer: invalid level number: %ld",
  282. Srp->Level,
  283. NULL
  284. );
  285. return;
  286. }
  287. return;
  288. } // FillFileInfoBuffer
  289. BOOLEAN
  290. FilterFiles (
  291. IN PSERVER_REQUEST_PACKET Srp,
  292. IN PVOID Block
  293. )
  294. /*++
  295. Routine Description:
  296. This routine is intended to be called by SrvEnumApiHandler to check
  297. whether a particular RFCB should be returned.
  298. Arguments:
  299. Srp - a pointer to the SRP for the operation. ResumeHandle is
  300. used if this is a NetFileGetInfo; Name1 is used as the path
  301. name and Name2 is used as the user name if this is a
  302. NetFileEnum.
  303. Block - a pointer to the RFCB to check.
  304. Return Value:
  305. TRUE if the block should be placed in the output buffer, FALSE
  306. if it should be passed over.
  307. --*/
  308. {
  309. PRFCB rfcb = Block;
  310. PLFCB lfcb = rfcb->Lfcb;
  311. PMFCB mfcb = lfcb->Mfcb;
  312. UNICODE_STRING pathName;
  313. PAGED_CODE( );
  314. //
  315. // Check if this is an Enum or GetInfo command. The SRP_RETURN_SINGLE_ENTRY
  316. // flag is set if this is a get info.
  317. //
  318. if ( (Srp->Flags & SRP_RETURN_SINGLE_ENTRY) == 0 ) {
  319. //
  320. // If a user name was specified, the user name on the session
  321. // must match the user name in the SRP exactly.
  322. //
  323. if ( Srp->Name2.Length != 0 ) {
  324. //
  325. // A user name was specified to NetFileEnum. Check if it
  326. // matches the user name on the session.
  327. //
  328. if ( !RtlEqualUnicodeString(
  329. &Srp->Name2,
  330. &lfcb->Session->UserName,
  331. TRUE ) ) {
  332. //
  333. // The names don't match. Don't put this RFCB in the
  334. // output buffer.
  335. //
  336. return FALSE;
  337. }
  338. }
  339. //
  340. // See if the names match to as many digits of precision as are in
  341. // the specified base name. Note that if no base name was
  342. // specified, then the length = 0 and the file path will always
  343. // match. Also note that the path name stored in the MFCB has a
  344. // leading backslash, while the passed-in path name will never have
  345. // this leading slash, hence the increment of the MFCB file name
  346. // buffer.
  347. //
  348. pathName.Buffer = mfcb->FileName.Buffer;
  349. pathName.Length =
  350. MIN( Srp->Name1.Length, mfcb->FileName.Length );
  351. pathName.MaximumLength = mfcb->FileName.MaximumLength;
  352. return RtlEqualUnicodeString(
  353. &Srp->Name1,
  354. &pathName,
  355. TRUE
  356. );
  357. }
  358. //
  359. // It's a GetInfo, so just see if the ResumeHandle in the SRP
  360. // matches the ResumeHandle on the RFCB. We increment the value in
  361. // the SRP because it was decremented before calling
  362. // SrvEnumApiHandler.
  363. //
  364. return (BOOLEAN)( Srp->Parameters.Get.ResumeHandle + 1==
  365. SrvGetResumeHandle( &SrvRfcbList, rfcb ) );
  366. } // FilterFiles
  367. ULONG
  368. SizeFiles (
  369. IN PSERVER_REQUEST_PACKET Srp,
  370. IN PVOID Block
  371. )
  372. /*++
  373. Routine Description:
  374. This routine returns the size the passed-in RFCB would take up
  375. in an API output buffer.
  376. Arguments:
  377. Srp - a pointer to the SRP for the operation. Only the level
  378. parameter is used.
  379. Block - a pointer to the RFCB to size.
  380. Return Value:
  381. ULONG - The number of bytes the file would take up in the output
  382. buffer.
  383. --*/
  384. {
  385. PRFCB rfcb = Block;
  386. PAGED_CODE( );
  387. return TOTAL_SIZE_OF_FILE( rfcb->Lfcb, Srp->Level );
  388. } // SizeFiles