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.

2946 lines
64 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. afpapi.c
  5. Abstract:
  6. This module contains the AFP API Dispatcher.
  7. Author:
  8. Jameel Hyder (microsoft!jameelh)
  9. Revision History:
  10. 25 Apr 1992 Initial Version
  11. Notes: Tab stop: 4
  12. --*/
  13. #define FILENUM FILE_AFPAPI
  14. #include <afp.h>
  15. #include <gendisp.h>
  16. #include <client.h>
  17. #include <fdparm.h>
  18. #include <forkio.h>
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text( PAGE, AfpStartApiProcessing)
  21. #endif
  22. /*
  23. * The following array is indexed by the AFP opcode. The rationale behind this
  24. * table is that the majority of codes are unused (> 200 out of 255). This
  25. * scheme makes the actual dispatch table much smaller at the cost of an extra
  26. * array look-up.
  27. */
  28. LOCAL BYTE AfpOpCodeTable[256] =
  29. {
  30. /*00-02*/ _AFP_INVALID_OPCODE, _AFP_BYTE_RANGE_LOCK, _AFP_CLOSE_VOL,
  31. /*03-05*/ _AFP_CLOSE_DIR, _AFP_CLOSE_FORK, _AFP_COPY_FILE,
  32. /*06-08*/ _AFP_CREATE_DIR, _AFP_CREATE_FILE, _AFP_DELETE,
  33. /*09-0B*/ _AFP_ENUMERATE, _AFP_FLUSH, _AFP_FLUSH_FORK,
  34. /*0C-0E*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_GET_FORK_PARMS,
  35. /*0F-11*/ _AFP_GET_SRVR_INFO, _AFP_GET_SRVR_PARMS, _AFP_GET_VOL_PARMS,
  36. /*12-14*/ _AFP_LOGIN, _AFP_LOGIN_CONT, _AFP_LOGOUT,
  37. /*15-17*/ _AFP_MAP_ID, _AFP_MAP_NAME, _AFP_MOVE_AND_RENAME,
  38. /*18-1A*/ _AFP_OPEN_VOL, _AFP_OPEN_DIR, _AFP_OPEN_FORK,
  39. /*1B-1D*/ _AFP_READ, _AFP_RENAME, _AFP_SET_DIR_PARMS,
  40. /*1E-20*/ _AFP_SET_FILE_PARMS, _AFP_SET_FORK_PARMS, _AFP_SET_VOL_PARMS,
  41. /*21-23*/ _AFP_WRITE, _AFP_GET_FILE_DIR_PARMS,_AFP_SET_FILE_DIR_PARMS,
  42. /*24-26*/ _AFP_CHANGE_PASSWORD, _AFP_GET_USER_INFO, _AFP_GET_SRVR_MSG,
  43. /*27-29*/ _AFP_CREATE_ID, _AFP_DELETE_ID, _AFP_RESOLVE_ID,
  44. /*2A-2C*/ _AFP_EXCHANGE_FILES, _AFP_CAT_SEARCH, _AFP_INVALID_OPCODE,
  45. /*2D-2F*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  46. /*30-32*/ _AFP_OPEN_DT, _AFP_CLOSE_DT, _AFP_INVALID_OPCODE,
  47. /*33-35*/ _AFP_GET_ICON, _AFP_GET_ICON_INFO, _AFP_ADD_APPL,
  48. /*36-38*/ _AFP_REMOVE_APPL, _AFP_GET_APPL, _AFP_ADD_COMMENT,
  49. /*39-3B*/ _AFP_REMOVE_COMMENT, _AFP_GET_COMMENT, _AFP_INVALID_OPCODE,
  50. /*3C-3E*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  51. /*3F-41*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  52. /*42-44*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  53. /*45-47*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  54. /*48-4A*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  55. /*4B-4D*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  56. /*4E-50*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  57. /*51-53*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  58. /*54-56*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  59. /*57-59*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  60. /*5A-5C*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  61. /*5D-5F*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  62. /*60-62*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  63. /*63-65*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  64. /*66-68*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  65. /*69-6B*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  66. /*6C-6E*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  67. /*6F-71*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  68. /*72-74*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  69. /*75-77*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  70. /*78-7A*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  71. /*7B-7D*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  72. /*7E-80*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  73. /*81-83*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  74. /*84-86*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  75. /*87-89*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  76. /*8A-8C*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  77. /*8D-8F*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  78. /*90-92*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  79. /*93-95*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  80. /*96-98*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  81. /*99-9B*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  82. /*9C-9E*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  83. /*9F-A1*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  84. /*A2-A4*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  85. /*A5-A7*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  86. /*A8-AA*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  87. /*AB-AD*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  88. /*AE-B0*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  89. /*B1-B3*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  90. /*B4-B6*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  91. /*B7-B9*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  92. /*BA-BC*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  93. /*BD-BF*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  94. /*C0-C2*/ _AFP_ADD_ICON, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  95. /*C3-C5*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  96. /*C6-C8*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  97. /*C9-CB*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  98. /*CC-CE*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  99. /*CF-D1*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  100. /*D2-D4*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  101. /*D5-D7*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  102. /*D8-DA*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  103. /*DB-DD*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  104. /*DE-E0*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  105. /*E1-E3*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  106. /*E4-E6*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  107. /*E7-E9*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  108. /*EA-EC*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  109. /*ED-EF*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  110. /*F0-F2*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  111. /*F3-F5*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  112. /*F6-F8*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  113. /*F9-FB*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  114. /*FC-FE*/ _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE, _AFP_INVALID_OPCODE,
  115. /*FF*/ _AFP_GET_DOMAIN_LIST
  116. };
  117. #if DBG
  118. PCHAR afpApiNames[] =
  119. { "AfpInvalidOpcode",
  120. "AfpUnsupportedOpcode",
  121. "AfpGetSrvrInfo",
  122. "AfpGetSrvrParms",
  123. "AfpChangePassword",
  124. "AfpLogin",
  125. "AfpLoginCont",
  126. "AfpLogout",
  127. "AfpMapId",
  128. "AfpMapName",
  129. "AfpGetUserInfo",
  130. "AfpGetSrvrMsg",
  131. "AfpGetDomainList",
  132. "AfpOpenVol",
  133. "AfpCloseVol",
  134. "AfpGetVolParms",
  135. "AfpSetVolParms",
  136. "AfpFlush",
  137. "AfpGetFileDirParms",
  138. "AfpSetFileDirParms",
  139. "AfpDelete",
  140. "AfpRename",
  141. "AfpMoveAndRename",
  142. "AfpOpenDir",
  143. "AfpCloseDir",
  144. "AfpCreateDir",
  145. "AfpEnumerate",
  146. "AfpSetDirParms",
  147. "AfpCreateFile",
  148. "AfpCopyFile",
  149. "AfpCreateId",
  150. "AfpDeleteId",
  151. "AfpResolveId",
  152. "AfpSetFileParms",
  153. "AfpExchangeFiles",
  154. "AfpOpenFork",
  155. "AfpCloseFork",
  156. "AfpFlushFork",
  157. "AfpRead",
  158. "AfpWrite",
  159. "AfpByteRangeLock",
  160. "AfpGetForkParms",
  161. "AfpSetForkParms",
  162. "AfpOpenDt",
  163. "AfpCloseDt",
  164. "AfpAddAppl",
  165. "AfpGetAppl",
  166. "AfpRemoveAppl",
  167. "AfpAddComment",
  168. "AfpGetComment",
  169. "AfpRemoveComment",
  170. "AfpAddIcon",
  171. "AfpGetIcon",
  172. "AfpGetIconInfo",
  173. "AfpCatSearch"
  174. };
  175. #endif
  176. /*
  177. * The following structure is the API Dispatch table. The structure is indexed
  178. * by the _AFP code. Each entry consists of the routine address that handles
  179. * the request and/or dispatches to FSP, the fixed size of the request
  180. * packet and optionally three variable size packets. The fixed size request
  181. * packet is further split up into SEVEN fields. Each field is of the type
  182. * FLD_BYTE, FLD_WORD or FLD_DWRD. A field of the type FLD_WORD and FLD_DWRD
  183. * is converted from on-the-wire format to the internal format. An FLD_NONE
  184. * entry stops the scan for the fixed part of the request.
  185. * NamexType where x is 1,2,3 defines what type of variable size packets
  186. * follow. A NONE on any of the fields stops the parsing. A type of BLOCK
  187. * consumes the balance of the packet. Each of the variable size packets are
  188. * copied to the sda_Namex field which is defined as ANSI_STRING. For the
  189. * TYP_BLOCK field, the Length field of the ANSI_STRING defines the length
  190. * of the block. The motivation for this structure is to conserve memory.
  191. * Since a request packet is 578 bytes long and most APIs use only a small
  192. * subset of that, the fixed portion of the packet is copied to the SDA
  193. * and a smaller buffer is allocated for the variable packet.
  194. * The orignal buffer cannot be accessed once we return back from this call.
  195. */
  196. // DO NOT CHANGE THE MANIFESTS BELOW BEFORE YOU CHECK THE CODE IN
  197. // AfpUnmarshallReq
  198. // Descriptor values for fixed data
  199. #define FLD_NONE 0x00 // Terminate
  200. #define FLD_BYTE sizeof(BYTE) // Byte field
  201. #define FLD_WORD sizeof(USHORT) // WORD field
  202. #define FLD_DWRD sizeof(DWORD) // DWORD field
  203. #define FLD_SIGNED 0x08 // The value is to be treated as a signed
  204. #define FLD_NON_ZERO 0x10 // The value cannot be zero
  205. #define FLD_CHECK_MASK 0x20 // Check against the mask in ReqPktMask
  206. #define FLD_NOCONV 0x40 // Skip conversion from on-the-wire to host
  207. #define FLD_NOPAD 0x80 // Do not EVEN align the next field
  208. #define FLD_PROP_MASK (FLD_SIGNED | \
  209. FLD_NON_ZERO | \
  210. FLD_CHECK_MASK | \
  211. FLD_NOCONV | \
  212. FLD_NOPAD)
  213. // Descriptor values for variable data
  214. #define TYP_NONE 0x00 // Terminate
  215. #define TYP_PATH 0x01 // AFPPATH -> ANSI_STRING
  216. #define TYP_STRING 0x02 // PASCALSTR -> ANSI_STRING
  217. #define TYP_BLK16 0x03 // Block of 16 bytes
  218. #define TYP_BLOCK 0x04 // Block of bytes
  219. #define TYP_NON_NULL 0x20 // The variable data cannot be null
  220. #define TYP_OPTIONAL 0x40 // This field can be optinal
  221. #define TYP_NOPAD 0x80 // Do not even align the next field
  222. #define TYP_PROP_MASK (TYP_NON_NULL | TYP_OPTIONAL | TYP_NOPAD)
  223. #define API_AFP21ONLY 0x01 // Valid only for AFP 2.1 clients
  224. #define API_SKIPLOGONVALIDATION 0x02 // Don't check if user is logged on
  225. #define API_NOSUBFUNCTION 0x04 // For the AfpLogin Function
  226. #define API_CHECK_VOLID 0x08 // This API reference volume
  227. #define API_CHECK_OFORKREFNUM 0x10 // This API reference open fork
  228. #define API_TYPE_WRITE 0x20 // This attempts a write
  229. #define API_QUEUE_IF_DPC 0x40 // This conditionally queues to worker only if at DPC
  230. #define API_MUST_BE_QUEUED 0x80 // The Api must be queued to the worker thread
  231. #define MAX_MASK_ENTRIES 4 // Max. bitmasks to validate
  232. LOCAL struct _DispatchTable
  233. {
  234. AFPAPIWORKER AfpWorkerRoutine; // Worker routine to call/queue
  235. BYTE AfpStatus; // Status to return on error
  236. // This has to be added to the base
  237. BYTE ApiOptions; // API_xxx values
  238. BYTE ReqPktDesc[MAX_REQ_ENTRIES]; // Fixed data desc
  239. BYTE NameXType[MAX_VAR_ENTRIES]; // Variable data desc
  240. USHORT ReqPktMask[MAX_MASK_ENTRIES]; // Valid values for bit-maps
  241. } AfpDispatchTable[_AFP_MAX_ENTRIES] =
  242. {
  243. /* 0x00 */
  244. {
  245. AfpFsdDispInvalidFunc,
  246. (AFP_ERR_BASE - AFP_ERR_PARAM),
  247. 0,
  248. {
  249. FLD_NONE,
  250. FLD_NONE,
  251. FLD_NONE,
  252. FLD_NONE,
  253. FLD_NONE,
  254. FLD_NONE,
  255. FLD_NONE
  256. },
  257. {
  258. TYP_NONE,
  259. TYP_NONE,
  260. TYP_NONE
  261. },
  262. {
  263. 0,
  264. 0,
  265. 0,
  266. 0
  267. }
  268. },
  269. /* 0x01 */
  270. {
  271. AfpFsdDispUnsupportedFunc,
  272. (AFP_ERR_BASE - AFP_ERR_PARAM),
  273. 0,
  274. {
  275. FLD_NONE,
  276. FLD_NONE,
  277. FLD_NONE,
  278. FLD_NONE,
  279. FLD_NONE,
  280. FLD_NONE,
  281. FLD_NONE
  282. },
  283. {
  284. TYP_NONE,
  285. TYP_NONE,
  286. TYP_NONE
  287. },
  288. {
  289. 0,
  290. 0,
  291. 0,
  292. 0
  293. }
  294. },
  295. /* SERVER APIs */
  296. /* 0x02 */
  297. {
  298. AfpFsdDispInvalidFunc,
  299. (AFP_ERR_BASE - AFP_ERR_PARAM),
  300. 0,
  301. {
  302. FLD_NONE,
  303. FLD_NONE,
  304. FLD_NONE,
  305. FLD_NONE,
  306. FLD_NONE,
  307. FLD_NONE,
  308. FLD_NONE
  309. },
  310. {
  311. TYP_NONE,
  312. TYP_NONE,
  313. TYP_NONE
  314. },
  315. {
  316. 0,
  317. 0,
  318. 0,
  319. 0
  320. }
  321. },
  322. /* 0x03 */
  323. {
  324. AfpFsdDispGetSrvrParms,
  325. (AFP_ERR_BASE - AFP_ERR_PARAM),
  326. API_NOSUBFUNCTION,
  327. {
  328. FLD_NONE,
  329. FLD_NONE,
  330. FLD_NONE,
  331. FLD_NONE,
  332. FLD_NONE,
  333. FLD_NONE,
  334. FLD_NONE
  335. },
  336. {
  337. TYP_NONE,
  338. TYP_NONE,
  339. TYP_NONE
  340. },
  341. {
  342. 0,
  343. 0,
  344. 0,
  345. 0
  346. }
  347. },
  348. /* 0x04 */
  349. {
  350. AfpFspDispChangePassword,
  351. (AFP_ERR_BASE - AFP_ERR_PARAM),
  352. API_SKIPLOGONVALIDATION+API_MUST_BE_QUEUED,
  353. {
  354. FLD_NONE,
  355. FLD_NONE,
  356. FLD_NONE,
  357. FLD_NONE,
  358. FLD_NONE,
  359. FLD_NONE,
  360. FLD_NONE
  361. },
  362. {
  363. TYP_STRING+TYP_NON_NULL, // UAM Name
  364. TYP_STRING+TYP_NON_NULL, // User Name
  365. TYP_BLOCK+TYP_NON_NULL // UAM dependent info
  366. },
  367. {
  368. 0,
  369. 0,
  370. 0,
  371. 0
  372. }
  373. },
  374. /* 0x05 */
  375. {
  376. AfpFspDispLogin,
  377. (AFP_ERR_BASE - AFP_ERR_PARAM),
  378. API_SKIPLOGONVALIDATION+API_NOSUBFUNCTION+API_MUST_BE_QUEUED,
  379. {
  380. FLD_NONE,
  381. FLD_NONE,
  382. FLD_NONE,
  383. FLD_NONE,
  384. FLD_NONE,
  385. FLD_NONE,
  386. FLD_NONE
  387. },
  388. {
  389. TYP_STRING+TYP_NOPAD+TYP_NON_NULL, // AFP Version
  390. TYP_STRING+TYP_NOPAD+TYP_NON_NULL, // UAM String
  391. TYP_BLOCK+TYP_NOPAD // UAM dependent data
  392. },
  393. {
  394. 0,
  395. 0,
  396. 0,
  397. 0
  398. }
  399. },
  400. /* 0x06 */
  401. {
  402. AfpFspDispLoginCont,
  403. (AFP_ERR_BASE - AFP_ERR_PARAM),
  404. API_SKIPLOGONVALIDATION+API_MUST_BE_QUEUED,
  405. {
  406. FLD_DWRD+FLD_NOCONV, //
  407. FLD_DWRD+FLD_NOCONV, //
  408. FLD_DWRD+FLD_NOCONV, // Response to Challenge
  409. FLD_DWRD+FLD_NOCONV, //
  410. FLD_DWRD+FLD_NOCONV, //
  411. FLD_DWRD+FLD_NOCONV, //
  412. FLD_NONE
  413. },
  414. {
  415. TYP_NONE,
  416. TYP_NONE,
  417. TYP_NONE
  418. },
  419. {
  420. 0,
  421. 0,
  422. 0,
  423. 0
  424. }
  425. },
  426. /* 0x07 */
  427. {
  428. AfpFspDispLogout,
  429. (AFP_ERR_BASE - AFP_ERR_PARAM),
  430. API_NOSUBFUNCTION+API_MUST_BE_QUEUED,
  431. {
  432. FLD_NONE,
  433. FLD_NONE,
  434. FLD_NONE,
  435. FLD_NONE,
  436. FLD_NONE,
  437. FLD_NONE,
  438. FLD_NONE
  439. },
  440. {
  441. TYP_NONE,
  442. TYP_NONE,
  443. TYP_NONE
  444. },
  445. {
  446. 0,
  447. 0,
  448. 0,
  449. 0
  450. }
  451. },
  452. /* 0x08 */
  453. {
  454. AfpFspDispMapId,
  455. (AFP_ERR_BASE - AFP_ERR_PARAM),
  456. API_MUST_BE_QUEUED,
  457. {
  458. FLD_DWRD, // User or Group Id
  459. FLD_NONE,
  460. FLD_NONE,
  461. FLD_NONE,
  462. FLD_NONE,
  463. FLD_NONE,
  464. FLD_NONE
  465. },
  466. {
  467. TYP_NONE,
  468. TYP_NONE,
  469. TYP_NONE
  470. },
  471. {
  472. 0,
  473. 0,
  474. 0,
  475. 0
  476. }
  477. },
  478. /* 0x09 */
  479. {
  480. AfpFspDispMapName,
  481. (AFP_ERR_BASE - AFP_ERR_PARAM),
  482. API_MUST_BE_QUEUED,
  483. {
  484. FLD_NONE,
  485. FLD_NONE,
  486. FLD_NONE,
  487. FLD_NONE,
  488. FLD_NONE,
  489. FLD_NONE,
  490. FLD_NONE
  491. },
  492. {
  493. TYP_STRING, // User or Group Name
  494. TYP_NONE,
  495. TYP_NONE
  496. },
  497. {
  498. 0,
  499. 0,
  500. 0,
  501. 0
  502. }
  503. },
  504. /* 0x0A */
  505. {
  506. AfpFspDispGetUserInfo,
  507. (AFP_ERR_BASE - AFP_ERR_PARAM),
  508. API_MUST_BE_QUEUED,
  509. {
  510. FLD_DWRD, // User Id
  511. FLD_WORD, // Bitmap
  512. FLD_NONE,
  513. FLD_NONE,
  514. FLD_NONE,
  515. FLD_NONE,
  516. FLD_NONE
  517. },
  518. {
  519. TYP_NONE,
  520. TYP_NONE,
  521. TYP_NONE
  522. },
  523. {
  524. 0,
  525. 0,
  526. 0,
  527. 0
  528. }
  529. },
  530. /* 0x0B */
  531. {
  532. AfpFsdDispGetSrvrMsg,
  533. (AFP_ERR_BASE - AFP_ERR_PARAM),
  534. API_AFP21ONLY,
  535. {
  536. FLD_WORD, // Message Type
  537. FLD_WORD, // Mesage Bitmap
  538. FLD_NONE,
  539. FLD_NONE,
  540. FLD_NONE,
  541. FLD_NONE,
  542. FLD_NONE
  543. },
  544. {
  545. TYP_NONE,
  546. TYP_NONE,
  547. TYP_NONE
  548. },
  549. {
  550. 0,
  551. 0,
  552. 0,
  553. 0
  554. }
  555. },
  556. /* 0x0C */
  557. {
  558. AfpFsdDispInvalidFunc,
  559. (AFP_ERR_BASE - AFP_ERR_PARAM),
  560. API_SKIPLOGONVALIDATION+API_MUST_BE_QUEUED,
  561. {
  562. FLD_NONE,
  563. FLD_NONE,
  564. FLD_NONE,
  565. FLD_NONE,
  566. FLD_NONE,
  567. FLD_NONE,
  568. FLD_NONE
  569. },
  570. {
  571. TYP_NONE,
  572. TYP_NONE,
  573. TYP_NONE
  574. },
  575. {
  576. 0,
  577. 0,
  578. 0,
  579. 0
  580. }
  581. },
  582. /* VOLUMEAPIs */
  583. /* 0x0D */
  584. {
  585. AfpFsdDispOpenVol,
  586. (AFP_ERR_BASE - AFP_ERR_PARAM),
  587. 0,
  588. {
  589. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Bitmap
  590. FLD_NONE,
  591. FLD_NONE,
  592. FLD_NONE,
  593. FLD_NONE,
  594. FLD_NONE,
  595. FLD_NONE
  596. },
  597. {
  598. TYP_STRING+TYP_NON_NULL, // Volume name
  599. TYP_BLOCK+TYP_OPTIONAL, // Volume password
  600. TYP_NONE
  601. },
  602. {
  603. VOL_BITMAP_MASK,
  604. 0,
  605. 0,
  606. 0
  607. }
  608. },
  609. /* 0x0E */
  610. {
  611. AfpFsdDispCloseVol,
  612. (AFP_ERR_BASE - AFP_ERR_PARAM),
  613. API_CHECK_VOLID,
  614. {
  615. FLD_WORD+FLD_NON_ZERO, // Volume Id
  616. FLD_NONE,
  617. FLD_NONE,
  618. FLD_NONE,
  619. FLD_NONE,
  620. FLD_NONE,
  621. FLD_NONE
  622. },
  623. {
  624. TYP_NONE,
  625. TYP_NONE,
  626. TYP_NONE
  627. },
  628. {
  629. 0,
  630. 0,
  631. 0,
  632. 0
  633. }
  634. },
  635. /* 0x0F */
  636. {
  637. AfpFsdDispGetVolParms,
  638. (AFP_ERR_BASE - AFP_ERR_PARAM),
  639. API_CHECK_VOLID,
  640. {
  641. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  642. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Bitmap
  643. FLD_NONE,
  644. FLD_NONE,
  645. FLD_NONE,
  646. FLD_NONE,
  647. FLD_NONE
  648. },
  649. {
  650. TYP_NONE,
  651. TYP_NONE,
  652. TYP_NONE
  653. },
  654. {
  655. 0,
  656. VOL_BITMAP_MASK,
  657. 0,
  658. 0
  659. }
  660. },
  661. /* 0x10 */
  662. {
  663. AfpFsdDispSetVolParms,
  664. (AFP_ERR_BASE - AFP_ERR_PARAM),
  665. API_CHECK_VOLID+API_TYPE_WRITE,
  666. {
  667. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  668. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Bitmap
  669. FLD_DWRD, // Backup date
  670. FLD_NONE,
  671. FLD_NONE,
  672. FLD_NONE,
  673. FLD_NONE
  674. },
  675. {
  676. TYP_NONE,
  677. TYP_NONE,
  678. TYP_NONE
  679. },
  680. {
  681. 0,
  682. VOL_BITMAP_BACKUPTIME,
  683. 0,
  684. 0
  685. }
  686. },
  687. /* 0x11 */
  688. {
  689. AfpFsdDispFlush,
  690. (AFP_ERR_BASE - AFP_ERR_PARAM),
  691. API_CHECK_VOLID,
  692. {
  693. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  694. FLD_NONE,
  695. FLD_NONE,
  696. FLD_NONE,
  697. FLD_NONE,
  698. FLD_NONE,
  699. FLD_NONE
  700. },
  701. {
  702. TYP_NONE,
  703. TYP_NONE,
  704. TYP_NONE
  705. },
  706. {
  707. 0,
  708. 0,
  709. 0,
  710. 0
  711. }
  712. },
  713. /* FILE-DIRECTORY APIs */
  714. /* 0x12 */
  715. {
  716. AfpFspDispGetFileDirParms,
  717. (AFP_ERR_BASE - AFP_ERR_PARAM),
  718. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  719. {
  720. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  721. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  722. FLD_WORD+FLD_CHECK_MASK, // File Bitmap
  723. FLD_WORD+FLD_CHECK_MASK, // Directory Bitmap
  724. FLD_NONE,
  725. FLD_NONE,
  726. FLD_NONE
  727. },
  728. {
  729. TYP_PATH, // Path
  730. TYP_NONE,
  731. TYP_NONE
  732. },
  733. {
  734. 0,
  735. 0,
  736. FILE_BITMAP_MASK,
  737. DIR_BITMAP_MASK
  738. }
  739. },
  740. /* 0x13 */
  741. {
  742. AfpFspDispSetFileDirParms,
  743. (AFP_ERR_BASE - AFP_ERR_PARAM),
  744. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  745. {
  746. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  747. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  748. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // File or Directory Bitmap
  749. FLD_NONE,
  750. FLD_NONE,
  751. FLD_NONE,
  752. FLD_NONE
  753. },
  754. {
  755. TYP_PATH, // Path
  756. TYP_BLOCK+TYP_NON_NULL, // Parameters (packed)
  757. TYP_NONE
  758. },
  759. {
  760. 0,
  761. 0,
  762. FD_VALID_SET_PARMS,
  763. 0
  764. }
  765. },
  766. /* 0x14 */
  767. {
  768. AfpFspDispDelete,
  769. (AFP_ERR_BASE - AFP_ERR_PARAM),
  770. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  771. {
  772. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  773. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  774. FLD_NONE,
  775. FLD_NONE,
  776. FLD_NONE,
  777. FLD_NONE,
  778. FLD_NONE
  779. },
  780. {
  781. TYP_PATH, // Path
  782. TYP_NONE,
  783. TYP_NONE
  784. },
  785. {
  786. 0,
  787. 0,
  788. 0,
  789. 0
  790. }
  791. },
  792. /* 0x15 */
  793. {
  794. AfpFspDispRename,
  795. (AFP_ERR_BASE - AFP_ERR_PARAM),
  796. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  797. {
  798. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  799. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  800. FLD_NONE,
  801. FLD_NONE,
  802. FLD_NONE,
  803. FLD_NONE,
  804. FLD_NONE
  805. },
  806. {
  807. TYP_PATH+TYP_NOPAD, // Path
  808. TYP_PATH+TYP_NOPAD+TYP_NON_NULL, // New Name
  809. TYP_NONE
  810. },
  811. {
  812. 0,
  813. 0,
  814. 0,
  815. 0
  816. }
  817. },
  818. /* 0x16 */
  819. {
  820. AfpFspDispMoveAndRename,
  821. (AFP_ERR_BASE - AFP_ERR_PARAM),
  822. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  823. {
  824. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  825. FLD_DWRD+FLD_NON_ZERO, // Src Directory Id
  826. FLD_DWRD+FLD_NON_ZERO, // Dst Directory Id
  827. FLD_NONE,
  828. FLD_NONE,
  829. FLD_NONE,
  830. FLD_NONE
  831. },
  832. {
  833. TYP_PATH+TYP_NOPAD, // Source path
  834. TYP_PATH+TYP_NOPAD, // Destination path
  835. TYP_PATH+TYP_NOPAD // New Name (optional)
  836. },
  837. {
  838. 0,
  839. 0,
  840. 0,
  841. 0
  842. }
  843. },
  844. /* DIRECTORY APIs */
  845. /* 0x17 */
  846. {
  847. AfpFspDispOpenDir,
  848. (AFP_ERR_BASE - AFP_ERR_PARAM),
  849. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  850. {
  851. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  852. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  853. FLD_NONE,
  854. FLD_NONE,
  855. FLD_NONE,
  856. FLD_NONE,
  857. FLD_NONE
  858. },
  859. {
  860. TYP_PATH+TYP_NON_NULL, // Directory Name
  861. TYP_NONE,
  862. TYP_NONE
  863. },
  864. {
  865. 0,
  866. 0,
  867. 0,
  868. 0
  869. }
  870. },
  871. /* 0x18 */
  872. {
  873. AfpFspDispCloseDir,
  874. (AFP_ERR_BASE - AFP_ERR_PARAM),
  875. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  876. {
  877. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  878. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  879. FLD_NONE,
  880. FLD_NONE,
  881. FLD_NONE,
  882. FLD_NONE,
  883. FLD_NONE
  884. },
  885. {
  886. TYP_NONE,
  887. TYP_NONE,
  888. TYP_NONE
  889. },
  890. {
  891. 0,
  892. 0,
  893. 0,
  894. 0
  895. }
  896. },
  897. /* 0x19 */
  898. {
  899. AfpFspDispCreateDir,
  900. (AFP_ERR_BASE - AFP_ERR_PARAM),
  901. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  902. {
  903. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  904. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  905. FLD_NONE,
  906. FLD_NONE,
  907. FLD_NONE,
  908. FLD_NONE,
  909. FLD_NONE
  910. },
  911. {
  912. TYP_PATH+TYP_NON_NULL, // Directory Name
  913. TYP_NONE,
  914. TYP_NONE
  915. },
  916. {
  917. 0,
  918. 0,
  919. 0,
  920. 0
  921. }
  922. },
  923. /* 0x1A */
  924. {
  925. AfpFspDispEnumerate,
  926. (AFP_ERR_BASE - AFP_ERR_PARAM),
  927. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  928. {
  929. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  930. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  931. FLD_WORD+FLD_CHECK_MASK, // File Bitmap
  932. FLD_WORD+FLD_CHECK_MASK, // Directory Bitmap
  933. FLD_WORD+FLD_SIGNED+FLD_NON_ZERO, // ReqCount
  934. FLD_WORD+FLD_SIGNED+FLD_NON_ZERO, // Start Index
  935. FLD_WORD+FLD_SIGNED+FLD_NON_ZERO, // ReplySize
  936. },
  937. {
  938. TYP_PATH, // Path to directory
  939. TYP_NONE,
  940. TYP_NONE
  941. },
  942. {
  943. 0,
  944. 0,
  945. FILE_BITMAP_MASK,
  946. DIR_BITMAP_MASK
  947. }
  948. },
  949. /* 0x1B */
  950. {
  951. AfpFspDispSetDirParms,
  952. (AFP_ERR_BASE - AFP_ERR_PARAM),
  953. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  954. {
  955. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  956. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  957. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Dir Bitmap
  958. FLD_NONE,
  959. FLD_NONE,
  960. FLD_NONE,
  961. FLD_NONE
  962. },
  963. {
  964. TYP_PATH, // Path
  965. TYP_BLOCK+TYP_NON_NULL, // Parameters (packed)
  966. TYP_NONE
  967. },
  968. {
  969. 0,
  970. 0,
  971. DIR_VALID_SET_PARMS,
  972. 0
  973. }
  974. },
  975. /* FILE APIs */
  976. /* 0x1C */
  977. {
  978. AfpFspDispCreateFile,
  979. (AFP_ERR_BASE - AFP_ERR_PARAM),
  980. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  981. {
  982. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  983. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  984. FLD_NONE,
  985. FLD_NONE,
  986. FLD_NONE,
  987. FLD_NONE,
  988. FLD_NONE
  989. },
  990. {
  991. TYP_PATH+TYP_NON_NULL, // Path
  992. TYP_NONE,
  993. TYP_NONE
  994. },
  995. {
  996. 0,
  997. 0,
  998. 0,
  999. 0
  1000. }
  1001. },
  1002. /* 0x1D */
  1003. {
  1004. AfpFspDispCopyFile,
  1005. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1006. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1007. {
  1008. FLD_WORD+FLD_NON_ZERO, // Src Volume_Id
  1009. FLD_DWRD+FLD_NON_ZERO, // Src Directory Id
  1010. FLD_WORD+FLD_NON_ZERO, // Dst Volume_Id
  1011. FLD_DWRD+FLD_NON_ZERO, // Dst Directory Id
  1012. FLD_NONE,
  1013. FLD_NONE,
  1014. FLD_NONE
  1015. },
  1016. {
  1017. TYP_PATH+TYP_NOPAD+TYP_NON_NULL, // Src Path
  1018. TYP_PATH+TYP_NOPAD,
  1019. TYP_PATH+TYP_NOPAD
  1020. },
  1021. {
  1022. 0,
  1023. 0,
  1024. 0,
  1025. 0
  1026. }
  1027. },
  1028. /* 0x1E */
  1029. {
  1030. AfpFspDispCreateId,
  1031. (AFP_ERR_BASE - AFP_ERR_OBJECT_TYPE),
  1032. API_AFP21ONLY+API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1033. {
  1034. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1035. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1036. FLD_NONE,
  1037. FLD_NONE,
  1038. FLD_NONE,
  1039. FLD_NONE,
  1040. FLD_NONE
  1041. },
  1042. {
  1043. TYP_PATH+TYP_NON_NULL, // Path
  1044. TYP_NONE,
  1045. TYP_NONE
  1046. },
  1047. {
  1048. 0,
  1049. 0,
  1050. 0,
  1051. 0
  1052. }
  1053. },
  1054. /* 0x1F */
  1055. {
  1056. AfpFspDispDeleteId,
  1057. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1058. API_AFP21ONLY+API_CHECK_VOLID+API_MUST_BE_QUEUED+API_TYPE_WRITE,
  1059. {
  1060. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1061. FLD_DWRD+FLD_NON_ZERO, // File Id
  1062. FLD_NONE,
  1063. FLD_NONE,
  1064. FLD_NONE,
  1065. FLD_NONE,
  1066. FLD_NONE
  1067. },
  1068. {
  1069. TYP_NONE,
  1070. TYP_NONE,
  1071. TYP_NONE
  1072. },
  1073. {
  1074. 0,
  1075. 0,
  1076. 0,
  1077. 0
  1078. }
  1079. },
  1080. /* 0x20 */
  1081. {
  1082. AfpFspDispResolveId,
  1083. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1084. API_AFP21ONLY+API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1085. {
  1086. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1087. FLD_DWRD, // File Id
  1088. FLD_WORD+FLD_CHECK_MASK, // Bitmap
  1089. FLD_NONE,
  1090. FLD_NONE,
  1091. FLD_NONE,
  1092. FLD_NONE
  1093. },
  1094. {
  1095. TYP_NONE,
  1096. TYP_NONE,
  1097. TYP_NONE
  1098. },
  1099. {
  1100. 0,
  1101. 0,
  1102. FILE_BITMAP_MASK,
  1103. 0
  1104. }
  1105. },
  1106. /* 0x21 */
  1107. {
  1108. AfpFspDispSetFileParms,
  1109. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1110. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1111. {
  1112. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1113. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1114. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // File Bitmap
  1115. FLD_NONE,
  1116. FLD_NONE,
  1117. FLD_NONE,
  1118. FLD_NONE
  1119. },
  1120. {
  1121. TYP_PATH+TYP_NON_NULL, // Path
  1122. TYP_BLOCK+TYP_NON_NULL, // Parameters (packed)
  1123. TYP_NONE
  1124. },
  1125. {
  1126. 0,
  1127. 0,
  1128. FILE_VALID_SET_PARMS,
  1129. 0
  1130. }
  1131. },
  1132. /* 0x22 */
  1133. {
  1134. AfpFspDispExchangeFiles,
  1135. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1136. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED+API_AFP21ONLY,
  1137. {
  1138. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1139. FLD_DWRD+FLD_NON_ZERO, // Srce. Directory Id
  1140. FLD_DWRD+FLD_NON_ZERO, // Dest. Directory Id
  1141. FLD_NONE,
  1142. FLD_NONE,
  1143. FLD_NONE,
  1144. FLD_NONE
  1145. },
  1146. {
  1147. TYP_PATH+TYP_NOPAD+TYP_NON_NULL, // Srce. Path
  1148. TYP_PATH+TYP_NOPAD+TYP_NON_NULL, // Dest. Path
  1149. TYP_NONE
  1150. },
  1151. {
  1152. 0,
  1153. 0,
  1154. 0,
  1155. 0
  1156. }
  1157. },
  1158. /* FORK APIs */
  1159. /* 0x23 */
  1160. {
  1161. AfpFspDispOpenFork,
  1162. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1163. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1164. {
  1165. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1166. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1167. FLD_WORD+FLD_CHECK_MASK, // Bitmap
  1168. FLD_WORD, // Access & Deny Modes
  1169. FLD_NONE,
  1170. FLD_NONE,
  1171. FLD_NONE
  1172. },
  1173. {
  1174. TYP_PATH+TYP_NON_NULL, // Path
  1175. TYP_NONE,
  1176. TYP_NONE
  1177. },
  1178. {
  1179. 0,
  1180. 0,
  1181. FILE_BITMAP_MASK,
  1182. 0
  1183. }
  1184. },
  1185. /* 0x24 */
  1186. {
  1187. AfpFspDispCloseFork,
  1188. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1189. API_CHECK_OFORKREFNUM+API_MUST_BE_QUEUED,
  1190. {
  1191. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1192. FLD_NONE,
  1193. FLD_NONE,
  1194. FLD_NONE,
  1195. FLD_NONE,
  1196. FLD_NONE,
  1197. FLD_NONE
  1198. },
  1199. {
  1200. TYP_NONE,
  1201. TYP_NONE,
  1202. TYP_NONE
  1203. },
  1204. {
  1205. 0,
  1206. 0,
  1207. 0,
  1208. 0
  1209. }
  1210. },
  1211. /* 0x25 */
  1212. {
  1213. AfpFspDispFlushFork,
  1214. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1215. API_CHECK_OFORKREFNUM+API_MUST_BE_QUEUED,
  1216. {
  1217. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1218. FLD_NONE,
  1219. FLD_NONE,
  1220. FLD_NONE,
  1221. FLD_NONE,
  1222. FLD_NONE,
  1223. FLD_NONE
  1224. },
  1225. {
  1226. TYP_NONE,
  1227. TYP_NONE,
  1228. TYP_NONE
  1229. },
  1230. {
  1231. 0,
  1232. 0,
  1233. 0,
  1234. 0
  1235. }
  1236. },
  1237. /* 0x26 */
  1238. {
  1239. AfpFspDispRead,
  1240. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1241. API_CHECK_OFORKREFNUM+API_QUEUE_IF_DPC+API_MUST_BE_QUEUED,
  1242. {
  1243. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1244. FLD_DWRD, // Offset
  1245. FLD_DWRD, // ReqCount
  1246. FLD_BYTE+FLD_NOPAD, // Newline Mask
  1247. FLD_BYTE+FLD_NOPAD, // Newline Char
  1248. FLD_NONE,
  1249. FLD_NONE
  1250. },
  1251. {
  1252. TYP_NONE,
  1253. TYP_NONE,
  1254. TYP_NONE
  1255. },
  1256. {
  1257. 0,
  1258. 0,
  1259. 0,
  1260. 0
  1261. }
  1262. },
  1263. /* 0x27 */
  1264. {
  1265. AfpFspDispWrite,
  1266. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1267. API_CHECK_OFORKREFNUM+API_TYPE_WRITE+API_QUEUE_IF_DPC+API_MUST_BE_QUEUED,
  1268. {
  1269. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1270. FLD_DWRD, // Offset
  1271. FLD_DWRD, // Length
  1272. FLD_NONE,
  1273. FLD_NONE,
  1274. FLD_NONE,
  1275. FLD_NONE
  1276. },
  1277. {
  1278. TYP_NONE,
  1279. TYP_NONE,
  1280. TYP_NONE
  1281. },
  1282. {
  1283. 0,
  1284. 0,
  1285. 0,
  1286. 0
  1287. }
  1288. },
  1289. /* 0x28 */
  1290. {
  1291. AfpFspDispByteRangeLock,
  1292. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1293. API_CHECK_OFORKREFNUM+API_QUEUE_IF_DPC+API_MUST_BE_QUEUED,
  1294. {
  1295. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1296. FLD_DWRD, // Offset
  1297. FLD_DWRD, // Length
  1298. FLD_NONE,
  1299. FLD_NONE,
  1300. FLD_NONE,
  1301. FLD_NONE
  1302. },
  1303. {
  1304. TYP_NONE,
  1305. TYP_NONE,
  1306. TYP_NONE
  1307. },
  1308. {
  1309. 0,
  1310. 0,
  1311. 0,
  1312. 0
  1313. }
  1314. },
  1315. /* 0x29 */
  1316. {
  1317. AfpFspDispGetForkParms,
  1318. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1319. API_CHECK_OFORKREFNUM+API_MUST_BE_QUEUED,
  1320. {
  1321. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1322. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Bitmap
  1323. FLD_NONE,
  1324. FLD_NONE,
  1325. FLD_NONE,
  1326. FLD_NONE,
  1327. FLD_NONE
  1328. },
  1329. {
  1330. TYP_NONE,
  1331. TYP_NONE,
  1332. TYP_NONE
  1333. },
  1334. {
  1335. 0,
  1336. FILE_BITMAP_MASK,
  1337. 0,
  1338. 0
  1339. }
  1340. },
  1341. /* 0x2A */
  1342. {
  1343. AfpFspDispSetForkParms,
  1344. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1345. API_CHECK_OFORKREFNUM+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1346. {
  1347. FLD_WORD+FLD_NON_ZERO, // Fork_Id
  1348. FLD_WORD+FLD_NON_ZERO+FLD_CHECK_MASK, // Bitmap
  1349. FLD_DWRD, // Fork Length
  1350. FLD_NONE,
  1351. FLD_NONE,
  1352. FLD_NONE,
  1353. FLD_NONE
  1354. },
  1355. {
  1356. TYP_NONE,
  1357. TYP_NONE,
  1358. TYP_NONE
  1359. },
  1360. {
  1361. 0,
  1362. FILE_BITMAP_DATALEN+FILE_BITMAP_RESCLEN,
  1363. 0,
  1364. 0
  1365. }
  1366. },
  1367. /* DESKTOP APIs */
  1368. /* 0x2B */
  1369. {
  1370. AfpFsdDispOpenDT,
  1371. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1372. API_CHECK_VOLID,
  1373. {
  1374. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1375. FLD_NONE,
  1376. FLD_NONE,
  1377. FLD_NONE,
  1378. FLD_NONE,
  1379. FLD_NONE,
  1380. FLD_NONE
  1381. },
  1382. {
  1383. TYP_NONE,
  1384. TYP_NONE,
  1385. TYP_NONE
  1386. },
  1387. {
  1388. 0,
  1389. 0,
  1390. 0,
  1391. 0
  1392. }
  1393. },
  1394. /* 0x2C */
  1395. {
  1396. AfpFsdDispCloseDT,
  1397. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1398. API_CHECK_VOLID,
  1399. {
  1400. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1401. FLD_NONE,
  1402. FLD_NONE,
  1403. FLD_NONE,
  1404. FLD_NONE,
  1405. FLD_NONE,
  1406. FLD_NONE
  1407. },
  1408. {
  1409. TYP_NONE,
  1410. TYP_NONE,
  1411. TYP_NONE
  1412. },
  1413. {
  1414. 0,
  1415. 0,
  1416. 0,
  1417. 0
  1418. }
  1419. },
  1420. /* 0x2D */
  1421. {
  1422. AfpFspDispAddAppl,
  1423. (AFP_ERR_BASE - AFP_ERR_OBJECT_TYPE),
  1424. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1425. {
  1426. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1427. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1428. FLD_DWRD+FLD_NOCONV, // Creator
  1429. FLD_DWRD, // Appl Tag
  1430. FLD_NONE,
  1431. FLD_NONE,
  1432. FLD_NONE
  1433. },
  1434. {
  1435. TYP_PATH+TYP_NON_NULL, // Path
  1436. TYP_NONE,
  1437. TYP_NONE
  1438. },
  1439. {
  1440. 0,
  1441. 0,
  1442. 0,
  1443. 0
  1444. }
  1445. },
  1446. /* 0x2E */
  1447. {
  1448. AfpFspDispGetAppl,
  1449. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1450. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1451. {
  1452. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1453. FLD_DWRD+FLD_NOCONV, // Creator
  1454. FLD_WORD, // Appl Index
  1455. FLD_WORD+FLD_CHECK_MASK, // Bitmap
  1456. FLD_NONE,
  1457. FLD_NONE,
  1458. FLD_NONE
  1459. },
  1460. {
  1461. TYP_NONE,
  1462. TYP_NONE,
  1463. TYP_NONE
  1464. },
  1465. {
  1466. 0,
  1467. 0,
  1468. 0,
  1469. FILE_BITMAP_MASK
  1470. }
  1471. },
  1472. /* 0x2F */
  1473. {
  1474. AfpFspDispRemoveAppl,
  1475. (AFP_ERR_BASE - AFP_ERR_ITEM_NOT_FOUND),
  1476. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1477. {
  1478. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1479. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1480. FLD_DWRD+FLD_NOCONV, // Creator
  1481. FLD_NONE,
  1482. FLD_NONE,
  1483. FLD_NONE,
  1484. FLD_NONE
  1485. },
  1486. {
  1487. TYP_PATH+TYP_NON_NULL, // Path
  1488. TYP_NONE,
  1489. TYP_NONE
  1490. },
  1491. {
  1492. 0,
  1493. 0,
  1494. 0,
  1495. 0
  1496. }
  1497. },
  1498. /* 0x30 */
  1499. {
  1500. AfpFspDispAddComment,
  1501. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1502. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1503. {
  1504. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1505. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1506. FLD_NONE,
  1507. FLD_NONE,
  1508. FLD_NONE,
  1509. FLD_NONE,
  1510. FLD_NONE
  1511. },
  1512. {
  1513. TYP_PATH,
  1514. TYP_STRING,
  1515. TYP_NONE
  1516. },
  1517. {
  1518. 0,
  1519. 0,
  1520. 0,
  1521. 0
  1522. }
  1523. },
  1524. /* 0x31 */
  1525. {
  1526. AfpFspDispGetComment,
  1527. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1528. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1529. {
  1530. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1531. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1532. FLD_NONE,
  1533. FLD_NONE,
  1534. FLD_NONE,
  1535. FLD_NONE,
  1536. FLD_NONE
  1537. },
  1538. {
  1539. TYP_PATH,
  1540. TYP_NONE,
  1541. TYP_NONE
  1542. },
  1543. {
  1544. 0,
  1545. 0,
  1546. 0,
  1547. 0
  1548. }
  1549. },
  1550. /* 0x32 */
  1551. {
  1552. AfpFspDispRemoveComment,
  1553. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1554. API_CHECK_VOLID+API_TYPE_WRITE+API_MUST_BE_QUEUED,
  1555. {
  1556. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1557. FLD_DWRD+FLD_NON_ZERO, // Directory Id
  1558. FLD_NONE,
  1559. FLD_NONE,
  1560. FLD_NONE,
  1561. FLD_NONE,
  1562. FLD_NONE
  1563. },
  1564. {
  1565. TYP_PATH,
  1566. TYP_NONE,
  1567. TYP_NONE
  1568. },
  1569. {
  1570. 0,
  1571. 0,
  1572. 0,
  1573. 0
  1574. }
  1575. },
  1576. /* 0x33 */
  1577. {
  1578. AfpFspDispAddIcon,
  1579. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1580. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1581. {
  1582. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1583. FLD_DWRD+FLD_NOCONV, // Creator
  1584. FLD_DWRD+FLD_NOCONV, // Type
  1585. FLD_BYTE, // IconType
  1586. FLD_DWRD, // IconTag
  1587. FLD_WORD+FLD_SIGNED, // Icon Size
  1588. FLD_NONE,
  1589. },
  1590. {
  1591. TYP_NONE,
  1592. TYP_NONE,
  1593. TYP_NONE
  1594. },
  1595. {
  1596. 0,
  1597. 0,
  1598. 0,
  1599. 0
  1600. }
  1601. },
  1602. /* 0x34 */
  1603. {
  1604. AfpFspDispGetIcon,
  1605. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1606. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1607. {
  1608. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1609. FLD_DWRD+FLD_NOCONV, // Creator
  1610. FLD_DWRD+FLD_NOCONV, // Type
  1611. FLD_BYTE, // IconType
  1612. FLD_WORD+FLD_SIGNED, // Length
  1613. FLD_NONE,
  1614. FLD_NONE
  1615. },
  1616. {
  1617. TYP_NONE,
  1618. TYP_NONE,
  1619. TYP_NONE
  1620. },
  1621. {
  1622. 0,
  1623. 0,
  1624. 0,
  1625. 0
  1626. }
  1627. },
  1628. /* 0x35 */
  1629. {
  1630. AfpFspDispGetIconInfo,
  1631. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1632. API_CHECK_VOLID+API_MUST_BE_QUEUED,
  1633. {
  1634. FLD_WORD+FLD_NON_ZERO, // DTRefNum (same as VolId)
  1635. FLD_DWRD+FLD_NOCONV, // Creator
  1636. FLD_WORD, // IconIndex
  1637. FLD_NONE,
  1638. FLD_NONE,
  1639. FLD_NONE,
  1640. FLD_NONE
  1641. },
  1642. {
  1643. TYP_NONE,
  1644. TYP_NONE,
  1645. TYP_NONE
  1646. },
  1647. {
  1648. 0,
  1649. 0,
  1650. 0,
  1651. 0
  1652. }
  1653. },
  1654. /* 0x36 */
  1655. {
  1656. AfpFspDispCatSearch,
  1657. (AFP_ERR_BASE - AFP_ERR_PARAM),
  1658. API_CHECK_VOLID+API_MUST_BE_QUEUED+API_AFP21ONLY,
  1659. {
  1660. FLD_WORD+FLD_NON_ZERO, // Volume_Id
  1661. FLD_DWRD+FLD_NON_ZERO, // Requested # of matches
  1662. FLD_DWRD, // Reserved
  1663. FLD_NONE,
  1664. FLD_NONE,
  1665. FLD_NONE,
  1666. FLD_NONE
  1667. },
  1668. {
  1669. TYP_BLK16+TYP_NON_NULL, // Catalog position
  1670. TYP_BLOCK+TYP_NON_NULL, // The rest of the stuff
  1671. TYP_NONE
  1672. },
  1673. {
  1674. 0,
  1675. 0,
  1676. 0,
  1677. 0
  1678. }
  1679. }
  1680. };
  1681. /*** AfpFsdDispInvalidFunc
  1682. *
  1683. * This handles invalid AFP functions.
  1684. */
  1685. AFPSTATUS FASTCALL
  1686. AfpFsdDispInvalidFunc(
  1687. IN PSDA pSda
  1688. )
  1689. {
  1690. return AFP_ERR_PARAM;
  1691. }
  1692. /*** AfpFsdDispUnsupportedFunc
  1693. *
  1694. * This handles un-supported AFP functions.
  1695. */
  1696. AFPSTATUS FASTCALL
  1697. AfpFsdDispUnsupportedFunc(
  1698. IN PSDA pSda
  1699. )
  1700. {
  1701. return AFP_ERR_CALL_NOT_SUPPORTED;
  1702. }
  1703. /*** AfpUnmarshallReq
  1704. *
  1705. * The request completion routine has determined the session that this
  1706. * request initiated from. Determine if this session is currently being
  1707. * serviced. If not, the request packet is then broken down as follows.
  1708. *
  1709. * Afp function code -> pSda->sda_AfpFunc
  1710. * Afp SubFunc code -> pSda->sda_AfpSubFunc
  1711. * Fixed part of the
  1712. * Api request parms -> pSda->sda_ReqBlock each field is converted to a
  1713. * dword from the on-the-wire format to the host
  1714. * format. Dictated by the table above.
  1715. * Variable part -> pSda->sda_Name1-3 as appropriate. Dictated by the
  1716. * table above. AFPPATH, BLOCK and PASCALSTR are
  1717. * all converted to ANSI_STRING.
  1718. *
  1719. * Buffers for sda_Namex is allocated out of NonPagedPool, if it cannot
  1720. * fit into sda_NameXSpace.
  1721. *
  1722. * A whole lot of book keeping is also done here. API statistics are maintained
  1723. * here and when the reply is posted.
  1724. *
  1725. * If there is no error, then the following possible error codes result:
  1726. * AFP_ERR_NONE The dispatch level worker can be called
  1727. * AFP_ERR_QUEUE The request must be queued
  1728. * AFP_ERR_DEFER The request must be deferred
  1729. * AFP_ERR_xxxxx Appropriate error code
  1730. *
  1731. * NOTE: This is called within ReceiveCompletion and hence at DISPATCH_LEVEL.
  1732. */
  1733. VOID FASTCALL
  1734. AfpUnmarshallReq(
  1735. IN PSDA pSda
  1736. )
  1737. {
  1738. LONG StrSize, Offset, i;
  1739. LONG NameOff = 0, SpaceLeft;
  1740. PREQUEST pRequest;
  1741. LONG RequestSize;
  1742. PBYTE pRequestBuf;
  1743. USHORT WriteSize = 0;
  1744. PBYTE pWriteBuf = NULL;
  1745. AFPSTATUS Status;
  1746. BYTE ApiCode;
  1747. LONG BytesToCopy;
  1748. struct _DispatchTable *pDispTab;
  1749. struct _RequestPacket
  1750. {
  1751. BYTE _Function;
  1752. BYTE _SubFunc;
  1753. BYTE _OtherParms;
  1754. } *pRqPkt;
  1755. #ifdef PROFILING
  1756. static TIME TimeLastRequest = { 0, 0 };
  1757. TIME TimeS, TimeD, TimeE;
  1758. AfpGetPerfCounter(&TimeS);
  1759. #endif
  1760. ASSERT (VALID_SDA(pSda));
  1761. ASSERT (pSda->sda_Flags & SDA_REQUEST_IN_PROCESS);
  1762. ASSERT (pSda->sda_Request != NULL);
  1763. pRequest = pSda->sda_Request;
  1764. RequestSize = pRequest->rq_RequestSize;
  1765. pRequestBuf = pRequest->rq_RequestBuf;
  1766. ASSERT (pRequestBuf != NULL);
  1767. pRqPkt = (struct _RequestPacket *)pRequestBuf;
  1768. if (pRequest->rq_WriteMdl != NULL)
  1769. {
  1770. // if Mdl (and the buffer) was allocated by us, find the buffer
  1771. if (pRequest->rq_CacheMgrContext == NULL)
  1772. {
  1773. pWriteBuf = MmGetSystemAddressForMdlSafe(
  1774. pRequest->rq_WriteMdl,
  1775. NormalPagePriority);
  1776. if (pWriteBuf == NULL)
  1777. {
  1778. Status = AFP_ERR_MISC;
  1779. ASSERT(0);
  1780. goto AfpUnmarshallReq_ErrExit;
  1781. }
  1782. }
  1783. WriteSize = (USHORT)AfpMdlChainSize(pRequest->rq_WriteMdl);
  1784. }
  1785. else
  1786. {
  1787. ASSERT(pRequest->rq_CacheMgrContext == NULL);
  1788. }
  1789. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  1790. #ifdef PROFILING
  1791. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpStatisticsLock);
  1792. if (TimeLastRequest.QuadPart != 0)
  1793. {
  1794. TimeD.QuadPart = TimeS.QuadPart - TimeLastRequest.QuadPart;
  1795. AfpServerProfile->perf_InterReqTime.QuadPart += TimeD.QuadPart;
  1796. AfpServerProfile->perf_ReqCount ++;
  1797. }
  1798. TimeLastRequest.QuadPart = TimeS.QuadPart;
  1799. RELEASE_SPIN_LOCK_FROM_DPC(&AfpStatisticsLock);
  1800. #endif
  1801. do
  1802. {
  1803. Offset = FIELD_OFFSET(struct _RequestPacket, _OtherParms);
  1804. #ifdef PROFILING
  1805. AfpGetPerfCounter(&pSda->sda_ApiStartTime);
  1806. #endif
  1807. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataIn,
  1808. RequestSize + WriteSize,
  1809. &AfpStatisticsLock);
  1810. ACQUIRE_SPIN_LOCK_AT_DPC(&pSda->sda_Lock);
  1811. // Send a dummy reply if we are shutting down the server or the session
  1812. // Also the request better be atleast the minimum size
  1813. if ((pSda->sda_Flags & SDA_CLOSING) ||
  1814. (AfpServerState & AFP_STATE_STOP_PENDING) ||
  1815. (RequestSize < sizeof(pRqPkt->_Function)))
  1816. {
  1817. // Set a function code so that we know what statictics to update at
  1818. // reply time
  1819. pSda->sda_AfpFunc = _AFP_INVALID_OPCODE;
  1820. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  1821. Status = AFP_ERR_PARAM;
  1822. break;
  1823. }
  1824. ApiCode = AfpOpCodeTable[pRqPkt->_Function];
  1825. // Translate the function code to what we understand
  1826. pDispTab = &AfpDispatchTable[ApiCode];
  1827. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  1828. ("AfpUnmarshallRequest: <%s>\n", afpApiNames[ApiCode]));
  1829. if (!(pSda->sda_Flags & SDA_USER_LOGGEDIN))
  1830. {
  1831. if (!(pDispTab->ApiOptions & API_SKIPLOGONVALIDATION))
  1832. {
  1833. Status = AFP_ERR_USER_NOT_AUTH;
  1834. if (pSda->sda_Flags & SDA_LOGIN_FAILED)
  1835. Status = AFP_ERR_PWD_NEEDS_CHANGE;
  1836. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  1837. break;
  1838. }
  1839. }
  1840. ASSERT (pDispTab->AfpWorkerRoutine != NULL);
  1841. // Initialize the worker routine
  1842. pSda->sda_WorkerRoutine = pDispTab->AfpWorkerRoutine;
  1843. // Check if this is an AFP 2.1 request and if we are in a position to honor it.
  1844. if ((pDispTab->ApiOptions & API_AFP21ONLY) &&
  1845. (pSda->sda_ClientVersion < AFP_VER_21))
  1846. {
  1847. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  1848. Status = AFP_ERR_CALL_NOT_SUPPORTED;
  1849. break;
  1850. }
  1851. Status = AFP_ERR_NONE;
  1852. pSda->sda_AfpFunc = ApiCode;
  1853. if (RequestSize >= FIELD_OFFSET(struct _RequestPacket, _SubFunc))
  1854. {
  1855. pSda->sda_AfpSubFunc = pRqPkt->_SubFunc;
  1856. }
  1857. pSda->sda_PathType = 0; // Invalid till we actually encounter one
  1858. pSda->sda_IOBuf = pWriteBuf;
  1859. pSda->sda_IOSize = WriteSize;
  1860. if (pDispTab->ApiOptions & API_QUEUE_IF_DPC)
  1861. {
  1862. pSda->sda_Flags |= SDA_QUEUE_IF_DPC;
  1863. }
  1864. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  1865. // Get all the fields from the request buffer to the sda_ReqBlock structure.
  1866. if (RequestSize >= FIELD_OFFSET(struct _RequestPacket, _OtherParms))
  1867. {
  1868. pRequestBuf = &pRqPkt->_OtherParms;
  1869. }
  1870. // Do this for APIs which do not provide a sub-function or a pad.
  1871. // Currently the only culprit is FPLogin
  1872. if (pDispTab->ApiOptions & API_NOSUBFUNCTION)
  1873. {
  1874. pSda->sda_AfpSubFunc = 0;
  1875. pRequestBuf --;
  1876. Offset --;
  1877. }
  1878. // Account for the function and subfunction (if any) from the request packet
  1879. RequestSize -= Offset;
  1880. //
  1881. // for the Apple native UAM's (Randnum Exchange, and 2-Way Randnum exchange),
  1882. // we special case and 'unmarshal' the parms directly (the Afp function code
  1883. // being the same for AfpLoginCont regardless of the UAM used, it would be a
  1884. // major hack if we had to 'unmarshal' the parms the regular way)
  1885. //
  1886. if ((ApiCode == _AFP_LOGIN_CONT) &&
  1887. ((pSda->sda_ClientType == SDA_CLIENT_RANDNUM) ||
  1888. (pSda->sda_ClientType == SDA_CLIENT_TWOWAY)))
  1889. {
  1890. // 8 bytes of Response, 2 bytes of LogonId
  1891. if (pSda->sda_ClientType == SDA_CLIENT_RANDNUM)
  1892. {
  1893. BytesToCopy = (RANDNUM_RESP_LEN+sizeof(USHORT));
  1894. }
  1895. // 8 bytes of Response, 8 bytes of Mac's challeng, 2 bytes of LogonId
  1896. else
  1897. {
  1898. BytesToCopy = (TWOWAY_RESP_LEN+sizeof(USHORT));
  1899. }
  1900. if (RequestSize < BytesToCopy)
  1901. {
  1902. ASSERT(0);
  1903. Status = AFP_ERR_PARAM;
  1904. break;
  1905. }
  1906. RtlCopyMemory((PBYTE)&pSda->sda_ReqBlock[0],
  1907. pRequestBuf,
  1908. BytesToCopy);
  1909. //
  1910. // skip everything else, now that we got what we wanted
  1911. //
  1912. Status = AFP_ERR_QUEUE;
  1913. break;
  1914. }
  1915. for (i = 0;
  1916. (i < MAX_REQ_ENTRIES) && (pDispTab->ReqPktDesc[i] != FLD_NONE);
  1917. i++)
  1918. {
  1919. // Check alignment
  1920. if (((pDispTab->ReqPktDesc[i] & FLD_NOPAD) == 0) &&
  1921. ((Offset % 2) != 0))
  1922. {
  1923. Offset ++;
  1924. RequestSize --;
  1925. pRequestBuf ++;
  1926. }
  1927. if (RequestSize < (pDispTab->ReqPktDesc[i] & ~FLD_PROP_MASK))
  1928. {
  1929. Status = AFP_ERR_PARAM;
  1930. break;
  1931. }
  1932. switch (pDispTab->ReqPktDesc[i] & ~FLD_PROP_MASK)
  1933. {
  1934. case FLD_BYTE:
  1935. ASSERT ((pDispTab->ReqPktDesc[i] & FLD_NOCONV) == 0);
  1936. GETBYTE2DWORD(&pSda->sda_ReqBlock[i], pRequestBuf);
  1937. break;
  1938. case FLD_WORD:
  1939. ASSERT ((pDispTab->ReqPktDesc[i] & FLD_NOCONV) == 0);
  1940. GETSHORT2DWORD(&pSda->sda_ReqBlock[i], pRequestBuf);
  1941. if (pDispTab->ReqPktDesc[i] & FLD_SIGNED)
  1942. pSda->sda_ReqBlock[i] = (LONG)((SHORT)pSda->sda_ReqBlock[i]);
  1943. break;
  1944. case FLD_DWRD:
  1945. if (pDispTab->ReqPktDesc[i] & FLD_NOCONV)
  1946. {
  1947. GETDWORD2DWORD_NOCONV(&pSda->sda_ReqBlock[i], pRequestBuf);
  1948. }
  1949. else
  1950. {
  1951. GETDWORD2DWORD(&pSda->sda_ReqBlock[i], pRequestBuf);
  1952. }
  1953. break;
  1954. default:
  1955. // How did we get here ?
  1956. KeBugCheck(0);
  1957. break;
  1958. }
  1959. if ((pDispTab->ReqPktDesc[i] & FLD_NON_ZERO) &&
  1960. (pSda->sda_ReqBlock[i] == 0))
  1961. {
  1962. if (pDispTab->ReqPktDesc[i] & FLD_CHECK_MASK)
  1963. {
  1964. ASSERT ( i < MAX_MASK_ENTRIES);
  1965. Status = AFP_ERR_BITMAP;
  1966. }
  1967. else
  1968. {
  1969. Status = AFP_ERR_PARAM;
  1970. }
  1971. break;
  1972. }
  1973. if ((pDispTab->ReqPktDesc[i] & FLD_CHECK_MASK) &&
  1974. (((USHORT)(pSda->sda_ReqBlock[i]) & ~pDispTab->ReqPktMask[i]) != 0))
  1975. {
  1976. ASSERT (i < MAX_MASK_ENTRIES);
  1977. Status = AFP_ERR_BITMAP;
  1978. break;
  1979. }
  1980. pRequestBuf += (pDispTab->ReqPktDesc[i] & ~FLD_PROP_MASK);
  1981. Offset += (pDispTab->ReqPktDesc[i] & ~FLD_PROP_MASK);
  1982. RequestSize -= (pDispTab->ReqPktDesc[i] & ~FLD_PROP_MASK);
  1983. }
  1984. if (Status != AFP_ERR_NONE)
  1985. {
  1986. break;
  1987. }
  1988. // Before we go any further, check for volume/fork references and such
  1989. //
  1990. // NOTE: The VolId and OForkRefNum are always the first parameter and
  1991. // hence referenced as such via the request packet structure
  1992. if (pDispTab->ApiOptions & API_CHECK_VOLID)
  1993. {
  1994. PCONNDESC pConnDesc;
  1995. struct _RequestPacket
  1996. {
  1997. DWORD _VolId;
  1998. };
  1999. struct _ModifiedPacket
  2000. {
  2001. ULONG_PTR _VolId;
  2002. };
  2003. if ((pReqPkt->_VolId == 0) ||
  2004. ((pConnDesc = AfpConnectionReferenceAtDpc(pSda, (ULONG)(pReqPkt->_VolId))) == NULL))
  2005. {
  2006. Status = AFP_ERR_PARAM;
  2007. break;
  2008. }
  2009. ACQUIRE_SPIN_LOCK_AT_DPC(&pSda->sda_Lock);
  2010. pSda->sda_Flags |= SDA_DEREF_VOLUME;
  2011. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  2012. //if (sizeof(DWORD) != sizeof(ULONG_PTR))
  2013. #ifdef _WIN64
  2014. // Create 64-bit space to hold VolDesc pointer
  2015. // Push array 1 DWORD down
  2016. {
  2017. for (i = MAX_REQ_ENTRIES;
  2018. i > 0;
  2019. i--)
  2020. {
  2021. pSda->sda_ReqBlock[i+1] = pSda->sda_ReqBlock[i];
  2022. }
  2023. }
  2024. #endif
  2025. pModPkt->_VolId = (ULONG_PTR)pConnDesc;
  2026. if ((pDispTab->ApiOptions & API_TYPE_WRITE) &&
  2027. (pConnDesc->cds_pVolDesc->vds_Flags & AFP_VOLUME_READONLY))
  2028. {
  2029. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_WARN,
  2030. ("AfpUnmarshallReq: Write operation on a RO volume\n"));
  2031. Status = AFP_ERR_VOLUME_LOCKED;
  2032. break;
  2033. }
  2034. if (pConnDesc->cds_pVolDesc->vds_Flags & VOLUME_CDFS_INVALID)
  2035. {
  2036. ASSERT(!IS_VOLUME_NTFS(pConnDesc->cds_pVolDesc));
  2037. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_WARN,
  2038. ("AfpUnmarshallReq: Access to a defunct CD-Volume\n"));
  2039. Status = AFP_ERR_MISC;
  2040. break;
  2041. }
  2042. }
  2043. else if (pDispTab->ApiOptions & API_CHECK_OFORKREFNUM)
  2044. {
  2045. POPENFORKENTRY pOpenForkEntry;
  2046. struct _RequestPacket
  2047. {
  2048. DWORD _OForkRefNum;
  2049. };
  2050. struct _ModifiedPacket
  2051. {
  2052. ULONG_PTR _OForkRefNum;
  2053. };
  2054. if ((pReqPkt->_OForkRefNum == 0) ||
  2055. ((pOpenForkEntry = AfpForkReferenceByRefNum(pSda, (ULONG)(pReqPkt->_OForkRefNum))) == NULL))
  2056. {
  2057. Status = AFP_ERR_PARAM;
  2058. break;
  2059. }
  2060. ACQUIRE_SPIN_LOCK_AT_DPC(&pSda->sda_Lock);
  2061. pSda->sda_Flags |= SDA_DEREF_OFORK;
  2062. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  2063. //if (sizeof(DWORD) != sizeof(ULONG_PTR))
  2064. #ifdef _WIN64
  2065. // Create 64-bit space to hold VolDesc pointer
  2066. // Push array 1 DWORD down
  2067. {
  2068. for (i = MAX_REQ_ENTRIES;
  2069. i > 0;
  2070. i--)
  2071. {
  2072. pSda->sda_ReqBlock[i+1] = pSda->sda_ReqBlock[i];
  2073. }
  2074. }
  2075. #endif
  2076. pModPkt->_OForkRefNum = (ULONG_PTR)pOpenForkEntry;
  2077. if ((pDispTab->ApiOptions & API_TYPE_WRITE) &&
  2078. !(pOpenForkEntry->ofe_OpenMode & FORK_OPEN_WRITE))
  2079. {
  2080. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_WARN,
  2081. ("AfpUnmarshallReq: AfpWrite on a Fork not opened for write\n"));
  2082. Status = AFP_ERR_ACCESS_DENIED;
  2083. break;
  2084. }
  2085. }
  2086. // Now get the sda_NameX fields. Allocate one chunk of memory for
  2087. // copying all the variable size data. Use sda_NameXSpace if it fits there
  2088. if ((pDispTab->NameXType[0] != TYP_NONE) &&
  2089. (RequestSize > 0))
  2090. {
  2091. SpaceLeft = RequestSize;
  2092. ACQUIRE_SPIN_LOCK_AT_DPC(&pSda->sda_Lock);
  2093. pSda->sda_NameBuf = NULL;
  2094. if ((RequestSize <= pSda->sda_SizeNameXSpace) &&
  2095. ((pSda->sda_Flags & SDA_NAMEXSPACE_IN_USE) == 0))
  2096. {
  2097. pSda->sda_NameBuf = pSda->sda_NameXSpace;
  2098. pSda->sda_Flags |= SDA_NAMEXSPACE_IN_USE;
  2099. }
  2100. RELEASE_SPIN_LOCK_FROM_DPC(&pSda->sda_Lock);
  2101. if ((pSda->sda_NameBuf == NULL) &&
  2102. (pSda->sda_NameBuf = AfpAllocNonPagedMemory(RequestSize)) == NULL)
  2103. {
  2104. Status = AFP_ERR_MISC;
  2105. break;
  2106. }
  2107. }
  2108. for (i = 0;
  2109. (i < MAX_VAR_ENTRIES) && (pDispTab->NameXType[i] != TYP_NONE) && (RequestSize > 0);
  2110. i++)
  2111. {
  2112. if (((pDispTab->NameXType[i] & TYP_NOPAD) == 0) &&
  2113. (RequestSize > 0) && ((Offset % 2) != 0))
  2114. {
  2115. Offset ++;
  2116. RequestSize --;
  2117. pRequestBuf ++;
  2118. }
  2119. switch (pDispTab->NameXType[i] & ~TYP_PROP_MASK)
  2120. {
  2121. case TYP_PATH:
  2122. // TYP_PATH is almost like TYP_STRING except that there is a
  2123. // leading PathType which should be valid. Just validate that
  2124. // and fall through to the TYP_STRING case. Validate the size
  2125. // to hold atleast the pathtype and the string length
  2126. ASSERT (!(pDispTab->NameXType[i] & TYP_OPTIONAL));
  2127. if ((RequestSize < 2*sizeof(BYTE)) ||
  2128. !VALIDPATHTYPE(*pRequestBuf)||
  2129. (VALIDPATHTYPE(pSda->sda_PathType) &&
  2130. (pSda->sda_PathType != *pRequestBuf)))
  2131. {
  2132. Status = AFP_ERR_PARAM;
  2133. break;
  2134. }
  2135. // Save the PathType and account for it
  2136. pSda->sda_PathType = *pRequestBuf++;
  2137. Offset ++;
  2138. RequestSize --;
  2139. case TYP_STRING:
  2140. // A TYP_STRING has a leading size byte and a string of that
  2141. // size. A null string is then atleast one byte long.
  2142. // Allow an optional string to be absent
  2143. if ((pDispTab->NameXType[i] & TYP_OPTIONAL) &&
  2144. (RequestSize == 0))
  2145. continue;
  2146. if ((RequestSize < sizeof(BYTE)) ||
  2147. ((StrSize = (LONG)pRequestBuf[0]) >
  2148. (RequestSize - (LONG)sizeof(BYTE))))
  2149. {
  2150. Status = AFP_ERR_PARAM;
  2151. break;
  2152. }
  2153. // Consume the string length
  2154. pRequestBuf++;
  2155. Offset ++;
  2156. RequestSize --;
  2157. break;
  2158. case TYP_BLK16:
  2159. if (RequestSize < 16)
  2160. {
  2161. Status = AFP_ERR_PARAM;
  2162. ASSERT(0);
  2163. break;
  2164. }
  2165. StrSize = 16;
  2166. break;
  2167. case TYP_BLOCK:
  2168. StrSize = RequestSize;
  2169. break;
  2170. default:
  2171. // How did we get here ?
  2172. KeBugCheck(0);
  2173. break;
  2174. }
  2175. if (Status != AFP_ERR_NONE)
  2176. {
  2177. break;
  2178. }
  2179. if (StrSize > 0)
  2180. {
  2181. ASSERT (StrSize <= SpaceLeft);
  2182. pSda->sda_Name[i].Buffer = (pSda->sda_NameBuf + NameOff);
  2183. SpaceLeft -= StrSize;
  2184. NameOff += StrSize;
  2185. pSda->sda_Name[i].Length =
  2186. pSda->sda_Name[i].MaximumLength = (USHORT)StrSize;
  2187. RtlCopyMemory(pSda->sda_Name[i].Buffer, pRequestBuf, StrSize);
  2188. pRequestBuf += StrSize;
  2189. Offset += StrSize;
  2190. RequestSize -= StrSize;
  2191. }
  2192. if ((pDispTab->NameXType[i] & TYP_NON_NULL) &&
  2193. (pSda->sda_Name[i].Length == 0))
  2194. Status = (AFP_ERR_BASE - pDispTab->AfpStatus);
  2195. }
  2196. // Change the status if we have no worker at dispatch level
  2197. if ((Status == AFP_ERR_NONE) && (pDispTab->ApiOptions & API_MUST_BE_QUEUED))
  2198. {
  2199. Status = AFP_ERR_QUEUE;
  2200. }
  2201. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2202. ("AfpUnmarshallReq: <%s> returning Status %ld\n",
  2203. afpApiNames[ApiCode], Status));
  2204. } while (False);
  2205. AfpUnmarshallReq_ErrExit:
  2206. //
  2207. // Kill the write buffer Mdl since we do not need it anymore. Of course,
  2208. // if the Mdl belongs to cache mgr, don't touch it!
  2209. //
  2210. if ((pRequest->rq_WriteMdl != NULL) &&
  2211. (pRequest->rq_CacheMgrContext == NULL))
  2212. {
  2213. AfpFreeMdl(pRequest->rq_WriteMdl);
  2214. pRequest->rq_WriteMdl = NULL;
  2215. }
  2216. if ((Status != AFP_ERR_NONE) &&
  2217. (Status != AFP_ERR_QUEUE))
  2218. {
  2219. if (pWriteBuf != NULL)
  2220. {
  2221. AfpIOFreeBuffer(pWriteBuf);
  2222. }
  2223. pSda->sda_IOBuf = NULL;
  2224. pSda->sda_IOSize = 0;
  2225. }
  2226. #ifdef PROFILING
  2227. AfpGetPerfCounter(&TimeE);
  2228. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  2229. INTERLOCKED_INCREMENT_LONG(&AfpServerProfile->perf_UnmarshallCount);
  2230. INTERLOCKED_ADD_LARGE_INTGR_DPC(&AfpServerProfile->perf_UnmarshallTime,
  2231. TimeD,
  2232. &AfpStatisticsLock);
  2233. #endif
  2234. AfpDisposeRequest(pSda, Status);
  2235. }
  2236. /*** AfpCompleteApiProcessing
  2237. *
  2238. * Called in when the API processing is complete. Book-keeping is performed
  2239. * and a reply sent. If any buffers were allocated during un-marshalling,
  2240. * then they are freed up.
  2241. *
  2242. * LOCKS: sda_Lock (SPIN), AfpStatisticsLock (SPIN)
  2243. *
  2244. */
  2245. VOID FASTCALL
  2246. AfpCompleteApiProcessing(
  2247. IN PSDA pSda,
  2248. IN AFPSTATUS RetCode
  2249. )
  2250. {
  2251. POPENFORKENTRY pOpenForkEntry = NULL;
  2252. PCONNDESC pConnDesc = NULL;
  2253. PDFRDREQQ pDfrdReq = NULL;
  2254. PLIST_ENTRY pList;
  2255. KIRQL OldIrql;
  2256. PMDL ReplyMdl;
  2257. PREQUEST pRequest;
  2258. struct _RequestPacket
  2259. {
  2260. union
  2261. {
  2262. PCONNDESC _pConnDesc;
  2263. POPENFORKENTRY _pOpenForkEntry;
  2264. };
  2265. };
  2266. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2267. ("AfpCompleteApiProcessing: Completed <%s>\n", afpApiNames[pSda->sda_AfpFunc]));
  2268. ACQUIRE_SPIN_LOCK(&pSda->sda_Lock, &OldIrql);
  2269. // If there is a deferred request, dequeue it now while we have the lock
  2270. if (!IsListEmpty(&pSda->sda_DeferredQueue))
  2271. {
  2272. pList = RemoveHeadList(&pSda->sda_DeferredQueue);
  2273. pDfrdReq = CONTAINING_RECORD(pList, DFRDREQQ, drq_Link);
  2274. }
  2275. ASSERT (pSda->sda_Flags & SDA_REQUEST_IN_PROCESS);
  2276. pSda->sda_Flags &= ~SDA_QUEUE_IF_DPC;
  2277. if (pSda->sda_Flags & SDA_DEREF_VOLUME)
  2278. {
  2279. pConnDesc = pReqPkt->_pConnDesc;
  2280. pReqPkt->_pConnDesc = NULL;
  2281. ASSERT(VALID_CONNDESC(pConnDesc));
  2282. pSda->sda_Flags &= ~SDA_DEREF_VOLUME;
  2283. // If we have a enumerated directory context, free it up
  2284. // but only if we are not in the middle of an enumerate
  2285. // and we are not doing the periodic GetVolParms either
  2286. if ((pConnDesc->cds_pEnumDir != NULL) &&
  2287. (pSda->sda_AfpFunc != _AFP_ENUMERATE) &&
  2288. (pSda->sda_AfpFunc != _AFP_GET_VOL_PARMS))
  2289. {
  2290. AfpFreeMemory(pConnDesc->cds_pEnumDir);
  2291. pConnDesc->cds_pEnumDir = NULL;
  2292. }
  2293. }
  2294. if (pSda->sda_Flags & SDA_DEREF_OFORK)
  2295. {
  2296. pOpenForkEntry = pReqPkt->_pOpenForkEntry;
  2297. ASSERT(VALID_OPENFORKENTRY(pOpenForkEntry));
  2298. pSda->sda_Flags &= ~SDA_DEREF_OFORK;
  2299. }
  2300. if (pSda->sda_NameBuf != NULL)
  2301. {
  2302. if (pSda->sda_NameBuf != pSda->sda_NameXSpace)
  2303. {
  2304. AfpFreeMemory(pSda->sda_NameBuf);
  2305. }
  2306. else
  2307. {
  2308. pSda->sda_Flags &= ~SDA_NAMEXSPACE_IN_USE;
  2309. }
  2310. pSda->sda_NameBuf = NULL;
  2311. }
  2312. // Clear these fields. We do not want left-overs from previous api lying around.
  2313. ASSERT((FIELD_OFFSET(SDA, sda_Name) - FIELD_OFFSET(SDA, sda_ReqBlock)) ==
  2314. sizeof(DWORD)*(MAX_REQ_ENTRIES_PLUS_1));
  2315. RtlZeroMemory(&pSda->sda_ReqBlock[0],
  2316. (sizeof(ANSI_STRING)*MAX_VAR_ENTRIES) + (sizeof(DWORD)*(MAX_REQ_ENTRIES_PLUS_1)));
  2317. pSda->sda_SecUtilResult = STATUS_SUCCESS;
  2318. ASSERT(pSda->sda_AfpFunc < _AFP_MAX_ENTRIES);
  2319. #ifdef PROFILING
  2320. {
  2321. TIME ApiEndTime, FuncTime;
  2322. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpStatisticsLock);
  2323. // Update profile info
  2324. AfpGetPerfCounter(&ApiEndTime);
  2325. FuncTime.QuadPart = ApiEndTime.QuadPart - pSda->sda_ApiStartTime.QuadPart;
  2326. AfpServerProfile->perf_ApiCounts[pSda->sda_AfpFunc] ++;
  2327. AfpServerProfile->perf_ApiCumTimes[pSda->sda_AfpFunc].QuadPart += FuncTime.QuadPart;
  2328. // Do not make this completely useless by recording times
  2329. // for apis that do not succeed. They detect an error early
  2330. // and hence make the Best Time fairly bogus
  2331. if (RetCode == AFP_ERR_NONE)
  2332. {
  2333. if ((FuncTime.QuadPart > AfpServerProfile->perf_ApiWorstTime[pSda->sda_AfpFunc].QuadPart) ||
  2334. (AfpServerProfile->perf_ApiWorstTime[pSda->sda_AfpFunc].QuadPart == 0))
  2335. AfpServerProfile->perf_ApiWorstTime[pSda->sda_AfpFunc].QuadPart = FuncTime.QuadPart;
  2336. if ((FuncTime.QuadPart < AfpServerProfile->perf_ApiBestTime[pSda->sda_AfpFunc].QuadPart) ||
  2337. (AfpServerProfile->perf_ApiBestTime[pSda->sda_AfpFunc].QuadPart == 0))
  2338. AfpServerProfile->perf_ApiBestTime[pSda->sda_AfpFunc].QuadPart = FuncTime.QuadPart;
  2339. }
  2340. RELEASE_SPIN_LOCK_FROM_DPC(&AfpStatisticsLock);
  2341. }
  2342. #endif
  2343. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataOut,
  2344. (LONG)pSda->sda_ReplySize + (LONG)sizeof(RetCode),
  2345. &AfpStatisticsLock);
  2346. pRequest = pSda->sda_Request;
  2347. // We are done with the request. Do not reset if we have a deferred request to process
  2348. if (pDfrdReq == NULL)
  2349. {
  2350. pSda->sda_Flags &= ~SDA_REQUEST_IN_PROCESS;
  2351. }
  2352. else
  2353. {
  2354. pSda->sda_Request = pDfrdReq->drq_pRequest;
  2355. }
  2356. // We are done with the request. Setup for reply.
  2357. pSda->sda_Flags |= SDA_REPLY_IN_PROCESS;
  2358. ReplyMdl = NULL;
  2359. //
  2360. // if we got Read Mdl from cache mgr, we don't allocate a new Mdl
  2361. //
  2362. if (pRequest->rq_CacheMgrContext)
  2363. {
  2364. ASSERT(pSda->sda_ReplyBuf == NULL);
  2365. ReplyMdl = ((PDELAYEDALLOC)(pRequest->rq_CacheMgrContext))->pMdl;
  2366. }
  2367. //
  2368. // nope, we are using our own buffer (if any). We must allocate our
  2369. // Mdl too
  2370. //
  2371. else
  2372. {
  2373. if (pSda->sda_ReplyBuf != NULL)
  2374. {
  2375. ASSERT ((pSda->sda_ReplySize > 0) && (pSda->sda_ReplySize <= pSda->sda_MaxWriteSize));
  2376. if ((ReplyMdl = AfpAllocMdl(
  2377. (pSda->sda_ReplyBuf - DSI_BACKFILL_OFFSET(pSda)),
  2378. (pSda->sda_ReplySize + DSI_BACKFILL_OFFSET(pSda)),
  2379. NULL)) == NULL)
  2380. {
  2381. RetCode = AFP_ERR_MISC;
  2382. AfpFreeReplyBuf(pSda, TRUE);
  2383. }
  2384. }
  2385. }
  2386. pSda->sda_ReplyBuf = NULL;
  2387. pSda->sda_ReplySize = 0;
  2388. RELEASE_SPIN_LOCK(&pSda->sda_Lock, OldIrql);
  2389. // Dereference the connection descriptor and the fork descriptor (from
  2390. // above where we cannot call dereference as we are holding the SDA lock.
  2391. if (pOpenForkEntry != NULL)
  2392. AfpForkDereference(pOpenForkEntry);
  2393. if (pConnDesc != NULL)
  2394. AfpConnectionDereference(pConnDesc);
  2395. pRequest->rq_ReplyMdl = ReplyMdl;
  2396. AfpSpReplyClient(pRequest, RetCode, pSda->sda_XportTable);
  2397. // Handle any deferred requests
  2398. if (pDfrdReq != NULL)
  2399. {
  2400. KIRQL OldIrql;
  2401. // Note that AfpUnmarshallReq expects to be called at DISPATCH_LEVEL
  2402. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2403. #ifdef PROFILING
  2404. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpStatisticsLock);
  2405. AfpServerProfile->perf_CurDfrdReqCount --;
  2406. RELEASE_SPIN_LOCK_FROM_DPC(&AfpStatisticsLock);
  2407. #endif
  2408. AfpUnmarshallReq(pSda);
  2409. KeLowerIrql(OldIrql);
  2410. AfpFreeMemory(pDfrdReq);
  2411. }
  2412. }
  2413. /*** AfpStartApiProcessing
  2414. *
  2415. * This is called when an API is queued up to the worker thread. This calls
  2416. * the real worker and then adjusts the count of outstanding worker requests.
  2417. */
  2418. VOID FASTCALL
  2419. AfpStartApiProcessing(
  2420. IN PSDA pSda
  2421. )
  2422. {
  2423. AFPSTATUS RetCode;
  2424. #ifdef PROFILING
  2425. TIME TimeE;
  2426. #endif
  2427. ASSERT(VALID_SDA(pSda) && (pSda->sda_WorkerRoutine != NULL));
  2428. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2429. ("AfpStartApiProcessing: Calling Fsp Worker for <%s>\n",
  2430. afpApiNames[pSda->sda_AfpFunc]));
  2431. #ifdef PROFILING
  2432. AfpGetPerfCounter(&TimeE);
  2433. TimeE.QuadPart -= pSda->sda_QueueTime.QuadPart;
  2434. INTERLOCKED_ADD_LARGE_INTGR(&AfpServerProfile->perf_QueueTime,
  2435. TimeE,
  2436. &AfpStatisticsLock);
  2437. #endif
  2438. // Call the real worker
  2439. RetCode = (*pSda->sda_WorkerRoutine)(pSda);
  2440. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2441. ("AfpStartApiProcessing: Fsp Worker returned %ld\n", RetCode));
  2442. ASSERT ((RetCode != AFP_ERR_QUEUE) &&
  2443. (RetCode != AFP_ERR_DEFER));
  2444. if (RetCode != AFP_ERR_EXTENDED)
  2445. {
  2446. AfpCompleteApiProcessing(pSda, RetCode);
  2447. }
  2448. }
  2449. /*** AfpDisposeRequest
  2450. *
  2451. * The request has been un-marshalled. Determine what to do with it. The
  2452. * return code determines the possible course of action.
  2453. */
  2454. VOID FASTCALL
  2455. AfpDisposeRequest(
  2456. IN PSDA pSda,
  2457. IN AFPSTATUS Status
  2458. )
  2459. {
  2460. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2461. ("AfpDisposeRequest: %ld\n", Status));
  2462. if ((Status == AFP_ERR_NONE) || (Status == AFP_ERR_QUEUE))
  2463. {
  2464. ASSERT(VALID_SDA(pSda) && (pSda->sda_WorkerRoutine != NULL));
  2465. }
  2466. else
  2467. {
  2468. ASSERT(VALID_SDA(pSda));
  2469. }
  2470. ASSERT (Status != AFP_ERR_DEFER);
  2471. // Now see if must call the worker or queue it or respond
  2472. if (Status == AFP_ERR_NONE)
  2473. {
  2474. Status = (*pSda->sda_WorkerRoutine)(pSda);
  2475. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2476. ("AfpDisposeRequest: Fsd Worker returned %ld\n", Status));
  2477. ASSERT (Status != AFP_ERR_DEFER);
  2478. }
  2479. if (Status == AFP_ERR_QUEUE)
  2480. {
  2481. if ((pSda->sda_Flags & SDA_QUEUE_IF_DPC) &&
  2482. (KeGetCurrentIrql() != DISPATCH_LEVEL))
  2483. {
  2484. Status = (*pSda->sda_WorkerRoutine)(pSda);
  2485. ASSERT ((Status != AFP_ERR_QUEUE) &&
  2486. (Status != AFP_ERR_DEFER));
  2487. if (Status != AFP_ERR_EXTENDED)
  2488. {
  2489. AfpCompleteApiProcessing(pSda, Status);
  2490. }
  2491. }
  2492. else
  2493. {
  2494. #ifdef PROFILING
  2495. AfpGetPerfCounter(&pSda->sda_QueueTime);
  2496. #endif
  2497. AfpQueueWorkItem(&pSda->sda_WorkItem);
  2498. }
  2499. }
  2500. else if ((Status != AFP_ERR_QUEUE) && (Status != AFP_ERR_EXTENDED))
  2501. {
  2502. AfpCompleteApiProcessing(pSda, Status);
  2503. }
  2504. }
  2505. /*** afpQueueDeferredRequest
  2506. *
  2507. * Queue a request in the deferred queue. The request is queued at the tail
  2508. * of the queue and dequeued at the head.
  2509. *
  2510. * LOCKS_ASSUMED: sda_Lock (SPIN)
  2511. */
  2512. VOID FASTCALL
  2513. afpQueueDeferredRequest(
  2514. IN PSDA pSda,
  2515. IN PREQUEST pRequest
  2516. )
  2517. {
  2518. PDFRDREQQ pDfrdReq;
  2519. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  2520. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_INFO,
  2521. ("afpQueueDeferredRequest: Deferring Request\n"));
  2522. #ifdef PROFILING
  2523. ACQUIRE_SPIN_LOCK_AT_DPC(&AfpStatisticsLock);
  2524. AfpServerProfile->perf_CurDfrdReqCount ++;
  2525. if (AfpServerProfile->perf_CurDfrdReqCount >
  2526. AfpServerProfile->perf_MaxDfrdReqCount)
  2527. AfpServerProfile->perf_MaxDfrdReqCount =
  2528. AfpServerProfile->perf_CurDfrdReqCount;
  2529. RELEASE_SPIN_LOCK_FROM_DPC(&AfpStatisticsLock);
  2530. #endif
  2531. pDfrdReq = (PDFRDREQQ)AfpAllocNonPagedMemory(sizeof(DFRDREQQ) + pRequest->rq_RequestSize);
  2532. if (pDfrdReq == NULL)
  2533. {
  2534. // Should we respond to this request ? How ? Should we drop this session ?
  2535. AFPLOG_DDERROR(AFPSRVMSG_DFRD_REQUEST,
  2536. STATUS_INSUFFICIENT_RESOURCES,
  2537. NULL,
  2538. 0,
  2539. NULL);
  2540. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_ERR,
  2541. ("afpQueueDeferredRequest: Unable to allocate DfrdReq packet, dropping request\n"));
  2542. DBGBRK(DBG_LEVEL_FATAL);
  2543. return;
  2544. }
  2545. RtlCopyMemory((PBYTE)pDfrdReq + sizeof(DFRDREQQ),
  2546. pRequest->rq_RequestBuf,
  2547. pRequest->rq_RequestSize);
  2548. pDfrdReq->drq_pRequest = pRequest;
  2549. pDfrdReq->drq_pRequest->rq_RequestBuf = (PBYTE)pDfrdReq + sizeof(DFRDREQQ);
  2550. InsertTailList(&pSda->sda_DeferredQueue, &pDfrdReq->drq_Link);
  2551. }
  2552. /*** AfpGetWriteBuffer
  2553. *
  2554. * This is called directly by the appletalk stack when a WRITE command is encountered.
  2555. * The request is examined for either FpWrite or FpAddIcon. These are the only reqs
  2556. * which uses a write command. If a request other than this is specified or if the
  2557. * size specified is 0 or if we fail to allocate memory or MDl, then a NULL is returned
  2558. * for the Mdl else a valid Mdl is returned.
  2559. */
  2560. NTSTATUS FASTCALL
  2561. AfpGetWriteBuffer(
  2562. IN PSDA pSda,
  2563. IN PREQUEST pRequest
  2564. )
  2565. {
  2566. PMDL pMdl = NULL;
  2567. PBYTE pBuf;
  2568. LONG BufSize = 0;
  2569. DWORD Offset;
  2570. USHORT ReqLen;
  2571. PDELAYEDALLOC pDelAlloc;
  2572. POPENFORKENTRY pOpenForkEntry;
  2573. DWORD OForkRefNum;
  2574. NTSTATUS status=STATUS_SUCCESS;
  2575. KIRQL OldIrql;
  2576. PFILE_OBJECT pFileObject;
  2577. PFAST_IO_DISPATCH pFastIoDisp;
  2578. struct _FuncHdr
  2579. {
  2580. BYTE _Func;
  2581. BYTE _SubFunc;
  2582. };
  2583. union _ReqHdr
  2584. {
  2585. struct _WriteReq
  2586. {
  2587. struct _FuncHdr _FuncHdr;
  2588. BYTE _ForkRefNum[2];
  2589. BYTE _Offset[4];
  2590. BYTE _Size[4];
  2591. } WriteReq;
  2592. struct _AddIconReq
  2593. {
  2594. struct _FuncHdr _FuncHdr;
  2595. BYTE _DTRefNum[2];
  2596. BYTE _Creator[4];
  2597. BYTE _Type[4];
  2598. BYTE _IconType;
  2599. BYTE _Reserved;
  2600. BYTE _IconTag[4];
  2601. BYTE _BitmapSize[2];
  2602. } AddIconReq;
  2603. } *pReqHdr;
  2604. ReqLen = (USHORT)pRequest->rq_RequestSize;
  2605. pReqHdr = (union _ReqHdr *)(pRequest->rq_RequestBuf);
  2606. ASSERT(pRequest->rq_WriteMdl == NULL);
  2607. pRequest->rq_WriteMdl = NULL;
  2608. if ((pReqHdr != NULL) && (ReqLen >= sizeof(struct _FuncHdr)))
  2609. {
  2610. if ((pReqHdr->WriteReq._FuncHdr._Func == AFP_WRITE) &&
  2611. (ReqLen >= sizeof(struct _WriteReq)))
  2612. {
  2613. GETDWORD2DWORD(&BufSize, pReqHdr->WriteReq._Size);
  2614. if (BufSize > (LONG)pSda->sda_MaxWriteSize)
  2615. {
  2616. BufSize = (LONG)pSda->sda_MaxWriteSize;
  2617. }
  2618. //
  2619. // if the Write is big enough, get an Mdl directly from cache mgr
  2620. //
  2621. if (BufSize >= CACHEMGR_WRITE_THRESHOLD)
  2622. {
  2623. // get the fork number from the request
  2624. GETSHORT2DWORD(&OForkRefNum, pReqHdr->WriteReq._ForkRefNum);
  2625. // get the offset at which to write
  2626. GETDWORD2DWORD(&Offset, pReqHdr->WriteReq._Offset);
  2627. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2628. pOpenForkEntry = AfpForkReferenceByRefNum(pSda, OForkRefNum);
  2629. KeLowerIrql(OldIrql);
  2630. if (pOpenForkEntry == NULL)
  2631. {
  2632. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_ERR,
  2633. ("AfpGetWriteBuffer: couldn't ref fork on %lx\n", pSda));
  2634. return(STATUS_CONNECTION_DISCONNECTED);
  2635. }
  2636. pFileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  2637. pFastIoDisp = pOpenForkEntry->ofe_pDeviceObject->DriverObject->FastIoDispatch;
  2638. if ((pFileObject->Flags & FO_CACHE_SUPPORTED) &&
  2639. (pFastIoDisp->PrepareMdlWrite != NULL))
  2640. {
  2641. pDelAlloc = AfpAllocDelAlloc();
  2642. if (pDelAlloc == NULL)
  2643. {
  2644. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_ERR,
  2645. ("AfpGetWriteBuffer: malloc for pDelAlloc failed\n"));
  2646. // remove the refcount we put before checking FO_CACHE_SUPPORTED
  2647. AfpForkDereference(pOpenForkEntry);
  2648. return(STATUS_INSUFFICIENT_RESOURCES);
  2649. }
  2650. // put DelayAlloc refcount
  2651. if (AfpSdaReferenceSessionByPointer(pSda) == NULL)
  2652. {
  2653. DBGPRINT(DBG_COMP_AFPAPI, DBG_LEVEL_ERR,
  2654. ("AfpGetWriteBuffer: session closing, rejecting request\n"));
  2655. AfpFreeDelAlloc(pDelAlloc);
  2656. // remove the refcount we put before checking FO_CACHE_SUPPORTED
  2657. AfpForkDereference(pOpenForkEntry);
  2658. return(STATUS_CONNECTION_DISCONNECTED);
  2659. }
  2660. pRequest->rq_CacheMgrContext = pDelAlloc;
  2661. AfpInitializeWorkItem(&pDelAlloc->WorkItem,
  2662. AfpAllocWriteMdl,
  2663. pDelAlloc);
  2664. pDelAlloc->pSda = pSda;
  2665. pDelAlloc->pRequest = pRequest;
  2666. pDelAlloc->Offset.QuadPart = Offset;
  2667. pDelAlloc->BufSize = BufSize;
  2668. pDelAlloc->pOpenForkEntry = pOpenForkEntry;
  2669. // DELALLOCQUEUE: unrem the #if 0 part and delete the AfpQueueWorkItem line
  2670. #if 0
  2671. KeInsertQueue(&AfpDelAllocQueue, &(pDelAlloc->WorkItem.wi_List));
  2672. #endif
  2673. AfpQueueWorkItem(&pDelAlloc->WorkItem);
  2674. return(STATUS_PENDING);
  2675. }
  2676. else
  2677. {
  2678. // remove the refcount we put before checking FO_CACHE_SUPPORTED
  2679. AfpForkDereference(pOpenForkEntry);
  2680. }
  2681. }
  2682. }
  2683. else if ((pReqHdr->AddIconReq._FuncHdr._Func == AFP_ADD_ICON) &&
  2684. (ReqLen >= sizeof(struct _AddIconReq)))
  2685. {
  2686. GETSHORT2DWORD(&BufSize, pReqHdr->AddIconReq._BitmapSize);
  2687. if ((BufSize < 0) || (BufSize > (LONG)pSda->sda_MaxWriteSize))
  2688. {
  2689. BufSize = 0;
  2690. }
  2691. }
  2692. if (BufSize > 0)
  2693. {
  2694. pBuf = AfpIOAllocBuffer(BufSize);
  2695. if (pBuf != NULL)
  2696. {
  2697. pMdl = AfpAllocMdl(pBuf, BufSize, NULL);
  2698. if (pMdl == NULL)
  2699. {
  2700. AfpIOFreeBuffer(pBuf);
  2701. status = STATUS_INSUFFICIENT_RESOURCES;
  2702. }
  2703. }
  2704. else
  2705. {
  2706. status = STATUS_INSUFFICIENT_RESOURCES;
  2707. }
  2708. }
  2709. }
  2710. pRequest->rq_WriteMdl = pMdl;
  2711. return (status);
  2712. }