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.

320 lines
8.5 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: ioctl.c
  7. //
  8. // Description: This module contains wrappers around the actual ioctl
  9. // call to the kernel mode FSD.
  10. //
  11. // History:
  12. // May 11,1992. NarenG Created original version.
  13. //
  14. // For Enums the FSD should use zero-based indexing.
  15. //
  16. #include "afpsvcp.h"
  17. //**
  18. //
  19. // Call: AfpServerIOCtrl
  20. //
  21. // Returns: NO_ERROR - success
  22. // non-zero returns from AfpFSDIOControl
  23. // ERROR_INVALID_PARAMETER
  24. //
  25. // Description: This procedure is a wrapper around the I/O control to the
  26. // AFP kernel mode FSD. It unmarshals the information in the
  27. // AFP_REQUEST_PACKET calls the driver and then marshalls the
  28. // returned information back into the AFP_REQUEST_PACKET and
  29. // returns.
  30. //
  31. // NOTE: This should never be called directly for Enum and
  32. // GetInfo type requests. AfpServerIOCtrlGetInfo should
  33. // be called. It will take care of buffer manipulation.
  34. //
  35. DWORD
  36. AfpServerIOCtrl(
  37. IN PAFP_REQUEST_PACKET pAfpSrp
  38. )
  39. {
  40. DWORD cbBytesReturned;
  41. PVOID pInputBuffer = NULL;
  42. PVOID pOutputBuffer = NULL;
  43. DWORD cbInputBufferSize = 0;
  44. DWORD cbOutputBufferSize = 0;
  45. DWORD dwRetCode;
  46. // Set up the input and output buffers depending on the type of operation
  47. //
  48. switch( pAfpSrp->dwApiType ) {
  49. // No input or output buffers requred for this type of API
  50. //
  51. case AFP_API_TYPE_COMMAND:
  52. break;
  53. // Input buffer contains information to be set.
  54. // No output buffer required.
  55. //
  56. case AFP_API_TYPE_SETINFO:
  57. pInputBuffer = pAfpSrp->Type.SetInfo.pInputBuf;
  58. cbInputBufferSize = pAfpSrp->Type.SetInfo.cbInputBufSize;
  59. ((PSETINFOREQPKT)pInputBuffer)->sirqp_parmnum =
  60. pAfpSrp->Type.SetInfo.dwParmNum;
  61. break;
  62. case AFP_API_TYPE_ADD:
  63. pInputBuffer = pAfpSrp->Type.Add.pInputBuf;
  64. cbInputBufferSize = pAfpSrp->Type.Add.cbInputBufSize;
  65. break;
  66. case AFP_API_TYPE_DELETE:
  67. pInputBuffer = pAfpSrp->Type.Delete.pInputBuf;
  68. cbInputBufferSize = pAfpSrp->Type.Delete.cbInputBufSize;
  69. break;
  70. // Input buffer contains resume handle
  71. // Output buffer needed to hold returned data
  72. //
  73. case AFP_API_TYPE_ENUM:
  74. pInputBuffer = (PVOID)&( pAfpSrp->Type.Enum.EnumRequestPkt );
  75. cbInputBufferSize = sizeof( pAfpSrp->Type.Enum.EnumRequestPkt );
  76. pOutputBuffer = pAfpSrp->Type.Enum.pOutputBuf;
  77. cbOutputBufferSize = pAfpSrp->Type.Enum.cbOutputBufSize;
  78. break;
  79. // Input buffer contains information regarding the entity for
  80. // which information is requested.
  81. // Output buffer will contain information regarding that entity.
  82. //
  83. case AFP_API_TYPE_GETINFO:
  84. pInputBuffer = pAfpSrp->Type.GetInfo.pInputBuf;
  85. cbInputBufferSize = pAfpSrp->Type.GetInfo.cbInputBufSize;
  86. pOutputBuffer = pAfpSrp->Type.GetInfo.pOutputBuf;
  87. cbOutputBufferSize = pAfpSrp->Type.GetInfo.cbOutputBufSize;
  88. break;
  89. default:
  90. return( ERROR_INVALID_PARAMETER );
  91. }
  92. dwRetCode = AfpFSDIOControl( AfpGlobals.hFSD,
  93. pAfpSrp->dwRequestCode,
  94. pInputBuffer,
  95. cbInputBufferSize,
  96. pOutputBuffer,
  97. cbOutputBufferSize,
  98. &cbBytesReturned
  99. );
  100. if ( (dwRetCode != ERROR_MORE_DATA) && (dwRetCode != NO_ERROR) )
  101. return( dwRetCode );
  102. // If API was of Enum type store the Total number of entries read,
  103. // total number of available entries and resumable handle into the
  104. // Srp
  105. //
  106. if ( pAfpSrp->dwApiType == AFP_API_TYPE_ENUM ) {
  107. pAfpSrp->Type.Enum.dwEntriesRead =
  108. ((PENUMRESPPKT)pOutputBuffer)->ersp_cInBuf;
  109. pAfpSrp->Type.Enum.dwTotalAvail =
  110. ((PENUMRESPPKT)pOutputBuffer)->ersp_cTotEnts;
  111. pAfpSrp->Type.Enum.EnumRequestPkt.erqp_Index =
  112. ((PENUMRESPPKT)pOutputBuffer)->ersp_hResume;
  113. // Shift the data to the start of the buffer, over-writing the
  114. // enum reponse information.
  115. //
  116. CopyMemory( pOutputBuffer,
  117. (PVOID)((ULONG_PTR)pOutputBuffer+sizeof(ENUMRESPPKT)),
  118. cbBytesReturned - sizeof(ENUMRESPPKT) );
  119. }
  120. // If API type was GetInfo, store the Total number of bytes available
  121. // and the total number of bytes read.
  122. //
  123. if ( pAfpSrp->dwApiType == AFP_API_TYPE_GETINFO )
  124. pAfpSrp->Type.GetInfo.cbTotalBytesAvail = cbBytesReturned;
  125. return( dwRetCode );
  126. }
  127. //**
  128. //
  129. // Call: AfpServerIOCtrlGetInfo
  130. //
  131. // Returns: NO_ERROR - success
  132. // non-zero returns from DeviceIOCtrl
  133. // Non-zero returns from CreateEvent
  134. // ERROR_NOT_ENOUGH_MEMORY
  135. // ERROR_INVALID_PARAMETER
  136. //
  137. // Description: This is a wrapper around the AfpServerIOCtrl call for GetInfo
  138. // and Enum type calls that can return variable amounts of data.
  139. //
  140. // For Enum calls, if AfpSrp.Enum.dwOutputBufSize == -1 it will
  141. // allocate and return ALL information that is available.
  142. // Otherwise it will allocate and return as much data that can
  143. // be contained in the AfpSrp.Enum.dwOutputBufSize parameter. The
  144. // caller of this procedure will set the value in
  145. // AfpSrp.Enum.dwOutputBufSize to be equal to the value of
  146. // MaxPreferredLength which was set by the caller of the Enum or
  147. // GetInfo API.
  148. //
  149. // For GetInfo type calls AfpSrp.Enum.dwOutputBufSize == -1 always,
  150. // so this routine will always try to get ALL the available
  151. // information.
  152. //
  153. DWORD
  154. AfpServerIOCtrlGetInfo(
  155. IN OUT PAFP_REQUEST_PACKET pAfpSrp
  156. )
  157. {
  158. DWORD dwRetCode;
  159. BOOL fGetEverything = FALSE;
  160. PVOID pOutputBuf;
  161. // Set up the output buffers
  162. //
  163. switch( pAfpSrp->dwApiType ) {
  164. case AFP_API_TYPE_ENUM:
  165. // Find out how much data the client wants.
  166. //
  167. if ( pAfpSrp->Type.Enum.cbOutputBufSize == -1 ) {
  168. // Client wants everything, so allocate a default size buffer
  169. //
  170. pAfpSrp->Type.Enum.cbOutputBufSize = AFP_INITIAL_BUFFER_SIZE +
  171. sizeof(ENUMRESPPKT);
  172. fGetEverything = TRUE;
  173. }
  174. else {
  175. // Otherwise just allocate enough for what the client wants
  176. //
  177. pAfpSrp->Type.Enum.cbOutputBufSize += sizeof(ENUMRESPPKT);
  178. }
  179. pOutputBuf = MIDL_user_allocate( pAfpSrp->Type.Enum.cbOutputBufSize );
  180. if ( pOutputBuf == NULL )
  181. return( ERROR_NOT_ENOUGH_MEMORY );
  182. pAfpSrp->Type.Enum.pOutputBuf = pOutputBuf;
  183. break;
  184. case AFP_API_TYPE_GETINFO:
  185. // Client will ALWAYS want everything
  186. //
  187. pAfpSrp->Type.GetInfo.cbOutputBufSize = AFP_INITIAL_BUFFER_SIZE;
  188. pOutputBuf = MIDL_user_allocate(pAfpSrp->Type.GetInfo.cbOutputBufSize);
  189. if ( pOutputBuf == NULL )
  190. return( ERROR_NOT_ENOUGH_MEMORY );
  191. pAfpSrp->Type.GetInfo.pOutputBuf = pOutputBuf;
  192. fGetEverything = TRUE;
  193. break;
  194. default:
  195. return( ERROR_INVALID_PARAMETER );
  196. }
  197. // Make the IOCTL to the FSD
  198. //
  199. dwRetCode = AfpServerIOCtrl( pAfpSrp );
  200. if ( (dwRetCode != NO_ERROR) && (dwRetCode != ERROR_MORE_DATA) ) {
  201. MIDL_user_free( pOutputBuf );
  202. return( dwRetCode );
  203. }
  204. // If we have obtained all requested data then we are done
  205. //
  206. if ( !(( dwRetCode == ERROR_MORE_DATA ) && fGetEverything ))
  207. return( dwRetCode );
  208. // Otherwise the client wants more data and there is more to be obtained
  209. //
  210. if ( pAfpSrp->dwApiType == AFP_API_TYPE_ENUM ) {
  211. // Increase the buffer size using a heuristic.
  212. //
  213. MIDL_user_free( pOutputBuf );
  214. pAfpSrp->Type.Enum.cbOutputBufSize = pAfpSrp->Type.Enum.dwTotalAvail
  215. * AFP_AVG_STRUCT_SIZE
  216. + AFP_INITIAL_BUFFER_SIZE
  217. + sizeof(ENUMRESPPKT);
  218. pOutputBuf = MIDL_user_allocate( pAfpSrp->Type.Enum.cbOutputBufSize );
  219. if ( pOutputBuf == NULL )
  220. return( ERROR_NOT_ENOUGH_MEMORY );
  221. pAfpSrp->Type.Enum.pOutputBuf = pOutputBuf;
  222. // If we are trying to get all the information then we reset the
  223. // resume handle to 0
  224. //
  225. if ( fGetEverything )
  226. pAfpSrp->Type.Enum.EnumRequestPkt.erqp_Index = 0;
  227. }
  228. if ( pAfpSrp->dwApiType == AFP_API_TYPE_GETINFO ) {
  229. // Increase the buffer size using the total available number
  230. // of bytes + Fudge Factor.
  231. //
  232. MIDL_user_free( pOutputBuf );
  233. pAfpSrp->Type.GetInfo.cbOutputBufSize =
  234. pAfpSrp->Type.GetInfo.cbTotalBytesAvail +
  235. AFP_INITIAL_BUFFER_SIZE;
  236. pOutputBuf=MIDL_user_allocate( pAfpSrp->Type.GetInfo.cbOutputBufSize );
  237. if ( pOutputBuf == NULL )
  238. return( ERROR_NOT_ENOUGH_MEMORY );
  239. pAfpSrp->Type.GetInfo.pOutputBuf = pOutputBuf;
  240. }
  241. // Make the IOCTL to the FSD, if we dont get all the data this time
  242. // we give up and return to the caller.
  243. //
  244. dwRetCode = AfpServerIOCtrl( pAfpSrp );
  245. if ( (dwRetCode != NO_ERROR) && (dwRetCode != ERROR_MORE_DATA) )
  246. MIDL_user_free( pOutputBuf );
  247. return( dwRetCode );
  248. }
  249.