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.

1491 lines
38 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fdparm.c
  5. Abstract:
  6. This module contains the routines for handling file parameters.
  7. Author:
  8. Jameel Hyder (microsoft!jameelh)
  9. Revision History:
  10. 25 Apr 1992 Initial Version
  11. Notes: Tab stop: 4
  12. --*/
  13. #define _FDPARM_LOCALS
  14. #define FILENUM FILE_FDPARM
  15. #include <seposix.h>
  16. #include <afp.h>
  17. #include <fdparm.h>
  18. #include <pathmap.h>
  19. #include <afpinfo.h>
  20. #include <client.h>
  21. #include <access.h>
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text( PAGE, AfpGetFileDirParmsReplyLength)
  24. #pragma alloc_text( PAGE, AfpPackFileDirParms)
  25. #pragma alloc_text( PAGE, AfpUnpackFileDirParms)
  26. #pragma alloc_text( PAGE, AfpUnpackCatSearchSpecs)
  27. #pragma alloc_text( PAGE, AfpSetFileDirParms)
  28. #pragma alloc_text( PAGE, AfpQuerySecurityIdsAndRights)
  29. #pragma alloc_text( PAGE, AfpConvertNTAttrToAfpAttr)
  30. #pragma alloc_text( PAGE, AfpConvertAfpAttrToNTAttr)
  31. #pragma alloc_text( PAGE, AfpNormalizeAfpAttr)
  32. #pragma alloc_text( PAGE, AfpMapFDBitmapOpenAccess)
  33. #pragma alloc_text( PAGE, AfpCheckForInhibit)
  34. #pragma alloc_text( PAGE, AfpIsCatSearchMatch)
  35. #endif
  36. /*** AfpGetFileDirParmsReplyLength
  37. *
  38. * Compute the size of buffer required to copy the file parameters based
  39. * on the bitmap.
  40. */
  41. USHORT
  42. AfpGetFileDirParmsReplyLength(
  43. IN PFILEDIRPARM pFDParm,
  44. IN DWORD Bitmap
  45. )
  46. {
  47. LONG i;
  48. USHORT Size = 0;
  49. static BYTE Bitmap2Size[14] =
  50. {
  51. sizeof(USHORT), // Attributes
  52. sizeof(DWORD), // Parent DirId
  53. sizeof(DWORD), // Create Date
  54. sizeof(DWORD), // Mod. Date
  55. sizeof(DWORD), // Backup Date
  56. sizeof(FINDERINFO),
  57. sizeof(USHORT) + sizeof(BYTE), // Long Name
  58. sizeof(USHORT) + sizeof(BYTE), // Short Name
  59. sizeof(DWORD), // DirId/FileNum
  60. sizeof(DWORD), // DataForkLength/Offspring Count
  61. sizeof(DWORD), // RescForkLength/Owner Id
  62. sizeof(DWORD), // Group Id
  63. sizeof(DWORD), // Access Rights
  64. sizeof(PRODOSINFO) // ProDos Info
  65. };
  66. PAGED_CODE( );
  67. ASSERT ((Bitmap & ~DIR_BITMAP_MASK) == 0);
  68. if (Bitmap & FD_BITMAP_LONGNAME)
  69. Size += pFDParm->_fdp_LongName.Length;
  70. if (Bitmap & FD_BITMAP_SHORTNAME)
  71. Size += pFDParm->_fdp_ShortName.Length;
  72. if (IsDir(pFDParm) && (Bitmap & DIR_BITMAP_OFFSPRINGS))
  73. Size -= sizeof(USHORT);
  74. for (i = 0; Bitmap; i++)
  75. {
  76. if (Bitmap & 1)
  77. Size += (USHORT)Bitmap2Size[i];
  78. Bitmap >>= 1;
  79. }
  80. return Size;
  81. }
  82. /*** AfpPackFileDirParms
  83. *
  84. * Pack file or directory parameters into the reply buffer in on-the-wire
  85. * format.
  86. */
  87. VOID
  88. AfpPackFileDirParms(
  89. IN PFILEDIRPARM pFDParm,
  90. IN DWORD Bitmap,
  91. IN PBYTE pReplyBuf
  92. )
  93. {
  94. LONG Offset = 0;
  95. LONG LongNameOff, ShortNameOff;
  96. PAGED_CODE( );
  97. if (Bitmap & FD_BITMAP_ATTR)
  98. {
  99. PUTSHORT2SHORT(pReplyBuf + Offset, pFDParm->_fdp_Attr);
  100. Offset += sizeof(USHORT);
  101. }
  102. if (Bitmap & FD_BITMAP_PARENT_DIRID)
  103. {
  104. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_ParentId);
  105. Offset += sizeof(DWORD);
  106. }
  107. if (Bitmap & FD_BITMAP_CREATETIME)
  108. {
  109. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_CreateTime);
  110. Offset += sizeof(DWORD);
  111. }
  112. if (Bitmap & FD_BITMAP_MODIFIEDTIME)
  113. {
  114. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_ModifiedTime);
  115. Offset += sizeof(DWORD);
  116. }
  117. if (Bitmap & FD_BITMAP_BACKUPTIME)
  118. {
  119. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_BackupTime);
  120. Offset += sizeof(DWORD);
  121. }
  122. if (Bitmap & FD_BITMAP_FINDERINFO)
  123. {
  124. if ((Bitmap & FD_BITMAP_ATTR) && (pFDParm->_fdp_Attr & FD_BITMAP_ATTR_INVISIBLE))
  125. pFDParm->_fdp_FinderInfo.fd_Attr1 |= FINDER_FLAG_INVISIBLE;
  126. RtlCopyMemory(pReplyBuf + Offset, (PBYTE)&pFDParm->_fdp_FinderInfo,
  127. sizeof(FINDERINFO));
  128. Offset += sizeof(FINDERINFO);
  129. }
  130. // Note the offset where the pointers to names will go. We'll have to
  131. // Fill it up later.
  132. if (Bitmap & FD_BITMAP_LONGNAME)
  133. {
  134. LongNameOff = Offset;
  135. Offset += sizeof(USHORT);
  136. }
  137. if (Bitmap & FD_BITMAP_SHORTNAME)
  138. {
  139. ShortNameOff = Offset;
  140. Offset += sizeof(USHORT);
  141. }
  142. // FileNum for files and DirId for Directories are in the same place
  143. if (Bitmap & FILE_BITMAP_FILENUM)
  144. {
  145. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_AfpId);
  146. Offset += sizeof(DWORD);
  147. }
  148. if (IsDir(pFDParm))
  149. {
  150. // Directory parameters
  151. if (Bitmap & DIR_BITMAP_OFFSPRINGS)
  152. {
  153. DWORD OffSpring;
  154. OffSpring = pFDParm->_fdp_FileCount + pFDParm->_fdp_DirCount;
  155. PUTDWORD2SHORT(pReplyBuf + Offset, OffSpring);
  156. Offset += sizeof(USHORT);
  157. }
  158. if (Bitmap & DIR_BITMAP_OWNERID)
  159. {
  160. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_OwnerId);
  161. Offset += sizeof(DWORD);
  162. }
  163. if (Bitmap & DIR_BITMAP_GROUPID)
  164. {
  165. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_GroupId);
  166. Offset += sizeof(DWORD);
  167. }
  168. if (Bitmap & DIR_BITMAP_ACCESSRIGHTS)
  169. {
  170. DWORD AccessInfo;
  171. AccessInfo = (pFDParm->_fdp_OwnerRights << OWNER_RIGHTS_SHIFT) +
  172. (pFDParm->_fdp_GroupRights << GROUP_RIGHTS_SHIFT) +
  173. (pFDParm->_fdp_WorldRights << WORLD_RIGHTS_SHIFT) +
  174. (pFDParm->_fdp_UserRights << USER_RIGHTS_SHIFT);
  175. PUTDWORD2DWORD(pReplyBuf + Offset, AccessInfo & ~OWNER_BITS_ALL);
  176. Offset += sizeof(DWORD);
  177. }
  178. }
  179. else
  180. {
  181. if (Bitmap & FILE_BITMAP_DATALEN)
  182. {
  183. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_DataForkLen);
  184. Offset += sizeof(DWORD);
  185. }
  186. // Resc Length for files and Owner Id for Directories are in the same place
  187. if (Bitmap & FILE_BITMAP_RESCLEN)
  188. {
  189. PUTDWORD2DWORD(pReplyBuf + Offset, pFDParm->_fdp_RescForkLen);
  190. Offset += sizeof(DWORD);
  191. }
  192. }
  193. if (Bitmap & FD_BITMAP_PRODOSINFO)
  194. {
  195. RtlCopyMemory(pReplyBuf + Offset, (PBYTE)&pFDParm->_fdp_ProDosInfo,
  196. sizeof(PRODOSINFO));
  197. Offset += sizeof(PRODOSINFO);
  198. }
  199. if (Bitmap & FD_BITMAP_LONGNAME)
  200. {
  201. ASSERT(pFDParm->_fdp_LongName.Length <= AFP_LONGNAME_LEN);
  202. PUTDWORD2SHORT(pReplyBuf + LongNameOff, Offset);
  203. PUTSHORT2BYTE(pReplyBuf + Offset, pFDParm->_fdp_LongName.Length);
  204. RtlCopyMemory(pReplyBuf + Offset + sizeof(BYTE),
  205. pFDParm->_fdp_LongName.Buffer,
  206. pFDParm->_fdp_LongName.Length);
  207. Offset += pFDParm->_fdp_LongName.Length + sizeof(BYTE);
  208. }
  209. if (Bitmap & FD_BITMAP_SHORTNAME)
  210. {
  211. ASSERT(pFDParm->_fdp_ShortName.Length <= AFP_SHORTNAME_LEN);
  212. PUTDWORD2SHORT(pReplyBuf + ShortNameOff, Offset);
  213. PUTSHORT2BYTE(pReplyBuf + Offset, pFDParm->_fdp_ShortName.Length);
  214. RtlCopyMemory(pReplyBuf + Offset + sizeof(BYTE),
  215. pFDParm->_fdp_ShortName.Buffer,
  216. pFDParm->_fdp_ShortName.Length);
  217. Offset += pFDParm->_fdp_ShortName.Length + sizeof(BYTE);
  218. }
  219. if (Offset & 1)
  220. *(pReplyBuf + Offset) = 0;
  221. }
  222. /*** AfpUnpackFileDirParms
  223. *
  224. * Unpack the information from the on-the-wire format to the FileDirParm
  225. * structure. Only the fields that can be set are looked at. The bitmaps
  226. * are validated by the caller.
  227. *
  228. * OPTIMIZATION: The finder is notorious for setting things needlessly.
  229. * We figure out if what is being set is same as what it
  230. * is currently and if it is just clear that bit.
  231. */
  232. AFPSTATUS
  233. AfpUnpackFileDirParms(
  234. IN PBYTE pBuffer,
  235. IN LONG Length,
  236. IN PDWORD pBitmap,
  237. OUT PFILEDIRPARM pFDParm
  238. )
  239. {
  240. DWORD Bitmap = *pBitmap;
  241. AFPTIME ModTime;
  242. USHORT Offset = 0;
  243. BOOLEAN SetModTime = False;
  244. AFPSTATUS Status = AFP_ERR_NONE;
  245. PAGED_CODE( );
  246. do
  247. {
  248. if ((LONG)AfpGetFileDirParmsReplyLength(pFDParm, *pBitmap) > Length)
  249. {
  250. DBGPRINT(DBG_COMP_AFPAPI_FD, DBG_LEVEL_FATAL,
  251. ("UnpackFileDirParms: Buffer not large enough!\n"));
  252. DBGBRK(DBG_LEVEL_FATAL);
  253. Status = AFP_ERR_PARAM;
  254. break;
  255. }
  256. if (Bitmap & FD_BITMAP_ATTR)
  257. {
  258. USHORT OldAttr, NewAttr;
  259. USHORT Set;
  260. GETSHORT2SHORT(&NewAttr, pBuffer+Offset);
  261. // keep track of if client wants to set bits or clear bits
  262. Set = (NewAttr & FD_BITMAP_ATTR_SET);
  263. // take off the 'set' bit to isolate the requested bits
  264. NewAttr &= ~FD_BITMAP_ATTR_SET;
  265. // the current effective settings of attributes
  266. OldAttr = (pFDParm->_fdp_Attr & ~FD_BITMAP_ATTR_SET);
  267. if ((NewAttr != 0) &&
  268. (((Set != 0) && ((OldAttr ^ NewAttr) != 0)) ||
  269. ((Set == 0) && ((OldAttr & NewAttr) != 0))))
  270. {
  271. // becomes the new resultant AFP attributes after setting
  272. pFDParm->_fdp_EffectiveAttr = (Set != 0) ?
  273. (pFDParm->_fdp_Attr | NewAttr) :
  274. (pFDParm->_fdp_Attr & ~NewAttr);
  275. // changing a directory's inhibit and invisible attributes from
  276. // their current settings can only be done by the dir owner
  277. if (IsDir(pFDParm) &&
  278. ((pFDParm->_fdp_EffectiveAttr & DIR_BITMAP_ATTR_CHG_X_OWNER_ONLY) ^
  279. (pFDParm->_fdp_Attr & DIR_BITMAP_ATTR_CHG_X_OWNER_ONLY)) &&
  280. !(pFDParm->_fdp_UserRights & DIR_ACCESS_OWNER))
  281. {
  282. Status = AFP_ERR_ACCESS_DENIED;
  283. break;
  284. }
  285. // becomes attribute bits requested to be set/cleared
  286. pFDParm->_fdp_Attr = (NewAttr | Set);
  287. }
  288. else *pBitmap &= ~FD_BITMAP_ATTR;
  289. Offset += sizeof(USHORT);
  290. }
  291. if (Bitmap & FD_BITMAP_CREATETIME)
  292. {
  293. AFPTIME CreateTime;
  294. GETDWORD2DWORD(&CreateTime, pBuffer+Offset);
  295. if (CreateTime == pFDParm->_fdp_CreateTime)
  296. *pBitmap &= ~FD_BITMAP_CREATETIME;
  297. else pFDParm->_fdp_CreateTime = CreateTime;
  298. Offset += sizeof(DWORD);
  299. }
  300. if (Bitmap & FD_BITMAP_MODIFIEDTIME)
  301. {
  302. GETDWORD2DWORD(&ModTime, pBuffer+Offset);
  303. if (ModTime == pFDParm->_fdp_ModifiedTime)
  304. {
  305. *pBitmap &= ~FD_BITMAP_MODIFIEDTIME;
  306. SetModTime = True;
  307. }
  308. else
  309. {
  310. pFDParm->_fdp_ModifiedTime = ModTime;
  311. }
  312. Offset += sizeof(DWORD);
  313. }
  314. if (Bitmap & FD_BITMAP_BACKUPTIME)
  315. {
  316. AFPTIME BackupTime;
  317. GETDWORD2DWORD(&BackupTime, pBuffer+Offset);
  318. if (BackupTime == pFDParm->_fdp_BackupTime)
  319. *pBitmap &= ~FD_BITMAP_BACKUPTIME;
  320. else pFDParm->_fdp_BackupTime = BackupTime;
  321. Offset += sizeof(DWORD);
  322. }
  323. if (Bitmap & FD_BITMAP_FINDERINFO)
  324. {
  325. int i, rlo = -1, rhi = -1; // Range of bytes that are different
  326. PBYTE pSrc, pDst;
  327. pSrc = pBuffer + Offset;
  328. pDst = (PBYTE)(&pFDParm->_fdp_FinderInfo);
  329. for (i = 0; i < sizeof(FINDERINFO); i++)
  330. {
  331. if (*pSrc++ != *pDst++)
  332. {
  333. if (rlo == -1)
  334. rlo = i;
  335. else rhi = i;
  336. }
  337. }
  338. if ((rlo != -1) && (rhi == -1))
  339. rhi = rlo;
  340. // Optimization: if nothing has changed, avoid a copy
  341. if (rlo == -1)
  342. {
  343. *pBitmap &= ~FD_BITMAP_FINDERINFO;
  344. }
  345. else
  346. {
  347. RtlCopyMemory((PBYTE)&pFDParm->_fdp_FinderInfo,
  348. pBuffer+Offset,
  349. sizeof(FINDERINFO));
  350. }
  351. Offset += sizeof(FINDERINFO);
  352. }
  353. if (IsDir(pFDParm) &&
  354. (Bitmap & (DIR_BITMAP_OWNERID |
  355. DIR_BITMAP_GROUPID |
  356. DIR_BITMAP_ACCESSRIGHTS)))
  357. {
  358. if (Bitmap & DIR_BITMAP_OWNERID)
  359. {
  360. DWORD OwnerId;
  361. GETDWORD2DWORD(&OwnerId, pBuffer+Offset);
  362. if (pFDParm->_fdp_OwnerId == OwnerId)
  363. Bitmap &= ~DIR_BITMAP_OWNERID;
  364. else pFDParm->_fdp_OwnerId = OwnerId;
  365. Offset += sizeof(DWORD);
  366. }
  367. if (Bitmap & DIR_BITMAP_GROUPID)
  368. {
  369. DWORD GroupId;
  370. GETDWORD2DWORD(&GroupId, pBuffer+Offset);
  371. if (pFDParm->_fdp_GroupId == GroupId)
  372. Bitmap &= ~DIR_BITMAP_GROUPID;
  373. else pFDParm->_fdp_GroupId = GroupId;
  374. Offset += sizeof(DWORD);
  375. }
  376. if (Bitmap & DIR_BITMAP_ACCESSRIGHTS)
  377. {
  378. DWORD AccessInfo;
  379. GETDWORD2DWORD(&AccessInfo, pBuffer+Offset);
  380. pFDParm->_fdp_OwnerRights =
  381. (BYTE)((AccessInfo >> OWNER_RIGHTS_SHIFT) & DIR_ACCESS_ALL);
  382. pFDParm->_fdp_GroupRights =
  383. (BYTE)((AccessInfo >> GROUP_RIGHTS_SHIFT) & DIR_ACCESS_ALL);
  384. pFDParm->_fdp_WorldRights =
  385. (BYTE)((AccessInfo >> WORLD_RIGHTS_SHIFT) & DIR_ACCESS_ALL);
  386. Offset += sizeof(DWORD);
  387. }
  388. if (Bitmap & (DIR_BITMAP_OWNERID | DIR_BITMAP_GROUPID))
  389. Bitmap |= DIR_BITMAP_ACCESSRIGHTS;
  390. }
  391. if (Bitmap & FD_BITMAP_PRODOSINFO)
  392. {
  393. int i;
  394. PBYTE pSrc, pDst;
  395. pSrc = pBuffer + Offset;
  396. pDst = (PBYTE)(&pFDParm->_fdp_ProDosInfo);
  397. for (i = 0; i < sizeof(PRODOSINFO); i++)
  398. if (*pSrc++ != *pDst++)
  399. break;
  400. if (i == sizeof(PRODOSINFO))
  401. *pBitmap &= ~FD_BITMAP_PRODOSINFO;
  402. else RtlCopyMemory((PBYTE)&pFDParm->_fdp_ProDosInfo,
  403. pBuffer+Offset,
  404. sizeof(PRODOSINFO));
  405. // Offset += sizeof(PRODOSINFO);
  406. }
  407. } while (False);
  408. // If anything is being set and modified time was dropped because it was identical
  409. // to what is already on, set the bitmap so that it is restored after the change.
  410. if (SetModTime && *pBitmap)
  411. {
  412. *pBitmap |= FD_BITMAP_MODIFIEDTIME;
  413. }
  414. return Status;
  415. }
  416. /*** AfpSetFileDirParms
  417. *
  418. * This is the worker for AfpGetFileDirParms/AfpSetFileParms/AfpSetDirParms.
  419. * This is callable only in the worker's context.
  420. *
  421. * LOCKS: vds_IdDbAccessLock (SWMR, Exclusive);
  422. */
  423. AFPSTATUS
  424. AfpSetFileDirParms(
  425. IN PVOLDESC pVolDesc,
  426. IN PPATHMAPENTITY pPME,
  427. IN DWORD Bitmap,
  428. IN PFILEDIRPARM pFDParm
  429. )
  430. {
  431. AFPSTATUS Status = AFP_ERR_NONE;
  432. BOOLEAN CleanupLock = False, SetROAttr = False;
  433. PDFENTRY pDfEntry = NULL;
  434. PAGED_CODE( );
  435. do
  436. {
  437. ASSERT(IS_VOLUME_NTFS(pVolDesc));
  438. // NOTE: should we take the SWMR while we set permissions?
  439. if (IsDir(pFDParm))
  440. {
  441. if (Bitmap & (DIR_BITMAP_OWNERID |
  442. DIR_BITMAP_GROUPID |
  443. DIR_BITMAP_ACCESSRIGHTS))
  444. {
  445. Status = AfpSetAfpPermissions(pPME->pme_Handle.fsh_FileHandle,
  446. Bitmap,
  447. pFDParm);
  448. if (!NT_SUCCESS(Status))
  449. break;
  450. }
  451. }
  452. if (Bitmap & (FD_BITMAP_FINDERINFO |
  453. FD_BITMAP_PRODOSINFO |
  454. FD_BITMAP_ATTR |
  455. FD_BITMAP_BACKUPTIME |
  456. DIR_BITMAP_ACCESSRIGHTS |
  457. DIR_BITMAP_OWNERID |
  458. DIR_BITMAP_GROUPID |
  459. FD_BITMAP_CREATETIME |
  460. FD_BITMAP_MODIFIEDTIME |
  461. FD_BITMAP_ATTR))
  462. {
  463. AfpSwmrAcquireExclusive(&pVolDesc->vds_IdDbAccessLock);
  464. CleanupLock = True;
  465. }
  466. if (Bitmap & (FD_BITMAP_FINDERINFO |
  467. FD_BITMAP_PRODOSINFO |
  468. FD_BITMAP_ATTR |
  469. FD_BITMAP_BACKUPTIME |
  470. DIR_BITMAP_ACCESSRIGHTS))
  471. {
  472. // Will update the cached AfpInfo as well as the stream
  473. Status = AfpSetAfpInfo(&pPME->pme_Handle,
  474. Bitmap,
  475. pFDParm,
  476. pVolDesc,
  477. &pDfEntry);
  478. if (Status != AFP_ERR_NONE)
  479. break;
  480. }
  481. if (Bitmap & (FD_BITMAP_CREATETIME |
  482. FD_BITMAP_MODIFIEDTIME |
  483. FD_BITMAP_ATTR |
  484. DIR_BITMAP_ACCESSRIGHTS |
  485. DIR_BITMAP_OWNERID |
  486. DIR_BITMAP_GROUPID))
  487. {
  488. DWORD SetNtAttr = 0, ClrNtAttr = 0;
  489. // need to update the cached times too. If we didn't get the
  490. // pDfEntry back from setting some other AfpInfo, look it up now
  491. if (pDfEntry == NULL)
  492. {
  493. pDfEntry = AfpFindDfEntryById(pVolDesc,
  494. pFDParm->_fdp_AfpId,
  495. IsDir(pFDParm) ? DFE_DIR : DFE_FILE);
  496. if (pDfEntry == NULL)
  497. {
  498. Status = AFP_ERR_OBJECT_NOT_FOUND;
  499. break;
  500. }
  501. }
  502. if (Bitmap & FD_BITMAP_ATTR)
  503. {
  504. if (pFDParm->_fdp_Attr & FD_BITMAP_ATTR_SET)
  505. SetNtAttr = AfpConvertAfpAttrToNTAttr(pFDParm->_fdp_Attr);
  506. else
  507. ClrNtAttr = AfpConvertAfpAttrToNTAttr(pFDParm->_fdp_Attr);
  508. if (pFDParm->_fdp_Attr & (FD_BITMAP_ATTR_RENAMEINH |
  509. FD_BITMAP_ATTR_DELETEINH))
  510. {
  511. SetROAttr = True;
  512. }
  513. if ((SetNtAttr == 0) && (ClrNtAttr == 0))
  514. {
  515. // Since there is no attribute being set/cleared that
  516. // corresponds to any NT attribute, we can clear the
  517. // ATTR bitmap since we've already set the Mac specific
  518. // stuff in the DFE and Afpinfo.
  519. Bitmap &= ~FD_BITMAP_ATTR;
  520. }
  521. }
  522. if (Bitmap & (FD_BITMAP_CREATETIME |
  523. FD_BITMAP_MODIFIEDTIME |
  524. FD_BITMAP_ATTR))
  525. {
  526. ASSERT(pPME->pme_FullPath.Buffer != NULL);
  527. Status = AfpIoSetTimesnAttr(&pPME->pme_Handle,
  528. ((Bitmap & FD_BITMAP_CREATETIME) != 0) ?
  529. (PAFPTIME)&pFDParm->_fdp_CreateTime : NULL,
  530. (((Bitmap & FD_BITMAP_MODIFIEDTIME) != 0) || (SetROAttr)) ?
  531. (PAFPTIME)&pFDParm->_fdp_ModifiedTime : NULL,
  532. SetNtAttr, ClrNtAttr,
  533. pVolDesc,
  534. &pPME->pme_FullPath);
  535. }
  536. if (!NT_SUCCESS(Status))
  537. break;
  538. if (Bitmap & FD_BITMAP_CREATETIME)
  539. {
  540. pDfEntry->dfe_CreateTime =
  541. (AFPTIME)pFDParm->_fdp_CreateTime;
  542. }
  543. if (Bitmap & FD_BITMAP_MODIFIEDTIME)
  544. {
  545. AfpConvertTimeFromMacFormat(pFDParm->_fdp_ModifiedTime,
  546. &pDfEntry->dfe_LastModTime);
  547. }
  548. else if (IsDir(pFDParm) &&
  549. ((Bitmap & (DIR_BITMAP_OWNERID |
  550. DIR_BITMAP_GROUPID |
  551. DIR_BITMAP_ACCESSRIGHTS)) ||
  552. SetROAttr))
  553. {
  554. ASSERT(VALID_DFE(pDfEntry));
  555. // Setting permissions on a dir or changing its RO attribute
  556. // should update the modified time on the dir (as observed
  557. // on Appleshare 4.0)
  558. AfpIoChangeNTModTime(&pPME->pme_Handle,
  559. &pDfEntry->dfe_LastModTime);
  560. }
  561. if (Bitmap & FD_BITMAP_ATTR)
  562. {
  563. if (pFDParm->_fdp_Attr & FD_BITMAP_ATTR_SET)
  564. pDfEntry->dfe_NtAttr |= (USHORT)SetNtAttr;
  565. else pDfEntry->dfe_NtAttr &= ~((USHORT)ClrNtAttr);
  566. }
  567. }
  568. AfpVolumeSetModifiedTime(pVolDesc);
  569. } while (False);
  570. if (CleanupLock)
  571. {
  572. AfpSwmrRelease(&pVolDesc->vds_IdDbAccessLock);
  573. }
  574. return Status;
  575. }
  576. /*** AfpQuerySecurityIdsAndRights
  577. *
  578. * Find the owner id and primary group id for this entity. Map the corres.
  579. * SIDs to their posix ids. Determine also the access rights for owner,
  580. * group, world and this user. The access rights are divided into the
  581. * following:
  582. *
  583. * Owner's rights
  584. * Primary group's rights
  585. * World rights
  586. * This user's rights
  587. *
  588. * The handle to the directory should be opened with READ_CONTROL
  589. * See Files vs. See Folders resolution for Owner/Group/World is already done.
  590. */
  591. LOCAL AFPSTATUS
  592. AfpQuerySecurityIdsAndRights(
  593. IN PSDA pSda,
  594. IN PFILESYSHANDLE pFSHandle,
  595. IN DWORD Bitmap,
  596. IN OUT PFILEDIRPARM pFDParm
  597. )
  598. {
  599. NTSTATUS Status;
  600. BYTE ORights, GRights, WRights;
  601. PAGED_CODE( );
  602. // Save contents of the AfpInfo stream access bits
  603. ORights = pFDParm->_fdp_OwnerRights | DIR_ACCESS_WRITE;
  604. GRights = pFDParm->_fdp_GroupRights | DIR_ACCESS_WRITE;
  605. WRights = pFDParm->_fdp_WorldRights | DIR_ACCESS_WRITE;
  606. // Initialize to no rights for everybody
  607. pFDParm->_fdp_Rights = 0;
  608. // Get the OwnerId and GroupId for this directory.
  609. // Determine the Owner/Group and World rights for this directory
  610. // Determine if this user is a member of the directory's group
  611. Status = AfpGetAfpPermissions(pSda,
  612. pFSHandle->fsh_FileHandle,
  613. pFDParm);
  614. if (!NT_SUCCESS(Status))
  615. return Status;
  616. // Modify owner/group/world rights for the SeeFiles/SeeFolder weirdness
  617. // Also if the ACLs say we have READ & SEARCH access but AfpInfo stream
  618. // says we don't, then ignore AfpInfo stream
  619. if ((pFDParm->_fdp_OwnerRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)) &&
  620. !(ORights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)))
  621. ORights |= (DIR_ACCESS_READ | DIR_ACCESS_SEARCH);
  622. pFDParm->_fdp_OwnerRights &= ORights;
  623. if ((pFDParm->_fdp_GroupRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)) &&
  624. !(GRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)))
  625. GRights |= (DIR_ACCESS_READ | DIR_ACCESS_SEARCH);
  626. pFDParm->_fdp_GroupRights &= GRights;
  627. if ((pFDParm->_fdp_WorldRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)) &&
  628. !(WRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)))
  629. WRights |= (DIR_ACCESS_READ | DIR_ACCESS_SEARCH);
  630. pFDParm->_fdp_WorldRights &= WRights;
  631. // One last bit of munging. Owner & Group can be the same and they both
  632. // could be everyone !! Coalese that.
  633. if (pFDParm->_fdp_OwnerId == SE_WORLD_POSIX_ID)
  634. {
  635. pFDParm->_fdp_WorldRights |= (pFDParm->_fdp_OwnerRights & ~DIR_ACCESS_OWNER);
  636. pFDParm->_fdp_OwnerRights |= pFDParm->_fdp_WorldRights;
  637. }
  638. if (pFDParm->_fdp_GroupId == SE_WORLD_POSIX_ID)
  639. {
  640. pFDParm->_fdp_WorldRights |= pFDParm->_fdp_GroupRights;
  641. pFDParm->_fdp_GroupRights |= pFDParm->_fdp_WorldRights;
  642. }
  643. if (pFDParm->_fdp_GroupId == pFDParm->_fdp_OwnerId)
  644. {
  645. pFDParm->_fdp_OwnerRights |= pFDParm->_fdp_GroupRights;
  646. pFDParm->_fdp_GroupRights |= (pFDParm->_fdp_OwnerRights & ~DIR_ACCESS_OWNER);
  647. }
  648. // Modify User rights for the SeeFiles/SeeFolder weirdness by determining
  649. // if the user is owner/group or world
  650. if (pFDParm->_fdp_UserRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH))
  651. {
  652. BYTE URights = (pFDParm->_fdp_UserRights & (DIR_ACCESS_WRITE | DIR_ACCESS_OWNER));
  653. if ((pFDParm->_fdp_WorldRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH))
  654. != (DIR_ACCESS_READ | DIR_ACCESS_SEARCH))
  655. {
  656. pFDParm->_fdp_UserRights = pFDParm->_fdp_WorldRights;
  657. if (pFDParm->_fdp_UserIsOwner)
  658. {
  659. pFDParm->_fdp_UserRights |= pFDParm->_fdp_OwnerRights;
  660. }
  661. if (pFDParm->_fdp_UserIsMemberOfDirGroup)
  662. {
  663. pFDParm->_fdp_UserRights |= pFDParm->_fdp_GroupRights;
  664. }
  665. if ((pFDParm->_fdp_UserRights & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH)) == 0)
  666. pFDParm->_fdp_UserRights |= (DIR_ACCESS_READ | DIR_ACCESS_SEARCH);
  667. pFDParm->_fdp_UserRights &= ~DIR_ACCESS_WRITE;
  668. pFDParm->_fdp_UserRights |= URights;
  669. }
  670. }
  671. return Status;
  672. }
  673. /*** AfpConvertNTAttrToAfpAttr
  674. *
  675. * Map NT Attributes to the AFP equivalents.
  676. */
  677. USHORT
  678. AfpConvertNTAttrToAfpAttr(
  679. IN DWORD Attr
  680. )
  681. {
  682. USHORT AfpAttr = FD_BITMAP_ATTR_SET;
  683. PAGED_CODE( );
  684. if (Attr & FILE_ATTRIBUTE_READONLY)
  685. {
  686. AfpAttr |= FD_BITMAP_ATTR_RENAMEINH | FD_BITMAP_ATTR_DELETEINH;
  687. if (!(Attr & FILE_ATTRIBUTE_DIRECTORY))
  688. AfpAttr |= FILE_BITMAP_ATTR_WRITEINH;
  689. }
  690. if (Attr & FILE_ATTRIBUTE_HIDDEN)
  691. AfpAttr |= FD_BITMAP_ATTR_INVISIBLE;
  692. if (Attr & FILE_ATTRIBUTE_SYSTEM)
  693. AfpAttr |= FD_BITMAP_ATTR_SYSTEM;
  694. if (Attr & FILE_ATTRIBUTE_ARCHIVE)
  695. {
  696. AfpAttr |= FD_BITMAP_ATTR_BACKUPNEED;
  697. }
  698. return AfpAttr;
  699. }
  700. /*** AfpConvertAfpAttrToNTAttr
  701. *
  702. * Map AFP Attributes to the NT equivalents.
  703. */
  704. DWORD
  705. AfpConvertAfpAttrToNTAttr(
  706. IN USHORT Attr
  707. )
  708. {
  709. DWORD NtAttr = 0;
  710. PAGED_CODE( );
  711. if (Attr & (FD_BITMAP_ATTR_RENAMEINH |
  712. FD_BITMAP_ATTR_DELETEINH |
  713. FILE_BITMAP_ATTR_WRITEINH))
  714. NtAttr |= FILE_ATTRIBUTE_READONLY;
  715. if (Attr & FD_BITMAP_ATTR_INVISIBLE)
  716. NtAttr |= FILE_ATTRIBUTE_HIDDEN;
  717. if (Attr & FD_BITMAP_ATTR_SYSTEM)
  718. NtAttr |= FILE_ATTRIBUTE_SYSTEM;
  719. if (Attr & FD_BITMAP_ATTR_BACKUPNEED)
  720. {
  721. NtAttr |= FILE_ATTRIBUTE_ARCHIVE;
  722. }
  723. return NtAttr;
  724. }
  725. /*** AfpNormalizeAfpAttr
  726. *
  727. * Normalize the various inhibit bits in afp attributes vs. the RO bit on the
  728. * disk.
  729. */
  730. VOID
  731. AfpNormalizeAfpAttr(
  732. IN OUT PFILEDIRPARM pFDParm,
  733. IN DWORD NtAttr
  734. )
  735. {
  736. USHORT AfpAttr;
  737. PAGED_CODE( );
  738. AfpAttr = AfpConvertNTAttrToAfpAttr(NtAttr);
  739. /*
  740. * The Attributes fall into two classes, the ones that are on
  741. * on the filesystem and the others maintained in the AfpInfo
  742. * stream. We need to coalesce these two sets. The RO bit on
  743. * the disk corres. to the three inhibit bits. Fine grain
  744. * control is possible.
  745. *
  746. * The other set of bits that are in the exclusive realm of
  747. * the AfpInfo stream are the RAlreadyOpen and DAlreadyOpen
  748. * bits and the multi-user bit.
  749. */
  750. if (((pFDParm->_fdp_Attr & FD_BITMAP_ATTR_NT_RO) == 0) ^
  751. ((AfpAttr & FD_BITMAP_ATTR_NT_RO) == 0))
  752. {
  753. if ((AfpAttr & FD_BITMAP_ATTR_NT_RO) == 0)
  754. pFDParm->_fdp_Attr &= ~FD_BITMAP_ATTR_NT_RO;
  755. else pFDParm->_fdp_Attr |= FD_BITMAP_ATTR_NT_RO;
  756. }
  757. pFDParm->_fdp_Attr &= (AfpAttr |
  758. (FILE_BITMAP_ATTR_MULTIUSER |
  759. FILE_BITMAP_ATTR_DATAOPEN |
  760. FILE_BITMAP_ATTR_RESCOPEN |
  761. FD_BITMAP_ATTR_SET));
  762. pFDParm->_fdp_Attr |= (AfpAttr & (FD_BITMAP_ATTR_BACKUPNEED |
  763. FD_BITMAP_ATTR_SYSTEM |
  764. FD_BITMAP_ATTR_INVISIBLE));
  765. }
  766. /***AfpMapFDBitmapOpenAccess
  767. *
  768. * Map the FD_INTERNAL_BITMAP_OPENACCESS_xxx bits to the appropriate
  769. * FILEIO_ACCESS_xxx values. The returned OpenAccess is used by the
  770. * pathmap code to open the data stream of a file/dir (under impersonation
  771. * for NTFS) for use in the AFP APIs.
  772. *
  773. */
  774. DWORD
  775. AfpMapFDBitmapOpenAccess(
  776. IN DWORD Bitmap,
  777. IN BOOLEAN IsDir
  778. )
  779. {
  780. DWORD OpenAccess = FILEIO_ACCESS_NONE;
  781. PAGED_CODE( );
  782. do
  783. {
  784. if (!(Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_ALL))
  785. {
  786. break;
  787. }
  788. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_READCTRL)
  789. {
  790. // For GetFileDirParms we don't know if it was a file or dir they
  791. // are asking for, so we had to OR the file and dir bitmaps together
  792. // before pathmapping.
  793. if (IsDir)
  794. OpenAccess = (FILEIO_ACCESS_NONE |
  795. READ_CONTROL |
  796. SYNCHRONIZE);
  797. break;
  798. }
  799. // Used by AfpAdmwDirectoryGetInfo
  800. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_ADMINGET)
  801. {
  802. OpenAccess = (FILE_READ_ATTRIBUTES |
  803. READ_CONTROL |
  804. SYNCHRONIZE);
  805. break;
  806. }
  807. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_ADMINSET)
  808. {
  809. OpenAccess = (FILE_READ_ATTRIBUTES |
  810. READ_CONTROL |
  811. SYNCHRONIZE |
  812. FILE_WRITE_ATTRIBUTES |
  813. WRITE_DAC |
  814. WRITE_OWNER);
  815. break;
  816. }
  817. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_RW_ATTR)
  818. {
  819. OpenAccess |= (FILEIO_ACCESS_NONE | FILE_WRITE_ATTRIBUTES);
  820. }
  821. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_RWCTRL)
  822. {
  823. OpenAccess |= (FILEIO_ACCESS_NONE |
  824. READ_CONTROL |
  825. WRITE_DAC |
  826. WRITE_OWNER |
  827. SYNCHRONIZE);
  828. break;
  829. }
  830. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_READ)
  831. {
  832. OpenAccess |= FILEIO_ACCESS_READ;
  833. }
  834. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_WRITE)
  835. {
  836. OpenAccess |= FILEIO_ACCESS_WRITE;
  837. }
  838. if (Bitmap & FD_INTERNAL_BITMAP_OPENACCESS_DELETE)
  839. {
  840. OpenAccess |= FILEIO_ACCESS_DELETE;
  841. }
  842. } while (False);
  843. return OpenAccess;
  844. }
  845. /*** AfpCheckForInhibit
  846. *
  847. * This routine checks for the setting of the Afp RenameInhibit, DeleteInhibit
  848. * or WriteInhibit attributes. It first queries for the host File/Dir
  849. * attributes to find out the setting of the ReadOnly attribute, then checks
  850. * that against the Afp InhibitBit of interest. AFP_ERR_NONE is returned if
  851. * the InhibitBit is not set, else AFP_ERR_OBJECT_LOCKED is returned.
  852. * The input handle must be a handle to the $DATA stream of the file/dir open
  853. * in server's context. The host attributes are returned in pNTAttr if the
  854. * error code is not AFP_ERR_MISC.
  855. *
  856. */
  857. AFPSTATUS
  858. AfpCheckForInhibit(
  859. IN PFILESYSHANDLE hData, // handle to DATA stream in server context
  860. IN DWORD InhibitBit,
  861. IN DWORD AfpAttr,
  862. OUT PDWORD pNTAttr
  863. )
  864. {
  865. AFPSTATUS Status = STATUS_SUCCESS;
  866. PAGED_CODE();
  867. do
  868. {
  869. if (!NT_SUCCESS(AfpIoQueryTimesnAttr(hData, NULL, NULL, pNTAttr)))
  870. {
  871. Status = AFP_ERR_MISC;
  872. break;
  873. }
  874. if (!(*pNTAttr & FILE_ATTRIBUTE_READONLY))
  875. {
  876. Status = AFP_ERR_NONE;
  877. break;
  878. }
  879. if (!(AfpAttr & FD_BITMAP_ATTR_NT_RO) || (AfpAttr & InhibitBit))
  880. {
  881. // The file/dir is ReadOnly, but NONE of the AFP Inhibit bits are
  882. // set, so we assume the PC has set the RO bit; or, the requested
  883. // inhibit bit IS set.
  884. Status = AFP_ERR_OBJECT_LOCKED;
  885. break;
  886. }
  887. } while (False);
  888. return Status;
  889. }
  890. /*** AfpUnpackCatSearchSpecs
  891. *
  892. * Unpack the information from the on-the-wire format to the FileDirParm
  893. * structures for Specification 1 and 2. Specification 1 contains the
  894. * CatSearch criteria for lower bounds and values. Specification 2
  895. * contains the CatSearch criteria for upper bounds and masks. The parameters
  896. * are packed in the same order that the bits are set in the request bitmap.
  897. * These are read into FILEDIRPARM structures.
  898. *
  899. * The fields in Specification 1 and Specification 2 have different uses:
  900. *
  901. * - In the name field, Specification 1 holds the target string and
  902. * Specification 2 must always have a nil name field.
  903. *
  904. * - In all date and length fields, Specification 1 holds the lowest value
  905. * in the target range and Specification 2 holds the highest value in the
  906. * target range.
  907. *
  908. * - In file attributes and Finder Info fields, Specification 1 holds the
  909. * target value, and Specification 2 holds the bitwise mask that specifies
  910. * which bits in that field in Specification 1 are relevant to the current
  911. * search.
  912. *
  913. */
  914. AFPSTATUS
  915. AfpUnpackCatSearchSpecs(
  916. IN PBYTE pBuffer, // Pointer to beginning of Spec data
  917. IN USHORT BufLength, // Length of Spec1 + Spec2 data
  918. IN DWORD Bitmap,
  919. OUT PFILEDIRPARM pFDParm1,
  920. OUT PFILEDIRPARM pFDParm2,
  921. OUT PUNICODE_STRING pMatchString
  922. )
  923. {
  924. PCATSEARCHSPEC pSpec1, pSpec2;
  925. PBYTE pBuffer1, pBuffer2, pEndOfBuffer;
  926. USHORT Offset = 0, MinSpecLength1, MinSpecLength2;
  927. AFPSTATUS Status = AFP_ERR_NONE;
  928. BOOLEAN NoNullString = False;
  929. PAGED_CODE( );
  930. pSpec1 = (PCATSEARCHSPEC) pBuffer;
  931. pSpec2 = (PCATSEARCHSPEC) ((PBYTE)pBuffer + sizeof(CATSEARCHSPEC) +
  932. pSpec1->__StructLength);
  933. // Point to data after the specification length and filler byte
  934. pBuffer1 = (PBYTE)pSpec1 + sizeof(CATSEARCHSPEC);
  935. pBuffer2 = (PBYTE)pSpec2 + sizeof(CATSEARCHSPEC);
  936. do
  937. {
  938. //
  939. // Make sure pSpec2 is at least pointing into the buffer we have, and
  940. // that its length is within the buffer as well.
  941. //
  942. pEndOfBuffer = pBuffer + BufLength;
  943. if (((PBYTE)pSpec2 >= pEndOfBuffer) ||
  944. ((PBYTE)pSpec2+pSpec2->__StructLength+sizeof(CATSEARCHSPEC)
  945. > pEndOfBuffer))
  946. {
  947. DBGPRINT(DBG_COMP_AFPAPI_FD, DBG_LEVEL_ERR,
  948. ("UnpackCatSearchParms: Buffer not large enough!\n"));
  949. Status = AFP_ERR_PARAM;
  950. break;
  951. }
  952. //
  953. // Validate that input buffer is long enough to hold all the info the
  954. // bitmap says it does. Note we cannot yet account for the length of
  955. // a longname string's characters if there was one specified.
  956. //
  957. MinSpecLength1 = MinSpecLength2 = sizeof(CATSEARCHSPEC) +
  958. AfpGetFileDirParmsReplyLength(pFDParm1, Bitmap);
  959. //
  960. // HACK: In order to support LLPT, if the catsearch is
  961. // asking to match filename, we should allow the Spec2 name to
  962. // be missing from the buffer (as opposed to being the null string),
  963. // but still expect the offset to the name.
  964. //
  965. // We also need to support system 7.1 who sends a zero length spec2
  966. // if the Bitmap == FD_BITMAP_LONGNAME.
  967. //
  968. // Real Appleshare handles both these cases with no error.
  969. //
  970. if (Bitmap & FD_BITMAP_LONGNAME)
  971. {
  972. if (pSpec2->__StructLength == (MinSpecLength2-sizeof(CATSEARCHSPEC)-sizeof(BYTE)) )
  973. {
  974. MinSpecLength2 -= sizeof(BYTE);
  975. NoNullString = True;
  976. }
  977. else if ((Bitmap == FD_BITMAP_LONGNAME) && (pSpec2->__StructLength == 0))
  978. {
  979. MinSpecLength2 -= sizeof(USHORT) + sizeof(BYTE);
  980. NoNullString = True;
  981. }
  982. }
  983. if ( ((MinSpecLength1 + MinSpecLength2) > BufLength) ||
  984. (pSpec1->__StructLength < (MinSpecLength1-sizeof(CATSEARCHSPEC))) ||
  985. (pSpec2->__StructLength < (MinSpecLength2-sizeof(CATSEARCHSPEC))) )
  986. {
  987. DBGPRINT(DBG_COMP_AFPAPI_FD, DBG_LEVEL_ERR,
  988. ("UnpackCatSearchParms: Buffer not large enough!\n"));
  989. Status = AFP_ERR_PARAM;
  990. break;
  991. }
  992. if (Bitmap & FD_BITMAP_ATTR)
  993. {
  994. GETSHORT2SHORT(&pFDParm1->_fdp_Attr, pBuffer1+Offset);
  995. GETSHORT2SHORT(&pFDParm2->_fdp_Attr, pBuffer2+Offset);
  996. if ((pFDParm2->_fdp_Attr & ~FD_BITMAP_ATTR_NT_RO) ||
  997. (pFDParm2->_fdp_Attr == 0))
  998. {
  999. Status = AFP_ERR_PARAM;
  1000. break;
  1001. }
  1002. Offset += sizeof(USHORT);
  1003. }
  1004. if (Bitmap & FD_BITMAP_PARENT_DIRID)
  1005. {
  1006. GETDWORD2DWORD(&pFDParm1->_fdp_ParentId, pBuffer1+Offset);
  1007. GETDWORD2DWORD(&pFDParm2->_fdp_ParentId, pBuffer2+Offset);
  1008. if (pFDParm1->_fdp_ParentId < AFP_ID_ROOT)
  1009. {
  1010. Status = AFP_ERR_PARAM;
  1011. break;
  1012. }
  1013. Offset += sizeof(DWORD);
  1014. }
  1015. if (Bitmap & FD_BITMAP_CREATETIME)
  1016. {
  1017. GETDWORD2DWORD(&pFDParm1->_fdp_CreateTime, pBuffer1+Offset);
  1018. GETDWORD2DWORD(&pFDParm2->_fdp_CreateTime, pBuffer2+Offset);
  1019. Offset += sizeof(DWORD);
  1020. }
  1021. if (Bitmap & FD_BITMAP_MODIFIEDTIME)
  1022. {
  1023. GETDWORD2DWORD(&pFDParm1->_fdp_ModifiedTime, pBuffer1+Offset);
  1024. GETDWORD2DWORD(&pFDParm2->_fdp_ModifiedTime, pBuffer2+Offset);
  1025. Offset += sizeof(DWORD);
  1026. }
  1027. if (Bitmap & FD_BITMAP_BACKUPTIME)
  1028. {
  1029. GETDWORD2DWORD(&pFDParm1->_fdp_BackupTime, pBuffer1+Offset);
  1030. GETDWORD2DWORD(&pFDParm2->_fdp_BackupTime, pBuffer2+Offset);
  1031. Offset += sizeof(DWORD);
  1032. }
  1033. if (Bitmap & FD_BITMAP_FINDERINFO)
  1034. {
  1035. RtlCopyMemory((PBYTE)&pFDParm1->_fdp_FinderInfo,
  1036. pBuffer1+Offset,
  1037. sizeof(FINDERINFO));
  1038. RtlCopyMemory((PBYTE)&pFDParm2->_fdp_FinderInfo,
  1039. pBuffer2+Offset,
  1040. sizeof(FINDERINFO));
  1041. Offset += sizeof(FINDERINFO);
  1042. }
  1043. if (Bitmap & FD_BITMAP_LONGNAME)
  1044. {
  1045. DWORD NameOffset1, NameOffset2;
  1046. //
  1047. // Get the parm relative offset to the start of the pascal string
  1048. //
  1049. GETSHORT2DWORD(&NameOffset1, pBuffer1+Offset);
  1050. if ((Bitmap == FD_BITMAP_LONGNAME) && (pSpec2->__StructLength == 0))
  1051. {
  1052. // HACK for system 7.1
  1053. NameOffset2 = NameOffset1;
  1054. pBuffer2 = NULL;
  1055. }
  1056. else
  1057. GETSHORT2DWORD(&NameOffset2, pBuffer2+Offset);
  1058. if ((NameOffset1 != NameOffset2) ||
  1059. (pBuffer1 + NameOffset1 >= (PBYTE)pSpec2) ||
  1060. (pBuffer2 + NameOffset2 > pEndOfBuffer))
  1061. {
  1062. Status = AFP_ERR_PARAM;
  1063. break;
  1064. }
  1065. Offset += sizeof(USHORT);
  1066. //
  1067. // Get the pascal string length
  1068. //
  1069. GETBYTE2SHORT(&pFDParm1->_fdp_LongName.Length, pBuffer1+NameOffset1);
  1070. // HACK: In order to support LLPT and system 7.1, if the catsearch is
  1071. // asking to match filename, we should allow the Spec2 name to
  1072. // be missing from the buffer (as opposed to being the null string).
  1073. // Real Appleshare handles this case with no error.
  1074. if (NoNullString)
  1075. pFDParm2->_fdp_LongName.Length = 0;
  1076. else
  1077. GETBYTE2SHORT(&pFDParm2->_fdp_LongName.Length, pBuffer2+NameOffset1);
  1078. if ((pFDParm1->_fdp_LongName.Length > AFP_LONGNAME_LEN) ||
  1079. (pFDParm2->_fdp_LongName.Length != 0) ||
  1080. (pBuffer1+NameOffset1+sizeof(BYTE)+pFDParm1->_fdp_LongName.Length > (PBYTE)pSpec2))
  1081. {
  1082. // Specification 2 must always have a nil name field. Also
  1083. // ensure that Specification 1 does not have a bogus string
  1084. // length.
  1085. Status = AFP_ERR_PARAM;
  1086. break;
  1087. }
  1088. RtlCopyMemory(pFDParm1->_fdp_LongName.Buffer,
  1089. pBuffer1+NameOffset1+sizeof(BYTE),
  1090. pFDParm1->_fdp_LongName.Length);
  1091. AfpConvertStringToMungedUnicode(&pFDParm1->_fdp_LongName, pMatchString);
  1092. }
  1093. // OFFSPRINGS bit for directories, DATALEN bit for files are the same
  1094. if (Bitmap & DIR_BITMAP_OFFSPRINGS)
  1095. {
  1096. ASSERT(pFDParm1->_fdp_Flags != (DFE_FLAGS_FILE_WITH_ID | DFE_FLAGS_DIR));
  1097. if (IsDir(pFDParm1))
  1098. {
  1099. // We have to combine total offspring count into the
  1100. // FileCount field here since the API does not separate
  1101. // them into separate file and dir offspring counts
  1102. GETSHORT2DWORD(&pFDParm1->_fdp_FileCount, pBuffer1+Offset);
  1103. GETSHORT2DWORD(&pFDParm2->_fdp_FileCount, pBuffer2+Offset);
  1104. Offset += sizeof(USHORT);
  1105. }
  1106. else
  1107. {
  1108. GETDWORD2DWORD(&pFDParm1->_fdp_DataForkLen, pBuffer1+Offset);
  1109. GETDWORD2DWORD(&pFDParm2->_fdp_DataForkLen, pBuffer2+Offset);
  1110. Offset += sizeof(DWORD);
  1111. }
  1112. }
  1113. if (Bitmap & FILE_BITMAP_RESCLEN)
  1114. {
  1115. ASSERT(pFDParm1->_fdp_Flags == DFE_FLAGS_FILE_WITH_ID);
  1116. GETDWORD2DWORD(&pFDParm1->_fdp_RescForkLen, pBuffer1+Offset);
  1117. GETDWORD2DWORD(&pFDParm2->_fdp_RescForkLen, pBuffer2+Offset);
  1118. Offset += sizeof(DWORD);
  1119. }
  1120. } while (False);
  1121. return Status;
  1122. }
  1123. /*** AfpIsCatSearchMatch
  1124. *
  1125. * Given a DFE and a set of search criteria, see if this item should be
  1126. * returned as a match in the catalog search.
  1127. *
  1128. *
  1129. * LOCKS_ASSUMED: vds_IdDbAccessLock (SWMR, Exclusive)
  1130. */
  1131. SHORT
  1132. AfpIsCatSearchMatch(
  1133. IN PDFENTRY pDFE,
  1134. IN DWORD Bitmap, // Search criteria
  1135. IN DWORD ReplyBitmap, // Info to return
  1136. IN PFILEDIRPARM pFDParm1,
  1137. IN PFILEDIRPARM pFDParm2,
  1138. IN PUNICODE_STRING pMatchName OPTIONAL
  1139. )
  1140. {
  1141. BOOLEAN IsMatch = True;
  1142. SHORT Length = 0;
  1143. PAGED_CODE();
  1144. do
  1145. {
  1146. if (Bitmap & FD_BITMAP_ATTR)
  1147. {
  1148. FILEDIRPARM fdp;
  1149. fdp._fdp_Attr = pDFE->dfe_AfpAttr;
  1150. AfpNormalizeAfpAttr(&fdp, pDFE->dfe_NtAttr);
  1151. if ((fdp._fdp_Attr & pFDParm2->_fdp_Attr) != pFDParm1->_fdp_Attr)
  1152. {
  1153. IsMatch = False;
  1154. break;
  1155. }
  1156. }
  1157. if (Bitmap & FD_BITMAP_PARENT_DIRID)
  1158. {
  1159. if ((pDFE->dfe_Parent->dfe_AfpId < pFDParm1->_fdp_ParentId) ||
  1160. (pDFE->dfe_Parent->dfe_AfpId > pFDParm2->_fdp_ParentId))
  1161. {
  1162. IsMatch = False;
  1163. break;
  1164. }
  1165. }
  1166. if (Bitmap & FD_BITMAP_CREATETIME)
  1167. {
  1168. if (((AFPTIME)pDFE->dfe_CreateTime < (AFPTIME)pFDParm1->_fdp_CreateTime) ||
  1169. ((AFPTIME)pDFE->dfe_CreateTime > (AFPTIME)pFDParm2->_fdp_CreateTime))
  1170. {
  1171. IsMatch = False;
  1172. break;
  1173. }
  1174. }
  1175. if (Bitmap & FD_BITMAP_MODIFIEDTIME)
  1176. {
  1177. AFPTIME ModTime;
  1178. ModTime = AfpConvertTimeToMacFormat(&pDFE->dfe_LastModTime);
  1179. if ((ModTime < pFDParm1->_fdp_ModifiedTime) ||
  1180. (ModTime > pFDParm2->_fdp_ModifiedTime))
  1181. {
  1182. IsMatch = False;
  1183. break;
  1184. }
  1185. }
  1186. if (Bitmap & FD_BITMAP_BACKUPTIME)
  1187. {
  1188. if ((pDFE->dfe_BackupTime < pFDParm1->_fdp_BackupTime) ||
  1189. (pDFE->dfe_BackupTime > pFDParm2->_fdp_BackupTime))
  1190. {
  1191. IsMatch = False;
  1192. break;
  1193. }
  1194. }
  1195. if (Bitmap & FD_BITMAP_FINDERINFO)
  1196. {
  1197. int i;
  1198. PBYTE pF, p1, p2;
  1199. FINDERINFO FinderInfo;
  1200. // NOTE: why doesn't dfe_FinderInfo.Attr1 correctly reflect the
  1201. // Nt Hidden attribute in the first place?
  1202. FinderInfo = pDFE->dfe_FinderInfo;
  1203. if (pDFE->dfe_NtAttr & FILE_ATTRIBUTE_HIDDEN)
  1204. FinderInfo.fd_Attr1 |= FINDER_FLAG_INVISIBLE;
  1205. pF = (PBYTE) &FinderInfo;
  1206. p1 = (PBYTE) &pFDParm1->_fdp_FinderInfo;
  1207. p2 = (PBYTE) &pFDParm2->_fdp_FinderInfo;
  1208. for (i = 0; i < sizeof(FINDERINFO); i++)
  1209. {
  1210. if ((*pF++ & *p2++) != *p1++)
  1211. {
  1212. IsMatch = False;
  1213. break; // out of for loop
  1214. }
  1215. }
  1216. if (IsMatch == False)
  1217. break; // out of while loop
  1218. }
  1219. if (Bitmap & FD_BITMAP_LONGNAME)
  1220. {
  1221. ASSERT(ARGUMENT_PRESENT(pMatchName));
  1222. if (pFDParm2->_fdp_fPartialName)
  1223. {
  1224. // Name must contain substring
  1225. if (!AfpIsProperSubstring(&pDFE->dfe_UnicodeName, pMatchName))
  1226. {
  1227. IsMatch = False;
  1228. break;
  1229. }
  1230. }
  1231. else if (!EQUAL_UNICODE_STRING(&pDFE->dfe_UnicodeName, pMatchName, True))
  1232. {
  1233. // Whole name must match
  1234. IsMatch = False;
  1235. break;
  1236. }
  1237. }
  1238. if (Bitmap & FILE_BITMAP_DATALEN)
  1239. {
  1240. // This bit is also used as DIR_BITMAP_OFFSPRINGS for directories
  1241. if (IsDir(pFDParm1))
  1242. {
  1243. DWORD count;
  1244. ASSERT(DFE_IS_DIRECTORY(pDFE) && DFE_CHILDREN_ARE_PRESENT(pDFE));
  1245. count = pDFE->dfe_DirOffspring + pDFE->dfe_FileOffspring;
  1246. // In this case, _fdp_FileCount holds total # of files and dirs
  1247. if ((count < pFDParm1->_fdp_FileCount) ||
  1248. (count > pFDParm2->_fdp_FileCount))
  1249. {
  1250. IsMatch = False;
  1251. break;
  1252. }
  1253. }
  1254. else
  1255. {
  1256. ASSERT(DFE_IS_FILE(pDFE));
  1257. if ((pDFE->dfe_DataLen < pFDParm1->_fdp_DataForkLen) ||
  1258. (pDFE->dfe_DataLen > pFDParm2->_fdp_DataForkLen))
  1259. {
  1260. IsMatch = False;
  1261. break;
  1262. }
  1263. }
  1264. }
  1265. if (Bitmap & FILE_BITMAP_RESCLEN)
  1266. {
  1267. ASSERT(DFE_IS_FILE(pDFE));
  1268. if ((pDFE->dfe_RescLen < pFDParm1->_fdp_RescForkLen) ||
  1269. (pDFE->dfe_RescLen > pFDParm2->_fdp_RescForkLen))
  1270. {
  1271. IsMatch = False;
  1272. break;
  1273. }
  1274. }
  1275. } while (False);
  1276. if (IsMatch)
  1277. {
  1278. Length = 2 * sizeof(BYTE); // Struct Length plus File/Dir Flag
  1279. if (ReplyBitmap & FD_BITMAP_PARENT_DIRID)
  1280. {
  1281. Length += sizeof(DWORD);
  1282. }
  1283. if (ReplyBitmap & FD_BITMAP_LONGNAME)
  1284. {
  1285. // Offset to string + pascal string length + characters
  1286. #ifdef DBCS
  1287. // FiX #11992 SFM: As a result of search, I get incorrect file information.
  1288. // 1996.09.26 V-HIDEKK
  1289. {
  1290. ANSI_STRING AName;
  1291. BYTE NameBuf[AFP_LONGNAME_LEN+1];
  1292. AfpInitAnsiStringWithNonNullTerm(&AName, sizeof(NameBuf), NameBuf);
  1293. AfpConvertMungedUnicodeToAnsi(&pDFE->dfe_UnicodeName, &AName);
  1294. Length += sizeof(USHORT) + sizeof(BYTE) + AName.Length;
  1295. }
  1296. #else
  1297. Length += sizeof(USHORT) + sizeof(BYTE) + pDFE->dfe_UnicodeName.Length/sizeof(WCHAR);
  1298. #endif
  1299. }
  1300. Length = EVENALIGN(Length);
  1301. }
  1302. return Length;
  1303. }
  1304.