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.

886 lines
21 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fsp_dir.c
  5. Abstract:
  6. This module contains the entry points for the AFP directory 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_dir.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_FSP_DIR
  17. #include <afp.h>
  18. #include <gendisp.h>
  19. #include <fdparm.h>
  20. #include <pathmap.h>
  21. #include <client.h>
  22. #include <afpinfo.h>
  23. #include <access.h>
  24. #define DEF_ID_CNT 128
  25. #define max(a,b) (((a) > (b)) ? (a) : (b))
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text( PAGE, AfpFspDispOpenDir)
  28. #pragma alloc_text( PAGE, AfpFspDispCloseDir)
  29. #pragma alloc_text( PAGE, AfpFspDispCreateDir)
  30. #pragma alloc_text( PAGE, AfpFspDispEnumerate)
  31. #pragma alloc_text( PAGE, AfpFspDispSetDirParms)
  32. #endif
  33. /*** AfpFspDispOpenDir
  34. *
  35. * This is the worker routine for the AfpOpenDir API.
  36. *
  37. * The request packet is represented below.
  38. *
  39. * sda_ReqBlock PCONNDESC pConnDesc
  40. * sda_ReqBlock DWORD ParentId
  41. * sda_Name1 ANSI_STRING DirName
  42. */
  43. AFPSTATUS FASTCALL
  44. AfpFspDispOpenDir(
  45. IN PSDA pSda
  46. )
  47. {
  48. FILEDIRPARM FDParm;
  49. PATHMAPENTITY PME;
  50. AFPSTATUS Status = AFP_ERR_PARAM;
  51. struct _RequestPacket
  52. {
  53. PCONNDESC _pConnDesc;
  54. DWORD _ParentId;
  55. };
  56. struct _ResponsePacket
  57. {
  58. BYTE __DirId[4];
  59. };
  60. PAGED_CODE( );
  61. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  62. ("AfpFspDispOpenDir: Entered\n"));
  63. ASSERT(VALID_CONNDESC(pReqPkt->_pConnDesc) &&
  64. VALID_VOLDESC(pReqPkt->_pConnDesc->cds_pVolDesc));
  65. AfpInitializePME(&PME, 0, NULL);
  66. if ((Status = AfpMapAfpPathForLookup(pReqPkt->_pConnDesc,
  67. pReqPkt->_ParentId,
  68. &pSda->sda_Name1,
  69. pSda->sda_PathType,
  70. DFE_DIR,
  71. DIR_BITMAP_DIRID,
  72. &PME,
  73. &FDParm)) == AFP_ERR_NONE)
  74. AfpIoClose(&PME.pme_Handle); // Close the handle
  75. if (Status == AFP_ERR_NONE)
  76. {
  77. pSda->sda_ReplySize = SIZE_RESPPKT;
  78. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  79. PUTDWORD2DWORD(pRspPkt->__DirId, FDParm._fdp_AfpId);
  80. }
  81. return Status;
  82. }
  83. /*** AfpFspDispCloseDir
  84. *
  85. * This routine implements the AfpCloseDir API.
  86. *
  87. * The request packet is represented below.
  88. *
  89. * sda_ReqBlock PCONNDESC pConnDesc
  90. * sda_ReqBlock DWORD DirId
  91. */
  92. AFPSTATUS FASTCALL
  93. AfpFspDispCloseDir(
  94. IN PSDA pSda
  95. )
  96. {
  97. FILEDIRPARM FDParm;
  98. PATHMAPENTITY PME;
  99. AFPSTATUS Status;
  100. struct _RequestPacket
  101. {
  102. PCONNDESC _pConnDesc;
  103. DWORD _DirId;
  104. };
  105. PAGED_CODE( );
  106. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  107. ("AfpFspDispCloseDir: Entered\n"));
  108. ASSERT(VALID_CONNDESC(pReqPkt->_pConnDesc) &&
  109. VALID_VOLDESC(pReqPkt->_pConnDesc->cds_pVolDesc));
  110. AfpInitializeFDParms(&FDParm);
  111. AfpInitializePME(&PME, 0, NULL);
  112. Status = AfpMapAfpIdForLookup(pReqPkt->_pConnDesc,
  113. pReqPkt->_DirId,
  114. DFE_DIR,
  115. 0,
  116. &PME,
  117. &FDParm);
  118. if (Status == AFP_ERR_NONE)
  119. {
  120. AfpIoClose(&PME.pme_Handle);
  121. }
  122. else Status = AFP_ERR_PARAM;
  123. return Status;
  124. }
  125. /*** AfpFspDispCreateDir
  126. *
  127. * This is the worker routine for the AfpCreateDir API.
  128. *
  129. * The request packet is represented below.
  130. *
  131. * sda_ReqBlock PCONNDESC pConnDesc
  132. * sda_ReqBlock DWORD ParentId
  133. * sda_Name1 ANSI_STRING DirName
  134. */
  135. AFPSTATUS FASTCALL
  136. AfpFspDispCreateDir(
  137. IN PSDA pSda
  138. )
  139. {
  140. AFPSTATUS Status = AFP_ERR_PARAM, PostStatus;
  141. PATHMAPENTITY PME;
  142. PDFENTRY pNewDfe;
  143. FILESYSHANDLE hNewDir, hAfpInfo;
  144. AFPINFO afpinfo;
  145. PVOLDESC pVolDesc; // For post-create processing
  146. BYTE PathType; // -- ditto --
  147. WCHAR PathBuf[BIG_PATH_LEN];
  148. BOOLEAN InRoot;
  149. struct _RequestPacket
  150. {
  151. PCONNDESC _pConnDesc;
  152. DWORD _ParentId;
  153. };
  154. struct _ResponsePacket
  155. {
  156. BYTE __DirId[4];
  157. };
  158. PAGED_CODE( );
  159. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  160. ("AfpFspDispCreateDir: Entered\n"));
  161. ASSERT(VALID_CONNDESC(pReqPkt->_pConnDesc));
  162. pVolDesc = pReqPkt->_pConnDesc->cds_pVolDesc;
  163. ASSERT(VALID_VOLDESC(pVolDesc));
  164. AfpSwmrAcquireExclusive(&pVolDesc->vds_IdDbAccessLock);
  165. do
  166. {
  167. hNewDir.fsh_FileHandle = NULL;
  168. hAfpInfo.fsh_FileHandle = NULL;
  169. AfpInitializePME(&PME, sizeof(PathBuf), PathBuf);
  170. if (!NT_SUCCESS(Status = AfpMapAfpPath(pReqPkt->_pConnDesc,
  171. pReqPkt->_ParentId,
  172. &pSda->sda_Name1,
  173. PathType = pSda->sda_PathType,
  174. SoftCreate,
  175. DFE_DIR,
  176. 0,
  177. &PME,
  178. NULL)))
  179. {
  180. break;
  181. }
  182. AfpImpersonateClient(pSda);
  183. InRoot = (PME.pme_ParentPath.Length == 0) ? True : False;
  184. Status = AfpIoCreate(&pVolDesc->vds_hRootDir,
  185. AFP_STREAM_DATA,
  186. &PME.pme_FullPath,
  187. FILEIO_ACCESS_NONE | FILEIO_ACCESS_DELETE | AFP_OWNER_ACCESS,
  188. FILEIO_DENY_NONE,
  189. FILEIO_OPEN_DIR,
  190. FILEIO_CREATE_SOFT,
  191. FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE,
  192. True,
  193. #ifdef INHERIT_DIRECTORY_PERMS
  194. NULL,
  195. #else
  196. pSda->sda_pSecDesc,
  197. #endif
  198. &hNewDir,
  199. NULL,
  200. pVolDesc,
  201. &PME.pme_FullPath,
  202. // we don't get notified of parent mod time changing if
  203. // there is no handle open for the parent dir at the time
  204. // of create, which we cannot predict here.
  205. &PME.pme_ParentPath);
  206. AfpRevertBack();
  207. if (!NT_SUCCESS(Status))
  208. {
  209. Status = AfpIoConvertNTStatusToAfpStatus(Status);
  210. break;
  211. }
  212. #ifdef INHERIT_DIRECTORY_PERMS
  213. {
  214. PFILEDIRPARM pFdParm;
  215. if ((pFdParm = (PFILEDIRPARM)AfpAllocNonPagedMemory(sizeof(FILEDIRPARM))) != NULL)
  216. {
  217. pFdParm->_fdp_OwnerId = pSda->sda_UID;
  218. pFdParm->_fdp_GroupId = pSda->sda_GID;
  219. pFdParm->_fdp_OwnerRights = DIR_ACCESS_ALL | DIR_ACCESS_OWNER;
  220. pFdParm->_fdp_GroupRights = 0;
  221. pFdParm->_fdp_WorldRights = 0;
  222. pFdParm->_fdp_Flags = DFE_FLAGS_DIR;
  223. // Now set the owner and group permissions on this folder
  224. Status = AfpSetAfpPermissions(hNewDir.fsh_FileHandle,
  225. DIR_BITMAP_OWNERID |
  226. DIR_BITMAP_GROUPID |
  227. DIR_BITMAP_ACCESSRIGHTS,
  228. pFdParm);
  229. AfpFreeMemory(pFdParm);
  230. }
  231. else
  232. {
  233. Status = AFP_ERR_MISC;
  234. }
  235. if (!NT_SUCCESS(Status))
  236. {
  237. AfpIoMarkFileForDelete(&hNewDir,
  238. pVolDesc,
  239. &PME.pme_FullPath,
  240. InRoot ? NULL : &PME.pme_ParentPath);
  241. break;
  242. }
  243. }
  244. #endif
  245. // Add this entry to the IdDb
  246. pNewDfe = AfpAddDfEntry(pVolDesc,
  247. PME.pme_pDfeParent,
  248. &PME.pme_UTail,
  249. True,
  250. 0);
  251. if (pNewDfe != NULL)
  252. {
  253. // If mac creates a dir we want it to show up as already
  254. // enumerated in the ID database since new things can only
  255. // be added after this.
  256. DFE_MARK_CHILDREN_PRESENT(pNewDfe);
  257. afpinfo.afpi_Id = pNewDfe->dfe_AfpId;
  258. // !!!HACK ALERT!!!
  259. // At this point we are pretty much done i.e. the create has succeeded
  260. // and we can return doing the rest of the work post-reply. Any errors
  261. // from now on SHOULD BE IGNORED. Also NO REFERENCE SHOULD BE MADE TO
  262. // the PSda & pConnDesc. Status should not be changed either. Also
  263. // reference the Volume for good measure. It cannot fail !!!
  264. AfpVolumeReference(pVolDesc);
  265. pSda->sda_ReplySize = SIZE_RESPPKT;
  266. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  267. PUTDWORD2DWORD(pRspPkt->__DirId, pNewDfe->dfe_AfpId);
  268. AfpCompleteApiProcessing(pSda, Status);
  269. Status = AFP_ERR_EXTENDED;
  270. // Create the AfpInfo stream and cache the afpinfo
  271. if (!NT_SUCCESS(AfpCreateAfpInfoStream(pVolDesc,
  272. &hNewDir,
  273. afpinfo.afpi_Id,
  274. True,
  275. NULL,
  276. &PME.pme_FullPath,
  277. &afpinfo,
  278. &hAfpInfo)))
  279. {
  280. // If we fail to add the AFP_AfpInfo stream, we must
  281. // rewind back to the original state. i.e. delete
  282. // the directory we just created, and remove it from
  283. // the Id database.
  284. AfpIoMarkFileForDelete(&hNewDir,
  285. pVolDesc,
  286. &PME.pme_FullPath,
  287. InRoot ? NULL : &PME.pme_ParentPath);
  288. AfpDeleteDfEntry(pVolDesc, pNewDfe);
  289. }
  290. else
  291. {
  292. DWORD Attr;
  293. // Get the rest of the File info, and cache it
  294. PostStatus = AfpIoQueryTimesnAttr(&hNewDir,
  295. &pNewDfe->dfe_CreateTime,
  296. &pNewDfe->dfe_LastModTime,
  297. &Attr);
  298. ASSERT(NT_SUCCESS(PostStatus));
  299. if (NT_SUCCESS(PostStatus))
  300. {
  301. pNewDfe->dfe_NtAttr = (USHORT)Attr & FILE_ATTRIBUTE_VALID_FLAGS;
  302. DFE_UPDATE_CACHED_AFPINFO(pNewDfe, &afpinfo);
  303. AfpVolumeSetModifiedTime(pVolDesc);
  304. AfpCacheParentModTime(pVolDesc, NULL,
  305. &PME.pme_ParentPath,
  306. pNewDfe->dfe_Parent,
  307. 0);
  308. }
  309. else
  310. {
  311. AfpIoMarkFileForDelete(&hNewDir,
  312. pVolDesc,
  313. &PME.pme_FullPath,
  314. InRoot ? NULL : &PME.pme_ParentPath);
  315. AfpDeleteDfEntry(pVolDesc, pNewDfe);
  316. }
  317. }
  318. }
  319. AfpVolumeDereference(pVolDesc);
  320. } while (False);
  321. AfpSwmrRelease(&pVolDesc->vds_IdDbAccessLock);
  322. if (hNewDir.fsh_FileHandle != NULL)
  323. AfpIoClose(&hNewDir);
  324. if (hAfpInfo.fsh_FileHandle != NULL)
  325. AfpIoClose(&hAfpInfo);
  326. if ((PME.pme_FullPath.Buffer != NULL) &&
  327. (PME.pme_FullPath.Buffer != PathBuf))
  328. AfpFreeMemory(PME.pme_FullPath.Buffer);
  329. return Status;
  330. }
  331. /*** AfpFspDispEnumerate
  332. *
  333. * This is the worker routine for the AfpEnumerate API.
  334. *
  335. * The request packet is represented below.
  336. *
  337. * sda_ReqBlock PCONNDESC pConnDesc
  338. * sda_ReqBlock DWORD ParentId
  339. * sda_ReqBlock DWORD File Bitmap
  340. * sda_ReqBlock DWORD Dir Bitmap
  341. * sda_ReqBlock LONG Request Count
  342. * sda_ReqBlock LONG Start Index
  343. * sda_ReqBlock LONG Max Reply Size
  344. * sda_Name1 ANSI_STRING DirName
  345. */
  346. AFPSTATUS FASTCALL
  347. AfpFspDispEnumerate(
  348. IN PSDA pSda
  349. )
  350. {
  351. AFPSTATUS Status = AFP_ERR_PARAM;
  352. PATHMAPENTITY PME;
  353. PVOLDESC pVolDesc;
  354. FILEDIRPARM FDParm;
  355. DWORD BitmapF, BitmapD, BitmapI = 0;
  356. LONG i = 0, ActCount = 0, ReqCnt = 0;
  357. PENUMDIR pEnumDir;
  358. PEIT pEit;
  359. SHORT CleanupFlags = 0;
  360. SHORT BaseLenD = 0, BaseLenF = 0;
  361. USHORT SizeUsed;
  362. BOOLEAN FreeReplyBuf = False;
  363. struct _RequestPacket
  364. {
  365. PCONNDESC _pConnDesc;
  366. DWORD _ParentId;
  367. DWORD _FileBitmap;
  368. DWORD _DirBitmap;
  369. LONG _ReqCnt;
  370. LONG _Index;
  371. LONG _ReplySize;
  372. };
  373. struct _ResponsePacket
  374. {
  375. BYTE __FileBitmap[2];
  376. BYTE __DirBitmap[2];
  377. BYTE __EnumCount[2];
  378. };
  379. typedef struct _EnumEntityPkt
  380. {
  381. BYTE __Length;
  382. BYTE __FileDirFlag;
  383. // The real parameters follow
  384. } EEP, *PEEP;
  385. PEEP pEep;
  386. PAGED_CODE( );
  387. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  388. ("AfpFspDispEnumerate: Entered\n"));
  389. ASSERT(VALID_CONNDESC(pReqPkt->_pConnDesc));
  390. pVolDesc = pReqPkt->_pConnDesc->cds_pVolDesc;
  391. ASSERT(VALID_VOLDESC(pVolDesc));
  392. if ((pReqPkt->_ReqCnt <= 0) ||
  393. (pReqPkt->_Index <= 0) ||
  394. (pReqPkt->_ReplySize <= 0))
  395. {
  396. return AFP_ERR_PARAM;
  397. }
  398. BitmapF = pReqPkt->_FileBitmap;
  399. BitmapD = pReqPkt->_DirBitmap;
  400. if ((BitmapF == 0) && (BitmapD == 0))
  401. {
  402. return AFP_ERR_BITMAP;
  403. }
  404. if (BitmapD & DIR_BITMAP_ACCESSRIGHTS)
  405. {
  406. BitmapI = FD_INTERNAL_BITMAP_OPENACCESS_READCTRL;
  407. }
  408. do
  409. {
  410. AfpInitializeFDParms(&FDParm);
  411. AfpInitializePME(&PME, 0, NULL);
  412. // This is the size of the buffer needed (plus the name) for enumerating
  413. // one entity. We do not want to do this many times.
  414. FDParm._fdp_Flags = DFE_FLAGS_DIR;
  415. if (BitmapD != 0)
  416. BaseLenD = ((SHORT)AfpGetFileDirParmsReplyLength(&FDParm, BitmapD) +
  417. sizeof(EEP));
  418. FDParm._fdp_Flags = 0;
  419. if (BitmapF != 0)
  420. BaseLenF = ((SHORT)AfpGetFileDirParmsReplyLength(&FDParm, BitmapF) +
  421. sizeof(EEP));
  422. if ((Status = AfpEnumerate(pReqPkt->_pConnDesc,
  423. pReqPkt->_ParentId,
  424. &pSda->sda_Name1,
  425. BitmapF,
  426. BitmapD,
  427. pSda->sda_PathType,
  428. 0,
  429. &pEnumDir)) != AFP_ERR_NONE)
  430. break;
  431. if (pEnumDir->ed_ChildCount < pReqPkt->_Index)
  432. {
  433. Status = AFP_ERR_OBJECT_NOT_FOUND;
  434. break;
  435. }
  436. ReqCnt = (DWORD)pReqPkt->_ReqCnt;
  437. if (ReqCnt > (pEnumDir->ed_ChildCount - pEnumDir->ed_BadCount - pReqPkt->_Index + 1))
  438. ReqCnt = (pEnumDir->ed_ChildCount - pEnumDir->ed_BadCount - pReqPkt->_Index + 1);
  439. // We have enumerated the directory and now have afp ids of all the
  440. // children. Allocate the reply buffer
  441. pSda->sda_ReplySize = (USHORT)pReqPkt->_ReplySize;
  442. AfpIOAllocBackFillBuffer(pSda);
  443. if (pSda->sda_ReplyBuf == NULL)
  444. {
  445. pSda->sda_ReplySize = 0;
  446. Status = AFP_ERR_MISC;
  447. break;
  448. }
  449. #if DBG
  450. AfpPutGuardSignature(pSda);
  451. #endif
  452. FreeReplyBuf = True;
  453. pEep = (PEEP)(pSda->sda_ReplyBuf + SIZE_RESPPKT);
  454. // For each of the enumerated entities, get the requested parameters
  455. // and pack it in the replybuf.
  456. // We also do not want to impersonate the user here. A Mac user expects
  457. // to see belted items as opposed to invisible ones.
  458. SizeUsed = SIZE_RESPPKT;
  459. pEit = &pEnumDir->ed_pEit[pReqPkt->_Index + pEnumDir->ed_BadCount - 1];
  460. for (i = 0, ActCount = 0; (i < ReqCnt); i++, pEit++)
  461. {
  462. SHORT Len;
  463. DWORD Bitmap;
  464. BOOLEAN NeedHandle = False;
  465. Bitmap = BitmapF;
  466. Len = BaseLenF;
  467. if (pEit->eit_Flags & DFE_DIR)
  468. {
  469. Bitmap = BitmapD | BitmapI;
  470. Len = BaseLenD;
  471. if (IS_VOLUME_NTFS(pVolDesc) &&
  472. (Bitmap & (DIR_BITMAP_ACCESSRIGHTS |
  473. DIR_BITMAP_OWNERID |
  474. DIR_BITMAP_GROUPID)))
  475. {
  476. NeedHandle = True;
  477. }
  478. }
  479. FDParm._fdp_LongName.Length = FDParm._fdp_ShortName.Length = 0;
  480. Status = AfpMapAfpIdForLookup(pReqPkt->_pConnDesc,
  481. pEit->eit_Id,
  482. pEit->eit_Flags,
  483. Bitmap |
  484. FD_BITMAP_ATTR |
  485. FD_INTERNAL_BITMAP_SKIP_IMPERSONATION,
  486. NeedHandle ? &PME : NULL,
  487. &FDParm);
  488. // This can fail if the enitity gets deleted in the interim or if the
  489. // user has no access to this entity.
  490. // An error here should not be treated as such.
  491. // Reset the Status to none since we do not want to fall out
  492. // with this error code
  493. if (!NT_SUCCESS(Status))
  494. {
  495. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_ERR,
  496. ("AfpFspDispEnumerate: Dropping id %ld\n", pEit->eit_Id));
  497. pEnumDir->ed_BadCount ++;
  498. Status = AFP_ERR_NONE;
  499. continue;
  500. }
  501. if (NeedHandle)
  502. {
  503. AfpIoClose(&PME.pme_Handle); // Close the handle to the entity
  504. }
  505. Bitmap &= ~BitmapI;
  506. if (Bitmap & FD_BITMAP_LONGNAME)
  507. Len += FDParm._fdp_LongName.Length;
  508. if (Bitmap & FD_BITMAP_SHORTNAME)
  509. Len += FDParm._fdp_ShortName.Length;
  510. Len = EVENALIGN(Len);
  511. if (Len > (pSda->sda_ReplySize - SizeUsed))
  512. {
  513. if (SizeUsed == SIZE_RESPPKT)
  514. {
  515. Status = AFP_ERR_PARAM;
  516. }
  517. break;
  518. }
  519. PUTSHORT2BYTE(&pEep->__Length, Len);
  520. pEep->__FileDirFlag = IsDir(&FDParm) ?
  521. FILEDIR_FLAG_DIR : FILEDIR_FLAG_FILE;
  522. AfpPackFileDirParms(&FDParm, Bitmap, (PBYTE)pEep + sizeof(EEP));
  523. pEep = (PEEP)((PBYTE)pEep + Len);
  524. SizeUsed += Len;
  525. ActCount ++;
  526. }
  527. if (Status == AFP_ERR_NONE)
  528. FreeReplyBuf = False;
  529. } while (False);
  530. if (FreeReplyBuf || (ActCount == 0))
  531. {
  532. AfpIOFreeBackFillBuffer(pSda);
  533. }
  534. if (Status == AFP_ERR_NONE)
  535. {
  536. if (ActCount > 0)
  537. {
  538. PUTSHORT2SHORT(&pRspPkt->__FileBitmap, BitmapF);
  539. PUTSHORT2SHORT(&pRspPkt->__DirBitmap, BitmapD);
  540. PUTSHORT2SHORT(&pRspPkt->__EnumCount, ActCount);
  541. pSda->sda_ReplySize = SizeUsed;
  542. }
  543. else Status = AFP_ERR_OBJECT_NOT_FOUND;
  544. }
  545. if (Status != AFP_ERR_NONE)
  546. {
  547. if (pReqPkt->_pConnDesc->cds_pEnumDir != NULL)
  548. {
  549. AfpFreeMemory(pReqPkt->_pConnDesc->cds_pEnumDir);
  550. pReqPkt->_pConnDesc->cds_pEnumDir = NULL;
  551. }
  552. }
  553. return Status;
  554. }
  555. /*** AfpFspDispSetDirParms
  556. *
  557. * This is the worker routine for the AfpSetDirParms API.
  558. *
  559. * The request packet is represented below.
  560. *
  561. * sda_ReqBlock PCONNDESC pConnDesc
  562. * sda_ReqBlock DWORD ParentId
  563. * sda_ReqBlock DWORD Dir Bitmap
  564. * sda_Name1 ANSI_STRING Path
  565. * sda_Name2 BLOCK Dir Parameters
  566. */
  567. AFPSTATUS FASTCALL
  568. AfpFspDispSetDirParms(
  569. IN PSDA pSda
  570. )
  571. {
  572. FILEDIRPARM FDParm;
  573. PATHMAPENTITY PME, PMEfile;
  574. PVOLDESC pVolDesc;
  575. WCHAR PathBuf[BIG_PATH_LEN];
  576. DWORD Bitmap,
  577. BitmapI = FD_INTERNAL_BITMAP_RETURN_PMEPATHS |
  578. FD_INTERNAL_BITMAP_OPENACCESS_RW_ATTR;
  579. AFPSTATUS Status = AFP_ERR_PARAM;
  580. struct _RequestPacket
  581. {
  582. PCONNDESC _pConnDesc;
  583. DWORD _ParentId;
  584. DWORD _Bitmap;
  585. };
  586. PAGED_CODE( );
  587. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  588. ("AfpFspDispSetDirParms: Entered\n"));
  589. ASSERT(VALID_CONNDESC(pReqPkt->_pConnDesc));
  590. pVolDesc = pReqPkt->_pConnDesc->cds_pVolDesc;
  591. ASSERT(VALID_VOLDESC(pVolDesc));
  592. Bitmap = pReqPkt->_Bitmap;
  593. AfpInitializeFDParms(&FDParm);
  594. AfpInitializePME(&PME, sizeof(PathBuf), PathBuf);
  595. do
  596. {
  597. if (Bitmap & (DIR_BITMAP_OWNERID |
  598. DIR_BITMAP_GROUPID |
  599. DIR_BITMAP_ACCESSRIGHTS |
  600. FD_BITMAP_ATTR))
  601. {
  602. BitmapI |= (pSda->sda_ClientType == SDA_CLIENT_ADMIN) ?
  603. (FD_INTERNAL_BITMAP_OPENACCESS_ADMINSET |
  604. DIR_BITMAP_OFFSPRINGS |
  605. FD_INTERNAL_BITMAP_RETURN_PMEPATHS) :
  606. (FD_INTERNAL_BITMAP_OPENACCESS_RWCTRL |
  607. FD_INTERNAL_BITMAP_RETURN_PMEPATHS |
  608. DIR_BITMAP_OFFSPRINGS |
  609. DIR_BITMAP_DIRID |
  610. DIR_BITMAP_ACCESSRIGHTS |
  611. DIR_BITMAP_OWNERID |
  612. DIR_BITMAP_GROUPID);
  613. }
  614. Status = AfpMapAfpPathForLookup(pReqPkt->_pConnDesc,
  615. pReqPkt->_ParentId,
  616. &pSda->sda_Name1,
  617. pSda->sda_PathType,
  618. DFE_DIR,
  619. Bitmap | BitmapI,
  620. &PME,
  621. &FDParm);
  622. if (!NT_SUCCESS(Status))
  623. {
  624. PME.pme_Handle.fsh_FileHandle = NULL;
  625. break;
  626. }
  627. // Check for Network Trash Folder and do not change its permissions
  628. if ((FDParm._fdp_AfpId == AFP_ID_NETWORK_TRASH) &&
  629. (Bitmap & (DIR_BITMAP_OWNERID |
  630. DIR_BITMAP_GROUPID |
  631. DIR_BITMAP_ACCESSRIGHTS)))
  632. {
  633. Bitmap &= ~(DIR_BITMAP_OWNERID |
  634. DIR_BITMAP_GROUPID |
  635. DIR_BITMAP_ACCESSRIGHTS);
  636. if (Bitmap == 0)
  637. {
  638. // We are not setting anything else, return success
  639. Status = STATUS_SUCCESS;
  640. break;
  641. }
  642. }
  643. // Make sure user has the necessary rights to change any of this
  644. if (pSda->sda_ClientType == SDA_CLIENT_ADMIN)
  645. {
  646. FDParm._fdp_UserRights = DIR_ACCESS_ALL | DIR_ACCESS_OWNER;
  647. }
  648. // If attributes are to be set, the check for access is done during unpacking
  649. else if ((Bitmap & (DIR_BITMAP_OWNERID |
  650. DIR_BITMAP_GROUPID |
  651. DIR_BITMAP_ACCESSRIGHTS)) &&
  652. !(FDParm._fdp_UserRights & DIR_ACCESS_OWNER))
  653. {
  654. Status = AFP_ERR_ACCESS_DENIED;
  655. break;
  656. }
  657. if ((Status = AfpUnpackFileDirParms(pSda->sda_Name2.Buffer,
  658. (LONG)pSda->sda_Name2.Length,
  659. &Bitmap,
  660. &FDParm)) != AFP_ERR_NONE)
  661. break;
  662. if (Bitmap != 0)
  663. {
  664. if ((Bitmap & FD_BITMAP_ATTR) &&
  665. (FDParm._fdp_Attr & (FILE_BITMAP_ATTR_MULTIUSER |
  666. FILE_BITMAP_ATTR_DATAOPEN |
  667. FILE_BITMAP_ATTR_RESCOPEN |
  668. FILE_BITMAP_ATTR_COPYPROT)))
  669. {
  670. Status = AFP_ERR_PARAM;
  671. break;
  672. }
  673. Status = AfpSetFileDirParms(pVolDesc,
  674. &PME,
  675. Bitmap,
  676. &FDParm);
  677. if (!NT_SUCCESS(Status))
  678. {
  679. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  680. ("AfpFspDispSetDirParms: AfpSetFileDirParms returned %ld\n", Status));
  681. break;
  682. }
  683. // Close the directory handle
  684. AfpIoClose(&PME.pme_Handle);
  685. // If any permissions are being changed, then apply them to all files within
  686. // this directory. Start off by enumerating the files in the directory and
  687. // then walk the list applying to each individual file.
  688. if ((Bitmap & (DIR_BITMAP_OWNERID |
  689. DIR_BITMAP_GROUPID |
  690. DIR_BITMAP_ACCESSRIGHTS)) &&
  691. (FDParm._fdp_FileCount != 0))
  692. {
  693. PENUMDIR pEnumDir;
  694. PEIT pEit;
  695. FILEDIRPARM FileParm;
  696. ANSI_STRING DummyName;
  697. LONG i;
  698. // Do not treat any of the following as errors from now on.
  699. // Quitely terminate
  700. AfpInitializeFDParms(&FileParm);
  701. AfpSetEmptyAnsiString(&DummyName, 1, "");
  702. if (AfpEnumerate(pReqPkt->_pConnDesc,
  703. FDParm._fdp_AfpId,
  704. &DummyName,
  705. 1, // Some non-zero value
  706. 0,
  707. AFP_LONGNAME,
  708. DFE_FILE,
  709. &pEnumDir) != AFP_ERR_NONE)
  710. break;
  711. FDParm._fdp_Flags &= ~DFE_FLAGS_DIR;
  712. AfpInitializePME(&PMEfile, 0, NULL);
  713. for (i = 0, pEit = &pEnumDir->ed_pEit[0];
  714. i < pEnumDir->ed_ChildCount; i++, pEit++)
  715. {
  716. AFPSTATUS Rc;
  717. Rc = AfpMapAfpIdForLookup(pReqPkt->_pConnDesc,
  718. pEit->eit_Id,
  719. DFE_FILE,
  720. FD_INTERNAL_BITMAP_OPENACCESS_RWCTRL |
  721. FD_BITMAP_LONGNAME,
  722. &PMEfile,
  723. &FileParm);
  724. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  725. ("AfpFspDispSetDirParms: AfpMapAfpIdForLookup returned %ld\n", Rc));
  726. if (Rc != AFP_ERR_NONE)
  727. continue;
  728. AfpSetAfpPermissions(PMEfile.pme_Handle.fsh_FileHandle,
  729. Bitmap,
  730. &FDParm);
  731. AfpIoClose(&PMEfile.pme_Handle);
  732. DBGPRINT(DBG_COMP_AFPAPI_DIR, DBG_LEVEL_INFO,
  733. ("AfpFspDispSetDirParms: AfpSetAfpPermissions returned %ld\n", Rc));
  734. }
  735. if (pReqPkt->_pConnDesc->cds_pEnumDir != NULL)
  736. {
  737. AfpFreeMemory(pReqPkt->_pConnDesc->cds_pEnumDir);
  738. pReqPkt->_pConnDesc->cds_pEnumDir = NULL;
  739. }
  740. }
  741. }
  742. } while (False);
  743. // NOTE: This is also called by the admin side so do not try the early reply trick
  744. // here. If it does get important to do it, then check for client type.
  745. if (PME.pme_Handle.fsh_FileHandle != NULL)
  746. AfpIoClose(&PME.pme_Handle);
  747. if ((PME.pme_FullPath.Buffer != NULL) &&
  748. (PME.pme_FullPath.Buffer != PathBuf))
  749. {
  750. AfpFreeMemory(PME.pme_FullPath.Buffer);
  751. }
  752. return Status;
  753. }