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.

618 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ApiFile.c
  5. Abstract:
  6. This module contains individual API handlers for the NetFile APIs.
  7. SUPPORTED - NetFileClose2, NetFileEnum2, NetFileGetInfo2.
  8. Author:
  9. Shanku Niyogi (w-shanku) 20-Feb-1991
  10. Revision History:
  11. --*/
  12. #include "XactSrvP.h"
  13. //
  14. // Declaration of descriptor strings.
  15. //
  16. STATIC const LPDESC Desc16_file_info_2 = REM16_file_info_2;
  17. STATIC const LPDESC Desc32_file_info_2 = REM32_file_info_2;
  18. STATIC const LPDESC Desc16_file_info_3 = REM16_file_info_3;
  19. STATIC const LPDESC Desc32_file_info_3 = REM32_file_info_3;
  20. NTSTATUS
  21. XsNetFileClose2 (
  22. API_HANDLER_PARAMETERS
  23. )
  24. /*++
  25. Routine Description:
  26. This routine handles a call to NetFileClose.
  27. Arguments:
  28. API_HANDLER_PARAMETERS - information about the API call. See
  29. XsTypes.h for details.
  30. Return Value:
  31. NTSTATUS - STATUS_SUCCESS or reason for failure.
  32. --*/
  33. {
  34. NET_API_STATUS status;
  35. PXS_NET_FILE_CLOSE_2 parameters = Parameters;
  36. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  37. try {
  38. //
  39. // Make the local call.
  40. //
  41. status = NetFileClose(
  42. NULL,
  43. SmbGetUlong( &parameters->FileId )
  44. );
  45. } except( EXCEPTION_EXECUTE_HANDLER ) {
  46. status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  47. }
  48. if ( !XsApiSuccess( status )) {
  49. IF_DEBUG(ERRORS) {
  50. NetpKdPrint(( "XsNetFileClose2: NetFileClose failed: %X\n",
  51. status ));
  52. }
  53. }
  54. //
  55. // No return data.
  56. //
  57. Header->Status = (WORD)status;
  58. return STATUS_SUCCESS;
  59. } // XsNetFileClose2
  60. NTSTATUS
  61. XsNetFileEnum2 (
  62. API_HANDLER_PARAMETERS
  63. )
  64. /*++
  65. Routine Description:
  66. This routine handles a call to NetFileEnum.
  67. Arguments:
  68. API_HANDLER_PARAMETERS - information about the API call. See
  69. XsTypes.h for details.
  70. Return Value:
  71. NTSTATUS - STATUS_SUCCESS or reason for failure.
  72. --*/
  73. {
  74. NET_API_STATUS status;
  75. PXS_NET_FILE_ENUM_2 parameters = Parameters;
  76. LPTSTR nativeBasePath = NULL; // Native parameters
  77. LPTSTR nativeUserName = NULL;
  78. LPVOID outBuffer = NULL;
  79. DWORD entriesRead;
  80. DWORD totalEntries;
  81. DWORD_PTR resumeKey = 0;
  82. DWORD entriesFilled = 0; // Conversion variables
  83. DWORD totalEntriesRead = 0;
  84. DWORD bytesRequired = 0;
  85. DWORD nativeBufferSize;
  86. LPDESC nativeStructureDesc;
  87. LPBYTE bufferBegin;
  88. DWORD bufferSize;
  89. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  90. IF_DEBUG(FILE) {
  91. NetpKdPrint(( "XsNetFileEnum2: header at %lx, params at %lx, "
  92. "level %ld, buf size %ld\n",
  93. Header, parameters, SmbGetUshort( &parameters->Level ),
  94. SmbGetUshort( &parameters->BufLen )));
  95. }
  96. try {
  97. //
  98. // Translate parameters, check for errors.
  99. //
  100. XsConvertTextParameter(
  101. nativeBasePath,
  102. (LPSTR)XsSmbGetPointer( &parameters->BasePath )
  103. );
  104. XsConvertTextParameter(
  105. nativeUserName,
  106. (LPSTR)XsSmbGetPointer( &parameters->UserName )
  107. );
  108. //
  109. // Copy input resume handle to output resume handle, and get a copy of it.
  110. //
  111. if ( SmbGetUlong( &parameters->ResumeKeyIn ) == 0 ) {
  112. Header->Status = ERROR_INVALID_PARAMETER;
  113. goto cleanup;
  114. }
  115. RtlCopyMemory( parameters->ResumeKeyOut,
  116. (LPBYTE)XsSmbGetPointer( &parameters->ResumeKeyIn ), 8 );
  117. resumeKey = (DWORD)SmbGetUlong( &parameters->ResumeKeyOut[2] );
  118. IF_DEBUG(FILE) {
  119. NetpKdPrint(( "XsNetFileEnum2: resume key is %ld\n", resumeKey ));
  120. }
  121. //
  122. // Use the level to determine the descriptor string.
  123. //
  124. switch ( SmbGetUshort( &parameters->Level ) ) {
  125. case 2:
  126. StructureDesc = Desc16_file_info_2;
  127. nativeStructureDesc = Desc32_file_info_2;
  128. break;
  129. case 3:
  130. StructureDesc = Desc16_file_info_3;
  131. nativeStructureDesc = Desc32_file_info_3;
  132. break;
  133. default:
  134. //
  135. // Unsupported levels, abort before any work.
  136. //
  137. Header->Status = ERROR_INVALID_LEVEL;
  138. goto cleanup;
  139. }
  140. //
  141. // NetFileEnum2 is a resumable API, so we cannot get more information
  142. // from the native call than we can send back. The most efficient way
  143. // to do this is in a loop...we use the 16-bit buffer size to determine
  144. // a safe native buffer size, make the call, fill the entries, then
  145. // take the amount of space remaining and determine a safe size again,
  146. // and so on, until NetFileEnum returns either no entries or all entries
  147. // read.
  148. //
  149. //
  150. // Initialize important variables for loop.
  151. //
  152. bufferBegin = (LPBYTE)XsSmbGetPointer( &parameters->Buffer );
  153. bufferSize = (DWORD)SmbGetUshort( &parameters->BufLen );
  154. totalEntriesRead = 0;
  155. for ( ; ; ) {
  156. //
  157. // Compute a safe size for the native buffer.
  158. //
  159. switch ( SmbGetUshort( &parameters->Level ) ) {
  160. case 2:
  161. nativeBufferSize = bufferSize;
  162. break;
  163. case 3:
  164. nativeBufferSize = bufferSize;
  165. break;
  166. }
  167. //
  168. // Make the local call.
  169. //
  170. status = NetFileEnum(
  171. NULL,
  172. nativeBasePath,
  173. nativeUserName,
  174. (DWORD)SmbGetUshort( &parameters->Level ),
  175. (LPBYTE *)&outBuffer,
  176. nativeBufferSize,
  177. &entriesRead,
  178. &totalEntries,
  179. &resumeKey
  180. );
  181. if ( !XsApiSuccess( status )) {
  182. IF_DEBUG(API_ERRORS) {
  183. NetpKdPrint(( "XsNetFileEnum2: NetFileEnum failed: %X\n",
  184. status ));
  185. }
  186. Header->Status = (WORD)status;
  187. goto cleanup;
  188. }
  189. IF_DEBUG(FILE) {
  190. NetpKdPrint(( "XsNetFileEnum2: received %ld entries at %lx\n",
  191. entriesRead, outBuffer ));
  192. NetpKdPrint(( "XsNetFileEnum2: resume key is now %Id\n",
  193. resumeKey ));
  194. }
  195. //
  196. // Was NetFileEnum able to read at least one complete entry?
  197. //
  198. if ( entriesRead == 0 ) {
  199. break;
  200. }
  201. //
  202. // Do the actual conversion from the 32-bit structures to 16-bit
  203. // structures.
  204. //
  205. XsFillEnumBuffer(
  206. outBuffer,
  207. entriesRead,
  208. nativeStructureDesc,
  209. bufferBegin,
  210. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  211. bufferSize,
  212. StructureDesc,
  213. NULL, // verify function
  214. &bytesRequired,
  215. &entriesFilled,
  216. NULL
  217. );
  218. IF_DEBUG(FILE) {
  219. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
  220. " Entries %ld of %ld\n",
  221. outBuffer, SmbGetUlong( &parameters->Buffer ),
  222. bytesRequired, entriesFilled, totalEntries ));
  223. }
  224. //
  225. // Very key assertion!
  226. //
  227. NetpAssert( entriesRead == entriesFilled );
  228. //
  229. // Update count of entries read.
  230. //
  231. totalEntriesRead += entriesRead;
  232. //
  233. // Are there any more entries to read?
  234. //
  235. if ( entriesRead == totalEntries ) {
  236. break;
  237. }
  238. //
  239. // Calculate new buffer beginning and size.
  240. //
  241. bufferBegin += entriesRead *
  242. RapStructureSize( StructureDesc, Response, FALSE );
  243. bufferSize -= bytesRequired;
  244. //
  245. // Free last native buffer.
  246. //
  247. NetApiBufferFree( outBuffer );
  248. outBuffer = NULL;
  249. }
  250. //
  251. // Upon exit from the loop, totalEntriesRead has the number of entries
  252. // read, entriesRead has the number read in the last call, totalEntries
  253. // has the number remaining plus entriesRead. Formulate return codes,
  254. // etc. from these values.
  255. //
  256. if ( totalEntries > entriesRead ) {
  257. Header->Status = ERROR_MORE_DATA;
  258. } else {
  259. Header->Converter = XsPackReturnData(
  260. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  261. SmbGetUshort( &parameters->BufLen ),
  262. StructureDesc,
  263. totalEntriesRead
  264. );
  265. }
  266. IF_DEBUG(FILE) {
  267. NetpKdPrint(( "XsNetFileEnum2: resume key is now %ld\n", resumeKey ));
  268. }
  269. //
  270. // Set up the response parameters.
  271. //
  272. SmbPutUshort( &parameters->EntriesRead, (WORD)totalEntriesRead );
  273. SmbPutUshort( &parameters->EntriesRemaining,
  274. (WORD)( totalEntries - entriesRead ));
  275. //
  276. // Over the wire, resumeKey is a true 32-bit index, so this cast works.
  277. //
  278. SmbPutUlong( (LPDWORD)&parameters->ResumeKeyOut[2], (DWORD)resumeKey );
  279. cleanup:
  280. ;
  281. } except( EXCEPTION_EXECUTE_HANDLER ) {
  282. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  283. }
  284. NetApiBufferFree( outBuffer );
  285. NetpMemoryFree( nativeBasePath );
  286. NetpMemoryFree( nativeUserName );
  287. //
  288. // Determine return buffer size.
  289. //
  290. XsSetDataCount(
  291. &parameters->BufLen,
  292. StructureDesc,
  293. Header->Converter,
  294. totalEntriesRead,
  295. Header->Status
  296. );
  297. return STATUS_SUCCESS;
  298. } // XsNetFileEnum2
  299. NTSTATUS
  300. XsNetFileGetInfo2 (
  301. API_HANDLER_PARAMETERS
  302. )
  303. /*++
  304. Routine Description:
  305. This routine handles a call to NetFileGetInfo2.
  306. Arguments:
  307. API_HANDLER_PARAMETERS - information about the API call. See
  308. XsTypes.h for details.
  309. Return Value:
  310. NTSTATUS - STATUS_SUCCESS or reason for failure.
  311. --*/
  312. {
  313. NET_API_STATUS status;
  314. PXS_NET_FILE_GET_INFO_2 parameters = Parameters;
  315. LPVOID outBuffer = NULL; // Native parameters
  316. LPBYTE stringLocation = NULL; // Conversion variables
  317. DWORD bytesRequired = 0;
  318. LPDESC nativeStructureDesc;
  319. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  320. IF_DEBUG(FILE) {
  321. NetpKdPrint(( "XsNetFileGetInfo2: header at %lx, "
  322. "params at %lx, level %ld\n",
  323. Header, parameters, SmbGetUshort( &parameters->Level ) ));
  324. }
  325. try {
  326. //
  327. // Check errors.
  328. //
  329. if ( XsWordParamOutOfRange( parameters->Level, 2, 3 )) {
  330. Header->Status = ERROR_INVALID_LEVEL;
  331. goto cleanup;
  332. }
  333. //
  334. // Make the local call.
  335. //
  336. status = NetFileGetInfo(
  337. NULL,
  338. SmbGetUlong( &parameters->FileId ),
  339. (DWORD)SmbGetUshort( &parameters->Level ),
  340. (LPBYTE *)&outBuffer
  341. );
  342. if ( !XsApiSuccess( status )) {
  343. IF_DEBUG(API_ERRORS) {
  344. NetpKdPrint(( "XsNetFileGetInfo2: NetFileGetInfo failed: "
  345. "%X\n", status ));
  346. }
  347. Header->Status = (WORD)status;
  348. goto cleanup;
  349. }
  350. //
  351. // Use the requested level to determine the format of the
  352. // data structure.
  353. //
  354. switch ( SmbGetUshort( &parameters->Level ) ) {
  355. case 2:
  356. StructureDesc = Desc16_file_info_2;
  357. nativeStructureDesc = Desc32_file_info_2;
  358. break;
  359. case 3:
  360. StructureDesc = Desc16_file_info_3;
  361. nativeStructureDesc = Desc32_file_info_3;
  362. break;
  363. }
  364. //
  365. // Convert the structure returned by the 32-bit call to a 16-bit
  366. // structure. The last possible location for variable data is
  367. // calculated from buffer location and length.
  368. //
  369. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->Buffer )
  370. + SmbGetUshort( &parameters->BufLen ) );
  371. status = RapConvertSingleEntry(
  372. outBuffer,
  373. nativeStructureDesc,
  374. FALSE,
  375. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  376. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  377. StructureDesc,
  378. TRUE,
  379. &stringLocation,
  380. &bytesRequired,
  381. Response,
  382. NativeToRap
  383. );
  384. if ( status != NERR_Success ) {
  385. IF_DEBUG(ERRORS) {
  386. NetpKdPrint(( "XsFileGetInfo2: RapConvertSingleEntry failed: "
  387. "%X\n", status ));
  388. }
  389. Header->Status = NERR_InternalError;
  390. goto cleanup;
  391. }
  392. IF_DEBUG(FILE) {
  393. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  394. outBuffer, SmbGetUlong( &parameters->Buffer ),
  395. bytesRequired ));
  396. }
  397. //
  398. // Determine return code based on the size of the buffer.
  399. //
  400. if ( !XsCheckBufferSize(
  401. SmbGetUshort( &parameters->BufLen ),
  402. StructureDesc,
  403. FALSE // not in native format
  404. )) {
  405. IF_DEBUG(ERRORS) {
  406. NetpKdPrint(( "XsNetFileGetInfo2: Buffer too small.\n" ));
  407. }
  408. Header->Status = NERR_BufTooSmall;
  409. } else {
  410. if ( bytesRequired > (DWORD)SmbGetUshort( &parameters-> BufLen )) {
  411. IF_DEBUG(ERRORS) {
  412. NetpKdPrint(( "NetFileGetInfo2: More data available.\n" ));
  413. }
  414. Header->Status = ERROR_MORE_DATA;
  415. } else {
  416. //
  417. // Pack the response data.
  418. //
  419. Header->Converter = XsPackReturnData(
  420. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  421. SmbGetUshort( &parameters->BufLen ),
  422. StructureDesc,
  423. 1
  424. );
  425. }
  426. }
  427. //
  428. // Set up the response parameters.
  429. //
  430. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  431. cleanup:
  432. ;
  433. } except( EXCEPTION_EXECUTE_HANDLER ) {
  434. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  435. }
  436. NetApiBufferFree( outBuffer );
  437. //
  438. // Determine return buffer size.
  439. //
  440. XsSetDataCount(
  441. &parameters->BufLen,
  442. StructureDesc,
  443. Header->Converter,
  444. 1,
  445. Header->Status
  446. );
  447. return STATUS_SUCCESS;
  448. } // XsNetFileGetInfo2