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.

272 lines
7.1 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fsd_srv.c
  5. Abstract:
  6. This module contains the entry points for the AFP server APIs. The API
  7. dispatcher calls these. These are all callable from FSD. All of the APIs
  8. complete in the DPC context. The ones which are completed in the FSP are
  9. directly queued to the workers in fsp_srv.c
  10. Author:
  11. Jameel Hyder (microsoft!jameelh)
  12. Revision History:
  13. 25 Apr 1992 Initial Version
  14. Notes: Tab stop: 4
  15. --*/
  16. #define FILENUM FILE_FSD_SRV
  17. #include <afp.h>
  18. #include <gendisp.h>
  19. /*** AfpFsdDispGetSrvrParms
  20. *
  21. * This routine implements the AfpGetSrvrParms API. This completes here i.e.
  22. * it is not queued up to the Fsp.
  23. *
  24. * There is no request packet for this API.
  25. *
  26. * Locks are acquired for both the volume list and individual volume descs.
  27. *
  28. * LOCKS: vds_VolLock (SPIN), AfpVolumeListLock (SPIN)
  29. *
  30. * LOCK_ORDER: vds_VolLock (SPIN) after AfpVolumeListLock (SPIN)
  31. */
  32. AFPSTATUS FASTCALL
  33. AfpFsdDispGetSrvrParms(
  34. IN PSDA pSda
  35. )
  36. {
  37. PBYTE pTemp; // Roving pointer
  38. PVOLDESC pVolDesc;
  39. LONG VolCount;
  40. AFPTIME MacTime;
  41. BOOLEAN MoreSpace = True;
  42. struct _ResponsePacket
  43. {
  44. BYTE __ServerTime[4];
  45. BYTE __NumVols;
  46. };
  47. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  48. ("AfpFsdDispGetSrvrParms: Entered\n"));
  49. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  50. /*
  51. * Estimate the size of reply buffer needed. We need one big enough to
  52. * either accomodate all volumes or the maximum size buffer whichever
  53. * is less.
  54. *
  55. * The reply consists of the server time, count of volumes and a list of
  56. * volumes and flags to indicate if this volume has a password.
  57. *
  58. * NOTE: If we decide to do private volumes, then the following code
  59. * has to change. Specifically AfpVolCount will have to be computed
  60. * based on how many private volumes exist and if there is one
  61. * for this user.
  62. */
  63. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpVolumeListLock);
  64. /*
  65. * Each volume entry takes a byte for flags, a byte for length and the
  66. * size of the volume name string. We estimate based on maximum size of
  67. * the volume name. On an average it will be less. For every volume, apart
  68. * from the volume name, we need a byte for volume flags and a byte for
  69. * the volume name length.
  70. */
  71. if ((pSda->sda_ReplySize = (USHORT)(SIZE_RESPPKT + AfpVolCount *
  72. (SIZE_PASCALSTR(AFP_VOLNAME_LEN+1) + sizeof(BYTE)))) > pSda->sda_MaxWriteSize)
  73. pSda->sda_ReplySize = (USHORT)pSda->sda_MaxWriteSize;
  74. if (AfpAllocReplyBuf(pSda) != AFP_ERR_NONE)
  75. {
  76. RELEASE_SPIN_LOCK_FROM_DPC(&AfpVolumeListLock);
  77. return AFP_ERR_MISC;
  78. }
  79. // Point pTemp past the response header
  80. pTemp = pSda->sda_ReplyBuf + SIZE_RESPPKT;
  81. for (VolCount = 0, pVolDesc = AfpVolumeList;
  82. (pVolDesc != NULL) && MoreSpace;
  83. pVolDesc = pVolDesc->vds_Next)
  84. {
  85. ACQUIRE_SPIN_LOCK_AT_DPC(&pVolDesc->vds_VolLock);
  86. do
  87. {
  88. // Ignore volumes that have not been added completely
  89. if (pVolDesc->vds_Flags & (VOLUME_INTRANSITION | VOLUME_DELETED | VOLUME_INITIAL_CACHE))
  90. break;
  91. // Ignore volumes that do not have guest access and the client
  92. // is guest
  93. if (!(pVolDesc->vds_Flags & AFP_VOLUME_GUESTACCESS) &&
  94. (pSda->sda_ClientType == SDA_CLIENT_GUEST))
  95. break;
  96. // See if we are likely to cross bounds. For each volume we need a
  97. // byte for the PASCALSTR name and a flag byte. Note that we do not
  98. // add any pads.
  99. if ((pTemp + SIZE_PASCALSTR(pVolDesc->vds_MacName.Length) +
  100. sizeof(BYTE)) >= (pSda->sda_ReplyBuf + pSda->sda_ReplySize))
  101. {
  102. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  103. ("AfpFsdDispGetSrvrParms: Out of space\n"));
  104. MoreSpace = False;
  105. break;
  106. }
  107. // Check for volume password. We never carry the HasConfigInfo bit !!
  108. *pTemp++ = (pVolDesc->vds_Flags & AFP_VOLUME_HASPASSWORD) ?
  109. SRVRPARMS_VOLUMEHASPASS : 0;
  110. *pTemp++ = (BYTE)pVolDesc->vds_MacName.Length;
  111. RtlCopyMemory(pTemp, pVolDesc->vds_MacName.Buffer,
  112. pVolDesc->vds_MacName.Length);
  113. pTemp += pVolDesc->vds_MacName.Length;
  114. VolCount ++;
  115. } while (False);
  116. RELEASE_SPIN_LOCK_FROM_DPC(&pVolDesc->vds_VolLock);
  117. }
  118. RELEASE_SPIN_LOCK_FROM_DPC(&AfpVolumeListLock);
  119. pSda->sda_ReplySize = (USHORT)(pTemp - pSda->sda_ReplyBuf);
  120. ASSERT (VolCount <= AfpVolCount);
  121. AfpGetCurrentTimeInMacFormat(&MacTime);
  122. PUTDWORD2DWORD(pRspPkt->__ServerTime, MacTime);
  123. PUTDWORD2BYTE(&pRspPkt->__NumVols, VolCount);
  124. return AFP_ERR_NONE;
  125. }
  126. /*** AfpFsdDispGetSrvrMsg
  127. *
  128. * This routine implements the AfpGetSrvrMsg API. This completes here i.e.
  129. * it is not queued up to the Fsp.
  130. *
  131. * The request packet is represented below.
  132. *
  133. * sda_ReqBlock DWORD MsgType
  134. * sda_ReqBlock DWORD Bitmap
  135. *
  136. * LOCKS: AfpServerGlobalLock (SPIN), sda_Lock (SPIN)
  137. * LOCK_ORDER: sda_Lock after AfpServerGlobalLock
  138. */
  139. AFPSTATUS FASTCALL
  140. AfpFsdDispGetSrvrMsg(
  141. IN PSDA pSda
  142. )
  143. {
  144. DWORD MsgType,
  145. Bitmap;
  146. AFPSTATUS Status = AFP_ERR_NONE;
  147. ANSI_STRING Message;
  148. struct _RequestPacket
  149. {
  150. DWORD _MsgType,
  151. _Bitmap;
  152. };
  153. struct _ResponsePacket
  154. {
  155. BYTE __MsgType[2],
  156. __Bitmap[2],
  157. __Message[1];
  158. };
  159. DBGPRINT(DBG_COMP_AFPAPI_SRV, DBG_LEVEL_INFO,
  160. ("AfpFsdDispGetSrvrMsg: Entered\n"));
  161. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  162. // Note: Should we be doing this ? Why not give it to him since he asked.
  163. if (pSda->sda_ClientVersion < AFP_VER_21)
  164. return AFP_ERR_CALL_NOT_SUPPORTED;
  165. MsgType = pReqPkt->_MsgType;
  166. Bitmap = pReqPkt->_Bitmap;
  167. do
  168. {
  169. if (Bitmap & ~SRVRMSG_BITMAP_MESSAGE)
  170. {
  171. Status = AFP_ERR_BITMAP;
  172. break;
  173. }
  174. if ((MsgType != SRVRMSG_LOGIN) &&
  175. (MsgType != SRVRMSG_SERVER))
  176. {
  177. Status = AFP_ERR_PARAM;
  178. break;
  179. }
  180. // Allocate a reply buffer for a maximum size message. We cannot hold the
  181. // SDA lock and call the AllocBuf routine since it calls AfpInterlocked...
  182. pSda->sda_ReplySize = SIZE_RESPPKT + AFP_MAXCOMMENTSIZE;
  183. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  184. {
  185. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpServerGlobalLock);
  186. ACQUIRE_SPIN_LOCK_AT_DPC(&pSda->sda_Lock);
  187. switch (MsgType)
  188. {
  189. case SRVRMSG_LOGIN:
  190. Message = AfpLoginMsg;
  191. break;
  192. case SRVRMSG_SERVER:
  193. if (pSda->sda_Message != NULL)
  194. Message = *(pSda->sda_Message);
  195. else if (AfpServerMsg != NULL)
  196. Message = *AfpServerMsg;
  197. else // Setup a default of No message.
  198. AfpSetEmptyAnsiString(&Message, 0, NULL);
  199. break;
  200. }
  201. pSda->sda_ReplySize = SIZE_RESPPKT + Message.Length;
  202. PUTSHORT2SHORT(pRspPkt->__MsgType, MsgType);
  203. PUTSHORT2SHORT(pRspPkt->__Bitmap, Bitmap);
  204. pRspPkt->__Message[0] = (BYTE) Message.Length;
  205. if (Message.Length > 0)
  206. {
  207. RtlCopyMemory( &pRspPkt->__Message[1],
  208. Message.Buffer,
  209. Message.Length);
  210. }
  211. // If this is not a broadcast message, then get rid of the
  212. // Sda message memory as it is consuming non-paged resources
  213. if ((MsgType == SRVRMSG_SERVER) &&
  214. (pSda->sda_Message != NULL))
  215. {
  216. AfpFreeMemory(pSda->sda_Message);
  217. pSda->sda_Message = NULL;
  218. }
  219. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  220. RELEASE_SPIN_LOCK_FROM_DPC(&AfpServerGlobalLock);
  221. }
  222. if (Status == AFP_ERR_NONE)
  223. INTERLOCKED_INCREMENT_LONG(&AfpServerStatistics.stat_NumMessagesSent);
  224. } while (False);
  225. return Status;
  226. }
  227.