Leaked source code of windows server 2003
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.

10473 lines
332 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. csc.c
  5. Abstract:
  6. This module implements the client side caching interface for the SMB mini rdr.
  7. Author:
  8. Joe Linn [joelinn] 21-jan-1997
  9. Revision History:
  10. Shishir Pardikar disconnected ops, parameter validation, bug fixes .....
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <smbdebug.h>
  15. #define Dbg (DEBUG_TRACE_MRXSMBCSC)
  16. RXDT_DefineCategory(MRXSMBCSC);
  17. //local prototype
  18. LONG
  19. MRxSmbCSCExceptionFilter (
  20. IN PRX_CONTEXT RxContext,
  21. IN PEXCEPTION_POINTERS ExceptionPointer
  22. );
  23. BOOLEAN
  24. CscpAccessCheck(
  25. PCACHED_SECURITY_INFORMATION pCachedSecurityInformation,
  26. ULONG CachedSecurityInformationLength,
  27. CSC_SID_INDEX SidIndex,
  28. ACCESS_MASK AccessMask,
  29. BOOLEAN *pSidHasAccessmask
  30. );
  31. BOOLEAN
  32. CscAccessCheck(
  33. HSHADOW hParent,
  34. HSHADOW hFile,
  35. PRX_CONTEXT RxContext,
  36. ACCESS_MASK AccessMask,
  37. PCACHED_SECURITY_INFORMATION pCachedSecurityInformationForShadow,
  38. PCACHED_SECURITY_INFORMATION pCachedSecurityInformationForShare
  39. );
  40. VOID
  41. MRxSmbCscFillWithoutNamesFind32FromFcb (
  42. IN PMINIMAL_CSC_SMBFCB MinimalCscSmbFcb,
  43. OUT _WIN32_FIND_DATA *Find32
  44. );
  45. NTSTATUS
  46. MRxSmbCscGetFileInfoForCshadow(
  47. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  48. );
  49. NTSTATUS
  50. MRxSmbGetFileInfoFromServer (
  51. IN OUT PRX_CONTEXT RxContext,
  52. IN PUNICODE_STRING FullFileName,
  53. OUT _WIN32_FIND_DATA *Find32,
  54. IN PMRX_SRV_OPEN pSrvOpen,
  55. OUT BOOLEAN *lpfIsRoot
  56. );
  57. BOOLEAN
  58. MRxSmbCscIsFatNameValid (
  59. IN PUNICODE_STRING FileName,
  60. IN BOOLEAN WildCardsPermissible
  61. );
  62. VOID
  63. MRxSmbCscGenerate83NameAsNeeded(
  64. IN CSC_SHADOW_HANDLE hDir,
  65. PWCHAR FileName,
  66. PWCHAR SFN
  67. );
  68. int
  69. RefreshShadow( HSHADOW hDir,
  70. IN HSHADOW hShadow,
  71. IN LPFIND32 lpFind32,
  72. OUT ULONG *lpuShadowStatus
  73. );
  74. NTSTATUS
  75. SmbPseExchangeStart_CloseCopyChunk(
  76. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  77. );
  78. NTSTATUS
  79. MRxSmbCscCloseExistingThruOpen(
  80. IN OUT PRX_CONTEXT RxContext
  81. );
  82. ULONG
  83. GetPathLevelFromUnicodeString (
  84. PUNICODE_STRING Name
  85. );
  86. NTSTATUS
  87. MRxSmbCscFixupFindFirst (
  88. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  89. );
  90. VOID
  91. MRxSmbCscLocateAndFillFind32WithinSmbbuf(
  92. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  93. );
  94. NTSTATUS
  95. MRxSmbCscGetFileInfoFromServerWithinExchange (
  96. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  97. PUNICODE_STRING FileName
  98. );
  99. NTSTATUS
  100. IoctlGetDebugInfo(
  101. PRX_CONTEXT RxContext,
  102. PBYTE InputBuffer,
  103. ULONG InputBufferLength,
  104. PBYTE OutputBuffer,
  105. ULONG OutputBufferLength);
  106. NTSTATUS
  107. MRxSmbCscLocalFileOpen(
  108. IN OUT PRX_CONTEXT RxContext
  109. );
  110. NTSTATUS
  111. MRxSmbCscObtainShadowHandles (
  112. IN OUT PRX_CONTEXT RxContext,
  113. IN OUT PNTSTATUS Status,
  114. IN OUT _WIN32_FIND_DATA *Find32,
  115. OUT PBOOLEAN Created,
  116. IN ULONG CreateShadowControls,
  117. IN BOOLEAN Disconnected
  118. );
  119. // type of buffer used to capture structures passed in which have embedded pointers.
  120. // Once we have captured the structure, the embedded pointers cannot be changed and
  121. // our parameter validation holds good throughout the duration of the call
  122. typedef union tagCAPTURE_BUFFERS
  123. {
  124. COPYPARAMSW sCP;
  125. SHADOWINFO sSI;
  126. SHAREINFO sSVI;
  127. }
  128. CAPTURE_BUFFERS, *LPCAPTURE_BUFFERS;
  129. // table entry type off which the parameter validation is driven
  130. typedef struct tagCSC_IOCTL_ENTRY
  131. {
  132. ULONG IoControlCode; // iocontrolcode for sanity check
  133. DWORD dwFlags; // bits indicating what type of strucutre is passed in
  134. DWORD dwLength; // size of the passed in strucutre
  135. }
  136. CSC_IOCTL_ENTRY;
  137. // defines for the flags in dwFlags field in CSC_IOCTL_ENTRY structure
  138. #define FLAG_CSC_IOCTL_PQPARAMS 0x00000001
  139. #define FLAG_CSC_IOCTL_COPYPARAMS 0x00000002
  140. #define FLAG_CSC_IOCTL_SHADOWINFO 0x00000004
  141. #define FLAG_CSC_IOCTL_COPYCHUNKCONTEXT 0x00000008
  142. #define FLAG_CSC_IOCTL_GLOBALSTATUS 0x00000010
  143. #define FLAG_CSC_IOCTL_BUFFERTYPE_MASK 0xff
  144. #define SMB_CSC_BITS_TO_DATABASE_CSC_BITS(CscFlags) (((CscFlags) << 4) & SHARE_CACHING_MASK)
  145. #define DATABASE_CSC_BITS_TO_SMB_CSC_BITS(CscFlags) (((CscFlags) & SHARE_CACHING_MASK) >> 4)
  146. // #define IOCTL_NAME_OF_SERVER_GOING_OFFLINE (_SHADOW_IOCTL_CODE(45))
  147. #ifdef DEBUG
  148. extern ULONG HookKdPrintVector = HOOK_KDP_BADERRORS;
  149. extern ULONG HookKdPrintVectorDef = HOOK_KDP_GOOD_DEFAULT;
  150. #endif
  151. #ifdef RX_PRIVATE_BUILD
  152. ULONG MRxSmbCscDbgPrintF = 0; // 1;
  153. #endif //ifdef RX_PRIVATE_BUILD
  154. //
  155. // this variable is used to "help" the agent know when to recalculate
  156. // the reference priorities
  157. //
  158. ULONG MRxSmbCscNumberOfShadowOpens = 0;
  159. ULONG MRxSmbCscActivityThreshold = 16;
  160. ULONG MRxSmbCscInitialRefPri = MAX_PRI;
  161. // these two lists are used to list up all the netroots and fcbs
  162. // that have shadows so that we can find them for the ioctls. today
  163. // are just doubly-linked lists but we can anticipate that this may
  164. // become a performance issue, particularly for fcbs. at that point, we
  165. // can either change to bucket hashing or tries
  166. LIST_ENTRY xCscFcbsList;
  167. PIRP vIrpReint = NULL;
  168. #define MRxSmbCscAddReverseFcbTranslation(smbFcb) {\
  169. InsertTailList(&xCscFcbsList, \
  170. &(smbFcb)->ShadowReverseTranslationLinks); \
  171. }
  172. #define MRxSmbCscRemoveReverseFcbTranslation(smbFcb) {\
  173. RemoveEntryList(&(smbFcb)->ShadowReverseTranslationLinks); \
  174. }
  175. PMRX_SMB_FCB
  176. MRxSmbCscRecoverMrxFcbFromFdb (
  177. IN PFDB Fdb
  178. );
  179. BOOL
  180. CscDfsShareIsInReint(
  181. IN PRX_CONTEXT RxContext
  182. );
  183. //
  184. // From zwapi.h.
  185. //
  186. NTSYSAPI
  187. NTSTATUS
  188. NTAPI
  189. ZwSetSecurityObject(
  190. IN HANDLE Handle,
  191. IN SECURITY_INFORMATION SecurityInformation,
  192. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  193. );
  194. NTSTATUS
  195. CaptureInputBufferIfNecessaryAndProbe(
  196. DWORD IoControlCode,
  197. PRX_CONTEXT pRxContext,
  198. PBYTE InputBuffer,
  199. LPCAPTURE_BUFFERS lpCapBuff,
  200. PBYTE *ppAuxBuf,
  201. PBYTE *ppOrgBuf,
  202. PBYTE *ppReturnBuffer
  203. );
  204. NTSTATUS
  205. ValidateCopyParams(
  206. LPCOPYPARAMS lpCP
  207. );
  208. NTSTATUS
  209. ValidateShadowInfo(
  210. DWORD IoControlCode,
  211. LPSHADOWINFO lpSI,
  212. LPBYTE *ppAuxBuf,
  213. LPBYTE *ppOrgBuf
  214. );
  215. NTSTATUS
  216. ValidateCopyChunkContext(
  217. PRX_CONTEXT RxContext,
  218. DWORD IoControlCode
  219. );
  220. NTSTATUS
  221. CscProbeForReadWrite(
  222. PBYTE pBuffer,
  223. DWORD dwSize
  224. );
  225. NTSTATUS
  226. CscProbeAndCaptureForReadWrite(
  227. PBYTE pBuffer,
  228. DWORD dwSize,
  229. PBYTE *ppAuxBuf
  230. );
  231. VOID
  232. CopyBackIfNecessary(
  233. DWORD IoControlCode,
  234. PBYTE InputBuffer,
  235. LPCAPTURE_BUFFERS lpCapBuff,
  236. PBYTE pAuxBuf,
  237. PBYTE pOrgBuf,
  238. BOOL fSuccess
  239. );
  240. VOID
  241. EnterShadowCritRx(
  242. PRX_CONTEXT pRxContext
  243. );
  244. VOID
  245. LeaveShadowCritRx(
  246. PRX_CONTEXT pRxContext
  247. );
  248. #if defined(REMOTE_BOOT)
  249. NTSYSAPI
  250. NTSTATUS
  251. NTAPI
  252. ZwOpenThreadToken(
  253. IN HANDLE ThreadHandle,
  254. IN ACCESS_MASK DesiredAccess,
  255. IN BOOLEAN OpenAsSelf,
  256. OUT PHANDLE TokenHandle
  257. );
  258. NTSYSAPI
  259. NTSTATUS
  260. NTAPI
  261. ZwOpenProcessToken(
  262. IN HANDLE ProcessHandle,
  263. IN ACCESS_MASK DesiredAccess,
  264. OUT PHANDLE TokenHandle
  265. );
  266. NTSYSAPI
  267. NTSTATUS
  268. NTAPI
  269. ZwDuplicateToken(
  270. IN HANDLE ExistingTokenHandle,
  271. IN ACCESS_MASK DesiredAccess,
  272. IN POBJECT_ATTRIBUTES ObjectAttributes,
  273. IN BOOLEAN EffectiveOnly,
  274. IN TOKEN_TYPE TokenType,
  275. OUT PHANDLE NewTokenHandle
  276. );
  277. NTSYSAPI
  278. NTSTATUS
  279. NTAPI
  280. ZwAdjustPrivilegesToken (
  281. IN HANDLE TokenHandle,
  282. IN BOOLEAN DisableAllPrivileges,
  283. IN PTOKEN_PRIVILEGES NewState OPTIONAL,
  284. IN ULONG BufferLength OPTIONAL,
  285. IN PTOKEN_PRIVILEGES PreviousState OPTIONAL,
  286. OUT PULONG ReturnLength
  287. );
  288. //
  289. // From ntrtl.h.
  290. //
  291. NTSYSAPI
  292. NTSTATUS
  293. NTAPI
  294. RtlGetSaclSecurityDescriptor (
  295. PSECURITY_DESCRIPTOR SecurityDescriptor,
  296. PBOOLEAN SaclPresent,
  297. PACL *Sacl,
  298. PBOOLEAN SaclDefaulted
  299. );
  300. NTSYSAPI
  301. NTSTATUS
  302. NTAPI
  303. RtlGetGroupSecurityDescriptor (
  304. PSECURITY_DESCRIPTOR SecurityDescriptor,
  305. PSID *Group,
  306. PBOOLEAN GroupDefaulted
  307. );
  308. #endif
  309. //sigh BUBUG get this stuff into an include file.....
  310. #define SHADOW_VERSION 0x8287
  311. extern char vszShadowDir[MAX_SHADOW_DIR_NAME+1];
  312. extern PVOID lpdbShadow;
  313. //CODE.IMPROFVEMENT this should be in a .h file
  314. extern PKEVENT MRxSmbAgentSynchronizationEvent;
  315. extern PKEVENT MRxSmbAgentFillEvent;
  316. extern PSMBCEDB_SERVER_ENTRY CscServerEntryBeingTransitioned;
  317. extern ULONG CscSessionIdCausingTransition;
  318. extern ULONG vulDatabaseStatus;
  319. extern unsigned cntInodeTransactions;
  320. extern VOID
  321. MRxSmbDecrementSrvOpenCount(
  322. PSMBCEDB_SERVER_ENTRY pServerEntry,
  323. LONG SrvOpenServerVersion,
  324. PMRX_SRV_OPEN SrvOpen);
  325. VOID ValidateSmbFcbList(VOID);
  326. BOOL SetOfflineOpenStatusForShare(
  327. CSC_SHARE_HANDLE hShare,
  328. CSC_SHADOW_HANDLE hRootDir,
  329. OUT PULONG pShareStatus
  330. );
  331. LONG CSCBeginReint(
  332. IN OUT PRX_CONTEXT RxContext,
  333. IN OUT LPSHADOWINFO lpSI
  334. );
  335. ULONG CSCEndReint(
  336. IN OUT LPSHADOWINFO lpSI
  337. );
  338. VOID CSCCancelReint(
  339. IN PDEVICE_OBJECT DeviceObject,
  340. IN PIRP ThisIrp
  341. );
  342. VOID
  343. CreateFakeFind32(
  344. CSC_SHADOW_HANDLE hDir,
  345. _WIN32_FIND_DATA *pFind32,
  346. PRX_CONTEXT RxContext,
  347. BOOLEAN LastComponentInName
  348. );
  349. NTSTATUS
  350. OkToDeleteObject(
  351. HSHADOW hDir,
  352. HSHADOW hShadow,
  353. _WIN32_FIND_DATA *Find32,
  354. ULONG uShadowStatus,
  355. BOOLEAN fDisconnected
  356. );
  357. #pragma alloc_text(PAGE, MRxSmbCSCExceptionFilter)
  358. #if defined(REMOTE_BOOT)
  359. #pragma alloc_text(PAGE, ZwImpersonateSelf)
  360. #pragma alloc_text(PAGE, ZwAdjustPrivilege)
  361. #pragma alloc_text(PAGE, RtlGetSecurityInformationFromSecurityDescriptor)
  362. #endif
  363. #pragma alloc_text(PAGE, MRxSmbInitializeCSC)
  364. #pragma alloc_text(PAGE, MRxSmbUninitializeCSC)
  365. #pragma alloc_text(PAGE, CscpAccessCheck)
  366. #pragma alloc_text(PAGE, CscAccessCheck)
  367. #pragma alloc_text(PAGE, MRxSmbCscAcquireSmbFcb)
  368. #pragma alloc_text(PAGE, MRxSmbCscReleaseSmbFcb)
  369. #pragma alloc_text(PAGE, MRxSmbCscSetFileInfoEpilogue)
  370. #pragma alloc_text(PAGE, MRxSmbCscIoCtl)
  371. #pragma alloc_text(PAGE, MRxSmbCscObtainShareHandles)
  372. #pragma alloc_text(PAGE, MRxSmbCscFillWithoutNamesFind32FromFcb)
  373. #pragma alloc_text(PAGE, MRxSmbCscGetFileInfoForCshadow)
  374. #pragma alloc_text(PAGE, MRxSmbGetFileInfoFromServer)
  375. #pragma alloc_text(PAGE, MRxSmbCscIsFatNameValid)
  376. #pragma alloc_text(PAGE, MRxSmbCscGenerate83NameAsNeeded)
  377. #pragma alloc_text(PAGE, MRxSmbCscCreateShadowFromPath)
  378. #pragma alloc_text(PAGE, RefreshShadow)
  379. #pragma alloc_text(PAGE, MRxSmbCscIsThisACopyChunkOpen)
  380. #pragma alloc_text(PAGE, SmbPseExchangeStart_CloseCopyChunk)
  381. #pragma alloc_text(PAGE, MRxSmbCscCloseExistingThruOpen)
  382. #pragma alloc_text(PAGE, MRxSmbCscCreatePrologue)
  383. #pragma alloc_text(PAGE, MRxSmbCscObtainShadowHandles)
  384. #if defined(REMOTE_BOOT)
  385. #pragma alloc_text(PAGE, MRxSmbCscSetSecurityOnShadow)
  386. #endif
  387. #pragma alloc_text(PAGE, MRxSmbCscCreateEpilogue)
  388. #pragma alloc_text(PAGE, MRxSmbCscDeleteAfterCloseEpilogue)
  389. #pragma alloc_text(PAGE, GetPathLevelFromUnicodeString)
  390. #pragma alloc_text(PAGE, MRxSmbCscRenameEpilogue)
  391. #pragma alloc_text(PAGE, MRxSmbCscCloseShadowHandle)
  392. #pragma alloc_text(PAGE, MRxSmbCscFixupFindFirst)
  393. #pragma alloc_text(PAGE, MRxSmbCscLocateAndFillFind32WithinSmbbuf)
  394. #pragma alloc_text(PAGE, MRxSmbCscGetFileInfoFromServerWithinExchange)
  395. #pragma alloc_text(PAGE, MRxSmbCscUpdateShadowFromClose)
  396. #pragma alloc_text(PAGE, MRxSmbCscDeallocateForFcb)
  397. #pragma alloc_text(PAGE, MRxSmbCscRecoverMrxFcbFromFdb)
  398. #pragma alloc_text(PAGE, MRxSmbCscFindFdbFromHShadow)
  399. #pragma alloc_text(PAGE, MRxSmbCscFindResourceFromHandlesWithModify)
  400. #pragma alloc_text(PAGE, MRxSmbCscFindLocalFlagsFromFdb)
  401. #pragma alloc_text(PAGE, MRxSmbCscSetSecurityPrologue)
  402. #pragma alloc_text(PAGE, MRxSmbCscSetSecurityEpilogue)
  403. #pragma alloc_text(PAGE, CaptureInputBufferIfNecessaryAndProbe)
  404. #pragma alloc_text(PAGE, ValidateCopyParams)
  405. #pragma alloc_text(PAGE, ValidateShadowInfo)
  406. #pragma alloc_text(PAGE, ValidateCopyChunkContext)
  407. #pragma alloc_text(PAGE, CscProbeForReadWrite)
  408. #pragma alloc_text(PAGE, CopyBackIfNecessary)
  409. #pragma alloc_text(PAGE, ValidateSmbFcbList)
  410. #pragma alloc_text(PAGE, SetOfflineOpenStatusForShare)
  411. #pragma alloc_text(PAGE, MRxSmbCscLocalFileOpen)
  412. #pragma alloc_text(PAGE, CSCCheckLocalOpens)
  413. #pragma alloc_text(PAGE, IsCSCBusy)
  414. #pragma alloc_text(PAGE, ClearCSCStateOnRedirStructures)
  415. #pragma alloc_text(PAGE, CscDfsShareIsInReint)
  416. #pragma alloc_text(PAGE, CloseOpenFiles)
  417. #pragma alloc_text(PAGE, CreateFakeFind32)
  418. #pragma alloc_text(PAGE, OkToDeleteObject)
  419. #pragma alloc_text(PAGE, IoctlGetDebugInfo)
  420. //remember whether to delete the link
  421. BOOLEAN MRxSmbCscLinkCreated = FALSE;
  422. PCONTEXT CSCExpCXR;
  423. PEXCEPTION_RECORD CSCExpEXR;
  424. PVOID CSCExpAddr;
  425. NTSTATUS CSCExpCode;
  426. LONG
  427. MRxSmbCSCExceptionFilter (
  428. IN PRX_CONTEXT RxContext,
  429. IN PEXCEPTION_POINTERS ExceptionPointer
  430. )
  431. /*++
  432. Routine Description:
  433. This routine is used to decide if we should or should not handle
  434. an exception status that is being raised. It first determines the true exception
  435. code by examining the exception record. If there is an Irp Context, then it inserts the status
  436. into the RxContext. Finally, it determines whether to handle the exception or bugcheck
  437. according to whether the except is one of the expected ones. in actuality, all exceptions are expected
  438. except for some lowlevel machine errors (see fsrtl\filter.c)
  439. Arguments:
  440. RxContext - the irp context of current operation for storing away the code.
  441. ExceptionPointer - Supplies the exception context.
  442. Return Value:
  443. ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks
  444. --*/
  445. {
  446. NTSTATUS ExceptionCode;
  447. //save these values in statics so i can see 'em on the debugger............
  448. ExceptionCode = CSCExpCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
  449. CSCExpAddr = ExceptionPointer->ExceptionRecord->ExceptionAddress;
  450. CSCExpEXR = ExceptionPointer->ExceptionRecord;
  451. CSCExpCXR = ExceptionPointer->ContextRecord;
  452. RxDbgTrace(0, Dbg, ("!!! ExceptioCode=%lx Addr=%lx EXR=%lx CXR=%lx\n", CSCExpCode, CSCExpAddr, CSCExpEXR, CSCExpCXR));
  453. RxLog(("!!! %lx %lx %lx %lx\n", CSCExpCode, CSCExpAddr, CSCExpEXR, CSCExpCXR));
  454. // ASSERT(FALSE);
  455. return EXCEPTION_EXECUTE_HANDLER;
  456. }
  457. #if defined(REMOTE_BOOT)
  458. //
  459. // Stolen from RTL, changed to use Zw APis.
  460. //
  461. NTSTATUS
  462. ZwImpersonateSelf(
  463. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
  464. )
  465. /*++
  466. Routine Description:
  467. This routine may be used to obtain an Impersonation token representing
  468. your own process's context. This may be useful for enabling a privilege
  469. for a single thread rather than for the entire process; or changing
  470. the default DACL for a single thread.
  471. The token is assigned to the callers thread.
  472. Arguments:
  473. ImpersonationLevel - The level to make the impersonation token.
  474. Return Value:
  475. STATUS_SUCCESS - The thread is now impersonating the calling process.
  476. Other - Status values returned by:
  477. ZwOpenProcessToken()
  478. ZwDuplicateToken()
  479. ZwSetInformationThread()
  480. --*/
  481. {
  482. NTSTATUS
  483. Status,
  484. IgnoreStatus;
  485. HANDLE
  486. Token1,
  487. Token2;
  488. OBJECT_ATTRIBUTES
  489. ObjectAttributes;
  490. SECURITY_QUALITY_OF_SERVICE
  491. Qos;
  492. InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL);
  493. Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  494. Qos.ImpersonationLevel = ImpersonationLevel;
  495. Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  496. Qos.EffectiveOnly = FALSE;
  497. ObjectAttributes.SecurityQualityOfService = &Qos;
  498. Status = ZwOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE, &Token1 );
  499. if (NT_SUCCESS(Status)) {
  500. Status = ZwDuplicateToken(
  501. Token1,
  502. TOKEN_IMPERSONATE,
  503. &ObjectAttributes,
  504. FALSE, //EffectiveOnly
  505. TokenImpersonation,
  506. &Token2
  507. );
  508. if (NT_SUCCESS(Status)) {
  509. Status = ZwSetInformationThread(
  510. NtCurrentThread(),
  511. ThreadImpersonationToken,
  512. &Token2,
  513. sizeof(HANDLE)
  514. );
  515. IgnoreStatus = ZwClose( Token2 );
  516. }
  517. IgnoreStatus = ZwClose( Token1 );
  518. }
  519. return(Status);
  520. }
  521. NTSTATUS
  522. ZwAdjustPrivilege(
  523. ULONG Privilege,
  524. BOOLEAN Enable,
  525. BOOLEAN Client,
  526. PBOOLEAN WasEnabled
  527. )
  528. /*++
  529. Routine Description:
  530. This procedure enables or disables a privilege process-wide.
  531. Arguments:
  532. Privilege - The lower 32-bits of the privilege ID to be enabled or
  533. disabled. The upper 32-bits is assumed to be zero.
  534. Enable - A boolean indicating whether the privilege is to be enabled
  535. or disabled. TRUE indicates the privilege is to be enabled.
  536. FALSE indicates the privilege is to be disabled.
  537. Client - A boolean indicating whether the privilege should be adjusted
  538. in a client token or the process's own token. TRUE indicates
  539. the client's token should be used (and an error returned if there
  540. is no client token). FALSE indicates the process's token should
  541. be used.
  542. WasEnabled - points to a boolean to receive an indication of whether
  543. the privilege was previously enabled or disabled. TRUE indicates
  544. the privilege was previously enabled. FALSE indicates the privilege
  545. was previoulsy disabled. This value is useful for returning the
  546. privilege to its original state after using it.
  547. Return Value:
  548. STATUS_SUCCESS - The privilege has been sucessfully enabled or disabled.
  549. STATUS_PRIVILEGE_NOT_HELD - The privilege is not held by the specified context.
  550. Other status values as may be returned by:
  551. ZwOpenProcessToken()
  552. ZwAdjustPrivilegesToken()
  553. --*/
  554. {
  555. NTSTATUS
  556. Status,
  557. TmpStatus;
  558. HANDLE
  559. Token;
  560. LUID
  561. LuidPrivilege;
  562. PTOKEN_PRIVILEGES
  563. NewPrivileges,
  564. OldPrivileges;
  565. ULONG
  566. Length;
  567. UCHAR
  568. Buffer1[sizeof(TOKEN_PRIVILEGES)+
  569. ((1-ANYSIZE_ARRAY)*sizeof(LUID_AND_ATTRIBUTES))],
  570. Buffer2[sizeof(TOKEN_PRIVILEGES)+
  571. ((1-ANYSIZE_ARRAY)*sizeof(LUID_AND_ATTRIBUTES))];
  572. NewPrivileges = (PTOKEN_PRIVILEGES)Buffer1;
  573. OldPrivileges = (PTOKEN_PRIVILEGES)Buffer2;
  574. //
  575. // Open the appropriate token...
  576. //
  577. if (Client == TRUE) {
  578. Status = ZwOpenThreadToken(
  579. NtCurrentThread(),
  580. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  581. FALSE,
  582. &Token
  583. );
  584. } else {
  585. Status = ZwOpenProcessToken(
  586. NtCurrentProcess(),
  587. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  588. &Token
  589. );
  590. }
  591. if (!NT_SUCCESS(Status)) {
  592. return(Status);
  593. }
  594. //
  595. // Initialize the privilege adjustment structure
  596. //
  597. LuidPrivilege = RtlConvertUlongToLuid(Privilege);
  598. NewPrivileges->PrivilegeCount = 1;
  599. NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  600. NewPrivileges->Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
  601. //
  602. // Adjust the privilege
  603. //
  604. Status = ZwAdjustPrivilegesToken(
  605. Token, // TokenHandle
  606. FALSE, // DisableAllPrivileges
  607. NewPrivileges, // NewPrivileges
  608. sizeof(Buffer1), // BufferLength
  609. OldPrivileges, // PreviousState (OPTIONAL)
  610. &Length // ReturnLength
  611. );
  612. TmpStatus = ZwClose(Token);
  613. ASSERT(NT_SUCCESS(TmpStatus));
  614. //
  615. // Map the success code NOT_ALL_ASSIGNED to an appropriate error
  616. // since we're only trying to adjust the one privilege.
  617. //
  618. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  619. Status = STATUS_PRIVILEGE_NOT_HELD;
  620. }
  621. if (NT_SUCCESS(Status)) {
  622. //
  623. // If there are no privileges in the previous state, there were
  624. // no changes made. The previous state of the privilege
  625. // is whatever we tried to change it to.
  626. //
  627. if (OldPrivileges->PrivilegeCount == 0) {
  628. (*WasEnabled) = Enable;
  629. } else {
  630. (*WasEnabled) =
  631. (OldPrivileges->Privileges[0].Attributes & SE_PRIVILEGE_ENABLED)
  632. ? TRUE : FALSE;
  633. }
  634. }
  635. return(Status);
  636. }
  637. //
  638. // May move this into RTL someday, and let it access internals directly.
  639. //
  640. NTSTATUS
  641. RtlGetSecurityInformationFromSecurityDescriptor(
  642. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  643. OUT PSECURITY_INFORMATION SecurityInformation
  644. )
  645. /*++
  646. Routine Description:
  647. This procedure sets the security information bits for fields
  648. that are valid in the security descriptor.
  649. Arguments:
  650. SecurityDescriptor - The passed-in security descriptor.
  651. SecurityInformation - Returns the bitmask.
  652. Return Value:
  653. STATUS_SUCCESS - The bitmask was returned successfully.
  654. Other status values if the security descriptor is invalid.
  655. --*/
  656. {
  657. SECURITY_INFORMATION BuiltSecurityInformation = 0;
  658. PACL TempAcl;
  659. PSID TempSid;
  660. BOOLEAN Present;
  661. BOOLEAN Defaulted;
  662. NTSTATUS Status;
  663. Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
  664. &Present,
  665. &TempAcl,
  666. &Defaulted);
  667. if (!NT_SUCCESS(Status)) {
  668. return Status;
  669. }
  670. if (Present) {
  671. BuiltSecurityInformation |= DACL_SECURITY_INFORMATION;
  672. }
  673. Status = RtlGetSaclSecurityDescriptor(SecurityDescriptor,
  674. &Present,
  675. &TempAcl,
  676. &Defaulted);
  677. if (!NT_SUCCESS(Status)) {
  678. return Status;
  679. }
  680. if (Present) {
  681. BuiltSecurityInformation |= SACL_SECURITY_INFORMATION;
  682. }
  683. Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
  684. &TempSid,
  685. &Defaulted);
  686. if (!NT_SUCCESS(Status)) {
  687. return Status;
  688. }
  689. if (TempSid != NULL) {
  690. BuiltSecurityInformation |= OWNER_SECURITY_INFORMATION;
  691. }
  692. Status = RtlGetGroupSecurityDescriptor(SecurityDescriptor,
  693. &TempSid,
  694. &Defaulted);
  695. if (!NT_SUCCESS(Status)) {
  696. return Status;
  697. }
  698. if (TempSid != NULL) {
  699. BuiltSecurityInformation |= GROUP_SECURITY_INFORMATION;
  700. }
  701. *SecurityInformation = BuiltSecurityInformation;
  702. return STATUS_SUCCESS;
  703. }
  704. #endif
  705. NTSTATUS
  706. MRxSmbInitializeCSC (
  707. PUNICODE_STRING SmbMiniRedirectorName
  708. )
  709. /*++
  710. Routine Description:
  711. This routine initializes the CSC database
  712. Arguments:
  713. SmbMiniRedirectorName - the mini redirector name
  714. Return Value:
  715. STATUS_SUCCESS if successfull otherwise appropriate error
  716. Notes:
  717. --*/
  718. {
  719. NTSTATUS Status = STATUS_SUCCESS;
  720. UNICODE_STRING CscLinkName;
  721. ULONG ii;
  722. C_ASSERT(sizeof(GENERICHEADER)==64);
  723. C_ASSERT(sizeof(INODEHEADER)==sizeof(GENERICHEADER));
  724. C_ASSERT(sizeof(SHAREHEADER)==sizeof(GENERICHEADER));
  725. C_ASSERT(sizeof(FILEHEADER)==sizeof(GENERICHEADER));
  726. C_ASSERT(sizeof(QHEADER)==sizeof(GENERICHEADER));
  727. if(!MRxSmbIsCscEnabled) {
  728. return (STATUS_SUCCESS);
  729. }
  730. try {
  731. InitializeListHead(&xCscFcbsList);
  732. ExInitializeFastMutex(&CscServerEntryTransitioningMutex);
  733. KeInitializeEvent(
  734. &CscServerEntryTransitioningEvent,
  735. NotificationEvent,
  736. FALSE);
  737. //initialize the "semaphore" for the shadow critical section......
  738. InitializeShadowCritStructures();
  739. //create a symbolic link for the agent
  740. RtlInitUnicodeString(&CscLinkName,MRXSMB_CSC_SYMLINK_NAME);
  741. IoDeleteSymbolicLink(&CscLinkName);
  742. Status = IoCreateSymbolicLink(&CscLinkName,SmbMiniRedirectorName);
  743. if (!NT_SUCCESS( Status )) {
  744. try_return( Status );
  745. }
  746. MRxSmbCscLinkCreated = TRUE;
  747. try_exit: NOTHING;
  748. } finally {
  749. if (Status != STATUS_SUCCESS) {
  750. MRxSmbUninitializeCSC();
  751. }
  752. }
  753. return(Status);
  754. }
  755. VOID
  756. MRxSmbUninitializeCSC(
  757. void
  758. )
  759. /*++
  760. Routine Description:
  761. This routine uninitializes the CSC database
  762. Notes:
  763. --*/
  764. {
  765. NTSTATUS Status;
  766. ULONG ii;
  767. if(!MRxSmbIsCscEnabled) {
  768. return;
  769. }
  770. if (MRxSmbCscLinkCreated) {
  771. UNICODE_STRING CscLinkName;
  772. RtlInitUnicodeString(&CscLinkName,MRXSMB_CSC_SYMLINK_NAME);
  773. Status = IoDeleteSymbolicLink(&CscLinkName);
  774. ASSERT(Status==STATUS_SUCCESS);
  775. }
  776. ii = CloseShadowDB();
  777. CleanupShadowCritStructures();
  778. //get rid of references on events
  779. if (MRxSmbAgentSynchronizationEvent!=NULL) {
  780. ObDereferenceObject(MRxSmbAgentSynchronizationEvent);
  781. MRxSmbAgentSynchronizationEvent = NULL;
  782. }
  783. if (MRxSmbAgentFillEvent!=NULL) {
  784. ObDereferenceObject(MRxSmbAgentFillEvent);
  785. MRxSmbAgentFillEvent = NULL;
  786. }
  787. }
  788. // The CSC database access rights are stored in terms of SID. The SID is the
  789. // user security id that persists across reboots. The retrieval of the SID
  790. // is a complicated process. This mechanism is captured by the two routines
  791. // CscRetrieveSid and CscDiscardSid. This mechanism is required to avoid
  792. // redundant copying of the SID data from the buffer allocated by the security
  793. // sub system to the redirector buffers. Consequently we need to create a new
  794. // data type which contains the SID alongwith the context ( security allocated
  795. // buffer ). This buffer is allocated on retrieval and freed on discard.
  796. NTSTATUS
  797. CscRetrieveSid(
  798. PRX_CONTEXT pRxContext,
  799. PSID_CONTEXT pSidContext)
  800. /*++
  801. Routine Description:
  802. This routine retrieves the SID associated with a given context
  803. Arguments:
  804. RxContext - the RX_CONTEXT instance
  805. pSidContext - the SID context
  806. Return Value:
  807. STATUS_SUCCESS if successfull otherwise appropriate error
  808. Notes:
  809. --*/
  810. {
  811. NTSTATUS Status;
  812. PIO_SECURITY_CONTEXT pSecurityContext;
  813. PACCESS_TOKEN pToken;
  814. pSecurityContext = pRxContext->Create.NtCreateParameters.SecurityContext;
  815. if (pSecurityContext != NULL) {
  816. pToken = pSecurityContext->AccessState->SubjectSecurityContext.ClientToken;
  817. if (pToken == NULL) {
  818. pToken = pSecurityContext->AccessState->SubjectSecurityContext.PrimaryToken;
  819. }
  820. } else {
  821. pSidContext->Context = NULL;
  822. pSidContext->pSid = NULL;
  823. return STATUS_SUCCESS;
  824. }
  825. if (pToken != NULL) {
  826. Status = SeQueryInformationToken(
  827. pToken,
  828. TokenUser,
  829. &pSidContext->Context);
  830. if (Status == STATUS_SUCCESS) {
  831. PTOKEN_USER pCurrentTokenUser;
  832. pCurrentTokenUser = (PTOKEN_USER)pSidContext->Context;
  833. pSidContext->pSid = pCurrentTokenUser->User.Sid;
  834. }
  835. }
  836. else {
  837. Status = STATUS_UNSUCCESSFUL;
  838. }
  839. return Status;
  840. }
  841. VOID
  842. CscDiscardSid(
  843. PSID_CONTEXT pSidContext)
  844. /*++
  845. Routine Description:
  846. This routine discards the sid context
  847. Arguments:
  848. pSidContext - the SID context
  849. --*/
  850. {
  851. PTOKEN_USER pTokenUser;
  852. pTokenUser = (PTOKEN_USER)pSidContext->Context;
  853. if (pTokenUser != NULL) {
  854. ASSERT(pTokenUser->User.Sid == pSidContext->pSid);
  855. ExFreePool(pTokenUser);
  856. }
  857. }
  858. BOOLEAN UseEagerEvaluation = TRUE;
  859. BOOLEAN
  860. CscpAccessCheck(
  861. PCACHED_SECURITY_INFORMATION pCachedSecurityInformation,
  862. ULONG CachedSecurityInformationLength,
  863. CSC_SID_INDEX SidIndex,
  864. ACCESS_MASK AccessMask,
  865. BOOLEAN *pSidHasAccessMask
  866. )
  867. /*++
  868. Routine Description:
  869. This routine evaluates the access rights for a given SID index with the
  870. cached security information
  871. Arguments:
  872. pCachedSecurityInformation - the cached security information
  873. CachedSecurityInformationLength - the cached security information length
  874. SidIndex - the SID index
  875. AccessMask - desired access
  876. --*/
  877. {
  878. CSC_SID_INDEX i;
  879. BOOLEAN AccessGranted = FALSE;
  880. *pSidHasAccessMask = FALSE;
  881. if (CachedSecurityInformationLength == sizeof(CACHED_SECURITY_INFORMATION)) {
  882. // Walk through the cached access rights to determine the
  883. // maximal permissible access rights.
  884. for (i = 0;
  885. ((i < CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES) &&
  886. (pCachedSecurityInformation->AccessRights[i].SidIndex != SidIndex));
  887. i++) {
  888. }
  889. if (i < CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES) {
  890. // Ensure that the desired access is a subset of the
  891. // maximal access rights allowed for this SID
  892. *pSidHasAccessMask = TRUE;
  893. AccessGranted = ((AccessMask &
  894. pCachedSecurityInformation->AccessRights[i].MaximalRights)
  895. == AccessMask);
  896. } else {
  897. // if the index cannot be found, ensure that the SID_INDEXES
  898. // are valid. If none of them are valid then we treat the
  899. // cached security information as being invalid and let the
  900. // access through
  901. for(i = 0;
  902. ((i < CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES) &&
  903. (pCachedSecurityInformation->AccessRights[i].SidIndex ==
  904. CSC_INVALID_SID_INDEX));
  905. i++);
  906. if (i == CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES) {
  907. AccessGranted = TRUE;
  908. }
  909. }
  910. } else if (CachedSecurityInformationLength == 0) {
  911. AccessGranted = TRUE;
  912. } else {
  913. AccessGranted = FALSE;
  914. }
  915. return AccessGranted;
  916. }
  917. BOOLEAN
  918. CscAccessCheck(
  919. HSHADOW hParent,
  920. HSHADOW hFile,
  921. PRX_CONTEXT RxContext,
  922. ACCESS_MASK AccessMask,
  923. PCACHED_SECURITY_INFORMATION pCachedSecurityInformationForShadow,
  924. PCACHED_SECURITY_INFORMATION pCachedSecurityInformationForShare
  925. )
  926. /*++
  927. Routine Description:
  928. This routine performs the access check for a given LUID and an ACCESS_MASK
  929. against the saved rights
  930. Arguments:
  931. Return Value:
  932. TRUE -- if access is granted
  933. FALSE -- if access is denied
  934. Notes:
  935. This routine is the primary routine for evaluating access rights. In order
  936. to acheive total encapsulation the signature of this routine needs to be
  937. specified such that the eager evaluation approach as well as the lazy
  938. evaluation approach can be supported.
  939. This is a kernel mode only routine.
  940. The ACCESS_MASK as specified in NT consists of two parts.. the lower 16 bits
  941. are specific rights ( specified by file system etc. ) while the upper 16 bits
  942. are generic rights common to all components.
  943. The cached access rights stored in the CSC data structure store the specific
  944. rights. Consequently the ACCESS_MASK specified needs to be stripped of the
  945. generic rights bit before comparing them.
  946. --*/
  947. {
  948. NTSTATUS Status;
  949. BOOLEAN AccessGranted = FALSE, SidHasAccessMask;
  950. SID_CONTEXT SidContext;
  951. Status = CscRetrieveSid(
  952. RxContext,
  953. &SidContext);
  954. if (Status == STATUS_SUCCESS) {
  955. if (UseEagerEvaluation) {
  956. HSHARE hShare = 0;
  957. CACHED_SECURITY_INFORMATION CachedSecurityInformation;
  958. ULONG BytesReturned,SidLength;
  959. DWORD CscStatus;
  960. CSC_SID_INDEX SidIndex;
  961. if (SidContext.pSid != NULL) {
  962. SidLength = RtlLengthSid(
  963. SidContext.pSid);
  964. SidIndex = CscMapSidToIndex(
  965. SidContext.pSid,
  966. SidLength);
  967. } else {
  968. SidIndex = CSC_INVALID_SID_INDEX;
  969. }
  970. if (SidIndex == CSC_INVALID_SID_INDEX) {
  971. // The sid was not located in the existing Sid mappings
  972. // Map this Sid to that of a Guest
  973. SidIndex = CSC_GUEST_SID_INDEX;
  974. }
  975. // Check the share level ACL if there is any.
  976. if (GetAncestorsHSHADOW(
  977. hFile,
  978. NULL,
  979. &hShare)) {
  980. BytesReturned = sizeof(CachedSecurityInformation);
  981. CscStatus = GetShareInfoEx(
  982. hShare,
  983. NULL,
  984. NULL,
  985. &CachedSecurityInformation,
  986. &BytesReturned);
  987. // return the info if the caller want's it
  988. if (pCachedSecurityInformationForShare)
  989. {
  990. *pCachedSecurityInformationForShare = CachedSecurityInformation;
  991. }
  992. if (CscStatus == ERROR_SUCCESS) {
  993. AccessGranted = CscpAccessCheck(
  994. &CachedSecurityInformation,
  995. BytesReturned,
  996. SidIndex,
  997. AccessMask & FILE_SHARE_VALID_FLAGS,
  998. &SidHasAccessMask
  999. );
  1000. // if access was not granted for a non-guest
  1001. // because there was no accessmask for him, then check whether
  1002. // he should be allowed access as guest
  1003. if (!AccessGranted && (SidIndex != CSC_GUEST_SID_INDEX) && !SidHasAccessMask)
  1004. {
  1005. AccessGranted = CscpAccessCheck(
  1006. &CachedSecurityInformation,
  1007. BytesReturned,
  1008. CSC_GUEST_SID_INDEX,
  1009. AccessMask & FILE_SHARE_VALID_FLAGS,
  1010. &SidHasAccessMask
  1011. );
  1012. }
  1013. }
  1014. }
  1015. if (AccessGranted) {
  1016. BytesReturned = sizeof(CachedSecurityInformation);
  1017. CscStatus = GetShadowInfoEx(
  1018. hParent,
  1019. hFile,
  1020. NULL,
  1021. NULL,
  1022. NULL,
  1023. &CachedSecurityInformation,
  1024. &BytesReturned);
  1025. if (CscStatus == ERROR_SUCCESS) {
  1026. // return the info if the caller want's it
  1027. if (pCachedSecurityInformationForShadow)
  1028. {
  1029. *pCachedSecurityInformationForShadow = CachedSecurityInformation;
  1030. }
  1031. AccessGranted = CscpAccessCheck(
  1032. &CachedSecurityInformation,
  1033. BytesReturned,
  1034. SidIndex,
  1035. AccessMask & 0x1ff,
  1036. &SidHasAccessMask
  1037. );
  1038. // if access was not granted for a non-guest
  1039. // because there was no accessmask for him, then check whether
  1040. // he should be allowed access as guest
  1041. if (!AccessGranted && (SidIndex != CSC_GUEST_SID_INDEX) && !SidHasAccessMask)
  1042. {
  1043. AccessGranted = CscpAccessCheck(
  1044. &CachedSecurityInformation,
  1045. BytesReturned,
  1046. CSC_GUEST_SID_INDEX,
  1047. AccessMask & 0x1ff,
  1048. &SidHasAccessMask
  1049. );
  1050. }
  1051. }
  1052. }
  1053. }
  1054. CscDiscardSid(&SidContext);
  1055. }
  1056. if (RxContext->CurrentIrp && (RxContext->CurrentIrp->Tail.Overlay.OriginalFileObject->FileName.Length > 0)) {
  1057. RxDbgTrace(0,Dbg,
  1058. ("CscAccessCheck for %wZ DesiredAccess %lx AccessGranted %lx\n",
  1059. &RxContext->CurrentIrp->Tail.Overlay.OriginalFileObject->FileName,
  1060. AccessMask,
  1061. AccessGranted));
  1062. } else {
  1063. RxDbgTrace(0,Dbg,
  1064. ("CscAccessCheck for DesiredAccess %lx AccessGranted %lx\n",
  1065. AccessMask,
  1066. AccessGranted));
  1067. }
  1068. return AccessGranted;
  1069. }
  1070. NTSTATUS
  1071. MRxSmbCscAcquireSmbFcb (
  1072. IN OUT PRX_CONTEXT RxContext,
  1073. IN ULONG TypeOfAcquirePlusFlags,
  1074. OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. This routine performs the readwrite synchronization that is required for
  1079. keeping the cache consistent. Basically, the rule is many-readers-one-writer.
  1080. This code relies on being able to use the minirdr context for links.
  1081. A key concept here is that if we are entered and the minirdr context
  1082. is nonull, then we are being reentered(!) after being queued and our
  1083. acquire has succeeded.
  1084. Arguments:
  1085. RxContext - the RDBSS context
  1086. TypeOfAcquirePlusFlags -- flags for resource acquisition
  1087. SmbFcbHoldingState -- resource holding state on exit
  1088. Return Value:
  1089. NTSTATUS - STATUS_SUCCESS - the lock was acquired
  1090. STATUS_CANCELLED - the operation was cancelled
  1091. while you were waiting
  1092. STATUS_PENDING - the lock was not acquire; the operation
  1093. will be issued when you do get it
  1094. STATUS_LOCK_NOT_GRANTED - couldn't get it and fail
  1095. immediately was spec'd
  1096. Notes:
  1097. --*/
  1098. {
  1099. NTSTATUS Status = STATUS_PENDING;
  1100. RxCaptureFcb;
  1101. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1102. BOOLEAN MutexAcquired = FALSE;
  1103. DEBUG_ONLY_DECL(BOOLEAN HadToWait = FALSE;)
  1104. USHORT TypeOfAcquire = (USHORT)TypeOfAcquirePlusFlags;
  1105. BOOLEAN FailImmediately = BooleanFlagOn(TypeOfAcquirePlusFlags,
  1106. FailImmediately_SmbFcbAcquire);
  1107. BOOLEAN DroppingFcbLock = BooleanFlagOn(TypeOfAcquirePlusFlags,
  1108. DroppingFcbLock_SmbFcbAcquire);
  1109. PMRXSMBCSC_SYNC_RX_CONTEXT pRxSyncContext
  1110. = MRxSmbGetMinirdrContextForCscSync(RxContext);
  1111. RxDbgTrace(0,Dbg,("MRxSmbCscAcquireSmbFcb"
  1112. " %08lx %08lx %08lx %08lx <%wZ>\n",
  1113. RxContext, TypeOfAcquire,
  1114. smbFcb, smbFcb->CscOutstandingReaders,
  1115. GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)));
  1116. ASSERT ((TypeOfAcquire==Shared_SmbFcbAcquire)
  1117. ||(TypeOfAcquire==Exclusive_SmbFcbAcquire));
  1118. ASSERT (sizeof(MRXSMBCSC_SYNC_RX_CONTEXT) <= MRX_CONTEXT_SIZE);
  1119. ExAcquireFastMutex(&MRxSmbSerializationMutex);
  1120. MutexAcquired = TRUE;
  1121. ASSERT(pRxSyncContext->Dummy == 0);
  1122. if (pRxSyncContext->TypeOfAcquire == 0) {
  1123. pRxSyncContext->TypeOfAcquire = TypeOfAcquire;
  1124. pRxSyncContext->FcbLockWasDropped = FALSE;
  1125. if (smbFcb->CscReadWriteWaitersList.Flink==NULL) {
  1126. InitializeListHead(&smbFcb->CscReadWriteWaitersList);
  1127. }
  1128. do {
  1129. if (pRxSyncContext->FcbLockWasDropped){
  1130. NTSTATUS AStatus;
  1131. RxDbgTrace(
  1132. 0,Dbg,
  1133. ("MRxSmbCscAcquireSmbFcb %08lx acquireing fcblock\n",
  1134. RxContext));
  1135. Status = RxAcquireExclusiveFcbResourceInMRx(capFcb);
  1136. if (Status != STATUS_SUCCESS) {
  1137. break;
  1138. }
  1139. pRxSyncContext->FcbLockWasDropped = FALSE;
  1140. Status = STATUS_PENDING;
  1141. // Acquire the mutex again
  1142. ExAcquireFastMutex(&MRxSmbSerializationMutex);
  1143. MutexAcquired = TRUE;
  1144. }
  1145. //if no one is waiting, maybe we can get right in.....
  1146. if (IsListEmpty(&smbFcb->CscReadWriteWaitersList)) {
  1147. if (TypeOfAcquire==Shared_SmbFcbAcquire) {
  1148. if (smbFcb->CscOutstandingReaders >= 0) {
  1149. smbFcb->CscOutstandingReaders++;
  1150. Status = STATUS_SUCCESS;
  1151. }
  1152. } else {
  1153. if (smbFcb->CscOutstandingReaders == 0) {
  1154. smbFcb->CscOutstandingReaders--; //sets to -1
  1155. Status = STATUS_SUCCESS;
  1156. }
  1157. }
  1158. }
  1159. if ((Status == STATUS_PENDING) && FailImmediately) {
  1160. Status = STATUS_LOCK_NOT_GRANTED;
  1161. }
  1162. if (Status == STATUS_PENDING) {
  1163. InsertTailList(&smbFcb->CscReadWriteWaitersList,
  1164. &pRxSyncContext->CscSyncLinks);
  1165. if (DroppingFcbLock) {
  1166. RxDbgTrace(
  1167. 0,Dbg,
  1168. ("MRxSmbCscAcquireSmbFcb %08lx dropping fcblock\n",
  1169. RxContext));
  1170. RxReleaseFcbResourceInMRx(capFcb);
  1171. pRxSyncContext->FcbLockWasDropped = TRUE;
  1172. }
  1173. if (FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)) {
  1174. ASSERT(Status == STATUS_PENDING);
  1175. goto FINALLY;
  1176. }
  1177. KeInitializeEvent( &RxContext->SyncEvent,
  1178. NotificationEvent,
  1179. FALSE );
  1180. ExReleaseFastMutex( &MRxSmbSerializationMutex );
  1181. MutexAcquired = FALSE;
  1182. RxWaitSync( RxContext );
  1183. if (BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_CANCELLED)) {
  1184. Status = STATUS_CANCELLED;
  1185. } else {
  1186. Status = STATUS_SUCCESS;
  1187. }
  1188. }
  1189. } while ( (pRxSyncContext->FcbLockWasDropped) && (Status == STATUS_SUCCESS) );
  1190. } else {
  1191. Status = STATUS_SUCCESS;
  1192. DbgDoit(
  1193. HadToWait = TRUE;
  1194. )
  1195. }
  1196. FINALLY:
  1197. ASSERT(pRxSyncContext->Dummy == 0);
  1198. if (MutexAcquired) {
  1199. ExReleaseFastMutex(&MRxSmbSerializationMutex);
  1200. }
  1201. if (Status == STATUS_SUCCESS) {
  1202. *SmbFcbHoldingState = TypeOfAcquire;
  1203. RxDbgTrace(0,Dbg,("MRxSmbCscAcquireSmbFcb"
  1204. " %08lx acquired %s %s c=%08lx,%08lx\n",
  1205. RxContext,
  1206. (TypeOfAcquire==Shared_SmbFcbAcquire)
  1207. ?"Shared":"Exclusive",
  1208. (HadToWait)?"HadToWait":"W/O waiting",
  1209. smbFcb->CscOutstandingReaders));
  1210. }
  1211. return(Status);
  1212. }
  1213. VOID
  1214. MRxSmbCscReleaseSmbFcb (
  1215. IN OUT PRX_CONTEXT RxContext,
  1216. IN SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. This routine performs the readwrite synchronization that is required for
  1221. keeping the cache consistent. Basically, the rule is many-readers-one-writer.
  1222. This code relies on being able to use the minirdr context for links.
  1223. A key concept here is that if we are entered and the minirdr context
  1224. is nonull, then we are being reentered(!) after being queued and our
  1225. acquire has succeeded.
  1226. Arguments:
  1227. RxContext - the RDBSS context
  1228. Return Value:
  1229. Notes:
  1230. --*/
  1231. {
  1232. NTSTATUS Status = STATUS_PENDING;
  1233. RxCaptureFcb;
  1234. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1235. BOOLEAN Reader = (RxContext->MajorFunction == IRP_MJ_READ);
  1236. PMRXSMBCSC_SYNC_RX_CONTEXT pRxSyncContext
  1237. = MRxSmbGetMinirdrContextForCscSync(RxContext);
  1238. RxDbgTrace(0,Dbg,("MRxSmbCscReleaseSmbFcb entry"
  1239. " %08lx %08lx %08lx <%wZ>\n",
  1240. RxContext, smbFcb,
  1241. smbFcb->CscOutstandingReaders,
  1242. GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)));
  1243. ASSERT(pRxSyncContext->Dummy == 0);
  1244. ASSERT(*SmbFcbHoldingState!=SmbFcb_NotHeld);
  1245. ExAcquireFastMutex(&MRxSmbSerializationMutex);
  1246. //first, undo my doings.....
  1247. if (*SmbFcbHoldingState == SmbFcb_HeldShared) {
  1248. ASSERT(smbFcb->CscOutstandingReaders>0);
  1249. smbFcb->CscOutstandingReaders--;
  1250. } else {
  1251. ASSERT(smbFcb->CscOutstandingReaders==-1);
  1252. smbFcb->CscOutstandingReaders++; //sets it to zero
  1253. }
  1254. //now start up some guys who may be waiting
  1255. if (!IsListEmpty(&smbFcb->CscReadWriteWaitersList)) {
  1256. PLIST_ENTRY ListEntry = smbFcb->CscReadWriteWaitersList.Flink;
  1257. for (;ListEntry != &smbFcb->CscReadWriteWaitersList;) {
  1258. PLIST_ENTRY ThisListEntry = ListEntry;
  1259. PMRXSMBCSC_SYNC_RX_CONTEXT innerRxSyncContext
  1260. = CONTAINING_RECORD(ListEntry,
  1261. MRXSMBCSC_SYNC_RX_CONTEXT,
  1262. CscSyncLinks);
  1263. PRX_CONTEXT innerRxContext
  1264. = CONTAINING_RECORD(innerRxSyncContext,
  1265. RX_CONTEXT,
  1266. MRxContext[0]);
  1267. ULONG innerTypeOfAcquire = (innerRxSyncContext->TypeOfAcquire);
  1268. //move down the list before removing this entry!!!
  1269. ListEntry = ListEntry->Flink;
  1270. // in the followng, Routine is used to restart an async guy. only
  1271. // create, read, and write currently come thru here and of these
  1272. // only read and write are async. so it is okay to ignore create
  1273. // w.r.t. seeting the Routine
  1274. ASSERT(innerRxSyncContext->Dummy == 0);
  1275. if (!innerRxSyncContext->FcbLockWasDropped) {
  1276. if (innerTypeOfAcquire==Shared_SmbFcbAcquire) {
  1277. if (smbFcb->CscOutstandingReaders < 0) break;
  1278. smbFcb->CscOutstandingReaders++;
  1279. } else {
  1280. if (smbFcb->CscOutstandingReaders != 0) break;
  1281. smbFcb->CscOutstandingReaders--; //sets to -1
  1282. }
  1283. }
  1284. ASSERT(&innerRxSyncContext->CscSyncLinks == ThisListEntry);
  1285. RemoveEntryList(ThisListEntry);
  1286. RxDbgTrace(
  1287. 0,Dbg,
  1288. ("MRxSmbCscReleaseSmbFcb acquired after for %s c=%08lx, %08lx\n",
  1289. (innerTypeOfAcquire==Shared_SmbFcbAcquire)
  1290. ?"Shared":"Exclusive",
  1291. smbFcb->CscOutstandingReaders,
  1292. innerRxContext));
  1293. if (FlagOn(innerRxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)) {
  1294. NTSTATUS PostStatus;
  1295. DbgDoit(InitializeListHead(&innerRxSyncContext->CscSyncLinks);)
  1296. PostStatus = RxPostToWorkerThread(
  1297. MRxSmbDeviceObject,
  1298. CriticalWorkQueue,
  1299. &innerRxContext->WorkQueueItem,
  1300. MRxSmbResumeAsyncReadWriteRequests,
  1301. innerRxContext);
  1302. ASSERT(PostStatus == STATUS_SUCCESS);
  1303. } else {
  1304. RxSignalSynchronousWaiter(innerRxContext);
  1305. }
  1306. }
  1307. }
  1308. ASSERT(smbFcb->CscOutstandingReaders>=-1);
  1309. ExReleaseFastMutex(&MRxSmbSerializationMutex);
  1310. *SmbFcbHoldingState = SmbFcb_NotHeld;
  1311. RxDbgTrace(0,Dbg,("MRxSmbCscReleaseSmbFcb exit"
  1312. " %08lx %08lx\n", RxContext, smbFcb->CscOutstandingReaders));
  1313. }
  1314. VOID
  1315. MRxSmbCscSetFileInfoEpilogue (
  1316. IN OUT PRX_CONTEXT RxContext,
  1317. IN OUT PNTSTATUS Status
  1318. )
  1319. /*++
  1320. Routine Description:
  1321. This routine performs the tail of a write operation for CSC. In
  1322. particular, if the written data overlaps or extends the cached prefix
  1323. then we write the data into the cache.
  1324. The status of the write operation is passed in case we someday find
  1325. things are so messed up that we want to return a failure even after
  1326. a successful read. not today however...
  1327. Arguments:
  1328. RxContext - the RDBSS context
  1329. Return Value:
  1330. NTSTATUS - The return status for the operation
  1331. Notes:
  1332. --*/
  1333. {
  1334. NTSTATUS LocalStatus = STATUS_SUCCESS;
  1335. ULONG iRet,ShadowFileLength;
  1336. RxCaptureFcb;RxCaptureFobx;
  1337. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1338. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  1339. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1340. BOOLEAN EnteredCriticalSection = FALSE;
  1341. FILE_INFORMATION_CLASS FileInformationClass;
  1342. PVOID pBuffer;
  1343. ULONG BufferLength;
  1344. _WIN32_FIND_DATA Find32;
  1345. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  1346. = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  1347. BOOLEAN fDisconnected;
  1348. ULONG uShadowStatus;
  1349. DWORD dwNotifyFilter=0;
  1350. if(!MRxSmbIsCscEnabled ||
  1351. (fShadow == 0)||
  1352. (!smbFcb->hShadow)
  1353. ) {
  1354. return;
  1355. }
  1356. fDisconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  1357. RxDbgTrace(+1, Dbg,
  1358. ("MRxSmbCscSetFileInfoEpilogue...%08lx on handle %08lx\n",
  1359. RxContext,
  1360. smbSrvOpen->hfShadow ));
  1361. if (*Status != STATUS_SUCCESS) {
  1362. RxDbgTrace(-1, Dbg, ("MRxSmbCscSetFileInfoEpilogue exit w/o extending -> %08lx\n", Status ));
  1363. goto FINALLY;
  1364. }
  1365. FileInformationClass = RxContext->Info.FileInformationClass;
  1366. pBuffer = RxContext->Info.Buffer;
  1367. BufferLength = RxContext->Info.Length;
  1368. RxDbgTrace(0, Dbg,
  1369. ("MRxSmbCscSetFileInfoEpilogue: Class %08lx size %08lx\n",
  1370. FileInformationClass,BufferLength));
  1371. switch (FileInformationClass) {
  1372. case FileBasicInformation:
  1373. break;
  1374. case FileAllocationInformation:
  1375. break;
  1376. case FileEndOfFileInformation:
  1377. break;
  1378. case FileDispositionInformation:
  1379. break;
  1380. case FileRenameInformation:
  1381. default:
  1382. goto FINALLY;
  1383. }
  1384. EnterShadowCritRx(RxContext);
  1385. EnteredCriticalSection = TRUE;
  1386. if(GetShadowInfo(smbFcb->hParentDir,
  1387. smbFcb->hShadow,
  1388. &Find32,
  1389. &uShadowStatus, NULL) < SRET_OK) {
  1390. goto FINALLY;
  1391. }
  1392. // Bypass the shadow if it is not visibile for this connection
  1393. if (!IsShadowVisible(fDisconnected,
  1394. Find32.dwFileAttributes,
  1395. uShadowStatus)) {
  1396. goto FINALLY;
  1397. }
  1398. if (FileInformationClass==FileBasicInformation) {
  1399. //copy the stuff from the userbuffer as appropriate...these values
  1400. //must be appropriate since we were successful
  1401. PFILE_BASIC_INFORMATION BasicInfo = (PFILE_BASIC_INFORMATION)pBuffer;
  1402. if (BasicInfo->FileAttributes != 0) {
  1403. Find32.dwFileAttributes = ((BasicInfo->FileAttributes & ~(FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY))
  1404. | (Find32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
  1405. ;
  1406. dwNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
  1407. if (fDisconnected)
  1408. {
  1409. uShadowStatus |= SHADOW_ATTRIB_CHANGE;
  1410. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_SHADOW_ATTRIB_MODIFIED;
  1411. }
  1412. }
  1413. if ((BasicInfo->CreationTime.QuadPart != 0)&&
  1414. (BasicInfo->CreationTime.QuadPart != 0xffffffffffffffff))
  1415. {
  1416. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32.ftCreationTime,
  1417. BasicInfo->CreationTime);
  1418. }
  1419. if ((BasicInfo->LastAccessTime.QuadPart != 0) &&
  1420. (BasicInfo->LastAccessTime.QuadPart != 0xffffffffffffffff))
  1421. {
  1422. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32.ftLastAccessTime,
  1423. BasicInfo->LastAccessTime);
  1424. }
  1425. //
  1426. // If the user is specifying -1 for a field, that means
  1427. // we should leave that field unchanged, even if we might
  1428. // have otherwise set it ourselves. We'll set the Ccb flag
  1429. // saying that the user set the field so that we
  1430. // don't do our default updating.
  1431. //
  1432. // We set the field to 0 then so we know not to actually
  1433. // set the field to the user-specified (and in this case,
  1434. // illegal) value.
  1435. //
  1436. if (BasicInfo->LastWriteTime.QuadPart == 0xffffffffffffffff)
  1437. {
  1438. BasicInfo->LastWriteTime.QuadPart = 0;
  1439. if (fDisconnected)
  1440. {
  1441. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_SHADOW_LWT_MODIFIED;
  1442. }
  1443. }
  1444. if (BasicInfo->LastWriteTime.QuadPart != 0)
  1445. {
  1446. ASSERT(BasicInfo->LastWriteTime.QuadPart != 0xffffffffffffffff);
  1447. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32.ftLastWriteTime,
  1448. BasicInfo->LastWriteTime);
  1449. if (fDisconnected)
  1450. {
  1451. uShadowStatus |= SHADOW_TIME_CHANGE;
  1452. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_SHADOW_LWT_MODIFIED;
  1453. }
  1454. dwNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
  1455. }
  1456. }
  1457. else if (FileInformationClass==FileDispositionInformation)
  1458. {
  1459. if (fDisconnected)
  1460. {
  1461. // if this is a file and we are trying to delete it
  1462. // without permissions, then bail
  1463. if (!(Find32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)&&
  1464. !(FILE_WRITE_DATA & smbSrvOpen->MaximalAccessRights)&&
  1465. !(FILE_WRITE_DATA & smbSrvOpen->GuestMaximalAccessRights))
  1466. {
  1467. *Status = STATUS_ACCESS_DENIED;
  1468. RxLog(("No rights to del %x in dcon Status=%x\n", smbFcb->hShadow, LocalStatus));
  1469. HookKdPrint(BADERRORS, ("No rights to del %x in dcon Status=%x\n", smbFcb->hShadow, LocalStatus));
  1470. }
  1471. else
  1472. {
  1473. LocalStatus = OkToDeleteObject(smbFcb->hParentDir, smbFcb->hShadow, &Find32, uShadowStatus, fDisconnected);
  1474. if (LocalStatus != STATUS_SUCCESS)
  1475. {
  1476. RxLog(("Can't del %x in dcon Status=%x\n", smbFcb->hShadow, LocalStatus));
  1477. *Status = LocalStatus;
  1478. }
  1479. }
  1480. }
  1481. goto FINALLY;
  1482. }
  1483. else {
  1484. //basically, all i can do here is to ensure that the shadow is no bigger than the size
  1485. //given, whether allocationsize or filesize. when we read back the actual size at close
  1486. //some readjusting may be required so we turn sparse on.
  1487. PFILE_END_OF_FILE_INFORMATION UserEndOfFileInformation
  1488. = (PFILE_END_OF_FILE_INFORMATION)pBuffer;
  1489. int iRet;
  1490. ULONG ShadowFileLength;
  1491. ASSERT( FIELD_OFFSET(FILE_END_OF_FILE_INFORMATION,EndOfFile)
  1492. == FIELD_OFFSET(FILE_ALLOCATION_INFORMATION,AllocationSize) );
  1493. //don't need the shadowreadwritemutex here because SetFileInfo has both resources...
  1494. //thus, no other operations can come down
  1495. if (!(CSCHFILE)(smbSrvOpen->hfShadow))
  1496. {
  1497. if (fDisconnected)
  1498. {
  1499. *Status = STATUS_OBJECT_TYPE_MISMATCH;
  1500. }
  1501. goto FINALLY;
  1502. }
  1503. iRet = GetFileSizeLocal((CSCHFILE)(smbSrvOpen->hfShadow), &ShadowFileLength);
  1504. if (iRet<0) {
  1505. if (fDisconnected)
  1506. {
  1507. *Status = STATUS_UNSUCCESSFUL;
  1508. }
  1509. goto FINALLY;
  1510. }
  1511. if (ShadowFileLength != UserEndOfFileInformation->EndOfFile.QuadPart) {
  1512. NTSTATUS SetStatus;
  1513. PNT5CSC_MINIFILEOBJECT MiniFileObject
  1514. = (PNT5CSC_MINIFILEOBJECT)(smbSrvOpen->hfShadow);
  1515. IO_STATUS_BLOCK IoStatusBlock;
  1516. ULONG DummyReturnedLength;
  1517. // If we are connected, don't extend sparse files!!!!
  1518. if (fDisconnected ||
  1519. (!(uShadowStatus & SHADOW_SPARSE) || (ShadowFileLength > UserEndOfFileInformation->EndOfFile.QuadPart)))
  1520. {
  1521. // DbgPrint("SetEof on %x Old=%x New=%x \n", smbFcb->hShadow, ShadowFileLength, UserEndOfFileInformation->EndOfFile.QuadPart);
  1522. SetStatus = Nt5CscXxxInformation(
  1523. (PCHAR)IRP_MJ_SET_INFORMATION,
  1524. MiniFileObject,
  1525. FileEndOfFileInformation,
  1526. sizeof(FILE_END_OF_FILE_INFORMATION),
  1527. pBuffer,
  1528. &DummyReturnedLength
  1529. );
  1530. }
  1531. #if defined(BITCOPY)
  1532. // Do I need to check if EOFinfo (a 64-bit value) is using
  1533. // the upper 32 bits? CscBmp library only supports 32-bit
  1534. // file sizes.
  1535. if (smbFcb->lpDirtyBitmap && fDisconnected &&
  1536. UserEndOfFileInformation->EndOfFile.HighPart == 0) {
  1537. // Is it ShadowFileLength?
  1538. CscBmpResize(
  1539. smbFcb->lpDirtyBitmap,
  1540. (DWORD)UserEndOfFileInformation->EndOfFile.QuadPart);
  1541. } else if (UserEndOfFileInformation->EndOfFile.HighPart != 0) {
  1542. // File is too big to be represented by a CscBmp, delete.
  1543. CscBmpMarkInvalid(smbFcb->lpDirtyBitmap);
  1544. }
  1545. #endif // defined(BITCOPY)
  1546. if (fDisconnected)
  1547. {
  1548. uShadowStatus |= SHADOW_DIRTY;
  1549. dwNotifyFilter |= FILE_NOTIFY_CHANGE_SIZE;
  1550. }
  1551. mSetBits(smbSrvOpen->Flags, SMB_SRVOPEN_FLAG_SHADOW_DATA_MODIFIED);
  1552. Find32.nFileSizeLow = (DWORD)UserEndOfFileInformation->EndOfFile.QuadPart;
  1553. }
  1554. }
  1555. if (fDisconnected)
  1556. {
  1557. MarkShareDirty(&smbFcb->sCscRootInfo.ShareStatus, smbFcb->sCscRootInfo.hShare);
  1558. }
  1559. if(SetShadowInfo(smbFcb->hParentDir,
  1560. smbFcb->hShadow,
  1561. &Find32,
  1562. uShadowStatus,
  1563. SHADOW_FLAGS_ASSIGN
  1564. | ((fDisconnected)?SHADOW_FLAGS_DONT_UPDATE_ORGTIME
  1565. :0)
  1566. ) < SRET_OK) {
  1567. goto FINALLY;
  1568. }
  1569. FINALLY:
  1570. if (EnteredCriticalSection) {
  1571. LeaveShadowCritRx(RxContext);
  1572. }
  1573. // in disconnected state, report the changes
  1574. if (fDisconnected && dwNotifyFilter)
  1575. {
  1576. FsRtlNotifyFullReportChange(
  1577. pNetRootEntry->NetRoot.pNotifySync,
  1578. &pNetRootEntry->NetRoot.DirNotifyList,
  1579. (PSTRING)GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb),
  1580. (USHORT)(GET_ALREADY_PREFIXED_NAME(SrvOpen, capFcb)->Length -
  1581. smbFcb->MinimalCscSmbFcb.LastComponentLength),
  1582. NULL,
  1583. NULL,
  1584. dwNotifyFilter,
  1585. FILE_ACTION_MODIFIED,
  1586. NULL);
  1587. }
  1588. RxDbgTrace(-1, Dbg, ("MRxSmbCscSetFileInfoEpilogue -> %08lx\n", Status ));
  1589. return;
  1590. }
  1591. //this could easily bein a .h file
  1592. int IoctlRegisterAgent(
  1593. ULONG_PTR uHwnd
  1594. );
  1595. int IoctlUnRegisterAgent(
  1596. ULONG_PTR uHwnd
  1597. );
  1598. int IoctlGetUNCPath(
  1599. LPCOPYPARAMS lpCopyParams
  1600. );
  1601. int IoctlBeginPQEnum(
  1602. LPPQPARAMS lpPQPar
  1603. );
  1604. int IoctlEndPQEnum(
  1605. LPPQPARAMS lpPQPar
  1606. );
  1607. int IoctlNextPriShadow(
  1608. LPPQPARAMS lpPQPar
  1609. );
  1610. int IoctlPrevPriShadow(
  1611. LPPQPARAMS lpPQPar
  1612. );
  1613. int IoctlGetShadowInfo(
  1614. LPSHADOWINFO lpShadowInfo
  1615. );
  1616. int IoctlSetShadowInfo(
  1617. LPSHADOWINFO lpShadowInfo
  1618. );
  1619. int IoctlChkUpdtStatus(
  1620. LPSHADOWINFO lpShadowInfo
  1621. );
  1622. int IoctlDoShadowMaintenance(
  1623. LPSHADOWINFO lpSI
  1624. );
  1625. BOOLEAN
  1626. CscCheckForNullW(
  1627. PWCHAR pBuf,
  1628. ULONG Count);
  1629. NTSTATUS
  1630. MRxSmbCscIoctlOpenForCopyChunk (
  1631. PRX_CONTEXT RxContext
  1632. );
  1633. NTSTATUS
  1634. MRxSmbCscIoctlCloseForCopyChunk (
  1635. PRX_CONTEXT RxContext
  1636. );
  1637. NTSTATUS
  1638. MRxSmbCscIoctlCopyChunk (
  1639. PRX_CONTEXT RxContext
  1640. );
  1641. int IoctlBeginReint(
  1642. LPSHADOWINFO lpShadowInfo
  1643. );
  1644. int IoctlEndReint(
  1645. LPSHADOWINFO lpShadowInfo
  1646. );
  1647. int IoctlCreateShadow(
  1648. LPSHADOWINFO lpSI
  1649. );
  1650. int IoctlDeleteShadow(
  1651. LPSHADOWINFO lpSI
  1652. );
  1653. int IoctlGetShareStatus(
  1654. LPSHADOWINFO lpSI
  1655. );
  1656. int IoctlSetShareStatus(
  1657. LPSHADOWINFO lpSI
  1658. );
  1659. int IoctlAddUse(
  1660. LPCOPYPARAMS lpCP
  1661. );
  1662. int IoctlDelUse(
  1663. LPCOPYPARAMS lpCP
  1664. );
  1665. int IoctlGetUse(
  1666. LPCOPYPARAMS lpCP
  1667. );
  1668. int IoctlSwitches(LPSHADOWINFO lpSI);
  1669. int IoctlGetShadow(
  1670. LPSHADOWINFO lpSI
  1671. );
  1672. int IoctlAddHint( // Add a new hint or change an existing hint
  1673. LPSHADOWINFO lpSI
  1674. );
  1675. int IoctlDeleteHint( // Delete an existing hint
  1676. LPSHADOWINFO lpSI
  1677. );
  1678. int IoctlGetHint(
  1679. LPSHADOWINFO lpSI
  1680. );
  1681. int IoctlGetGlobalStatus(
  1682. ULONG SessionId,
  1683. LPGLOBALSTATUS lpGS
  1684. );
  1685. int IoctlFindOpenHSHADOW
  1686. (
  1687. LPSHADOWINFO lpSI
  1688. );
  1689. int IoctlFindNextHSHADOW
  1690. (
  1691. LPSHADOWINFO lpSI
  1692. );
  1693. int IoctlFindCloseHSHADOW
  1694. (
  1695. LPSHADOWINFO lpSI
  1696. );
  1697. int IoctlFindOpenHint
  1698. (
  1699. LPSHADOWINFO lpSI
  1700. );
  1701. int IoctlFindNextHint
  1702. (
  1703. LPSHADOWINFO lpSI
  1704. );
  1705. int IoctlFindCloseHint
  1706. (
  1707. LPSHADOWINFO lpSI
  1708. );
  1709. int IoctlSetPriorityHSHADOW(
  1710. LPSHADOWINFO lpSI
  1711. );
  1712. int IoctlGetPriorityHSHADOW(
  1713. LPSHADOWINFO lpSI
  1714. );
  1715. int IoctlGetAliasHSHADOW(
  1716. LPSHADOWINFO lpSI
  1717. );
  1718. #define CSC_CASE(__case) \
  1719. case __case: \
  1720. RxDbgTrace(0,Dbg,("MRxSmbCscIoctl %08lx %s %08lx %08lx\n",RxContext,#__case,InputBuffer,OutputBuffer));
  1721. ULONG GetNextPriShadowCount = 0;
  1722. NTSTATUS
  1723. MRxSmbCscIoCtl(
  1724. IN OUT PRX_CONTEXT RxContext
  1725. )
  1726. /*++
  1727. Routine Description:
  1728. This routine performs the special IOCTL operation for the CSC agent.
  1729. Arguments:
  1730. RxContext - the RDBSS context
  1731. Return Value:
  1732. NTSTATUS - The return status for the operation
  1733. Notes:
  1734. ShadowIRet is overloaded:
  1735. -1 == error, copy the error back
  1736. 0 == error, return Wrong password (STATUS_WRONG_PASSWORD)
  1737. 1 == success, output params, copy them back
  1738. 2 == return status unmodified, no output params
  1739. --*/
  1740. {
  1741. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  1742. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  1743. ULONG IoControlCode = LowIoContext->ParamsFor.IoCtl.IoControlCode;
  1744. PBYTE InputBuffer = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
  1745. PBYTE pNewInputBuffer=NULL;
  1746. ULONG InputBufferLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  1747. PBYTE OutputBuffer = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
  1748. ULONG OutputBufferLength = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
  1749. LONG ShadowIRet = 0;
  1750. CAPTURE_BUFFERS sCapBuff;
  1751. PBYTE pAuxBuf = NULL;
  1752. PBYTE pOrgBuf = NULL;
  1753. BOOLEAN SuppressFinalTrace = FALSE, fEnteredShadowCrit=FALSE;
  1754. KPROCESSOR_MODE RequestorMode;
  1755. ULONG SessionId = 0;
  1756. #if defined (_WIN64)
  1757. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  1758. RxDbgTrace(0, Dbg, ("32 bit IOCTL in 64 bit returning STATUS_NOT_IMPLEMENTED\n"));
  1759. return STATUS_NOT_IMPLEMENTED;
  1760. }
  1761. #endif // _WIN64
  1762. if (RxContext != NULL && RxContext->CurrentIrp != NULL)
  1763. IoGetRequestorSessionId(RxContext->CurrentIrp, &SessionId);
  1764. try
  1765. {
  1766. RequestorMode = RxContext->CurrentIrp->RequestorMode;
  1767. if (
  1768. RequestorMode != KernelMode
  1769. &&
  1770. IoControlCode != IOCTL_GET_DEBUG_INFO
  1771. ) {
  1772. if (CaptureInputBufferIfNecessaryAndProbe(
  1773. IoControlCode,
  1774. RxContext,
  1775. InputBuffer,
  1776. &sCapBuff,
  1777. &pAuxBuf,
  1778. &pOrgBuf,
  1779. &pNewInputBuffer)!=STATUS_SUCCESS) {
  1780. RxDbgTrace(0, Dbg, ("Invalid parameters for Ioctl=%x\n", IoControlCode));
  1781. return STATUS_INVALID_PARAMETER;
  1782. }
  1783. }
  1784. else
  1785. {
  1786. pNewInputBuffer = InputBuffer;
  1787. }
  1788. // DbgPrint("MRxSmbCscIoCtl IoControlCode=%d\n", (IoControlCode >> 2) & 0xfff);
  1789. switch (IoControlCode) {
  1790. CSC_CASE(IOCTL_SHADOW_GETVERSION)
  1791. Status = (NTSTATUS)(SHADOW_VERSION); // no-op
  1792. break;
  1793. CSC_CASE(IOCTL_SHADOW_REGISTER_AGENT)
  1794. ShadowIRet = IoctlRegisterAgent((ULONG_PTR)pNewInputBuffer);
  1795. if (ShadowIRet>=0) {
  1796. MRxSmbCscReleaseRxContextFromAgentWait();
  1797. }
  1798. break;
  1799. CSC_CASE(IOCTL_SHADOW_UNREGISTER_AGENT)
  1800. ShadowIRet = IoctlUnRegisterAgent((ULONG_PTR)pNewInputBuffer);
  1801. if (ShadowIRet>=0) {
  1802. MRxSmbCscReleaseRxContextFromAgentWait();
  1803. }
  1804. break;
  1805. CSC_CASE(IOCTL_SHADOW_GET_UNC_PATH)
  1806. ShadowIRet = IoctlGetUNCPath((LPCOPYPARAMS)pNewInputBuffer);
  1807. break;
  1808. CSC_CASE(IOCTL_SHADOW_BEGIN_PQ_ENUM)
  1809. ShadowIRet = IoctlBeginPQEnum((LPPQPARAMS)pNewInputBuffer);
  1810. GetNextPriShadowCount = 0;
  1811. break;
  1812. CSC_CASE(IOCTL_SHADOW_END_PQ_ENUM)
  1813. ShadowIRet = IoctlEndPQEnum((LPPQPARAMS)pNewInputBuffer);
  1814. break;
  1815. //CSC_CASE(IOCTL_SHADOW_NEXT_PRI_SHADOW)
  1816. case IOCTL_SHADOW_NEXT_PRI_SHADOW: \
  1817. if ((GetNextPriShadowCount<6) || ((GetNextPriShadowCount%40)==0)) {
  1818. RxDbgTrace(0,Dbg,("MRxSmbCscIoctl %08lx %s(%d) %08lx %08lx\n",
  1819. RxContext,
  1820. "IOCTL_SHADOW_NEXT_PRI_SHADOW",GetNextPriShadowCount,
  1821. pNewInputBuffer,OutputBuffer));
  1822. }
  1823. ShadowIRet = IoctlNextPriShadow((LPPQPARAMS)pNewInputBuffer);
  1824. GetNextPriShadowCount++;
  1825. SuppressFinalTrace = TRUE;
  1826. break;
  1827. CSC_CASE(IOCTL_SHADOW_PREV_PRI_SHADOW)
  1828. ShadowIRet = IoctlPrevPriShadow((LPPQPARAMS)pNewInputBuffer);
  1829. break;
  1830. CSC_CASE(IOCTL_SHADOW_GET_SHADOW_INFO)
  1831. ShadowIRet = IoctlGetShadowInfo((LPSHADOWINFO)pNewInputBuffer);
  1832. break;
  1833. CSC_CASE(IOCTL_SHADOW_SET_SHADOW_INFO)
  1834. ShadowIRet = IoctlSetShadowInfo((LPSHADOWINFO)pNewInputBuffer);
  1835. break;
  1836. CSC_CASE(IOCTL_SHADOW_CHK_UPDT_STATUS)
  1837. ShadowIRet = IoctlChkUpdtStatus((LPSHADOWINFO)pNewInputBuffer);
  1838. break;
  1839. CSC_CASE(IOCTL_DO_SHADOW_MAINTENANCE)
  1840. {
  1841. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1842. #if defined(REMOTE_BOOT)
  1843. // If this IOCTL is for turning caching back on we need to update
  1844. // the mini redirector accordingly.
  1845. if ((pShadowInfo->uOp == SHADOW_CHANGE_HANDLE_CACHING_STATE) &&
  1846. (pShadowInfo->uStatus != FALSE)) {
  1847. RxDbgTrace(0, Dbg, ("RB Client : Turning caching back on\n"));
  1848. MRxSmbOplocksDisabledOnRemoteBootClients = FALSE;
  1849. }
  1850. #endif // defined(REMOTE_BOOT)
  1851. ShadowIRet = IoctlDoShadowMaintenance(pShadowInfo);
  1852. }
  1853. break;
  1854. CSC_CASE(IOCTL_GET_DEBUG_INFO)
  1855. ShadowIRet = 2;
  1856. Status = IoctlGetDebugInfo(
  1857. RxContext,
  1858. InputBuffer,
  1859. InputBufferLength,
  1860. OutputBuffer,
  1861. OutputBufferLength);
  1862. break;
  1863. CSC_CASE(IOCTL_SHADOW_COPYCHUNK)
  1864. ShadowIRet = 2; //not -1, 0 or 1, No out parameters, Status is returned unmodified
  1865. Status = MRxSmbCscIoctlCopyChunk(RxContext);
  1866. break;
  1867. CSC_CASE(IOCTL_CLOSEFORCOPYCHUNK)
  1868. ShadowIRet = 2; //not -1, 0 or 1, No out parameters, Status is returned unmodified
  1869. Status = MRxSmbCscIoctlCloseForCopyChunk(RxContext);
  1870. break;
  1871. CSC_CASE(IOCTL_OPENFORCOPYCHUNK)
  1872. ShadowIRet = 2; //not -1, 0 or 1, No out parameters, Status is returned unmodified
  1873. Status = MRxSmbCscIoctlOpenForCopyChunk(RxContext);
  1874. break;
  1875. CSC_CASE(IOCTL_IS_SERVER_OFFLINE)
  1876. {
  1877. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1878. if (pShadowInfo->lpBuffer == NULL
  1879. ||
  1880. CscCheckForNullW(pShadowInfo->lpBuffer, pShadowInfo->cbBufferSize/sizeof(WCHAR)) == TRUE
  1881. ) {
  1882. ShadowIRet = 1;
  1883. pShadowInfo->uStatus = CscIsServerOffline((PWCHAR)pShadowInfo->lpBuffer);
  1884. }
  1885. }
  1886. break;
  1887. CSC_CASE(IOCTL_TAKE_SERVER_OFFLINE)
  1888. {
  1889. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1890. if (pShadowInfo->lpBuffer != NULL
  1891. &&
  1892. CscCheckForNullW(pShadowInfo->lpBuffer, pShadowInfo->cbBufferSize/sizeof(WCHAR)) == TRUE
  1893. ) {
  1894. ShadowIRet = 1;
  1895. pShadowInfo->uStatus = CscTakeServerOffline( (PWCHAR)pShadowInfo->lpBuffer);
  1896. }
  1897. }
  1898. break;
  1899. CSC_CASE(IOCTL_TRANSITION_SERVER_TO_OFFLINE)
  1900. {
  1901. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1902. ShadowIRet = 2; //not -1, 0 or 1, No out parameters, Status is returned unmodified
  1903. Status = CscTransitionServerToOffline(
  1904. SessionId,
  1905. pShadowInfo->hShare,
  1906. pShadowInfo->uStatus);
  1907. // DbgPrint("###IOCTL_TRANSITION_SERVER_TO_OFFLINE: pulsing fill event\n");
  1908. MRxSmbCscSignalFillAgent(NULL, 0);
  1909. }
  1910. break;
  1911. CSC_CASE(IOCTL_TRANSITION_SERVER_TO_ONLINE)
  1912. {
  1913. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1914. ShadowIRet = 2; //not -1, 0 or 1, No out parameters, Status is returned unmodified
  1915. Status = CscTransitionServerToOnline(
  1916. pShadowInfo->hShare);
  1917. // DbgPrint("###IOCTL_TRANSITION_SERVER_TO_ONLINE: pulsing fill event\n");
  1918. MRxSmbCscSignalFillAgent(NULL, 0);
  1919. }
  1920. break;
  1921. CSC_CASE(IOCTL_NAME_OF_SERVER_GOING_OFFLINE)
  1922. {
  1923. LPSHADOWINFO lpSI = (LPSHADOWINFO)pNewInputBuffer;
  1924. ShadowIRet = 1;
  1925. CscGetServerNameWaitingToGoOffline(
  1926. lpSI->lpBuffer,
  1927. &(lpSI->cbBufferSize),
  1928. &Status);
  1929. if (Status == STATUS_BUFFER_TOO_SMALL)
  1930. {
  1931. ((LPSHADOWINFO)InputBuffer)->cbBufferSize = lpSI->cbBufferSize;
  1932. HookKdPrint(ALWAYS, ("Buffer too small, Need %d \n", ((LPSHADOWINFO)InputBuffer)->cbBufferSize));
  1933. }
  1934. }
  1935. break;
  1936. CSC_CASE(IOCTL_SHAREID_TO_SHARENAME)
  1937. {
  1938. LPSHADOWINFO lpSI = (LPSHADOWINFO)pNewInputBuffer;
  1939. ShadowIRet = 1;
  1940. CscShareIdToShareName(
  1941. lpSI->hShare,
  1942. lpSI->lpBuffer,
  1943. &(lpSI->cbBufferSize),
  1944. &Status);
  1945. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1946. ((LPSHADOWINFO)InputBuffer)->cbBufferSize = lpSI->cbBufferSize;
  1947. HookKdPrint(
  1948. ALWAYS,
  1949. ("Buffer small, Need %d \n", ((LPSHADOWINFO)InputBuffer)->cbBufferSize));
  1950. } else if (Status != STATUS_SUCCESS) {
  1951. lpSI->dwError = ERROR_FILE_NOT_FOUND;
  1952. ShadowIRet = -1;
  1953. }
  1954. }
  1955. break;
  1956. CSC_CASE(IOCTL_SHADOW_BEGIN_REINT)
  1957. ShadowIRet = CSCBeginReint(RxContext, (LPSHADOWINFO)pNewInputBuffer);
  1958. if (ShadowIRet >= 1)
  1959. {
  1960. ShadowIRet = 2;
  1961. Status = STATUS_PENDING;
  1962. }
  1963. break;
  1964. CSC_CASE(IOCTL_SHADOW_END_REINT)
  1965. ShadowIRet = CSCEndReint((LPSHADOWINFO)pNewInputBuffer);
  1966. break;
  1967. CSC_CASE(IOCTL_SHADOW_CREATE)
  1968. {
  1969. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  1970. ShadowIRet = -1;
  1971. if (pShadowInfo->lpFind32
  1972. &&
  1973. CscCheckForNullW(pShadowInfo->lpFind32->cFileName, MAX_PATH) == TRUE
  1974. ) {
  1975. ShadowIRet = IoctlCreateShadow(pShadowInfo);
  1976. }
  1977. }
  1978. break;
  1979. CSC_CASE(IOCTL_SHADOW_DELETE)
  1980. ShadowIRet = IoctlDeleteShadow((LPSHADOWINFO)pNewInputBuffer);
  1981. break;
  1982. CSC_CASE(IOCTL_GET_SHARE_STATUS)
  1983. ShadowIRet = IoctlGetShareStatus((LPSHADOWINFO)pNewInputBuffer);
  1984. break;
  1985. CSC_CASE(IOCTL_SET_SHARE_STATUS)
  1986. ShadowIRet = IoctlSetShareStatus((LPSHADOWINFO)pNewInputBuffer);
  1987. break;
  1988. CSC_CASE(IOCTL_ADDUSE)
  1989. //ShadowIRet = IoctlAddUse((LPCOPYPARAMS)pNewInputBuffer);
  1990. break;
  1991. CSC_CASE(IOCTL_DELUSE)
  1992. //ShadowIRet = IoctlDelUse((LPCOPYPARAMS)pNewInputBuffer);
  1993. break;
  1994. CSC_CASE(IOCTL_GETUSE)
  1995. //ShadowIRet = IoctlGetUse((LPCOPYPARAMS)pNewInputBuffer);
  1996. break;
  1997. CSC_CASE(IOCTL_SWITCHES)
  1998. ShadowIRet = IoctlSwitches((LPSHADOWINFO)pNewInputBuffer);
  1999. break;
  2000. CSC_CASE(IOCTL_GETSHADOW)
  2001. {
  2002. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  2003. ShadowIRet = -1;
  2004. if (pShadowInfo->lpFind32
  2005. &&
  2006. CscCheckForNullW(pShadowInfo->lpFind32->cFileName, MAX_PATH) == TRUE
  2007. ) {
  2008. ShadowIRet = IoctlGetShadow(pShadowInfo);
  2009. }
  2010. }
  2011. break;
  2012. CSC_CASE(IOCTL_GETGLOBALSTATUS)
  2013. ShadowIRet = IoctlGetGlobalStatus(SessionId, (LPGLOBALSTATUS)pNewInputBuffer);
  2014. break;
  2015. CSC_CASE(IOCTL_FINDOPEN_SHADOW)
  2016. {
  2017. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  2018. ShadowIRet = -1;
  2019. if (pShadowInfo->lpFind32
  2020. &&
  2021. CscCheckForNullW(pShadowInfo->lpFind32->cFileName, MAX_PATH) == TRUE
  2022. ) {
  2023. ShadowIRet = IoctlFindOpenHSHADOW(pShadowInfo);
  2024. }
  2025. }
  2026. break;
  2027. CSC_CASE(IOCTL_FINDNEXT_SHADOW)
  2028. ShadowIRet = IoctlFindNextHSHADOW((LPSHADOWINFO)pNewInputBuffer);
  2029. break;
  2030. CSC_CASE(IOCTL_FINDCLOSE_SHADOW)
  2031. ShadowIRet = IoctlFindCloseHSHADOW((LPSHADOWINFO)pNewInputBuffer);
  2032. break;
  2033. CSC_CASE(IOCTL_GETPRIORITY_SHADOW)
  2034. ShadowIRet = IoctlGetPriorityHSHADOW((LPSHADOWINFO)pNewInputBuffer);
  2035. break;
  2036. CSC_CASE(IOCTL_SETPRIORITY_SHADOW)
  2037. ShadowIRet = IoctlSetPriorityHSHADOW((LPSHADOWINFO)pNewInputBuffer);
  2038. break;
  2039. CSC_CASE(IOCTL_ADD_HINT)
  2040. ShadowIRet = IoctlAddHint((LPSHADOWINFO)pNewInputBuffer);
  2041. break;
  2042. CSC_CASE(IOCTL_DELETE_HINT)
  2043. ShadowIRet = IoctlDeleteHint((LPSHADOWINFO)pNewInputBuffer);
  2044. break;
  2045. CSC_CASE(IOCTL_FINDOPEN_HINT)
  2046. {
  2047. LPSHADOWINFO pShadowInfo = (LPSHADOWINFO)pNewInputBuffer;
  2048. ShadowIRet = -1;
  2049. if (pShadowInfo->lpFind32
  2050. &&
  2051. CscCheckForNullW(pShadowInfo->lpFind32->cFileName, MAX_PATH) == TRUE
  2052. ) {
  2053. ShadowIRet = IoctlFindOpenHint(pShadowInfo);
  2054. }
  2055. }
  2056. break;
  2057. CSC_CASE(IOCTL_FINDNEXT_HINT)
  2058. ShadowIRet = IoctlFindNextHint((LPSHADOWINFO)pNewInputBuffer);
  2059. break;
  2060. CSC_CASE(IOCTL_FINDCLOSE_HINT)
  2061. ShadowIRet = IoctlFindCloseHint((LPSHADOWINFO)pNewInputBuffer);
  2062. break;
  2063. default:
  2064. RxDbgTrace(-1, Dbg, ("MRxSmbCscIoCtl not csc ioctl-> %08lx\n", Status ));
  2065. return Status;
  2066. }
  2067. if (ShadowIRet == 0) {
  2068. Status = STATUS_WRONG_PASSWORD;
  2069. } else if (ShadowIRet == -1) {
  2070. if (RequestorMode != KernelMode)
  2071. {
  2072. CopyBackIfNecessary(
  2073. IoControlCode,
  2074. InputBuffer,
  2075. &sCapBuff,
  2076. pAuxBuf,
  2077. pOrgBuf,
  2078. FALSE);
  2079. }
  2080. Status = STATUS_UNSUCCESSFUL;
  2081. } else if (ShadowIRet == 1) {
  2082. if (RequestorMode != KernelMode)
  2083. {
  2084. CopyBackIfNecessary(
  2085. IoControlCode,
  2086. InputBuffer,
  2087. &sCapBuff,
  2088. pAuxBuf,
  2089. pOrgBuf,
  2090. TRUE);
  2091. }
  2092. Status = STATUS_SUCCESS;
  2093. }
  2094. if (SuppressFinalTrace) {
  2095. RxDbgTraceUnIndent(-1, Dbg);
  2096. } else {
  2097. RxDbgTrace(-1, Dbg,
  2098. ("MRxSmbCscIoCtl -> %08lx %08lx\n", Status, ShadowIRet ));
  2099. }
  2100. }
  2101. except(MRxSmbCSCExceptionFilter( RxContext, GetExceptionInformation() ))
  2102. {
  2103. RxDbgTrace(0, Dbg, ("MrxSmbCSCIoctl: took an exception \r\n"));
  2104. LeaveShadowCritIfThisThreadOwnsIt();
  2105. Status = STATUS_INVALID_PARAMETER;
  2106. }
  2107. if (pAuxBuf != NULL) {
  2108. // DbgPrint("Freeing pAuxBuf\n");
  2109. RxFreePool(pAuxBuf);
  2110. }
  2111. // DbgPrint("MRxSmbCscIoCtl exit 0x%x\n", Status);
  2112. return Status;
  2113. }
  2114. NTSTATUS
  2115. MRxSmbCscObtainShareHandles (
  2116. IN OUT PUNICODE_STRING ShareName,
  2117. IN BOOLEAN DisconnectedMode,
  2118. IN BOOLEAN CopyChunkOpen,
  2119. IN OUT PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  2120. )
  2121. /*++
  2122. Routine Description:
  2123. This routine performs the obtains the handles (Share and root directory)
  2124. for a particular \server\share, updating the values in the netrootentry
  2125. if found.
  2126. Arguments:
  2127. pNetRootEntry - the SMB MRX net root data structure
  2128. Return Value:
  2129. NTSTATUS - The return status for the operation
  2130. STATUS_NOT_INPLEMENTED - couldn't find or create
  2131. STATUS_SUCCESS - found or created
  2132. Notes:
  2133. --*/
  2134. {
  2135. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  2136. BOOLEAN CreateIfNotFound = FALSE;
  2137. SHADOWINFO ShadowInfo;
  2138. DbgDoit(ASSERT(vfInShadowCrit));
  2139. if (fShadow == 0) {
  2140. return(Status);
  2141. }
  2142. if (pNetRootEntry->NetRoot.sCscRootInfo.hShare != 0) {
  2143. Status = STATUS_SUCCESS;
  2144. goto FINALLY;
  2145. }
  2146. // At this stage one of the following two assumptions should be TRUE.
  2147. // Connected Mode Operation ...
  2148. // In this instance the call can succeed only if the Net Root is
  2149. // marked as being shadowable by the CSC client and iot is of type
  2150. // Disk.
  2151. // Disconnected Mode Operation ...
  2152. // In this case we have not yet ascertained the type and attributes
  2153. // Therefore we let the call go through. If we can open the handle
  2154. // to the Share then we mark the net root to be of the appropriate
  2155. // type.
  2156. if ( !DisconnectedMode &&
  2157. !CopyChunkOpen &&
  2158. (/*!pNetRootEntry->NetRoot.CscEnabled ||*/
  2159. (pNetRootEntry->NetRoot.NetRootType != NET_ROOT_DISK))) {
  2160. goto FINALLY;
  2161. }
  2162. // allocate a buffer that's the right size: one extra char is
  2163. // for a trailing null and the other for a preceding L'\\'
  2164. if (ShadowingON()) {
  2165. if (!DisconnectedMode &&
  2166. pNetRootEntry->NetRoot.CscShadowable) {
  2167. CreateIfNotFound = TRUE;
  2168. }
  2169. }
  2170. RxDbgTrace(0, Dbg,
  2171. ("MRxSmbCscObtainShareHandles...servershare=%wZ %08lx\n",
  2172. ShareName,CreateIfNotFound));
  2173. if (FindCreateShareForNt(
  2174. ShareName,
  2175. CreateIfNotFound,
  2176. &ShadowInfo,
  2177. NULL //this means don't tell me if you create
  2178. ) == SRET_OK ) {
  2179. ASSERT(ShadowInfo.hShare != 0);
  2180. pNetRootEntry->NetRoot.sCscRootInfo.hShare = ShadowInfo.hShare;
  2181. pNetRootEntry->NetRoot.sCscRootInfo.hRootDir = ShadowInfo.hShadow;
  2182. pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus = (USHORT)(ShadowInfo.uStatus);
  2183. pNetRootEntry->NetRoot.sCscRootInfo.Flags = 0;
  2184. RxLog(("OSHH...hDir=%x\n",pNetRootEntry->NetRoot.sCscRootInfo.hRootDir));
  2185. // if we are connected, by this time we have the smb caching flags
  2186. // we check to see whether these match those on the database
  2187. // If they don't, we stamp the new ones
  2188. if (!DisconnectedMode)
  2189. {
  2190. if ((ShadowInfo.uStatus & SHARE_CACHING_MASK)!=
  2191. (ULONG)SMB_CSC_BITS_TO_DATABASE_CSC_BITS(pNetRootEntry->NetRoot.CscFlags))
  2192. {
  2193. // RxDbgTrace(0, Dbg, ("Mismatched smb caching flags, stamping %x on hShare=%x\n",
  2194. // SMB_CSC_BITS_TO_DATABASE_CSC_BITS(pNetRootEntry->NetRoot.CscFlags),
  2195. // pNetRootEntry->NetRoot.sCscRootInfo.hShare));
  2196. pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus &= ~SHARE_CACHING_MASK;
  2197. pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus |= SMB_CSC_BITS_TO_DATABASE_CSC_BITS(pNetRootEntry->NetRoot.CscFlags);
  2198. SetShareStatus( pNetRootEntry->NetRoot.sCscRootInfo.hShare,
  2199. pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus,
  2200. SHADOW_FLAGS_ASSIGN);
  2201. }
  2202. }
  2203. else
  2204. {
  2205. // in disconnected mode we use the last set of flags
  2206. pNetRootEntry->NetRoot.CscFlags = DATABASE_CSC_BITS_TO_SMB_CSC_BITS(pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus);
  2207. RxDbgTrace(0, Dbg, ("Setting CscFlags=%x on the netrootentry %x in disconnected state\n",pNetRootEntry->NetRoot.CscFlags, pNetRootEntry));
  2208. switch (pNetRootEntry->NetRoot.CscFlags) {
  2209. case SMB_CSC_CACHE_AUTO_REINT:
  2210. case SMB_CSC_CACHE_VDO:
  2211. pNetRootEntry->NetRoot.CscEnabled = TRUE;
  2212. pNetRootEntry->NetRoot.CscShadowable = TRUE;
  2213. break;
  2214. case SMB_CSC_CACHE_MANUAL_REINT:
  2215. pNetRootEntry->NetRoot.CscEnabled = TRUE;
  2216. pNetRootEntry->NetRoot.CscShadowable = FALSE;
  2217. break;
  2218. case SMB_CSC_NO_CACHING:
  2219. pNetRootEntry->NetRoot.CscEnabled = FALSE;
  2220. pNetRootEntry->NetRoot.CscShadowable = FALSE;
  2221. }
  2222. }
  2223. Status = STATUS_SUCCESS;
  2224. } else {
  2225. if (DisconnectedMode) {
  2226. Status = STATUS_BAD_NETWORK_PATH;
  2227. } else if (!CreateIfNotFound) {
  2228. pNetRootEntry->NetRoot.sCscRootInfo.hShare = 0;
  2229. pNetRootEntry->NetRoot.sCscRootInfo.hRootDir = 0;
  2230. pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus = 0;
  2231. pNetRootEntry->NetRoot.sCscRootInfo.Flags = 0;
  2232. Status = STATUS_SUCCESS;
  2233. }
  2234. }
  2235. FINALLY:
  2236. RxDbgTrace(
  2237. -1,
  2238. Dbg,
  2239. ("MRxSmbCscObtainShareHandles -> %08lx (h=%08lx)\n",
  2240. Status, pNetRootEntry->NetRoot.sCscRootInfo.hShare ));
  2241. return Status;
  2242. }
  2243. NTSTATUS
  2244. MRxSmbCscPartOfCreateVNetRoot (
  2245. IN PRX_CONTEXT RxContext,
  2246. IN OUT PMRX_NET_ROOT NetRoot )
  2247. {
  2248. NTSTATUS Status;
  2249. PMRX_SRV_CALL SrvCall;
  2250. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2251. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  2252. HSHARE hShare;
  2253. if(!MRxSmbIsCscEnabled ||
  2254. (fShadow == 0)
  2255. ) {
  2256. return(STATUS_SUCCESS);
  2257. }
  2258. ASSERT(RxContext->MajorFunction == IRP_MJ_CREATE);
  2259. pServerEntry = SmbCeGetAssociatedServerEntry(NetRoot->pSrvCall);
  2260. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  2261. if (!CscIsDfsOpen(RxContext)) {
  2262. BOOLEAN Disconnected = SmbCeIsServerInDisconnectedMode(pServerEntry);
  2263. EnterShadowCritRx(RxContext);
  2264. // force a database entry refresh
  2265. hShare = pNetRootEntry->NetRoot.sCscRootInfo.hShare;
  2266. pNetRootEntry->NetRoot.sCscRootInfo.hShare = 0;
  2267. #if 0
  2268. if ((NetRoot->pNetRootName->Length >= (sizeof(L"\\win95b\\fat")-2)) &&
  2269. !memcmp(NetRoot->pNetRootName->Buffer, L"\\win95b\\fat", sizeof(L"\\win95b\\fat")-2))
  2270. {
  2271. pNetRootEntry->NetRoot.CscShadowable =
  2272. pNetRootEntry->NetRoot.CscEnabled = TRUE;
  2273. }
  2274. #endif
  2275. Status = MRxSmbCscObtainShareHandles(
  2276. NetRoot->pNetRootName,
  2277. Disconnected,
  2278. FALSE,
  2279. pNetRootEntry
  2280. );
  2281. // update the share rights if necessary
  2282. if (!Disconnected) {
  2283. if(pNetRootEntry->NetRoot.UpdateCscShareRights) {
  2284. if (pNetRootEntry->NetRoot.sCscRootInfo.hShare != 0) {
  2285. CSC_SID_ACCESS_RIGHTS AccessRights[2];
  2286. DWORD CscStatus;
  2287. SID_CONTEXT SidContext;
  2288. // not a DFS root
  2289. pNetRootEntry->NetRoot.sCscRootInfo.Flags = 0;
  2290. if (CscRetrieveSid(RxContext,&SidContext) == STATUS_SUCCESS) {
  2291. AccessRights[0].pSid = SidContext.pSid;
  2292. AccessRights[0].SidLength = RtlLengthSid(SidContext.pSid);
  2293. AccessRights[0].MaximalAccessRights = pNetRootEntry->MaximalAccessRights;
  2294. AccessRights[1].pSid = CSC_GUEST_SID;
  2295. AccessRights[1].SidLength = CSC_GUEST_SID_LENGTH;
  2296. AccessRights[1].MaximalAccessRights = pNetRootEntry->GuestMaximalAccessRights;
  2297. CscStatus = CscAddMaximalAccessRightsForShare(
  2298. pNetRootEntry->NetRoot.sCscRootInfo.hShare,
  2299. 2,
  2300. AccessRights);
  2301. if (CscStatus != ERROR_SUCCESS) {
  2302. RxDbgTrace(
  2303. 0,
  2304. Dbg,
  2305. ("MRxSmbCscCreateEpilogue Error Updating Access rights %lx\n",
  2306. Status));
  2307. }
  2308. else
  2309. {
  2310. pNetRootEntry->NetRoot.UpdateCscShareRights = FALSE;
  2311. }
  2312. CscDiscardSid(&SidContext);
  2313. }
  2314. }
  2315. }
  2316. }
  2317. LeaveShadowCritRx(RxContext);
  2318. } else {
  2319. pNetRootEntry->NetRoot.sCscRootInfo.hShare = 0;
  2320. pNetRootEntry->NetRoot.sCscRootInfo.hRootDir = 0;
  2321. pNetRootEntry->NetRoot.sCscRootInfo.Flags = 0;
  2322. Status = STATUS_SUCCESS;
  2323. }
  2324. return Status;
  2325. }
  2326. #ifndef MRXSMB_BUILD_FOR_CSC_DCON
  2327. VOID
  2328. MRxSmbCscFillWithoutNamesFind32FromFcb (
  2329. IN PMINIMAL_CSC_SMBFCB MinimalCscSmbFcb,
  2330. OUT _WIN32_FIND_DATA *Find32
  2331. )
  2332. /*++
  2333. Routine Description:
  2334. This routine copies the nonname stuff from the fcb to the find32.
  2335. Arguments:
  2336. Fcb
  2337. Find32
  2338. Return Value:
  2339. none
  2340. Notes:
  2341. --*/
  2342. {
  2343. PFCB wrapperFcb = (PFCB)(MinimalCscSmbFcb->ContainingFcb);
  2344. if (wrapperFcb==NULL) {
  2345. return;
  2346. }
  2347. Find32->dwFileAttributes = wrapperFcb->Attributes; //&~FILE_ATTRIBUTE_NORMAL??
  2348. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32->ftLastWriteTime,
  2349. wrapperFcb->LastWriteTime);
  2350. //COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32->ftChangeTime,
  2351. // wrapperFcb->LastChangeTime);
  2352. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32->ftCreationTime,
  2353. wrapperFcb->CreationTime);
  2354. COPY_LARGEINTEGER_TO_STRUCTFILETIME(Find32->ftLastAccessTime,
  2355. wrapperFcb->LastAccessTime);
  2356. Find32->nFileSizeHigh = wrapperFcb->Header.FileSize.HighPart;
  2357. Find32->nFileSizeLow = wrapperFcb->Header.FileSize.LowPart;
  2358. }
  2359. #endif //#ifndef MRXSMB_BUILD_FOR_CSC_DCON
  2360. NTSTATUS
  2361. MRxSmbCscGetFileInfoForCshadow(
  2362. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  2363. )
  2364. /*++
  2365. Routine Description:
  2366. This is the start routine that basically continues the implementation
  2367. of MRxSmbGetFileInfoFromServer within the exchange initiation.
  2368. Arguments:
  2369. Return Value:
  2370. RXSTATUS - The return status for the operation
  2371. --*/
  2372. {
  2373. NTSTATUS Status;
  2374. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  2375. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  2376. Status = MRxSmbCscGetFileInfoFromServerWithinExchange (
  2377. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  2378. NULL); //NULL means the name is already in the exchange
  2379. return(Status);
  2380. }
  2381. NTSTATUS
  2382. MRxSmbGetFileInfoFromServer (
  2383. IN OUT PRX_CONTEXT RxContext,
  2384. IN PUNICODE_STRING FullFileName,
  2385. OUT _WIN32_FIND_DATA *Find32,
  2386. IN PMRX_SRV_OPEN pSrvOpen,
  2387. OUT BOOLEAN *lpfIsRoot
  2388. )
  2389. /*++
  2390. Routine Description:
  2391. This routine goes to the server to get a both_directory_info for
  2392. the file mentioned. Here, we have no exchange so we have to get
  2393. one. the underlying machinery for this leaves the pointer in the
  2394. exchange structure. We can then copy it out into the Find32 passed
  2395. in here.
  2396. Arguments:
  2397. RxContext - the RDBSS context
  2398. Return Value:
  2399. NTSTATUS - The return status for the operation
  2400. Notes:
  2401. --*/
  2402. {
  2403. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  2404. RxCaptureFcb; RxCaptureFobx;
  2405. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2406. PMRX_SRV_OPEN SrvOpen = NULL;
  2407. PMRX_SMB_SRV_OPEN smbSrvOpen = NULL;
  2408. PMRX_V_NET_ROOT VNetRootToUse = NULL;
  2409. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = NULL;
  2410. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  2411. BOOLEAN FinalizationComplete;
  2412. UNICODE_STRING uniRealName;
  2413. PAGED_CODE();
  2414. RxDbgTrace(+1, Dbg, ("MRxSmbGetFileInfoFromServer\n", 0 ));
  2415. if (pSrvOpen)
  2416. {
  2417. SrvOpen = pSrvOpen;
  2418. }
  2419. else
  2420. {
  2421. SrvOpen = capFobx->pSrvOpen;
  2422. }
  2423. if (lpfIsRoot)
  2424. {
  2425. *lpfIsRoot = FALSE;
  2426. }
  2427. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2428. VNetRootToUse = SrvOpen->pVNetRoot;
  2429. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(VNetRootToUse);
  2430. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2431. Status = SmbPseCreateOrdinaryExchange(
  2432. RxContext,
  2433. SrvOpen->pVNetRoot,
  2434. SMBPSE_OE_FROM_GETFILEINFOFORCSHADOW,
  2435. MRxSmbCscGetFileInfoForCshadow,
  2436. &OrdinaryExchange);
  2437. if (Status != STATUS_SUCCESS) {
  2438. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  2439. return Status;
  2440. }
  2441. if (smbFcb->uniDfsPrefix.Buffer)
  2442. {
  2443. UNICODE_STRING DfsName;
  2444. if((Status = CscDfsDoDfsNameMapping(&smbFcb->uniDfsPrefix,
  2445. &smbFcb->uniActualPrefix,
  2446. FullFileName,
  2447. FALSE, // fDFSNameToResolvedName
  2448. &uniRealName
  2449. )) != STATUS_SUCCESS)
  2450. {
  2451. RxDbgTrace(-1, Dbg, ("Couldn't map DFS name to real name!\n"));
  2452. return Status;
  2453. }
  2454. // DbgPrint("MrxSmbCscgetFileInfoFromServer: %wZ, real name %wZ\n",FullFileName, &uniRealName);
  2455. // if this is a root, then fixup the filename
  2456. if ((uniRealName.Length == 0) ||
  2457. ((uniRealName.Length == 2)&&(*uniRealName.Buffer == L'\\')))
  2458. {
  2459. if (lpfIsRoot)
  2460. {
  2461. *lpfIsRoot = TRUE;
  2462. }
  2463. }
  2464. }
  2465. else
  2466. {
  2467. uniRealName = *FullFileName;
  2468. }
  2469. OrdinaryExchange->pPathArgument1 = &uniRealName;
  2470. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  2471. ASSERT (Status!=RX_MAP_STATUS(PENDING));
  2472. if (Status == STATUS_SUCCESS) {
  2473. RtlCopyMemory(Find32, OrdinaryExchange->Find32WithinSmbbuf,sizeof(*Find32));
  2474. }
  2475. FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  2476. ASSERT(FinalizationComplete);
  2477. if (smbFcb->uniDfsPrefix.Buffer){
  2478. RxFreePool(uniRealName.Buffer);
  2479. }
  2480. RxDbgTrace(-1, Dbg, ("MRxSmbGetFileInfoFromServer exit with status=%08lx\n", Status ));
  2481. return(Status);
  2482. }
  2483. BOOLEAN
  2484. MRxSmbCscIsFatNameValid (
  2485. IN PUNICODE_STRING FileName,
  2486. IN BOOLEAN WildCardsPermissible
  2487. )
  2488. /*++
  2489. Routine Description:
  2490. This routine checks if the specified file name is conformant to the
  2491. Fat 8.3 file naming rules.
  2492. Arguments:
  2493. FileName - Supplies the name to check.
  2494. WildCardsPermissible - Tells us if wild card characters are ok.
  2495. Return Value:
  2496. BOOLEAN - TRUE if the name is valid, FALSE otherwise.
  2497. Notes:
  2498. i just lifted this routine from ntfs (jll-7-30-97)
  2499. --*/
  2500. {
  2501. BOOLEAN Results;
  2502. STRING DbcsName;
  2503. USHORT i;
  2504. CHAR Buffer[24];
  2505. WCHAR wc;
  2506. BOOLEAN AllowExtendedChars = TRUE;
  2507. PAGED_CODE();
  2508. //
  2509. // If the name is more than 24 bytes then it can't be a valid Fat name.
  2510. //
  2511. if (FileName->Length > 24) {
  2512. return FALSE;
  2513. }
  2514. //
  2515. // We will do some extra checking ourselves because we really want to be
  2516. // fairly restrictive of what an 8.3 name contains. That way
  2517. // we will then generate an 8.3 name for some nomially valid 8.3
  2518. // names (e.g., names that contain DBCS characters). The extra characters
  2519. // we'll filter off are those characters less than and equal to the space
  2520. // character and those beyond lowercase z.
  2521. //
  2522. if (AllowExtendedChars) {
  2523. for (i = 0; i < FileName->Length / sizeof( WCHAR ); i += 1) {
  2524. wc = FileName->Buffer[i];
  2525. if ((wc <= 0x0020) || (wc == 0x007c)) { return FALSE; }
  2526. }
  2527. } else {
  2528. for (i = 0; i < FileName->Length / sizeof( WCHAR ); i += 1) {
  2529. wc = FileName->Buffer[i];
  2530. if ((wc <= 0x0020) || (wc >= 0x007f) || (wc == 0x007c)) { return FALSE; }
  2531. }
  2532. }
  2533. //
  2534. // The characters match up okay so now build up the dbcs string to call
  2535. // the fsrtl routine to check for legal 8.3 formation
  2536. //
  2537. Results = FALSE;
  2538. DbcsName.MaximumLength = 24;
  2539. DbcsName.Buffer = Buffer;
  2540. if (NT_SUCCESS(RtlUnicodeStringToCountedOemString( &DbcsName, FileName, FALSE))) {
  2541. if (FsRtlIsFatDbcsLegal( DbcsName, WildCardsPermissible, FALSE, FALSE )) {
  2542. Results = TRUE;
  2543. }
  2544. }
  2545. //
  2546. // And return to our caller
  2547. //
  2548. return Results;
  2549. }
  2550. VOID
  2551. MRxSmbCscGenerate83NameAsNeeded(
  2552. IN CSC_SHADOW_HANDLE hDir,
  2553. PWCHAR FileName,
  2554. PWCHAR SFN
  2555. )
  2556. /*++
  2557. Routine Description:
  2558. This routine generates a SFN for a filename if it's not already
  2559. an SFN.
  2560. Arguments:
  2561. SFN - Not checking the allocated size of SFN in this function, but it
  2562. is always called from within core CSC. It is always pointing to
  2563. Find32->cAlternateFileName.
  2564. Return Value:
  2565. Notes:
  2566. --*/
  2567. {
  2568. UNICODE_STRING FileNameU;
  2569. WCHAR ShortNameBuffer[14];
  2570. UNICODE_STRING ShortUnicodeName;
  2571. GENERATE_NAME_CONTEXT Context;
  2572. //set up for no short name
  2573. *SFN = 0;
  2574. RtlInitUnicodeString(&FileNameU,FileName);
  2575. if (MRxSmbCscIsFatNameValid (&FileNameU,FALSE)) {
  2576. RxDbgTrace(0, Dbg,
  2577. ("MRxSmbCscGenerate83NameAsNeeded no SFN needed for ...<%ws>\n",
  2578. FileName));
  2579. return;
  2580. }
  2581. RxDbgTrace(0, Dbg,
  2582. ("MRxSmbCscGenerate83NameAsNeeded need SFN for ...<%ws>\n",
  2583. FileName));
  2584. // Now generate a short name.
  2585. //
  2586. ShortUnicodeName.Length = 0;
  2587. ShortUnicodeName.MaximumLength = 12 * sizeof(WCHAR);
  2588. ShortUnicodeName.Buffer = ShortNameBuffer;
  2589. RtlZeroMemory( &Context, sizeof( GENERATE_NAME_CONTEXT ) );
  2590. while ( TRUE ) {
  2591. NTSTATUS Status;
  2592. ULONG StatusOfShadowApiCall;
  2593. CSC_SHADOW_HANDLE hNew;
  2594. ULONG ShadowStatus;
  2595. RtlGenerate8dot3Name( &FileNameU, TRUE, &Context, &ShortUnicodeName );
  2596. //add the zero.....sigh......
  2597. ShortUnicodeName.Buffer[ShortUnicodeName.Length/sizeof(WCHAR)] = 0;
  2598. RxDbgTrace(0, Dbg,
  2599. ("MRxSmbCscGenerate83NameAsNeeded tryinh SFN <%ws>\n",
  2600. ShortUnicodeName.Buffer));
  2601. //look for existing shadow by that name
  2602. hNew = 0;
  2603. StatusOfShadowApiCall = GetShadow(
  2604. hDir, // HSHADOW hDir,
  2605. ShortUnicodeName.Buffer,
  2606. // USHORT *lpName,
  2607. &hNew, // LPHSHADOW lphShadow,
  2608. NULL, // LPFIND32 lpFind32,
  2609. &ShadowStatus,
  2610. // ULONG far *lpuShadowStatus,
  2611. NULL // LPOTHERINFO lpOI
  2612. );
  2613. if (hNew == 0) {
  2614. //the name was not found.....we're in business
  2615. RtlCopyMemory(SFN,
  2616. ShortUnicodeName.Buffer,
  2617. ShortUnicodeName.Length+sizeof(WCHAR));
  2618. RxDbgTrace(0, Dbg,
  2619. ("MRxSmbCscGenerate83NameAsNeeded using SFN <%ws>\n",
  2620. SFN));
  2621. return;
  2622. }
  2623. }
  2624. }
  2625. DEBUG_ONLY_DECL(ULONG MRxSmbCscCreateShadowEarlyExits = 0;)
  2626. NTSTATUS
  2627. MRxSmbCscCreateShadowFromPath (
  2628. IN PUNICODE_STRING AlreadyPrefixedName,
  2629. IN PCSC_ROOT_INFO pCscRootInfo,
  2630. OUT _WIN32_FIND_DATA *Find32,
  2631. OUT PBOOLEAN Created OPTIONAL,
  2632. IN ULONG Controls,
  2633. IN OUT PMINIMAL_CSC_SMBFCB MinimalCscSmbFcb,
  2634. IN OUT PRX_CONTEXT RxContext,
  2635. IN BOOLEAN fDisconnected,
  2636. OUT ULONG *pulInheritedHintFlags
  2637. )
  2638. /*++
  2639. Routine Description:
  2640. This routine walks down the current name creating/verifying shadows as it goes.
  2641. Arguments:
  2642. AlreadyPrefixedName - the filename for which is a shadow is found/created
  2643. pNetRootEntry - the netroot which is the base for the shadow
  2644. Find32 - a FIND32 structure filled in with the stored info for the shadow
  2645. Created OPT - (NULL or) a PBOOLEANset to TRUE if a new shadow is created
  2646. Controls - some special flags controlling when shadows are created
  2647. MinimalCscSmbFcb - the place where the shadow info is reported
  2648. RxContext - the RDBSS context
  2649. Disconnected - indicates the mode of operation
  2650. Return Value:
  2651. NTSTATUS - The return status for the operation
  2652. Notes:
  2653. --*/
  2654. {
  2655. NTSTATUS Status=STATUS_SUCCESS, LocalStatus;
  2656. UNICODE_STRING PathName, ComponentName;
  2657. PWCHAR PreviousSlash,NextSlash,Limit;
  2658. CSC_SHADOW_HANDLE hNew;
  2659. CSC_SHADOW_HANDLE hDir = pCscRootInfo->hRootDir;
  2660. ULONG StatusOfShadowApiCall;
  2661. ULONG ShadowStatus;
  2662. BOOLEAN LastComponentInName = FALSE, fRootHintFlagsObtained=FALSE;
  2663. ULONG DirectoryLevel, ulHintFlags=0;
  2664. OTHERINFO sOI; //hint/refpri data
  2665. BOOLEAN JunkCreated;
  2666. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2667. //CODE.IMPROVEMENT this is a little dangerous.....not everyone who
  2668. // calls this routine has an actual smbFcb. we should get some asserts
  2669. // going wheever we use this that it's the same as the one that
  2670. // we could have gotten from the RxContext.
  2671. PMRX_SMB_FCB smbFcb = CONTAINING_RECORD(MinimalCscSmbFcb,
  2672. MRX_SMB_FCB,
  2673. MinimalCscSmbFcb);
  2674. BEGIN_TIMING(MRxSmbCscCreateShadowFromPath);
  2675. RxDbgTrace(+1, Dbg, ("MRxSmbCscCreateShadowFromPath...<%wZ> %08lx %08lx\n",
  2676. AlreadyPrefixedName,hDir,Controls));
  2677. DbgDoit(ASSERT(vfInShadowCrit));
  2678. ASSERT(hDir);
  2679. if (Created == NULL) {
  2680. Created = &JunkCreated;
  2681. }
  2682. *Created = FALSE;
  2683. PathName = *AlreadyPrefixedName;
  2684. // Fix for Bug# 554061 CSC should not handle loopback
  2685. if(RxContext->pRelevantSrvOpen) {
  2686. pServerEntry = SmbCeGetAssociatedServerEntry(RxContext->pRelevantSrvOpen->pVNetRoot->pNetRoot->pSrvCall);
  2687. }
  2688. else {
  2689. // RxContext->pRelevantSrvOpen is NULL only in the case of a tree connect
  2690. // to a directory on a disconnected server.
  2691. ASSERT(RxContext->MajorFunction == IRP_MJ_CREATE);
  2692. ASSERT(RxContext->Create.ThisIsATreeConnectOpen);
  2693. pServerEntry = SmbCeGetAssociatedServerEntry(RxContext->Create.pSrvCall);
  2694. }
  2695. if(pServerEntry->Server.IsLoopBack)
  2696. {
  2697. Status = STATUS_UNSUCCESSFUL;
  2698. goto bailout;
  2699. }
  2700. if (FlagOn(Controls, CREATESHADOW_CONTROL_STRIP_SHARE_NAME))
  2701. {
  2702. ASSERT(!fDisconnected);
  2703. if(CscDfsStripLeadingServerShare(&PathName) != STATUS_SUCCESS)
  2704. {
  2705. return Status;
  2706. }
  2707. }
  2708. Limit = (PWCHAR)(((PBYTE)PathName.Buffer)+ PathName.Length);
  2709. // strip out trailing 0s and slash
  2710. if (PathName.Length > 2)
  2711. {
  2712. while ((*(Limit-1)==0)||(*(Limit-1)=='\\'))
  2713. {
  2714. --Limit;
  2715. PathName.Length -= 2;
  2716. ASSERT((*Limit == 0) || (*Limit == '\\'));
  2717. if (Limit == PathName.Buffer)
  2718. {
  2719. ASSERT(FALSE);
  2720. break;
  2721. }
  2722. }
  2723. }
  2724. PreviousSlash = PathName.Buffer;
  2725. // in connected mode apply the character exclusion list + filetype exclusion list
  2726. // in disconnected mode only apply the character exclusion list
  2727. MinimalCscSmbFcb->fDoBitCopy = FALSE;
  2728. if (CheckForBandwidthConservation(PathName.Buffer, // name
  2729. PathName.Length/sizeof(USHORT))) // size in bytes
  2730. {
  2731. MinimalCscSmbFcb->fDoBitCopy = TRUE;
  2732. HookKdPrint(BITCOPY, ("Bitcopy enabled for %wZ \n", &PathName));
  2733. }
  2734. else if (ExcludeFromCreateShadow(PathName.Buffer, // name
  2735. PathName.Length/sizeof(USHORT), // size in bytes
  2736. (fDisconnected==0))) // Check filetype Exclusion List
  2737. {
  2738. Controls |= CREATESHADOW_CONTROL_NOCREATE;
  2739. }
  2740. if ((PathName.Length == 0) ||
  2741. ((PathName.Length == 2) &&
  2742. (*PreviousSlash == OBJ_NAME_PATH_SEPARATOR))) {
  2743. //in disconnected mode, we have to handle opening the root dir
  2744. RxDbgTrace(0,
  2745. Dbg,
  2746. ("MRxSmbCscCreateShadowFromPath basdir ret/handles...<%08lx>\n",
  2747. hDir));
  2748. //fill in the stuff that we have.....
  2749. MinimalCscSmbFcb->hParentDir = 0;
  2750. MinimalCscSmbFcb->hShadow = hDir;
  2751. MinimalCscSmbFcb->LastComponentOffset = 0;
  2752. MinimalCscSmbFcb->LastComponentLength = 0;
  2753. if (!FlagOn(Controls,CREATESHADOW_CONTROL_NOREVERSELOOKUP)
  2754. && (smbFcb->ShadowReverseTranslationLinks.Flink == 0)) {
  2755. ValidateSmbFcbList();
  2756. smbFcb->ContainingFcb->fMiniInited = TRUE;
  2757. MRxSmbCscAddReverseFcbTranslation(smbFcb);
  2758. }
  2759. //fill in a vacuous find32structure
  2760. RtlZeroMemory(Find32,sizeof(_WIN32_FIND_DATA));
  2761. Find32->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  2762. //make sure that we avoid the loop below
  2763. PreviousSlash = Limit;
  2764. //we're outta here......
  2765. }
  2766. // stop the guy if he doesn't have access
  2767. if (FlagOn(Controls,CREATESHADOW_CONTROL_DO_SHARE_ACCESS_CHECK))
  2768. {
  2769. ASSERT(fDisconnected);
  2770. if(!CscAccessCheck(
  2771. 0,
  2772. hDir,
  2773. RxContext,
  2774. RxContext->Create.NtCreateParameters.DesiredAccess,
  2775. NULL,
  2776. NULL
  2777. ))
  2778. {
  2779. Status = STATUS_ACCESS_DENIED;
  2780. HookKdPrint(BADERRORS, ("CSFP: Access Check failed on root directory %x", hDir));
  2781. goto bailout;
  2782. }
  2783. }
  2784. for (DirectoryLevel=1;;DirectoryLevel++) {
  2785. BOOLEAN UsingExistingShadow;
  2786. if (PreviousSlash >= Limit) {
  2787. break;
  2788. }
  2789. NextSlash = PreviousSlash + 1;
  2790. for (;;NextSlash++) {
  2791. if (NextSlash >= Limit) {
  2792. LastComponentInName = TRUE;
  2793. break;
  2794. }
  2795. if (*NextSlash == OBJ_NAME_PATH_SEPARATOR) {
  2796. // assert that we don't have a trailing slash at the end
  2797. ASSERT((NextSlash+1) < Limit);
  2798. break;
  2799. }
  2800. }
  2801. ComponentName.Buffer = PreviousSlash+1;
  2802. ComponentName.Length =
  2803. (USHORT)(((PBYTE)(NextSlash)) - ((PBYTE)ComponentName.Buffer));
  2804. PreviousSlash = NextSlash;
  2805. RtlZeroMemory(Find32,sizeof(_WIN32_FIND_DATA));
  2806. RtlCopyMemory(&Find32->cFileName[0],
  2807. ComponentName.Buffer,
  2808. ComponentName.Length);
  2809. //lastcomponentname stuff for connected has been moved below.....
  2810. RxDbgTrace(0, Dbg,
  2811. ("MRxSmbCscCreateShadowFromPath name from find32 for GetShadow...<%ws>\n",
  2812. &Find32->cFileName[0]));
  2813. hNew = 0;
  2814. UsingExistingShadow = FALSE;
  2815. ASSERT(Find32->cFileName[0]);
  2816. StatusOfShadowApiCall = GetShadow(
  2817. hDir, // HSHADOW hDir,
  2818. &Find32->cFileName[0], // USHORT *lpName,
  2819. &hNew, // LPHSHADOW lphShadow,
  2820. Find32, // LPFIND32 lpFind32,
  2821. &ShadowStatus, // ULONG far *lpuShadowStatus,
  2822. &sOI // LPOTHERINFO lpOI
  2823. );
  2824. if (StatusOfShadowApiCall != SRET_OK) {
  2825. //no need to fail the open but we get no shadow info
  2826. break;
  2827. }
  2828. if (hNew) {
  2829. // accumulate pin inheritance flags
  2830. ulHintFlags |= (sOI.ulHintFlags & FLAG_CSC_HINT_INHERIT_MASK);
  2831. }
  2832. //we will have to do something about it if a directory turns
  2833. // a file or viceversa for connected
  2834. if (hNew==0) {
  2835. LPOTHERINFO lpOI=NULL;
  2836. UNICODE_STRING ComponentPath;
  2837. if (FlagOn(Controls,CREATESHADOW_CONTROL_NOCREATE)) {
  2838. //if no creates...we're outta here.......
  2839. if (FALSE) {
  2840. DbgDoit({
  2841. if ( ((MRxSmbCscCreateShadowEarlyExits++)&0x7f) == 0x7f ) {
  2842. RxLog(("Csc EarlyExit no create %d\n",
  2843. MRxSmbCscCreateShadowEarlyExits));
  2844. }
  2845. })
  2846. }
  2847. break;
  2848. }
  2849. if (LastComponentInName && FlagOn(Controls,CREATESHADOW_CONTROL_NOCREATELEAF)) {
  2850. //if no creates...we're outta here.......but we still need to set what
  2851. //would be the hParentDir......and the name offsets
  2852. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateShadowFromPath noleaf ret/handles..."
  2853. "<%08lx><%08lx><%08lx>\n",
  2854. StatusOfShadowApiCall,hDir,hNew));
  2855. MinimalCscSmbFcb->hParentDir = hDir;
  2856. MinimalCscSmbFcb->LastComponentOffset = (USHORT)(ComponentName.Buffer - AlreadyPrefixedName->Buffer);
  2857. MinimalCscSmbFcb->LastComponentLength = ComponentName.Length;
  2858. break;
  2859. }
  2860. if (!LastComponentInName && FlagOn(Controls,CREATESHADOW_CONTROL_NOCREATENONLEAF)) {
  2861. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateShadowFromPath nocreatenonleaf ret/handles..."
  2862. "<%08lx><%08lx><%08lx>\n",
  2863. StatusOfShadowApiCall,hDir,hNew));
  2864. break;
  2865. }
  2866. ASSERT(RxContext!=NULL);
  2867. ShadowStatus = 0;
  2868. if (!fDisconnected){ //ok for dcon start of big dcon blob 1
  2869. BOOLEAN fIsRoot = FALSE;
  2870. BEGIN_TIMING(MRxSmbGetFileInfoFromServer);
  2871. ComponentPath.Buffer = PathName.Buffer;
  2872. ComponentPath.Length =
  2873. (USHORT)(((PBYTE)(NextSlash)) - ((PBYTE)ComponentPath.Buffer));
  2874. LeaveShadowCritRx(RxContext);
  2875. Status = MRxSmbGetFileInfoFromServer(RxContext,&ComponentPath,Find32, NULL, &fIsRoot);
  2876. EnterShadowCritRx(RxContext);
  2877. END_TIMING(MRxSmbGetFileInfoFromServer);
  2878. if (Status != STATUS_SUCCESS)
  2879. {
  2880. // if this is a DFS path and we couldn't reverse map, it
  2881. // just create a directory or file with fake info and mark it as stale
  2882. if (smbFcb->uniDfsPrefix.Buffer && (Status == STATUS_NO_SUCH_FILE))
  2883. {
  2884. ShadowStatus |= SHADOW_STALE;
  2885. CreateFakeFind32(hDir, Find32, RxContext, LastComponentInName);
  2886. HookKdPrint(NAME, ("Fake win32 for DFS share %ls\n", Find32->cFileName));
  2887. Status = STATUS_SUCCESS;
  2888. }
  2889. else
  2890. {
  2891. HookKdPrint(BADERRORS, (" MRxSmbGetFileInfoFromServer failed %ls Status=%x\n", Find32->cFileName, Status));
  2892. // we change the STATUS_RETRY to something worse. STATUS_RETRY is used
  2893. if (Status == STATUS_RETRY)
  2894. {
  2895. Status = STATUS_UNSUCCESSFUL;
  2896. }
  2897. break;
  2898. }
  2899. }
  2900. else
  2901. {
  2902. // in case of DFS, this could be a root, in which case the naem we get back won't be
  2903. // correct. Restore it to the original name
  2904. if (smbFcb->uniDfsPrefix.Buffer && fIsRoot)
  2905. {
  2906. ShadowStatus |= SHADOW_STALE;
  2907. RtlCopyMemory(&Find32->cFileName[0],
  2908. ComponentName.Buffer,
  2909. ComponentName.Length);
  2910. Find32->cFileName[ComponentName.Length/sizeof(USHORT)] = 0;
  2911. MRxSmbCscGenerate83NameAsNeeded(hDir,
  2912. &Find32->cFileName[0],
  2913. &Find32->cAlternateFileName[0]);
  2914. }
  2915. }
  2916. } else {
  2917. ShadowStatus = SHADOW_LOCALLY_CREATED;
  2918. //CODE.IMPROVEMENT...should we check for 0-length as well
  2919. RxDbgTrace(0, Dbg,
  2920. ("MRxSmbCscCreateShadowFromPath setting to locallycreated...<%ws>\n",
  2921. &Find32->cFileName[0],ShadowStatus));
  2922. CreateFakeFind32(hDir, Find32, RxContext, LastComponentInName);
  2923. }
  2924. if (!LastComponentInName ||
  2925. FlagOn(Controls,CREATESHADOW_CONTROL_SPARSECREATE) ||
  2926. FlagOn(Find32->dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY) ) {
  2927. ShadowStatus |= SHADOW_SPARSE;
  2928. //CODE.IMPROVEMENT...should we check for 0-length as well
  2929. RxDbgTrace(0, Dbg,
  2930. ("MRxSmbCscCreateShadowFromPath setting to sparse...<%ws>\n",
  2931. &Find32->cFileName[0],ShadowStatus));
  2932. }
  2933. // check for pin flag inheritance when creating anything
  2934. if(!fRootHintFlagsObtained) {
  2935. StatusOfShadowApiCall = GetShadowInfo(
  2936. 0,
  2937. pCscRootInfo->hRootDir,
  2938. NULL,
  2939. NULL,
  2940. &sOI
  2941. );
  2942. if(StatusOfShadowApiCall != SRET_OK) {
  2943. break;
  2944. }
  2945. fRootHintFlagsObtained = TRUE;
  2946. // or the inheritance bits
  2947. ulHintFlags |= (sOI.ulHintFlags & FLAG_CSC_HINT_INHERIT_MASK);
  2948. }
  2949. // If there is any tunnelling info then use it to create this guy
  2950. if (RetrieveTunnelInfo(
  2951. hDir,
  2952. &Find32->cFileName[0], // potential SFN OK for red/yellow
  2953. (fDisconnected)?Find32:NULL, // get LFN only when disconnected
  2954. &sOI)) {
  2955. lpOI = &sOI;
  2956. }
  2957. // are we supposed to do any inheritance?
  2958. if (ulHintFlags & (FLAG_CSC_HINT_INHERIT_MASK)) {
  2959. if (!lpOI) {
  2960. InitOtherInfo(&sOI);
  2961. lpOI = &sOI;
  2962. lpOI->ulHintFlags = 0;
  2963. }
  2964. if (ulHintFlags & FLAG_CSC_HINT_PIN_INHERIT_USER) {
  2965. lpOI->ulHintFlags |= FLAG_CSC_HINT_PIN_USER;
  2966. }
  2967. if (ulHintFlags & FLAG_CSC_HINT_PIN_INHERIT_SYSTEM) {
  2968. lpOI->ulHintFlags |= FLAG_CSC_HINT_PIN_SYSTEM;
  2969. }
  2970. }
  2971. // if this is a file on which special heuristic needs to be applied
  2972. // and none of it's parents have system pin inheritance bit set
  2973. // then we do not create the file.
  2974. // Thus on remoteboot shares, we will create entries for these files
  2975. // even if they are opend without the execute flag set.
  2976. // This takes care of the upgrade NT50 to an RB machine scenario
  2977. if ((Controls & CREATESHADOW_CONTROL_FILE_WITH_HEURISTIC)&&
  2978. !(ulHintFlags & FLAG_CSC_HINT_PIN_INHERIT_SYSTEM))
  2979. {
  2980. break;
  2981. }
  2982. #if defined(REMOTE_BOOT)
  2983. //
  2984. // In the remote boot case, there was an extra PVOID lpContext
  2985. // parameter to CreateShadowInternal, to which we passed a pointer
  2986. // to a structure. The structure held the cp value (NT_CREATE_PARAMETERS)
  2987. // from &RxContext->Create.NtCreateParameters and the address of
  2988. // a local NTSTATUS value. Eventually this caused the underlying
  2989. // call to IoCreateFile to be done while impersonating the current
  2990. // user, and the status from IoCreateFile was readable upon
  2991. // return from the local value.
  2992. //
  2993. #endif
  2994. StatusOfShadowApiCall = CreateShadowInternal (
  2995. hDir, // HSHADOW hDir,
  2996. Find32, // LPFIND32 lpFind32,
  2997. ShadowStatus,// ULONG uFlags,
  2998. lpOI, // LPOTHERINFO lpOI,
  2999. &hNew // LPHSHADOW lphNew
  3000. );
  3001. HookKdPrint(NAME, ("Create %ws in hDir=%x, hShadow=%x Status=%x StatusOfShadowApiCall=%x\n\n", Find32->cFileName, hDir, hNew, ShadowStatus, StatusOfShadowApiCall));
  3002. if (StatusOfShadowApiCall != SRET_OK) {
  3003. RxDbgTrace(0, Dbg,
  3004. ("MRxSmbCscCreateShadowFromPath createshadowinternal failed!!!...<%ws>\n",
  3005. &Find32->cFileName[0],ShadowStatus));
  3006. break; //no need to fail the open but we get no shadow info
  3007. }
  3008. *Created = LastComponentInName;
  3009. RxLog(("Created %ws in hDir=%x, hShadow=%x Status=%x\n\n", Find32->cFileName, hDir, hNew, ShadowStatus));
  3010. } else {
  3011. RxDbgTrace(0,Dbg,
  3012. ("MRxSmbCscCreateShadowFromPath name from getsh <%ws>\n",
  3013. &Find32->cFileName[0]));
  3014. if (!fDisconnected) // nothing in connected mode
  3015. {
  3016. // Check if this file should be invisible in connected state
  3017. // We won't want to do this for VDO
  3018. if( (!(Find32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) &&
  3019. mShadowNeedReint(ShadowStatus))
  3020. {
  3021. HookKdPrint(BADERRORS, ("File needs merge %x %x Stts=%x %ls\n", hDir, hNew, ShadowStatus, Find32->cFileName));
  3022. Status = STATUS_ACCESS_DENIED;
  3023. break;
  3024. }
  3025. }
  3026. else // lots in disconnected mode
  3027. {
  3028. if (LastComponentInName && (FlagOn(Controls,CREATESHADOW_CONTROL_NOCREATELEAF)||
  3029. FlagOn(Controls,CREATESHADOW_CONTROL_NOCREATE)))
  3030. {
  3031. // if this is the last component and we are not supposed to
  3032. // create it then skip it.
  3033. }
  3034. else
  3035. {
  3036. // If it is marked deleted then it is time to recreate it
  3037. if (mShadowDeleted(ShadowStatus))
  3038. {
  3039. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  3040. // Check for a type change from a deleted filename
  3041. // to a directory name; the other way around is not possible
  3042. // in our scheme where shadowed directories are not deletable
  3043. // just bailout
  3044. if(((IsFile(Find32->dwFileAttributes) != 0) // pre type
  3045. != ((LastComponentInName && !FlagOn(cp->CreateOptions,FILE_DIRECTORY_FILE))!=0)))
  3046. {
  3047. RxLog(("MRxSmbCscCreateShadowFromPath: type change, failing\n"));
  3048. HookKdPrint(BADERRORS, ("MRxSmbCscCreateShadowFromPath: type change, failing\n"));
  3049. Status = STATUS_ACCESS_DENIED;
  3050. break;
  3051. }
  3052. KeQuerySystemTime(((PLARGE_INTEGER)(&Find32->ftCreationTime)));
  3053. Find32->ftLastAccessTime = Find32->ftLastWriteTime = Find32->ftCreationTime;
  3054. //already zero Find32->nFileSizeHigh = Find32->nFileSizeLow = 0;
  3055. ShadowStatus = SHADOW_DIRTY|SHADOW_TIME_CHANGE|SHADOW_ATTRIB_CHANGE|SHADOW_REUSED;
  3056. // Update the shadow info without changing the version stamp
  3057. if(SetShadowInfo(hDir, hNew, Find32, ShadowStatus,
  3058. SHADOW_FLAGS_ASSIGN|SHADOW_FLAGS_DONT_UPDATE_ORGTIME
  3059. ) < SRET_OK)
  3060. {
  3061. hNew = 0;
  3062. break;
  3063. }
  3064. // set created flag to true. Based on the Recreated bit, we will know whether
  3065. // this entry was resurrected or not
  3066. *Created = TRUE;
  3067. }
  3068. else if (IsFile(Find32->dwFileAttributes) && (mShadowSparse(ShadowStatus)))
  3069. {
  3070. ShadowStatus = SHADOW_DIRTY|SHADOW_TIME_CHANGE|SHADOW_ATTRIB_CHANGE|SHADOW_REUSED;
  3071. Find32->ftLastAccessTime = Find32->ftLastWriteTime = Find32->ftCreationTime;
  3072. Find32->nFileSizeHigh = Find32->nFileSizeLow = 0;
  3073. if ((TruncateDataHSHADOW(hDir, hNew)>=SRET_OK)&&
  3074. (SetShadowInfo(hDir, hNew, Find32, ShadowStatus,SHADOW_FLAGS_ASSIGN)>=SRET_OK))
  3075. {
  3076. // set created flag to true. Based on the Recreated bit, we will know whether
  3077. // this entry was resurrected or not
  3078. *Created = TRUE;
  3079. }
  3080. else
  3081. {
  3082. Status = STATUS_UNSUCCESSFUL;
  3083. hNew = 0;
  3084. break;
  3085. }
  3086. }
  3087. }
  3088. }
  3089. }
  3090. if (LastComponentInName && (hNew!=0)) {
  3091. LONG nFileSizeLow, nFileSizeHigh;
  3092. // if we are here from the createepilogue then we need to see whether there is an
  3093. // FCB floating around for this name that has a delete_on_close issued on one of the fobxs
  3094. // and is ready for purge. If it isn't ready for purging, ie. there are some
  3095. // outstanding opens on it then this current create is an invalid operation
  3096. if(FlagOn(Controls,CREATESHADOW_CONTROL_FAIL_IF_MARKED_FOR_DELETION))
  3097. {
  3098. PMRX_SMB_FCB pSmbFcb = MRxSmbCscRecoverMrxFcbFromFdb(MRxSmbCscFindFdbFromHShadow(hNew));
  3099. if (pSmbFcb && (pSmbFcb->LocalFlags & FLAG_FDB_DELETE_ON_CLOSE))
  3100. {
  3101. RxCaptureFcb;
  3102. RxLog(("delonclose FCB=%x\n", pSmbFcb));
  3103. RxLog(("prgrelfobx \n"));
  3104. LeaveShadowCritRx(RxContext);
  3105. RxScavengeFobxsForNetRoot((PNET_ROOT)(capFcb->pNetRoot),(PFCB)capFcb);
  3106. EnterShadowCritRx(RxContext);
  3107. if (MRxSmbCscFindFdbFromHShadow(hNew))
  3108. {
  3109. RxLog(("ACCESS_DENIED FCB=%x \n", capFcb));
  3110. HookKdPrint(BADERRORS, ("ACCESS_DENIED FCB=%x \n", capFcb));
  3111. Status = STATUS_ACCESS_DENIED;
  3112. break;
  3113. }
  3114. // we potentially have an inode which has been deleted
  3115. // let us try to get the inode again
  3116. RxLog(("purged relfobx \n"));
  3117. Status = STATUS_RETRY;
  3118. hNew = 0;
  3119. break;
  3120. }
  3121. }
  3122. if (hNew!=0) {
  3123. // When any local changes are made ensure that the share in the
  3124. // CSC database is marked dirty if it has not been prevoiously
  3125. // marked. This facilitates the easy detection of changes for
  3126. // reintegration by the agent.
  3127. if (ShadowStatus & SHADOW_MODFLAGS) {
  3128. MarkShareDirty(&pCscRootInfo->ShareStatus, (ULONG)(pCscRootInfo->hShare));
  3129. }
  3130. //okay, lets remember this in the fcb
  3131. smbFcb->hParentDir = hDir;
  3132. smbFcb->hShadow = hNew;
  3133. smbFcb->ShadowStatus = (USHORT)ShadowStatus;
  3134. //it's excellent if we can find the last component again...fast
  3135. smbFcb->LastComponentOffset = (USHORT)(ComponentName.Buffer -
  3136. AlreadyPrefixedName->Buffer);
  3137. smbFcb->LastComponentLength = ComponentName.Length;
  3138. if (!FlagOn(Controls,CREATESHADOW_CONTROL_NOREVERSELOOKUP)
  3139. && (smbFcb->ShadowReverseTranslationLinks.Flink == 0)) {
  3140. ValidateSmbFcbList();
  3141. smbFcb->ContainingFcb->fMiniInited = TRUE;
  3142. MRxSmbCscAddReverseFcbTranslation(smbFcb);
  3143. smbFcb->OriginalShadowSize.LowPart = Find32->nFileSizeLow;
  3144. smbFcb->OriginalShadowSize.HighPart = Find32->nFileSizeHigh;
  3145. }
  3146. // Initialize the serialization mechanism used for reads/writes
  3147. ExInitializeFastMutex(&smbFcb->CscShadowReadWriteMutex);
  3148. }
  3149. }
  3150. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateShadowFromPath ret/handles...<%08lx><%08lx><%08lx><%08lx>\n",
  3151. StatusOfShadowApiCall,hDir,hNew));
  3152. hDir = hNew;
  3153. }
  3154. if (pulInheritedHintFlags)
  3155. {
  3156. *pulInheritedHintFlags = ulHintFlags;
  3157. }
  3158. bailout:
  3159. RxDbgTrace(-1, Dbg, ("MRxSmbCscCreateShadowFromPath -> %08lx\n", Status ));
  3160. END_TIMING(MRxSmbCscCreateShadowFromPath);
  3161. return Status;
  3162. }
  3163. //CODE.IMPROVEMENT this routine should be in cshadow.c in the record
  3164. // manager.....but it's in hook.c for the shadow VxD so maybe hookcmmn.c
  3165. int RefreshShadow( HSHADOW hDir,
  3166. IN HSHADOW hShadow,
  3167. IN LPFIND32 lpFind32,
  3168. OUT ULONG *lpuShadowStatus
  3169. )
  3170. /*++
  3171. Routine Description:
  3172. This routine, checks whether the local copy is current or not. If it isn't then it
  3173. stamps the local copy as being stale.
  3174. Arguments:
  3175. hShadow Inode representing the local copy
  3176. lpFind32 The new find32 info as obtained from the Share
  3177. lpuShadowStatus Returns the new status of the inode
  3178. Return Value:
  3179. Success if >= 0, failed other wise
  3180. Notes:
  3181. --*/
  3182. {
  3183. int iRet = -1;
  3184. int iLocalRet;
  3185. ULONG uShadowStatus;
  3186. // ACHTUNG never called in disconnected state
  3187. RxLog(("Refresh %x \n", hShadow));
  3188. if (ChkUpdtStatusHSHADOW(hDir, hShadow, lpFind32, &uShadowStatus) < 0)
  3189. {
  3190. goto bailout;
  3191. }
  3192. if (uShadowStatus & SHADOW_STALE)
  3193. {
  3194. long nFileSizeHigh, nFileSizeLow;
  3195. if (uShadowStatus & SHADOW_DIRTY)
  3196. {
  3197. KdPrint(("RefreshShadow: conflict on %x\r\n", hShadow));
  3198. iRet = -2;
  3199. goto bailout;// conflict
  3200. }
  3201. // DbgPrint("Tuncating %ws %x \n", lpFind32->cFileName, hShadow);
  3202. // Truncate the data to 0, this also adjusts the shadow space usage
  3203. TruncateDataHSHADOW(hDir, hShadow);
  3204. // Set status flags to indicate sparse file
  3205. uShadowStatus = SHADOW_SPARSE;
  3206. // ACHTUNG!!! We know we are connected,
  3207. // hence we don't use SHADOW_FLAG_DONT_UPDATE_ORGTIME
  3208. iLocalRet = SetShadowInfo(hDir,
  3209. hShadow,
  3210. lpFind32,
  3211. uShadowStatus,
  3212. SHADOW_FLAGS_ASSIGN
  3213. );
  3214. if (iLocalRet < SRET_OK)
  3215. {
  3216. goto bailout;
  3217. }
  3218. #ifdef MAYBE
  3219. MakeSpace(lpFind32->nFileSizeHigh, lpFind32->nFileSizeLow);
  3220. #endif //MAYBE
  3221. // AllocShadowSpace(lpFind32->nFileSizeHigh, lpFind32->nFileSizeLow, TRUE);
  3222. iRet = 1;
  3223. }
  3224. else
  3225. {
  3226. iRet = 0;
  3227. }
  3228. *lpuShadowStatus = uShadowStatus;
  3229. bailout:
  3230. return (iRet);
  3231. }
  3232. BOOLEAN
  3233. MRxSmbCscIsThisACopyChunkOpen (
  3234. IN PRX_CONTEXT RxContext,
  3235. BOOLEAN *lpfAgent
  3236. )
  3237. /*++
  3238. Routine Description:
  3239. This routine determines if the open described by the RxContext is
  3240. a open-with-chunk intent.
  3241. Arguments:
  3242. RxContext - the RDBSS context
  3243. Return Value:
  3244. NTSTATUS - The return status for the operation
  3245. Notes:
  3246. --*/
  3247. {
  3248. BOOLEAN IsChunkOpen = FALSE;
  3249. RxCaptureFcb;
  3250. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  3251. if ((CreateParameters->DesiredAccess == (FILE_READ_ATTRIBUTES | SYNCHRONIZE)) &&
  3252. (CreateParameters->Disposition == FILE_OPEN) &&
  3253. (CreateParameters->AllocationSize.HighPart ==
  3254. MRxSmbSpecialCopyChunkAllocationSizeMarker)) {
  3255. IsChunkOpen = (TRUE);
  3256. if (lpfAgent)
  3257. {
  3258. *lpfAgent = (CreateParameters->AllocationSize.LowPart != 0);
  3259. }
  3260. }
  3261. return IsChunkOpen;
  3262. }
  3263. NTSTATUS
  3264. SmbPseExchangeStart_CloseCopyChunk(
  3265. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  3266. )
  3267. /*++
  3268. Routine Description:
  3269. This is the start routine for close.
  3270. Arguments:
  3271. pExchange - the exchange instance
  3272. Return Value:
  3273. RXSTATUS - The return status for the operation
  3274. --*/
  3275. {
  3276. NTSTATUS Status = STATUS_SUCCESS;
  3277. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  3278. RxCaptureFcb;RxCaptureFobx;
  3279. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  3280. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3281. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3282. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  3283. PSMBCEDB_SERVER_ENTRY pServerEntry= SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  3284. PAGED_CODE();
  3285. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_CloseCopyChunk %08lx\n", RxContext ));
  3286. ASSERT(OrdinaryExchange->Type == ORDINARY_EXCHANGE);
  3287. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  3288. Status = MRxSmbBuildClose(StufferState);
  3289. if (Status == STATUS_SUCCESS) {
  3290. // Ensure that the Fid is validated....
  3291. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  3292. Status = SmbPseOrdinaryExchange(
  3293. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  3294. SMBPSE_OETYPE_CLOSE
  3295. );
  3296. // Ensure that the Fid validation is disabled
  3297. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  3298. ASSERT (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE));
  3299. }
  3300. //even if it didn't work there's nothing i can do......keep going
  3301. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  3302. MRxSmbDecrementSrvOpenCount(pServerEntry,smbSrvOpen->Version,SrvOpen);
  3303. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_CloseCopyChunk %08lx exit w %08lx\n", RxContext, Status ));
  3304. return Status;
  3305. }
  3306. NTSTATUS
  3307. MRxSmbCscCloseExistingThruOpen(
  3308. IN OUT PRX_CONTEXT RxContext
  3309. )
  3310. /*++
  3311. Routine Description:
  3312. This routine closes the existing copychunk thru open and marks it as not open
  3313. Arguments:
  3314. RxContext - the RDBSS context
  3315. Return Value:
  3316. NTSTATUS - The return status for the operation
  3317. --*/
  3318. {
  3319. NTSTATUS Status = STATUS_SUCCESS;
  3320. PUNICODE_STRING RemainingName;
  3321. RxCaptureFcb;
  3322. PMRX_FOBX SaveFobxFromContext = RxContext->pFobx;
  3323. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  3324. PMRX_FOBX capFobx = smbFcb->CopyChunkThruOpen;
  3325. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3326. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3327. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  3328. PAGED_CODE();
  3329. ASSERT ( NodeTypeIsFcb(capFcb) );
  3330. RxDbgTrace(+1, Dbg, ("MRxSmbCscCloseExistingThruOpen %08lx %08lx %wZ\n",
  3331. RxContext,SrvOpen,GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext) ));
  3332. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  3333. ASSERT(smbSrvOpen->hfShadow == 0);
  3334. RxDbgTrace(-1, Dbg, ("CopyChunkOpen already closed\n"));
  3335. return (STATUS_SUCCESS);
  3336. }
  3337. //briefly shanghai the capfobx field in the RxContext
  3338. ASSERT(SaveFobxFromContext==NULL);
  3339. RxContext->pFobx = capFobx;
  3340. if (smbSrvOpen->hfShadow != 0){
  3341. MRxSmbCscCloseShadowHandle(RxContext);
  3342. }
  3343. Status = SmbPseCreateOrdinaryExchange(
  3344. RxContext,
  3345. SrvOpen->pVNetRoot,
  3346. SMBPSE_OE_FROM_CLOSECOPYCHUNKSRVCALL,
  3347. SmbPseExchangeStart_CloseCopyChunk,
  3348. &OrdinaryExchange);
  3349. if (Status != STATUS_SUCCESS) {
  3350. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  3351. RxContext->pFobx = SaveFobxFromContext;
  3352. return(Status);
  3353. }
  3354. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  3355. ASSERT (Status != (STATUS_PENDING));
  3356. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  3357. RxDbgTrace(-1, Dbg,
  3358. ("MRxSmbCscCloseExistingThruOpen exit w/ status=%08lx\n", Status ));
  3359. RxContext->pFobx = SaveFobxFromContext;
  3360. if (smbSrvOpen->Flags & SMB_SRVOPEN_FLAG_AGENT_COPYCHUNK_OPEN)
  3361. {
  3362. smbFcb->CopyChunkThruOpen = NULL;
  3363. smbSrvOpen->Flags &= ~SMB_SRVOPEN_FLAG_AGENT_COPYCHUNK_OPEN;
  3364. }
  3365. RxDbgTrace(0, Dbg, ("MRxSmbCscCloseExistingThruOpen status=%x\n", Status));
  3366. return(Status);
  3367. }
  3368. ULONG SuccessfulSurrogateOpens = 0;
  3369. NTSTATUS
  3370. MRxSmbCscCreatePrologue (
  3371. IN OUT PRX_CONTEXT RxContext,
  3372. OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  3373. )
  3374. /*++
  3375. Routine Description:
  3376. This routine performs the correct synchronization among opens. This
  3377. synchronization required because CopyChunk-thru opens are not allowed
  3378. to exist alongside any other kind.
  3379. So, we first must identify copychunk opens and fixup the access,
  3380. allocationsize, etc.
  3381. Arguments:
  3382. RxContext - the RDBSS context
  3383. Return Value:
  3384. NTSTATUS - The return status for the operation
  3385. Notes:
  3386. --*/
  3387. {
  3388. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  3389. RxCaptureFcb;
  3390. PMRX_SMB_FCB smbFcb;
  3391. PMRX_SRV_OPEN SrvOpen;
  3392. PMRX_SMB_SRV_OPEN smbSrvOpen;
  3393. PMRX_NET_ROOT NetRoot;
  3394. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  3395. PSMBCEDB_SERVER_ENTRY pServerEntry;
  3396. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  3397. BOOLEAN IsCopyChunkOpen, IsThisTheAgent=FALSE;
  3398. PNT_CREATE_PARAMETERS CreateParameters;
  3399. BOOLEAN EnteredCriticalSection = FALSE;
  3400. NTSTATUS AcquireStatus = STATUS_UNSUCCESSFUL;
  3401. ULONG AcquireOptions;
  3402. BOOLEAN Disconnected = FALSE;
  3403. DWORD dwEarlyOut = 0;
  3404. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  3405. if(!MRxSmbIsCscEnabled ||
  3406. (fShadow == 0)) {
  3407. return Status;
  3408. }
  3409. SrvOpen = RxContext->pRelevantSrvOpen;
  3410. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot);
  3411. if (FlagOn(
  3412. pVNetRootContext->Flags,
  3413. SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE)) {
  3414. RxLog(("%wZ is a an AgentInstance\n", &(pVNetRootContext->pNetRootEntry->Name)));
  3415. HookKdPrint(AGENT, ("%wZ is a an AgentInstance\n", &(pVNetRootContext->pNetRootEntry->Name)));
  3416. ASSERT(SrvOpen->pVNetRoot->Flags & VNETROOT_FLAG_CSCAGENT_INSTANCE);
  3417. // DbgPrint("Skipping agent instances\n");
  3418. return Status;
  3419. }
  3420. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  3421. PDFS_NAME_CONTEXT pDfsNameContext = NULL;
  3422. pDfsNameContext = CscIsValidDfsNameContext(RxContext->Create.NtCreateParameters.DfsNameContext);
  3423. if (pDfsNameContext && (pDfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT))
  3424. {
  3425. RxLog(("%wZ is a a DFS AgentInstance\n", &(pVNetRootContext->pNetRootEntry->Name)));
  3426. HookKdPrint(NAME, ("%wZ is a DFS AgentInstance\n", &(pVNetRootContext->pNetRootEntry->Name)));
  3427. return Status;
  3428. }
  3429. }
  3430. NetRoot = capFcb->pNetRoot;
  3431. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  3432. pServerEntry = SmbCeGetAssociatedServerEntry(NetRoot->pSrvCall);
  3433. if (pNetRootEntry->NetRoot.NetRootType != NET_ROOT_DISK) {
  3434. if (!SmbCeIsServerInDisconnectedMode(pServerEntry))
  3435. {
  3436. return Status;
  3437. }
  3438. else
  3439. {
  3440. return STATUS_NETWORK_UNREACHABLE;
  3441. }
  3442. }
  3443. // Check with CSC whether any opens need to fail on this share
  3444. if(hShareReint &&
  3445. ((pNetRootEntry->NetRoot.sCscRootInfo.hShare == hShareReint)||
  3446. (CscDfsShareIsInReint(RxContext))))
  3447. {
  3448. HookKdPrint(BADERRORS, ("Share %x merging \n", hShareReint));
  3449. return STATUS_ACCESS_DENIED;
  3450. }
  3451. smbFcb = MRxSmbGetFcbExtension(capFcb);
  3452. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3453. CreateParameters = &RxContext->Create.NtCreateParameters;
  3454. Disconnected = SmbCeIsServerInDisconnectedMode(pServerEntry);
  3455. RxDbgTrace(+1, Dbg,
  3456. ("MRxSmbCscCreatePrologue(%08lx)...%08lx\n",
  3457. RxContext,Disconnected ));
  3458. HookKdPrint(NAME, ("CreatePrologue: Create %wZ Disposition=%x Options=%x DCON=%d \n",
  3459. GET_ALREADY_PREFIXED_NAME(NULL,capFcb),
  3460. CreateParameters->Disposition,
  3461. CreateParameters->CreateOptions,
  3462. Disconnected));
  3463. if (smbFcb->ContainingFcb == NULL) {
  3464. smbFcb->ContainingFcb = capFcb;
  3465. } else {
  3466. ASSERT(smbFcb->ContainingFcb == capFcb);
  3467. }
  3468. IsCopyChunkOpen = MRxSmbCscIsThisACopyChunkOpen(RxContext, &IsThisTheAgent);
  3469. if (IsCopyChunkOpen) {
  3470. PLIST_ENTRY ListEntry;
  3471. ULONG NumNonCopyChunkOpens = 0;
  3472. HookKdPrint(NAME, ("CreatePrologue: Copychunk Open \n"));
  3473. CreateParameters->AllocationSize.QuadPart = 0;
  3474. CreateParameters->DesiredAccess |= FILE_READ_DATA;
  3475. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_COPYCHUNK_OPEN);
  3476. if (IsThisTheAgent)
  3477. {
  3478. HookKdPrint(NAME, ("CreatePrologue: Agent Copychunk Open \n"));
  3479. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_AGENT_COPYCHUNK_OPEN);
  3480. }
  3481. SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_COLLAPSING_DISABLED);
  3482. if (Disconnected) {
  3483. Status = STATUS_NETWORK_UNREACHABLE;
  3484. // RxDbgTrace(0, Dbg, ("Network Unreacheable, aborting copychunk\n"));
  3485. dwEarlyOut = 1;
  3486. goto FINALLY;
  3487. }
  3488. //check for a surrogate.....this would be studly.....
  3489. RxLog(("Checking for surrogate\n"));
  3490. for ( ListEntry = capFcb->SrvOpenList.Flink;
  3491. ListEntry != &capFcb->SrvOpenList;
  3492. ListEntry = ListEntry->Flink
  3493. ) {
  3494. PMRX_SRV_OPEN SurrogateSrvOpen = CONTAINING_RECORD(
  3495. ListEntry,
  3496. MRX_SRV_OPEN,
  3497. SrvOpenQLinks);
  3498. PMRX_SMB_SRV_OPEN smbSurrogateSrvOpen = MRxSmbGetSrvOpenExtension(SurrogateSrvOpen);
  3499. if (smbSurrogateSrvOpen == NULL)
  3500. continue;
  3501. if (smbFcb->hShadow == 0) {
  3502. // if we don't have the shadow handle...just blow it off....
  3503. RxLog(("No shadow handle, quitting\n"));
  3504. break;
  3505. }
  3506. if (smbFcb->SurrogateSrvOpen != NULL) {
  3507. // if we already have a surrogate, just use it....
  3508. SurrogateSrvOpen = smbFcb->SurrogateSrvOpen;
  3509. }
  3510. ASSERT(SurrogateSrvOpen && NodeType(SurrogateSrvOpen) == RDBSS_NTC_SRVOPEN);
  3511. if (FlagOn(smbSurrogateSrvOpen->Flags,SMB_SRVOPEN_FLAG_COPYCHUNK_OPEN)) {
  3512. //cant surrogate on a copychunk open!
  3513. continue;
  3514. }
  3515. NumNonCopyChunkOpens++;
  3516. // if it's not open or not open successfully...cant surrogate
  3517. if (FlagOn(smbSurrogateSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  3518. continue;
  3519. }
  3520. if (!FlagOn(smbSurrogateSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN)) {
  3521. continue;
  3522. }
  3523. // if it doesn't have access for read or execute, cant surrogate
  3524. if ((SurrogateSrvOpen->DesiredAccess &
  3525. (FILE_READ_DATA|FILE_EXECUTE)) == 0) {
  3526. continue;
  3527. }
  3528. ASSERT( (smbFcb->SurrogateSrvOpen == SurrogateSrvOpen)
  3529. || (smbFcb->SurrogateSrvOpen == NULL));
  3530. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_OPEN_SURROGATED);
  3531. smbFcb->SurrogateSrvOpen = SurrogateSrvOpen;
  3532. smbSrvOpen->Fid = smbSurrogateSrvOpen->Fid;
  3533. smbSrvOpen->Version = smbSurrogateSrvOpen->Version;
  3534. RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx(RxContext, SrvOpen);
  3535. if (RxContext->pFobx == NULL) {
  3536. Status = (STATUS_INSUFFICIENT_RESOURCES);
  3537. RxDbgTrace(0, Dbg, ("Failed fobx create, aborting copychunk\n"));
  3538. goto FINALLY;
  3539. }
  3540. // i thought about just using the surrogate's handle here but
  3541. // decided against it. the surrogate's localopen may have failed
  3542. // for some reason that no longer obtains...so i get my own
  3543. // handle.
  3544. #if defined(BITCOPY)
  3545. OpenFileHSHADOWAndCscBmp(
  3546. smbFcb->hShadow,
  3547. 0,
  3548. 0,
  3549. (CSCHFILE *)(&(smbSrvOpen->hfShadow)),
  3550. smbFcb->fDoBitCopy,
  3551. 0,
  3552. NULL
  3553. );
  3554. #else
  3555. OpenFileHSHADOW(
  3556. smbFcb->hShadow,
  3557. 0,
  3558. 0,
  3559. (CSCHFILE *)(&(smbSrvOpen->hfShadow))
  3560. );
  3561. #endif // defined(BITCOPY)
  3562. if (smbSrvOpen->hfShadow == 0) {
  3563. Status = STATUS_UNSUCCESSFUL;
  3564. RxLog(("Couldn't find a file to piggyback on, failing copychunk\n"));
  3565. } else {
  3566. SuccessfulSurrogateOpens++;
  3567. Status = STATUS_SUCCESS;
  3568. RxLog(("Found a file to piggyback on, succeeding copychunk\n"));
  3569. }
  3570. dwEarlyOut = 2;
  3571. goto FINALLY;
  3572. }
  3573. #if 0
  3574. //couldn't find a surrogate.......if there are existing opens then blowoff
  3575. //this open...the agent will come back later
  3576. #endif
  3577. if (NumNonCopyChunkOpens>0) {
  3578. RxLog(("CscCrPro Creating thru open when NonNumCopyChunkOpens is non-zero %d for hShadow=%x\n",
  3579. NumNonCopyChunkOpens, smbFcb->hShadow));
  3580. RxDbgTrace(0, Dbg, ("MRxSmbCscCreatePrologue Creating thru open when NonNumCopyChunkOpens is non-zero %d for hShadow=%x\n",
  3581. NumNonCopyChunkOpens, smbFcb->hShadow));
  3582. }
  3583. } else {
  3584. NTSTATUS LocalStatus;
  3585. LocalStatus = CscInitializeServerEntryDfsRoot(
  3586. RxContext,
  3587. pServerEntry);
  3588. if (LocalStatus != STATUS_SUCCESS) {
  3589. Status = LocalStatus;
  3590. goto FINALLY;
  3591. }
  3592. LocalStatus = MRxSmbCscLocalFileOpen(RxContext);
  3593. if (LocalStatus == STATUS_SUCCESS)
  3594. {
  3595. RxLog(("LocalOpen\n"));
  3596. Status = STATUS_SUCCESS;
  3597. Disconnected = TRUE; // do a fake disconnected open
  3598. }
  3599. else if (LocalStatus != STATUS_MORE_PROCESSING_REQUIRED)
  3600. {
  3601. RxLog(("LocalOpen Failed Status=%x\n", LocalStatus));
  3602. Status = LocalStatus;
  3603. goto FINALLY;
  3604. }
  3605. }
  3606. if (IsCopyChunkOpen) {
  3607. AcquireOptions = (Exclusive_SmbFcbAcquire |
  3608. DroppingFcbLock_SmbFcbAcquire |
  3609. FailImmediately_SmbFcbAcquire);
  3610. } else {
  3611. AcquireOptions = (Shared_SmbFcbAcquire |
  3612. DroppingFcbLock_SmbFcbAcquire);
  3613. }
  3614. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  3615. AcquireStatus = MRxSmbCscAcquireSmbFcb(
  3616. RxContext,
  3617. AcquireOptions,
  3618. SmbFcbHoldingState);
  3619. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  3620. if (AcquireStatus != STATUS_SUCCESS) {
  3621. //we couldn't acquire.....get out
  3622. Status = AcquireStatus;
  3623. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  3624. RxDbgTrace(0, Dbg,
  3625. ("MRxSmbCscCreatePrologue couldn't acquire!!!-> %08lx %08lx\n",
  3626. RxContext,Status ));
  3627. RxLog(("CSC AcquireStatus=%x\n", AcquireStatus));
  3628. dwEarlyOut = 3;
  3629. goto FINALLY;
  3630. }
  3631. ASSERT( IsCopyChunkOpen?(smbFcb->CscOutstandingReaders == -1)
  3632. :(smbFcb->CscOutstandingReaders > 0));
  3633. // There are two cases in which the open request can be satisfied locally.
  3634. // Either we are in a disconnected mode of operation for this share or the
  3635. // share has been marked for a mode of operation which calls for the
  3636. // suppression of opens and closes ( hereafter we will refer to it as
  3637. // (Suppress Opens Client Side Caching (SOCSC)) mode of operation to
  3638. // distinguish it from VDO ( virtual disconnected operation ) which is
  3639. // slated for subsequent releases of NT
  3640. // Note that in the SOCSC mode it is likely that we do not have the
  3641. // corresponding file cached locally. In such cases the open needs to be
  3642. // propagated to the client, i.e., you cannot create a local file without
  3643. // checking with the server for the existence of a file with the same name
  3644. if (Disconnected) {
  3645. SMBFCB_HOLDING_STATE FakeSmbFcbHoldingState = SmbFcb_NotHeld;
  3646. RxDbgTrace(0, Dbg,
  3647. ("MRxSmbCscCreatePrologue calling epilog directly!!!-> %08lx %08lx\n",
  3648. RxContext,Status ));
  3649. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_DISCONNECTED_OPEN;
  3650. //we pass a fake holdingstate and do the release from out finally
  3651. MRxSmbCscCreateEpilogue(
  3652. RxContext,
  3653. &Status,
  3654. &FakeSmbFcbHoldingState);
  3655. dwEarlyOut = 4;
  3656. goto FINALLY;
  3657. }
  3658. // deal with any existing thru-open
  3659. if (smbFcb->CopyChunkThruOpen != NULL) {
  3660. if (IsCopyChunkOpen && IsThisTheAgent){
  3661. // here we're a thruopen and there's an existing one...
  3662. // fail the new one....
  3663. Status = STATUS_UNSUCCESSFUL;
  3664. // DbgPrint("Agent being turned away while attempting fill on %x\n", smbFcb->hShadow);
  3665. RxDbgTrace(0, Dbg,
  3666. ("MRxSmbCscCreatePrologue failing new thru open!!!-> %08lx %08lx\n",
  3667. RxContext,Status ));
  3668. dwEarlyOut = 5;
  3669. goto FINALLY;
  3670. } else {
  3671. // the new open if not a thru open or it is a thruopen from the agent.
  3672. // get rid of it now
  3673. #ifdef DBG
  3674. if (IsCopyChunkOpen)
  3675. {
  3676. // This is a copychunk open by the sync manager
  3677. // assert that the thruopen being nuked is that of the agent
  3678. PMRX_SMB_SRV_OPEN psmbSrvOpenT = MRxSmbGetSrvOpenExtension(smbFcb->CopyChunkThruOpen->pSrvOpen);
  3679. // ASSERT(psmbSrvOpenT->Flags & SMB_SRVOPEN_FLAG_AGENT_COPYCHUNK_OPEN);
  3680. }
  3681. #endif
  3682. MRxSmbCscCloseExistingThruOpen(RxContext);
  3683. }
  3684. }
  3685. FINALLY:
  3686. if (EnteredCriticalSection) {
  3687. LeaveShadowCrit();
  3688. }
  3689. if (Status!=STATUS_MORE_PROCESSING_REQUIRED) {
  3690. if (AcquireStatus == STATUS_SUCCESS) {
  3691. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  3692. }
  3693. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  3694. }
  3695. if (Disconnected) {
  3696. // at shutdown, there can be a situation where an open comes down
  3697. // but CSC has already been shutdown. If CSC is shutdown, return the appropriate error
  3698. if (fShadow)
  3699. {
  3700. if (Status==STATUS_MORE_PROCESSING_REQUIRED)
  3701. {
  3702. RxDbgTrace(0, Dbg, ("MRxSmbCscCreatePrologue: STATUS_MORE_PROCESSING_REQUIRED, dwEarlyOut=%d\r\n", dwEarlyOut));
  3703. }
  3704. ASSERT(Status!=STATUS_MORE_PROCESSING_REQUIRED);
  3705. }
  3706. else
  3707. {
  3708. if (AcquireStatus == STATUS_SUCCESS &&
  3709. *SmbFcbHoldingState!=SmbFcb_NotHeld) {
  3710. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  3711. }
  3712. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  3713. Status = STATUS_NETWORK_UNREACHABLE;
  3714. }
  3715. }
  3716. RxLog(("CscCrPro %x %x\n", RxContext, Status ));
  3717. RxDbgTrace(-1, Dbg, ("MRxSmbCscCreatePrologue -> %08lx %08lx\n",
  3718. RxContext, Status ));
  3719. return Status;
  3720. }
  3721. NTSTATUS
  3722. MRxSmbCscObtainShadowHandles (
  3723. IN OUT PRX_CONTEXT RxContext,
  3724. IN OUT PNTSTATUS Status,
  3725. IN OUT _WIN32_FIND_DATA *Find32,
  3726. OUT PBOOLEAN Created,
  3727. IN ULONG CreateShadowControls,
  3728. IN BOOLEAN Disconnected
  3729. )
  3730. /*++
  3731. Routine Description:
  3732. This routine tries to obtain the shadow handles for a given fcb. If it can,
  3733. it also will get the share handle as part of the process.
  3734. Arguments:
  3735. RxContext - the RDBSS context
  3736. Return Value:
  3737. NTSTATUS - The return status for the operation
  3738. Notes:
  3739. The netroot entry may have the rootinode for the actual share or it's DFS alternate.
  3740. If it is a root for the DFS alternate, the appropritae bit in the Flags field of the
  3741. sCscRootInfo structure in NetRootEntry is set.
  3742. This routine essentially manufactures the correct root inode for the incoming path
  3743. and stuffs it in the sCscRootInfo for the smbfcb. This root indoe is used for
  3744. all subsequent operations on this file.
  3745. --*/
  3746. {
  3747. NTSTATUS LocalStatus;
  3748. RxCaptureFcb;
  3749. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  3750. PMRX_SRV_OPEN SrvOpen;
  3751. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  3752. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  3753. CSC_SHARE_HANDLE hShare;
  3754. CSC_SHADOW_HANDLE hShadow;
  3755. CSC_ROOT_INFO *pCscRootInfo, sCscRootInfoSav;
  3756. BOOLEAN DisconnectedMode;
  3757. UNICODE_STRING ShadowPath,SharePath,ServerPath;
  3758. PDFS_NAME_CONTEXT pDfsNameContext = NULL;
  3759. DWORD cntRetry = 0;
  3760. BOOLEAN fSaved = FALSE;
  3761. DbgDoit(ASSERT(vfInShadowCrit));
  3762. LocalStatus = STATUS_SUCCESS;
  3763. SrvOpen = RxContext->pRelevantSrvOpen;
  3764. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  3765. pDfsNameContext = CscIsValidDfsNameContext(RxContext->Create.NtCreateParameters.DfsNameContext);
  3766. //SrvOpen = RxContext->Create.pSrvOpen;
  3767. } else {
  3768. RxCaptureFobx;
  3769. if (SrvOpen)
  3770. {
  3771. ASSERT((SrvOpen == capFobx->pSrvOpen));
  3772. }
  3773. }
  3774. if (smbFcb->ContainingFcb == NULL) {
  3775. smbFcb->ContainingFcb = capFcb;
  3776. } else {
  3777. ASSERT(smbFcb->ContainingFcb == capFcb);
  3778. }
  3779. if (pDfsNameContext) {
  3780. LocalStatus = CscDfsParseDfsPath(
  3781. &pDfsNameContext->UNCFileName,
  3782. &ServerPath,
  3783. &SharePath,
  3784. &ShadowPath);
  3785. HookKdPrint(NAME, ("OSHH: DfsName %wZ %wZ\n", &SharePath, &ShadowPath));
  3786. DisconnectedMode = FALSE;
  3787. pCscRootInfo = &(smbFcb->sCscRootInfo);
  3788. if (pNetRootEntry->NetRoot.sCscRootInfo.hShare)
  3789. {
  3790. sCscRootInfoSav = pNetRootEntry->NetRoot.sCscRootInfo;
  3791. fSaved = TRUE;
  3792. }
  3793. // clear this so ObtainSharehandles is forced to obtain them
  3794. memset( &(pNetRootEntry->NetRoot.sCscRootInfo),
  3795. 0,
  3796. sizeof(pNetRootEntry->NetRoot.sCscRootInfo));
  3797. } else {
  3798. PSMBCEDB_SERVER_ENTRY pServerEntry;
  3799. pServerEntry = SmbCeGetAssociatedServerEntry(NetRoot->pSrvCall);
  3800. DisconnectedMode = SmbCeIsServerInDisconnectedMode(pServerEntry);
  3801. SharePath = *(NetRoot->pNetRootName);
  3802. ShadowPath = *GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  3803. HookKdPrint(NAME, ("OSHH: NormalName %wZ %wZ\n", &SharePath, &ShadowPath));
  3804. if (pNetRootEntry->NetRoot.sCscRootInfo.Flags & CSC_ROOT_INFO_FLAG_DFS_ROOT)
  3805. {
  3806. // ASSERT(pNetRootEntry->NetRoot.sCscRootInfo.hShare);
  3807. sCscRootInfoSav = pNetRootEntry->NetRoot.sCscRootInfo;
  3808. fSaved = TRUE;
  3809. // clear this so ObtainSharehandles is forced to obtain them
  3810. memset( &(pNetRootEntry->NetRoot.sCscRootInfo),
  3811. 0,
  3812. sizeof(pNetRootEntry->NetRoot.sCscRootInfo));
  3813. }
  3814. pCscRootInfo = &(pNetRootEntry->NetRoot.sCscRootInfo);
  3815. }
  3816. HookKdPrint(NAME, ("hShare=%x, hRoot=%x, hDir=%x hShadow=%x \n",
  3817. smbFcb->sCscRootInfo.hShare,
  3818. smbFcb->sCscRootInfo.hRootDir,
  3819. smbFcb->hParentDir,
  3820. smbFcb->hShadow));
  3821. if (LocalStatus == STATUS_SUCCESS){
  3822. PMRX_SMB_SRV_OPEN smbSrvOpen;
  3823. if(pCscRootInfo->hShare == 0)
  3824. {
  3825. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3826. LocalStatus = MRxSmbCscObtainShareHandles(
  3827. &SharePath,
  3828. DisconnectedMode,
  3829. BooleanFlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_COPYCHUNK_OPEN),
  3830. SmbCeGetAssociatedNetRootEntry(NetRoot)
  3831. );
  3832. if (LocalStatus != STATUS_SUCCESS) {
  3833. if (pDfsNameContext) {
  3834. pNetRootEntry->NetRoot.sCscRootInfo = sCscRootInfoSav;
  3835. }
  3836. RxLog(("CscObtShdH no share handle %x %x\n", RxContext,LocalStatus ));
  3837. RxDbgTrace(0, Dbg,("MRxSmbCscObtainShadowHandles no share handle -> %08xl %08lx\n",
  3838. RxContext,LocalStatus ));
  3839. return STATUS_SUCCESS;
  3840. }
  3841. else {
  3842. // if this is DFS name get the reverse mapping
  3843. if (pDfsNameContext && !smbFcb->uniDfsPrefix.Buffer)
  3844. {
  3845. UNICODE_STRING uniTemp;
  3846. uniTemp = *GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  3847. if (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))
  3848. {
  3849. int i, cntSlashes=0;
  3850. // Strip the first two elements
  3851. for (i=0; i<uniTemp.Length; i+=2, uniTemp.Buffer++)
  3852. {
  3853. if (*uniTemp.Buffer == L'\\')
  3854. {
  3855. if (++cntSlashes > 2)
  3856. {
  3857. break;
  3858. }
  3859. }
  3860. }
  3861. if (uniTemp.Length > (USHORT)i)
  3862. {
  3863. uniTemp.Length -= (USHORT)i;
  3864. }
  3865. else
  3866. {
  3867. uniTemp.Length = 0;
  3868. }
  3869. }
  3870. if ((LocalStatus = CscDfsObtainReverseMapping(&ShadowPath,
  3871. &uniTemp,
  3872. &smbFcb->uniDfsPrefix,
  3873. &smbFcb->uniActualPrefix)) != STATUS_SUCCESS)
  3874. {
  3875. pNetRootEntry->NetRoot.sCscRootInfo = sCscRootInfoSav;
  3876. return LocalStatus;
  3877. }
  3878. HookKdPrint(NAME, ("%wZ %wZ DfsPrefix=%wZ ActualPrefix=%wZ\n", &ShadowPath, &uniTemp, &smbFcb->uniDfsPrefix, &smbFcb->uniActualPrefix));
  3879. }
  3880. // note the fact that the NetRootEntry has the
  3881. // root inode corresponding to the DFS
  3882. if (pDfsNameContext)
  3883. {
  3884. if (pNetRootEntry->NetRoot.sCscRootInfo.hShare)
  3885. {
  3886. pNetRootEntry->NetRoot.sCscRootInfo.Flags = CSC_ROOT_INFO_FLAG_DFS_ROOT;
  3887. }
  3888. }
  3889. else
  3890. {
  3891. ASSERT(!(pNetRootEntry->NetRoot.sCscRootInfo.Flags & CSC_ROOT_INFO_FLAG_DFS_ROOT));
  3892. }
  3893. // stuff the FCB with the correct root info
  3894. smbFcb->sCscRootInfo = pNetRootEntry->NetRoot.sCscRootInfo;
  3895. }
  3896. }
  3897. else
  3898. {
  3899. // if this is a normal share or we are operating in disconnected state
  3900. // then we need to make sure that the info that is in the NETROOT entry
  3901. // is stuffed into the FCB
  3902. if (!pDfsNameContext && (smbFcb->sCscRootInfo.hShare == 0))
  3903. {
  3904. // stuff the FCB with the correct root info
  3905. smbFcb->sCscRootInfo = pNetRootEntry->NetRoot.sCscRootInfo;
  3906. }
  3907. }
  3908. }
  3909. // if saved, restore the original rootinfo on the netroot
  3910. if (fSaved)
  3911. {
  3912. pNetRootEntry->NetRoot.sCscRootInfo = sCscRootInfoSav;
  3913. }
  3914. if ((LocalStatus == STATUS_SUCCESS)&&(smbFcb->sCscRootInfo.hRootDir != 0)) {
  3915. if (smbFcb->sCscRootInfo.hShare == hShareReint)
  3916. {
  3917. smbFcb->hShadow = 0;
  3918. smbFcb->hParentDir = 0;
  3919. LocalStatus = STATUS_SUCCESS;
  3920. }
  3921. else
  3922. {
  3923. RxDbgTrace( 0, Dbg,
  3924. ("MRxSmbCscObtainShadowHandles h's= %08lx %08lx\n",
  3925. pCscRootInfo->hShare, pCscRootInfo->hRootDir));
  3926. HookKdPrint(NAME, ("Obtainshdowhandles %wZ Controls=%x\n", &ShadowPath, CreateShadowControls));
  3927. // due to a race condition in the way RDBSS handles FCBs
  3928. // we may get a retyr from CreateShadowFromPath.
  3929. // see the comments in that routine near the
  3930. // check for CREATESHADOW_CONTROL_FAIL_IF_MARKED_FOR_DELETION
  3931. do
  3932. {
  3933. LocalStatus = MRxSmbCscCreateShadowFromPath(
  3934. &ShadowPath,
  3935. &smbFcb->sCscRootInfo,
  3936. Find32,
  3937. Created,
  3938. CreateShadowControls,
  3939. &smbFcb->MinimalCscSmbFcb,
  3940. RxContext,
  3941. Disconnected,
  3942. NULL // don't want inherited hint flags
  3943. );
  3944. if (LocalStatus != STATUS_RETRY)
  3945. {
  3946. LocalStatus=STATUS_SUCCESS;
  3947. break;
  3948. }
  3949. if (++cntRetry > 4)
  3950. {
  3951. LocalStatus=STATUS_SUCCESS;
  3952. ASSERT(FALSE);
  3953. }
  3954. }
  3955. while (TRUE);
  3956. }
  3957. }
  3958. #if 0
  3959. DbgPrint("hShare=%x, hRoot=%x, hDir=%x hShadow=%x \n",
  3960. smbFcb->sCscRootInfo.hShare,
  3961. smbFcb->sCscRootInfo.hRootDir,
  3962. smbFcb->hParentDir,
  3963. smbFcb->hShadow);
  3964. #endif
  3965. return LocalStatus;
  3966. }
  3967. #if defined(REMOTE_BOOT)
  3968. NTSTATUS
  3969. MRxSmbCscSetSecurityOnShadow(
  3970. HSHADOW hShadow,
  3971. SECURITY_INFORMATION SecurityInformation,
  3972. PSECURITY_DESCRIPTOR SecurityDescriptor
  3973. )
  3974. /*++
  3975. Routine Description:
  3976. Given an HSHADOW, this routine opens the file and sets the
  3977. security information passed in.
  3978. Arguments:
  3979. hShadow - the handle to the shadow file
  3980. SecurityInformation - the security information to set
  3981. SecurityDescriptor - the security descriptor to set
  3982. Return Value:
  3983. Notes:
  3984. --*/
  3985. {
  3986. PWCHAR fileName;
  3987. DWORD fileNameSize;
  3988. UNICODE_STRING fileNameString;
  3989. OBJECT_ATTRIBUTES objectAttributes;
  3990. IO_STATUS_BLOCK ioStatusBlock;
  3991. HANDLE fileHandle;
  3992. NTSTATUS ZwStatus;
  3993. int iRet;
  3994. fileNameSize = sizeof(WCHAR) * MAX_PATH;
  3995. fileName = RxAllocatePoolWithTag(NonPagedPool, fileNameSize, RX_MISC_POOLTAG);
  3996. if (fileName == NULL) {
  3997. ZwStatus = STATUS_INSUFFICIENT_RESOURCES;
  3998. } else {
  3999. iRet = GetWideCharLocalNameHSHADOW(
  4000. hShadow,
  4001. fileName,
  4002. &fileNameSize,
  4003. FALSE);
  4004. if (iRet == SRET_OK) {
  4005. //
  4006. // Open the file and set the security descriptor on it.
  4007. //
  4008. RtlInitUnicodeString(&fileNameString, fileName);
  4009. InitializeObjectAttributes(
  4010. &objectAttributes,
  4011. &fileNameString,
  4012. OBJ_CASE_INSENSITIVE,
  4013. NULL,
  4014. NULL);
  4015. ZwStatus = ZwOpenFile(
  4016. &fileHandle,
  4017. FILE_GENERIC_WRITE,
  4018. &objectAttributes,
  4019. &ioStatusBlock,
  4020. FILE_SHARE_READ | FILE_SHARE_WRITE,
  4021. FILE_SYNCHRONOUS_IO_NONALERT);
  4022. if (!NT_SUCCESS(ZwStatus) || !NT_SUCCESS(ioStatusBlock.Status)) {
  4023. //
  4024. // We've been getting bogus names from CSC, ignore this error for now.
  4025. //
  4026. if (ZwStatus == STATUS_OBJECT_NAME_NOT_FOUND) {
  4027. ZwStatus = STATUS_SUCCESS;
  4028. } else {
  4029. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not ZwOpenFile %ws %lx %lx\n", fileName, ZwStatus, ioStatusBlock.Status));
  4030. }
  4031. } else {
  4032. HANDLE TokenHandle = NULL;
  4033. BOOLEAN Impersonated = FALSE;
  4034. BOOLEAN WasEnabled;
  4035. //
  4036. // If we are going to set the owner, need to have privilege.
  4037. //
  4038. if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
  4039. ZwStatus = ZwOpenThreadToken(NtCurrentThread(),
  4040. TOKEN_QUERY,
  4041. FALSE,
  4042. &TokenHandle);
  4043. if (ZwStatus == STATUS_NO_TOKEN) {
  4044. TokenHandle = NULL;
  4045. ZwStatus = STATUS_SUCCESS;
  4046. }
  4047. if (!NT_SUCCESS(ZwStatus)) {
  4048. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not NtOpenThread %ws %lx\n", fileName, ZwStatus));
  4049. } else {
  4050. ZwStatus = ZwImpersonateSelf(SecurityImpersonation);
  4051. if (!NT_SUCCESS(ZwStatus)) {
  4052. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not RtlImpersonateSelf for %ws %lx\n", fileName, ZwStatus));
  4053. } else {
  4054. Impersonated = TRUE;
  4055. ZwStatus = ZwAdjustPrivilege(
  4056. SE_RESTORE_PRIVILEGE,
  4057. TRUE,
  4058. TRUE,
  4059. &WasEnabled);
  4060. if (!NT_SUCCESS(ZwStatus)) {
  4061. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not RtlAdjustPrivilege for %ws %lx %d\n", fileName, ZwStatus, WasEnabled));
  4062. }
  4063. }
  4064. }
  4065. }
  4066. if (NT_SUCCESS(ZwStatus)) {
  4067. ZwStatus = ZwSetSecurityObject(
  4068. fileHandle,
  4069. SecurityInformation,
  4070. SecurityDescriptor);
  4071. if (!NT_SUCCESS(ZwStatus)) {
  4072. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not ZwSetSecurityObject %ws %lx\n", fileName, ZwStatus));
  4073. }
  4074. }
  4075. if (Impersonated) {
  4076. NTSTATUS TmpStatus;
  4077. TmpStatus = ZwSetInformationThread(NtCurrentThread(),
  4078. ThreadImpersonationToken,
  4079. &TokenHandle,
  4080. sizeof(HANDLE));
  4081. if (!NT_SUCCESS(TmpStatus)) {
  4082. KdPrint(("MRxSmbCscSetSecurityOnShadow: Could not revert thread %lx!\n", TmpStatus));
  4083. }
  4084. }
  4085. if (TokenHandle != NULL) {
  4086. ZwClose(TokenHandle);
  4087. }
  4088. ZwClose(fileHandle);
  4089. }
  4090. } else {
  4091. ZwStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  4092. }
  4093. RxFreePool(fileName);
  4094. }
  4095. return ZwStatus;
  4096. }
  4097. #endif
  4098. VOID
  4099. MRxSmbCscCreateEpilogue (
  4100. IN OUT PRX_CONTEXT RxContext,
  4101. IN OUT PNTSTATUS Status,
  4102. IN SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  4103. )
  4104. /*++
  4105. Routine Description:
  4106. This routine performs the tail of a create operation for CSC.
  4107. Arguments:
  4108. RxContext - the RDBSS context
  4109. Status - in disconnected mode, we return the overall status of the open
  4110. SmbFcbHoldingState - indicates whether a ReleaseSmbFcb is required or not
  4111. Return Value:
  4112. Notes:
  4113. This is a workhorse of a routine for most of the CSC operations. It has become unwieldy and
  4114. very messy but at this point in time we don't want to mess with it (SPP)
  4115. --*/
  4116. {
  4117. NTSTATUS LocalStatus;
  4118. RxCaptureFcb;RxCaptureFobx;
  4119. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  4120. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  4121. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  4122. BOOLEAN ThisIsAPseudoOpen =
  4123. BooleanFlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  4124. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  4125. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  4126. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry =
  4127. SmbCeGetAssociatedNetRootEntry(NetRoot);
  4128. BOOLEAN Disconnected;
  4129. CSC_SHARE_HANDLE hShare;
  4130. CSC_SHADOW_HANDLE hRootDir,hShadow,hParentDir;
  4131. BOOLEAN ShadowWasRefreshed = FALSE;
  4132. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  4133. ULONG ReturnedCreateInformation
  4134. = RxContext->Create.ReturnedCreateInformation;
  4135. ULONG CreateInformation; //the new stuff for disconnected mode......
  4136. ULONG CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;
  4137. ULONG CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
  4138. _WIN32_FIND_DATA *lpFind32=NULL; //this should not be on the stack CODE.IMPROVEMENT
  4139. OTHERINFO oSI;
  4140. BOOLEAN bGotOtherInfo = FALSE;
  4141. BOOLEAN CreatedShadow = FALSE;
  4142. BOOLEAN NeedTruncate = FALSE; //ok for red/yellow
  4143. BOOLEAN EnteredCriticalSection = FALSE;
  4144. DWORD dwEarlyOuts=0, dwNotifyFilter=0, dwFileAction=0;
  4145. ASSERT(RxContext!=NULL);
  4146. ASSERT(RxContext->MajorFunction == IRP_MJ_CREATE);
  4147. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot);
  4148. // If we shouldn't be doing CSC, quit right from here
  4149. if(pVNetRootContext == NULL ||
  4150. !MRxSmbIsCscEnabled || // MrxSmb not enabled for csc
  4151. (fShadow == 0)) // record manager not enabled for csc
  4152. {
  4153. return;
  4154. }
  4155. if (FlagOn( // agent call
  4156. pVNetRootContext->Flags,
  4157. SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE)
  4158. ) {
  4159. RxLog(("%wZ AgntInst\n", &(pVNetRootContext->pNetRootEntry->Name)));
  4160. ASSERT(SrvOpen->pVNetRoot->Flags & VNETROOT_FLAG_CSCAGENT_INSTANCE);
  4161. // DbgPrint("Skipping agent instances\n");
  4162. goto EarlyOut;
  4163. }
  4164. {
  4165. // we know that this is a create
  4166. PDFS_NAME_CONTEXT pDfsNameContext = CscIsValidDfsNameContext(
  4167. RxContext->Create.NtCreateParameters.DfsNameContext);
  4168. if (pDfsNameContext && (pDfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT)) {
  4169. RxLog(("%wZ DFS AgntInst\n", &(pVNetRootContext->pNetRootEntry->Name)));
  4170. goto EarlyOut;
  4171. }
  4172. }
  4173. // check whether this is a disconnected open or not
  4174. Disconnected = BooleanFlagOn(
  4175. smbSrvOpen->Flags,
  4176. SMB_SRVOPEN_FLAG_DISCONNECTED_OPEN);
  4177. HookKdPrint(NAME, ("CreateEpilogue: Create %wZ Disposition=%x Options=%x DCON=%d \n",
  4178. GET_ALREADY_PREFIXED_NAME(NULL,capFcb),
  4179. CreateDisposition,
  4180. CreateOptions,
  4181. Disconnected));
  4182. // If the open is for a netroot which is not a disk, then we quit from here
  4183. // and let the redir handle it in connected state
  4184. // CSC is a filesystem cache.
  4185. if (pNetRootEntry->NetRoot.NetRootType != NET_ROOT_DISK) {
  4186. if (Disconnected) {
  4187. *Status = STATUS_ONLY_IF_CONNECTED;
  4188. }
  4189. return;
  4190. }
  4191. // quit if we are doing sparse filling via copychunks
  4192. if (!Disconnected &&
  4193. (!pNetRootEntry->NetRoot.CscEnabled) &&
  4194. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_COPYCHUNK_OPEN)) {
  4195. goto EarlyOut;
  4196. }
  4197. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  4198. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateEpilogue...early release %08lx\n",
  4199. RxContext));
  4200. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  4201. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  4202. }
  4203. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  4204. if ((*Status != STATUS_SUCCESS) &&
  4205. (*Status != STATUS_ACCESS_DENIED)) {
  4206. if (!Disconnected ||
  4207. (*Status != STATUS_MORE_PROCESSING_REQUIRED)) {
  4208. return;
  4209. }
  4210. }
  4211. // Shadow database locked
  4212. EnterShadowCritRx(RxContext);
  4213. EnteredCriticalSection = TRUE;
  4214. lpFind32 = RxAllocatePoolWithTag(
  4215. NonPagedPool,
  4216. sizeof(_WIN32_FIND_DATA),
  4217. MRXSMB_MISC_POOLTAG );
  4218. if (!lpFind32)
  4219. {
  4220. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateShadowFromPath: Failed allocation of find32 structure \n"));
  4221. dwEarlyOuts=1;
  4222. *Status = STATUS_INSUFFICIENT_RESOURCES;
  4223. goto FINALLY;
  4224. }
  4225. RxDbgTrace(+1, Dbg, ("MRxSmbCscCreateEpilogue...%08lx %wZ %wZ\n",
  4226. RxContext,NetRoot->pNetRootName,GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)));
  4227. // if this is a copychunk thru-open....say so in the fcb
  4228. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_COPYCHUNK_OPEN)) {
  4229. // ASSERT(smbFcb->CopyChunkThruOpen == NULL);
  4230. smbFcb->CopyChunkThruOpen = capFobx;
  4231. RxDbgTrace( 0, Dbg,
  4232. ("MRxSmbCscCreateEpilogue set ccto %08lx %08lx %08lx %08lx\n",
  4233. RxContext, capFcb, capFobx, SrvOpen));
  4234. }
  4235. if (ThisIsAPseudoOpen && !Disconnected) {
  4236. PDFS_NAME_CONTEXT pDfsNameContext = NULL;
  4237. pDfsNameContext = CscIsValidDfsNameContext(RxContext->Create.NtCreateParameters.DfsNameContext);
  4238. if (pDfsNameContext)
  4239. {
  4240. LocalStatus = MRxSmbCscObtainShadowHandles(
  4241. RxContext,
  4242. Status,
  4243. lpFind32,
  4244. &CreatedShadow,
  4245. CREATESHADOW_CONTROL_NOCREATE,
  4246. FALSE);
  4247. }
  4248. hShadow = 0;
  4249. } else {
  4250. // if we have no shadow, make one as required..........ok red/yellow
  4251. if (smbFcb->hShadow == 0){
  4252. ULONG CreateShadowControl;
  4253. if (!Disconnected) {
  4254. if (*Status == STATUS_ACCESS_DENIED) {
  4255. CreateShadowControl = CREATESHADOW_CONTROL_NOCREATE;
  4256. } else {
  4257. CreateShadowControl = (pNetRootEntry->NetRoot.CscShadowable)
  4258. ? CREATESHADOW_NO_SPECIAL_CONTROLS
  4259. : CREATESHADOW_CONTROL_NOCREATE;
  4260. // The step below is done to save bandwidth and make some apps
  4261. // like edit.exe work.
  4262. // It essentially creates an entry in the database for a file which
  4263. // is being created from this client on the server.
  4264. // Thus the temp files created by apps like word get created
  4265. // in the database and filled up during the writes.
  4266. if((ReturnedCreateInformation<= FILE_MAXIMUM_DISPOSITION) &&
  4267. (ReturnedCreateInformation!=FILE_OPENED)) {
  4268. CreateShadowControl &= ~CREATESHADOW_CONTROL_NOCREATE;
  4269. }
  4270. // disallow autocaching of encrypted files if the database is
  4271. // not encrypted.
  4272. if ((vulDatabaseStatus & FLAG_DATABASESTATUS_ENCRYPTED) == 0
  4273. &&
  4274. smbFcb->dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED
  4275. ) {
  4276. CreateShadowControl |= CREATESHADOW_CONTROL_NOCREATE;
  4277. }
  4278. //
  4279. // The Windows Explorer likes to open .DLL and .EXE files to extract
  4280. // the ICON -- and it does this whenever it is trying to show the contents
  4281. // of a directory. We don't want this explorer activity to force the files
  4282. // to be cached. So we only automatically cache .DLL and .EXE files if they
  4283. // are being opened for execution
  4284. // We make an exception for VDO shares. The rational being that most
  4285. // often the users would run apps without opening a folders
  4286. if( CreateShadowControl == CREATESHADOW_NO_SPECIAL_CONTROLS &&
  4287. !(CreateParameters->DesiredAccess & FILE_EXECUTE)
  4288. &&(pNetRootEntry->NetRoot.CscFlags != SMB_CSC_CACHE_VDO)) {
  4289. PUNICODE_STRING fileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  4290. UNICODE_STRING exe = { 3*sizeof(WCHAR), 3*sizeof(WCHAR), L"exe" };
  4291. UNICODE_STRING dll = { 3*sizeof(WCHAR), 3*sizeof(WCHAR), L"dll" };
  4292. UNICODE_STRING s;
  4293. //
  4294. // If the filename ends in .DLL or .EXE, then we do not cache it this time
  4295. //
  4296. if( fileName->Length > 4 * sizeof(WCHAR) &&
  4297. fileName->Buffer[ fileName->Length/sizeof(WCHAR) - 4 ] == L'.'){
  4298. s.Length = s.MaximumLength = 3 * sizeof( WCHAR );
  4299. s.Buffer = &fileName->Buffer[ (fileName->Length - s.Length)/sizeof(WCHAR) ];
  4300. if( RtlCompareUnicodeString( &s, &exe, TRUE ) == 0 ||
  4301. RtlCompareUnicodeString( &s, &dll, TRUE ) == 0 ) {
  4302. CreateShadowControl = CREATESHADOW_CONTROL_FILE_WITH_HEURISTIC;
  4303. }
  4304. }
  4305. }
  4306. }
  4307. } else { //disconnected
  4308. switch (CreateDisposition) {
  4309. case FILE_OVERWRITE:
  4310. case FILE_OPEN:
  4311. CreateShadowControl = CREATESHADOW_CONTROL_NOCREATE;
  4312. break;
  4313. case FILE_CREATE:
  4314. case FILE_SUPERSEDE: //NTRAID-455238-1/31/2000-shishirp supersede not implemented
  4315. case FILE_OVERWRITE_IF:
  4316. case FILE_OPEN_IF:
  4317. default:
  4318. CreateShadowControl = CREATESHADOW_NO_SPECIAL_CONTROLS;
  4319. break;
  4320. }
  4321. if (*Status != STATUS_MORE_PROCESSING_REQUIRED) {
  4322. dwEarlyOuts=2;
  4323. goto FINALLY;
  4324. }
  4325. // make sure we do share access check before we do any damage
  4326. CreateShadowControl |= CREATESHADOW_CONTROL_DO_SHARE_ACCESS_CHECK;
  4327. } // if (!Disconnected)
  4328. CreateShadowControl |= CREATESHADOW_CONTROL_FAIL_IF_MARKED_FOR_DELETION;
  4329. if (!Disconnected &&
  4330. ((ReturnedCreateInformation==FILE_OPENED) ||
  4331. (ReturnedCreateInformation==FILE_OVERWRITTEN) ) ){
  4332. CreateShadowControl |= CREATESHADOW_CONTROL_SPARSECREATE;
  4333. }
  4334. LocalStatus = MRxSmbCscObtainShadowHandles(
  4335. RxContext,
  4336. Status,
  4337. lpFind32,
  4338. &CreatedShadow,
  4339. CreateShadowControl,
  4340. Disconnected);
  4341. if (LocalStatus != STATUS_SUCCESS) {
  4342. RxDbgTrace(-1, Dbg,
  4343. ("MRxSmbCscCreateEpilogue no handles-> %08lx %08lx\n",RxContext,LocalStatus ));
  4344. dwEarlyOuts=3;
  4345. *Status = LocalStatus;
  4346. goto FINALLY;
  4347. }
  4348. // if we got an inode for a file which was opened or created recently
  4349. // and there have been some writes on it before this
  4350. // then we need to truncate the data so we don't give stale data to the user
  4351. if (smbFcb->hShadow &&
  4352. IsFile(lpFind32->dwFileAttributes) &&
  4353. !CreatedShadow &&
  4354. FlagOn(smbFcb->MFlags, SMB_FCB_FLAG_WRITES_PERFORMED))
  4355. {
  4356. if(TruncateDataHSHADOW(smbFcb->hParentDir, smbFcb->hShadow) < SRET_OK)
  4357. {
  4358. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateEpilogue: Failed to get shadowinfo for hDir=%x hShadow=%x \r\n", smbFcb->hParentDir, smbFcb->hShadow));
  4359. dwEarlyOuts=31;
  4360. goto FINALLY;
  4361. }
  4362. }
  4363. } else { //
  4364. ULONG uShadowStatus;
  4365. int iRet;
  4366. RxDbgTrace( 0, Dbg,
  4367. ("MRxSmbCscCreateEpilogue found existing hdir/hshadow= %08lx %08lx\n",
  4368. smbFcb->hParentDir, smbFcb->hShadow));
  4369. iRet = GetShadowInfo(
  4370. smbFcb->hParentDir,
  4371. smbFcb->hShadow,
  4372. lpFind32,
  4373. &uShadowStatus,
  4374. &oSI);
  4375. if (iRet < SRET_OK) {
  4376. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateEpilogue: Failed to get shadowinfo for hDir=%x hShadow=%x \r\n", smbFcb->hParentDir, smbFcb->hShadow));
  4377. dwEarlyOuts=4;
  4378. goto FINALLY;
  4379. }
  4380. bGotOtherInfo = TRUE;
  4381. //
  4382. // Notepad bug (175322) - quick open/close/open can lose bits - OR in the disk bits
  4383. // with the in-memory bits.
  4384. //
  4385. smbFcb->ShadowStatus |= (USHORT)uShadowStatus;
  4386. RxDbgTrace(0, Dbg,
  4387. ("MRxSmbCscCreateEpilogue name from lpFind32..<%ws>\n",lpFind32->cFileName));
  4388. }
  4389. hShadow = smbFcb->hShadow;
  4390. hParentDir = smbFcb->hParentDir;
  4391. //
  4392. // If a file is encrypted, but the cache is not, we only allow a file
  4393. // to be cached when the user explicitly asks to do so.
  4394. //
  4395. // Unless we're in the middle of an inode transaction...
  4396. //
  4397. if (
  4398. !Disconnected
  4399. &&
  4400. hShadow != 0
  4401. &&
  4402. cntInodeTransactions == 0
  4403. &&
  4404. (vulDatabaseStatus & FLAG_DATABASESTATUS_ENCRYPTED) == 0
  4405. &&
  4406. (smbFcb->dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0
  4407. ) {
  4408. int iRet = SRET_OK;
  4409. ULONG uShadowStatus;
  4410. if (bGotOtherInfo == FALSE) {
  4411. iRet = GetShadowInfo(
  4412. smbFcb->hParentDir,
  4413. smbFcb->hShadow,
  4414. lpFind32,
  4415. &uShadowStatus,
  4416. &oSI);
  4417. }
  4418. if (
  4419. iRet >= SRET_OK
  4420. &&
  4421. (oSI.ulHintFlags & (FLAG_CSC_HINT_PIN_USER | FLAG_CSC_HINT_PIN_SYSTEM)) == 0
  4422. &&
  4423. oSI.ulHintPri == 0
  4424. ) {
  4425. DeleteShadow(hParentDir, hShadow);
  4426. hShadow = smbFcb->hShadow = 0;
  4427. }
  4428. }
  4429. if (hShadow != 0) {
  4430. if (Disconnected)
  4431. {
  4432. if ((CreateOptions & FILE_DIRECTORY_FILE) && !(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  4433. {
  4434. *Status = STATUS_OBJECT_TYPE_MISMATCH;
  4435. goto FINALLY;
  4436. }
  4437. if ((CreateOptions & FILE_NON_DIRECTORY_FILE) && (lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  4438. {
  4439. *Status = STATUS_FILE_IS_A_DIRECTORY;
  4440. goto FINALLY;
  4441. }
  4442. // don't allow writing to a readonly file
  4443. if (!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // a file
  4444. (lpFind32->dwFileAttributes & FILE_ATTRIBUTE_READONLY) && // readonly attribute set
  4445. (CreateParameters->DesiredAccess & (FILE_WRITE_DATA|FILE_APPEND_DATA))) // wants to modify
  4446. {
  4447. if (!CreatedShadow)
  4448. {
  4449. HookKdPrint(NAME, ("Modifying RO file %x %x\n", hParentDir, hShadow));
  4450. *Status = STATUS_ACCESS_DENIED;
  4451. goto FINALLY;
  4452. }
  4453. }
  4454. }
  4455. // If the Shadow handle was successfully manufactured we have one of
  4456. // two possibilities -- In a disconnected state the access check
  4457. // needs to be made and in the connected state the access rights need
  4458. // to be updated.
  4459. #if defined(REMOTE_BOOT)
  4460. // For remote boot, this whole next section (the if(Disconnected)
  4461. // and the else clause) was not done, since we later impersonated
  4462. // the user while opening the file.
  4463. #endif
  4464. if (Disconnected) {
  4465. BOOLEAN AccessGranted;
  4466. CACHED_SECURITY_INFORMATION CachedSecurityInformationForShare;
  4467. memset(&CachedSecurityInformationForShare, 0, sizeof(CachedSecurityInformationForShare));
  4468. AccessGranted = CscAccessCheck(
  4469. hParentDir,
  4470. hShadow,
  4471. RxContext,
  4472. CreateParameters->DesiredAccess,
  4473. NULL,
  4474. &CachedSecurityInformationForShare
  4475. );
  4476. if (!AccessGranted) {
  4477. HookKdPrint(BADERRORS, ("Security access denied %x %x\n", hParentDir, hShadow));
  4478. *Status = STATUS_ACCESS_DENIED;
  4479. hShadow = 0;
  4480. }
  4481. else if (CreatedShadow && !(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  4482. {
  4483. DWORD CscStatus, i;
  4484. SID_CONTEXT SidContext;
  4485. CSC_SID_ACCESS_RIGHTS AccessRights[2];
  4486. // if the file has been created in offline mode, give the
  4487. // creator all the rights
  4488. if (CscRetrieveSid(RxContext,&SidContext) == STATUS_SUCCESS) {
  4489. if (SidContext.pSid != NULL) {
  4490. AccessRights[0].pSid = SidContext.pSid;
  4491. AccessRights[0].SidLength = RtlLengthSid(SidContext.pSid);
  4492. AccessRights[0].MaximalAccessRights = FILE_ALL_ACCESS;
  4493. AccessRights[1].pSid = CSC_GUEST_SID;
  4494. AccessRights[1].SidLength = CSC_GUEST_SID_LENGTH;
  4495. AccessRights[1].MaximalAccessRights = 0;
  4496. #if 0
  4497. for (i=0;i<CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES;++i)
  4498. {
  4499. if(CachedSecurityInformationForShare.AccessRights[i].SidIndex == CSC_GUEST_SID_INDEX)
  4500. {
  4501. AccessRights[1].MaximalAccessRights = CachedSecurityInformationForShare.AccessRights[i].MaximalRights;
  4502. break;
  4503. }
  4504. }
  4505. #endif
  4506. CscStatus = CscAddMaximalAccessRightsForSids(
  4507. hParentDir,
  4508. hShadow,
  4509. 2,
  4510. AccessRights);
  4511. if (CscStatus != ERROR_SUCCESS) {
  4512. RxDbgTrace(
  4513. 0,
  4514. Dbg,
  4515. ("MRxSmbCscCreateEpilogue Error Updating Access rights %lx\n",Status));
  4516. }
  4517. } // if (SidContext.pSid != NULL)
  4518. CscDiscardSid(&SidContext);
  4519. }
  4520. }
  4521. } else {
  4522. CSC_SID_ACCESS_RIGHTS AccessRights[2];
  4523. DWORD CscStatus;
  4524. SID_CONTEXT SidContext;
  4525. if (CscRetrieveSid(RxContext,&SidContext) == STATUS_SUCCESS) {
  4526. if (SidContext.pSid != NULL) {
  4527. AccessRights[0].pSid = SidContext.pSid;
  4528. AccessRights[0].SidLength = RtlLengthSid(SidContext.pSid);
  4529. // update the share right if necessary
  4530. if (pNetRootEntry->NetRoot.UpdateCscShareRights)
  4531. {
  4532. AccessRights[0].MaximalAccessRights = pNetRootEntry->MaximalAccessRights;
  4533. AccessRights[1].pSid = CSC_GUEST_SID;
  4534. AccessRights[1].SidLength = CSC_GUEST_SID_LENGTH;
  4535. AccessRights[1].MaximalAccessRights = pNetRootEntry->GuestMaximalAccessRights;
  4536. CscStatus = CscAddMaximalAccessRightsForShare(
  4537. smbFcb->sCscRootInfo.hShare,
  4538. 2,
  4539. AccessRights);
  4540. if (CscStatus != ERROR_SUCCESS) {
  4541. RxDbgTrace(
  4542. 0,
  4543. Dbg,
  4544. ("MRxSmbCscCreateEpilogue Error Updating Access rights %lx\n",
  4545. Status));
  4546. }
  4547. else
  4548. {
  4549. pNetRootEntry->NetRoot.UpdateCscShareRights = FALSE;
  4550. }
  4551. }
  4552. if (!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  4553. {
  4554. AccessRights[0].MaximalAccessRights = smbSrvOpen->MaximalAccessRights;
  4555. AccessRights[1].pSid = CSC_GUEST_SID;
  4556. AccessRights[1].SidLength = CSC_GUEST_SID_LENGTH;
  4557. AccessRights[1].MaximalAccessRights = smbSrvOpen->GuestMaximalAccessRights;
  4558. if (*Status == STATUS_ACCESS_DENIED) {
  4559. AccessRights[0].MaximalAccessRights = 0;
  4560. AccessRights[1].MaximalAccessRights = 0;
  4561. } else {
  4562. AccessRights[0].MaximalAccessRights = smbSrvOpen->MaximalAccessRights;
  4563. AccessRights[1].MaximalAccessRights = smbSrvOpen->GuestMaximalAccessRights;
  4564. }
  4565. CscStatus = CscAddMaximalAccessRightsForSids(
  4566. hParentDir,
  4567. hShadow,
  4568. 2,
  4569. AccessRights);
  4570. if (CscStatus != ERROR_SUCCESS) {
  4571. RxDbgTrace(
  4572. 0,
  4573. Dbg,
  4574. ("MRxSmbCscCreateEpilogue Error Updating Access rights %lx\n",Status));
  4575. }
  4576. }
  4577. } // if (SidContext.pSid != NULL)
  4578. CscDiscardSid(&SidContext);
  4579. } // if (CscRetrieveSid(RxContext,&SidContext) == STATUS_SUCCESS)
  4580. // having updated the access fields, we quit from here.
  4581. if (*Status == STATUS_ACCESS_DENIED)
  4582. {
  4583. goto FINALLY;
  4584. }
  4585. }
  4586. } // if (hShadow != 0)
  4587. if ((hShadow != 0) &&
  4588. !Disconnected && //ok for red/yellow
  4589. (NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE)) {
  4590. // here we check to see if the timestamp of the file has changed
  4591. // if so, the shadow needs to be truncated so we don't use it anymore
  4592. ULONG ShadowStatus;
  4593. LONG ShadowApiReturn;
  4594. lpFind32->ftLastWriteTime.dwHighDateTime = smbFcb->LastCscTimeStampHigh;
  4595. lpFind32->ftLastWriteTime.dwLowDateTime = smbFcb->LastCscTimeStampLow;
  4596. lpFind32->nFileSizeHigh = smbFcb->NewShadowSize.HighPart;
  4597. lpFind32->nFileSizeLow = smbFcb->NewShadowSize.LowPart;
  4598. lpFind32->dwFileAttributes = smbFcb->dwFileAttributes;
  4599. RxDbgTrace(0, Dbg,
  4600. ("MRxSmbCscCreateEpilogue trying for refresh...<%ws>\n",lpFind32->cFileName));
  4601. ShadowApiReturn = RefreshShadow(
  4602. hParentDir, //HSHADOW hDir,
  4603. hShadow, //HSHADOW hShadow,
  4604. lpFind32, //LPFIND32 lpFind32,
  4605. &ShadowStatus //ULONG *lpuShadowStatus
  4606. );
  4607. if (ShadowApiReturn<0) {
  4608. hShadow = 0;
  4609. RxDbgTrace(0, Dbg,
  4610. ("MRxSmbCscCreateEpilogue refresh failed..%08lx.<%ws>\n",RxContext,lpFind32->cFileName));
  4611. } else {
  4612. smbFcb->ShadowStatus = (USHORT)ShadowStatus;
  4613. if ( ShadowApiReturn==1)
  4614. {
  4615. ShadowWasRefreshed = 1;
  4616. //WinSE Bug 28543
  4617. //Set this flag so that we remember that we truncated the file
  4618. //and so in MrxSmbCSCUpdateShadowFromClose we don't reset the
  4619. //SPARSE flag. - NavjotV
  4620. SetFlag(smbFcb->MFlags,SMB_FCB_FLAG_CSC_TRUNCATED_SHADOW);
  4621. }
  4622. }
  4623. }
  4624. }
  4625. NeedTruncate = FALSE;
  4626. RxDbgTrace(0, Dbg,
  4627. ("MRxSmbCscCreateEpilogue trying for truncate...%08lx %08lx %08lx %08lx\n",
  4628. RxContext,hShadow,CreatedShadow,
  4629. RxContext->Create.ReturnedCreateInformation));
  4630. if (hShadow != 0) {
  4631. if (!Disconnected) {
  4632. CreateInformation = ReturnedCreateInformation;
  4633. if (!CreatedShadow &&
  4634. (ReturnedCreateInformation<= FILE_MAXIMUM_DISPOSITION) &&
  4635. (ReturnedCreateInformation!=FILE_OPENED) ) {
  4636. if ((NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE)) {
  4637. NeedTruncate = TRUE;
  4638. }
  4639. }
  4640. }
  4641. else { // Disconnected
  4642. ULONG ShadowStatus = smbFcb->ShadowStatus;
  4643. BOOLEAN ItsAFile = !BooleanFlagOn(lpFind32->dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY);
  4644. CreateInformation = FILE_OPENED;
  4645. switch (CreateDisposition) {
  4646. case FILE_OPEN:
  4647. NOTHING;
  4648. break;
  4649. case FILE_OPEN_IF:
  4650. if (CreatedShadow) {
  4651. CreateInformation = FILE_CREATED;
  4652. } else if (FlagOn(ShadowStatus,SHADOW_SPARSE)) {
  4653. NeedTruncate = ItsAFile;
  4654. CreateInformation = FILE_CREATED;
  4655. }
  4656. break;
  4657. case FILE_OVERWRITE:
  4658. case FILE_OVERWRITE_IF:
  4659. if (CreatedShadow) {
  4660. ASSERT(CreateDisposition==FILE_OVERWRITE_IF);
  4661. CreateInformation = FILE_CREATED;
  4662. } else {
  4663. NeedTruncate = ItsAFile;
  4664. CreateInformation = FILE_OVERWRITTEN;
  4665. }
  4666. break;
  4667. case FILE_CREATE:
  4668. if (!CreatedShadow)
  4669. {
  4670. *Status = STATUS_OBJECT_NAME_COLLISION;
  4671. goto FINALLY;
  4672. }
  4673. case FILE_SUPERSEDE:
  4674. if (!CreatedShadow) {
  4675. NeedTruncate = ItsAFile;
  4676. };
  4677. CreateInformation = FILE_CREATED;
  4678. break;
  4679. default:
  4680. ASSERT(FALSE);
  4681. }
  4682. // In disconnected state, note down the changes that have occurred
  4683. // in order to notify them to the fsrtl package.
  4684. if (CreatedShadow)
  4685. {
  4686. dwNotifyFilter = (IsFile(smbFcb->dwFileAttributes)?FILE_NOTIFY_CHANGE_FILE_NAME:FILE_NOTIFY_CHANGE_DIR_NAME);
  4687. dwFileAction = FILE_ACTION_ADDED;
  4688. }
  4689. else if (NeedTruncate)
  4690. {
  4691. dwNotifyFilter = FILE_NOTIFY_CHANGE_SIZE;
  4692. dwFileAction = FILE_ACTION_MODIFIED;
  4693. }
  4694. } // if (!Disconnected)
  4695. }
  4696. if (NeedTruncate) {
  4697. int iLocalRet;
  4698. ULONG uShadowStatus = smbFcb->ShadowStatus;
  4699. uShadowStatus &= ~SHADOW_SPARSE;
  4700. lpFind32->nFileSizeLow = lpFind32->nFileSizeHigh = 0;
  4701. ASSERT(hShadow!=0);
  4702. HookKdPrint(NAME, ("CreateEpilogue needtruncate %ws %08lx\n",lpFind32->cFileName,uShadowStatus));
  4703. RxDbgTrace(0, Dbg,
  4704. ("MRxSmbCscCreateEpilogue needtruncate...<%ws> %08lx\n",
  4705. lpFind32->cFileName,uShadowStatus));
  4706. TruncateDataHSHADOW(hParentDir, hShadow);
  4707. iLocalRet = SetShadowInfo(
  4708. hParentDir,
  4709. hShadow,
  4710. lpFind32,
  4711. uShadowStatus,
  4712. SHADOW_FLAGS_ASSIGN |
  4713. ((Disconnected) ?SHADOW_FLAGS_DONT_UPDATE_ORGTIME :0)
  4714. );
  4715. if (iLocalRet < SRET_OK) {
  4716. hShadow = 0;
  4717. } else {
  4718. smbFcb->ShadowStatus = (USHORT)uShadowStatus;
  4719. }
  4720. } // if (NeedTruncate)
  4721. if (Disconnected) {
  4722. ULONG ShadowStatus = smbFcb->ShadowStatus;
  4723. if (*Status == STATUS_MORE_PROCESSING_REQUIRED) {
  4724. CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;
  4725. RxDbgTrace(0, Dbg,
  4726. ("MRxSmbCscCreateEpilogue lastDCON...<%ws> %08lx %08lx %08lx\n",
  4727. lpFind32->cFileName,ShadowStatus,CreateDisposition,lpFind32->dwFileAttributes));
  4728. switch (CreateDisposition) {
  4729. case FILE_OPEN:
  4730. case FILE_OVERWRITE:
  4731. if ((hShadow==0) ||
  4732. ( FlagOn(ShadowStatus,SHADOW_SPARSE) &&
  4733. !FlagOn(lpFind32->dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY))
  4734. ) {
  4735. *Status = STATUS_NO_SUCH_FILE;
  4736. } else {
  4737. // Bypass the shadow if it is not visibile for this connection
  4738. if (!IsShadowVisible(Disconnected,
  4739. lpFind32->dwFileAttributes,
  4740. ShadowStatus)) {
  4741. *Status = STATUS_NO_SUCH_FILE;
  4742. }
  4743. else
  4744. {
  4745. *Status = STATUS_SUCCESS;
  4746. }
  4747. }
  4748. break;
  4749. case FILE_OPEN_IF:
  4750. case FILE_OVERWRITE_IF:
  4751. case FILE_CREATE:
  4752. case FILE_SUPERSEDE:
  4753. if (hShadow==0) {
  4754. *Status = STATUS_NO_SUCH_FILE;
  4755. } else {
  4756. *Status = STATUS_SUCCESS;
  4757. //CreateInformation == FILE_OPENED|CREATED set in switch above;
  4758. }
  4759. break;
  4760. default:
  4761. ASSERT(FALSE);
  4762. }
  4763. }
  4764. if (*Status == STATUS_SUCCESS) {
  4765. //next, we have to do everything that the create code would have done...
  4766. //specifically, we have to build a fobx and we have to do a initfcb.
  4767. //basically, we have to do the create success tail........
  4768. BOOLEAN MustRegainExclusiveResource = FALSE;
  4769. PSMBPSE_FILEINFO_BUNDLE FileInfo = &smbSrvOpen->FileInfo;
  4770. SMBFCB_HOLDING_STATE FakeSmbFcbHoldingState = SmbFcb_NotHeld;
  4771. RX_FILE_TYPE StorageType;
  4772. //RtlZeroMemory(FileInfo,sizeof(FileInfo));
  4773. FileInfo->Basic.FileAttributes = lpFind32->dwFileAttributes;
  4774. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  4775. FileInfo->Basic.CreationTime,
  4776. lpFind32->ftCreationTime);
  4777. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  4778. FileInfo->Basic.LastAccessTime,
  4779. lpFind32->ftLastAccessTime);
  4780. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  4781. FileInfo->Basic.LastWriteTime,
  4782. lpFind32->ftLastWriteTime);
  4783. FileInfo->Standard.NumberOfLinks = 1;
  4784. FileInfo->Standard.EndOfFile.HighPart = lpFind32->nFileSizeHigh;
  4785. FileInfo->Standard.EndOfFile.LowPart = lpFind32->nFileSizeLow;
  4786. FileInfo->Standard.AllocationSize = FileInfo->Standard.EndOfFile; //rdr1 actually rounds up based of svr disk attribs
  4787. FileInfo->Standard.Directory = BooleanFlagOn(lpFind32->dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY);
  4788. //CODE.IMRPOVEMENT successtail should figure out the storage type
  4789. StorageType = FlagOn(lpFind32->dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY)
  4790. ?(FileTypeDirectory)
  4791. :(FileTypeFile);
  4792. *Status = MRxSmbCreateFileSuccessTail (
  4793. RxContext,
  4794. &MustRegainExclusiveResource,
  4795. &FakeSmbFcbHoldingState,
  4796. StorageType,
  4797. 0xf00d,
  4798. 0xbaad,
  4799. SMB_OPLOCK_LEVEL_BATCH,
  4800. CreateInformation,
  4801. FileInfo
  4802. );
  4803. HookKdPrint(NAME, ("CreateEpilogue %ws attrib=%x \n",lpFind32->cFileName,lpFind32->dwFileAttributes));
  4804. }
  4805. if (*Status != STATUS_SUCCESS){
  4806. hShadow = 0;
  4807. }
  4808. } // if (Disconnected)
  4809. if (hShadow != 0) {
  4810. PUNICODE_STRING pName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  4811. // upcase it so change notification will get it right
  4812. // this works because rdbss always does caseinsensitive compare
  4813. UniToUpper(pName->Buffer, pName->Buffer, pName->Length);
  4814. // here we get a local handle on behalf of this srvopen; we only do this
  4815. // open if it's a file (not a directory) AND if the access rights specified
  4816. // indicate that we might use/modify the data in the shadow.
  4817. if (NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE) {
  4818. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  4819. // why are we not using macros provided in ntioapi.h for access rights?
  4820. ULONG NeedShadowAccessRights = FILE_READ_DATA
  4821. | FILE_WRITE_DATA
  4822. | FILE_READ_ATTRIBUTES
  4823. | FILE_WRITE_ATTRIBUTES
  4824. | FILE_APPEND_DATA
  4825. | FILE_EXECUTE;
  4826. if ( (CreateParameters->DesiredAccess & NeedShadowAccessRights) != 0 ) {
  4827. // ASSERT( sizeof(HFILE) == sizeof(HANDLE) );
  4828. ASSERT( hShadow == smbFcb->hShadow );
  4829. ASSERT( hParentDir == smbFcb->hParentDir );
  4830. #if defined(REMOTE_BOOT)
  4831. //
  4832. // In the remote boot case, there was an extra context
  4833. // parameter to OpenFileHSHADOW which held a pointer
  4834. // to CreateParameters and a local status value.
  4835. //
  4836. #endif
  4837. #if !defined(BITCOPY)
  4838. OpenFileHSHADOW(
  4839. hShadow,
  4840. 0,
  4841. 0,
  4842. (CSCHFILE *)(&(smbSrvOpen->hfShadow))
  4843. );
  4844. #else
  4845. OpenFileHSHADOWAndCscBmp(
  4846. smbFcb->hShadow,
  4847. 0,
  4848. 0,
  4849. (CSCHFILE *)(&(smbSrvOpen->hfShadow)),
  4850. smbFcb->fDoBitCopy,
  4851. 0,
  4852. NULL
  4853. );
  4854. // Check if needed to Open a CSC_BITMAP
  4855. if (
  4856. smbFcb->fDoBitCopy == TRUE
  4857. &&
  4858. smbFcb->NewShadowSize.HighPart == 0 // no 64-bit
  4859. &&
  4860. Disconnected // only in dcon mode
  4861. &&
  4862. !FlagOn(smbFcb->ShadowStatus,SHADOW_SPARSE)
  4863. &&
  4864. smbFcb->lpDirtyBitmap == NULL // shadow file not sparse
  4865. &&
  4866. // have not been created before
  4867. (FlagOn(
  4868. CreateParameters->DesiredAccess,
  4869. FILE_WRITE_DATA|FILE_APPEND_DATA))
  4870. // opened for writes
  4871. // && is NTFS -- see below
  4872. ) {
  4873. BOOL fHasStreams;
  4874. if (HasStreamSupport(smbSrvOpen->hfShadow, &fHasStreams) &&
  4875. (fHasStreams == TRUE))
  4876. {
  4877. OpenCscBmp(hShadow, &((LPCSC_BITMAP)(smbFcb->lpDirtyBitmap)));
  4878. }
  4879. }
  4880. #endif // defined(BITCOPY)
  4881. #if defined(REMOTE_BOOT)
  4882. //
  4883. // Here we checked the local status value and set
  4884. // *Status from it if (iRet != SRET_OK).
  4885. //
  4886. #endif
  4887. if (smbSrvOpen->hfShadow != 0) {
  4888. HookKdPrint(NAME, ("Opened file %ws, hShadow=%x handle=%x \n", lpFind32->cFileName, hShadow, smbSrvOpen->hfShadow));
  4889. RxLog(("CSC Opened file %ws, hShadow=%x capFcb=%x SrvOpen=%x\n", lpFind32->cFileName, hShadow, capFcb, SrvOpen));
  4890. // NeedToReportFileOpen = TRUE;
  4891. SetPriorityHSHADOW(hParentDir, hShadow, MAX_PRI, RETAIN_VALUE);
  4892. if (Disconnected)
  4893. {
  4894. MRxSmbCSCObtainRightsForUserOnFile(RxContext,
  4895. hParentDir,
  4896. hShadow,
  4897. &smbSrvOpen->MaximalAccessRights,
  4898. &smbSrvOpen->GuestMaximalAccessRights);
  4899. }
  4900. }
  4901. }
  4902. } // if (NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
  4903. IF_DEBUG {
  4904. if (FALSE) {
  4905. BOOL thisone, nextone;
  4906. PFDB smbLookedUpFcb,smbLookedUpFcbNext;
  4907. smbLookedUpFcb = PFindFdbFromHShadow(hShadow);
  4908. smbLookedUpFcbNext = PFindFdbFromHShadow(hShadow+1);
  4909. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateEpilogue lookups -> %08lx %08lx %08lx\n",
  4910. smbFcb,
  4911. MRxSmbCscRecoverMrxFcbFromFdb(smbLookedUpFcb),
  4912. MRxSmbCscRecoverMrxFcbFromFdb(smbLookedUpFcbNext) ));
  4913. }
  4914. }
  4915. } // if (hShadow != 0)
  4916. FINALLY:
  4917. if (lpFind32)
  4918. {
  4919. RxFreePool(lpFind32);
  4920. }
  4921. if (EnteredCriticalSection) {
  4922. LeaveShadowCritRx(RxContext);
  4923. }
  4924. #if 0
  4925. if (NeedToReportFileOpen) {
  4926. //this is a bit strange....it's done this way because MRxSmbCscReportFileOpens
  4927. //enters the critsec for himself.....it is also called from within MRxSmbCollapseOpen
  4928. //if instead MRxSmbCollapseOpen called a wrapper routine, we could have
  4929. //MRxSmbCscReportFileOpens not enter and we could do this above
  4930. MRxSmbCscReportFileOpens(); //CODE.IMPROVEMENT this guy shouldn't enter
  4931. }
  4932. #endif
  4933. if (Disconnected)
  4934. {
  4935. if(*Status == STATUS_MORE_PROCESSING_REQUIRED) {
  4936. // if we ever get here after CSC is shutdown, we need to return appropriate error
  4937. if (fShadow)
  4938. {
  4939. RxLog(("EarlyOut = %d \r\n", dwEarlyOuts));
  4940. // should never get here
  4941. DbgPrint("MRxSmbCscCreateEpilogue: EarlyOut = %d \r\n", dwEarlyOuts);
  4942. ASSERT(FALSE);
  4943. }
  4944. else
  4945. {
  4946. *Status = STATUS_NETWORK_UNREACHABLE;
  4947. }
  4948. }
  4949. else if (*Status == STATUS_SUCCESS)
  4950. {
  4951. // report changes to the notification package
  4952. if (dwNotifyFilter)
  4953. {
  4954. ASSERT(dwFileAction);
  4955. RxLog(("chngnot hShadow=%x filter=%x\n",smbFcb->hShadow, dwNotifyFilter));
  4956. FsRtlNotifyFullReportChange(
  4957. pNetRootEntry->NetRoot.pNotifySync,
  4958. &pNetRootEntry->NetRoot.DirNotifyList,
  4959. (PSTRING)GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb),
  4960. (USHORT)(GET_ALREADY_PREFIXED_NAME(SrvOpen, capFcb)->Length -
  4961. smbFcb->MinimalCscSmbFcb.LastComponentLength),
  4962. NULL,
  4963. NULL,
  4964. dwNotifyFilter,
  4965. dwFileAction,
  4966. NULL);
  4967. }
  4968. }
  4969. }
  4970. HookKdPrint(NAME, ("CreateEpilogue Out: returnedCreateInfo=%x Status=%x\n",
  4971. ReturnedCreateInformation, *Status));
  4972. RxDbgTrace(-1, Dbg, ("MRxSmbCscCreateEpilogue ->%08lx %08lx\n",RxContext, *Status ));
  4973. RxLog(("CscCrEpi %x %x\n",RxContext, *Status ));
  4974. return;
  4975. EarlyOut:
  4976. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  4977. RxDbgTrace(0, Dbg, ("MRxSmbCscCreateEpilogue...early release %08lx\n",
  4978. RxContext));
  4979. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  4980. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  4981. }
  4982. return;
  4983. }
  4984. VOID
  4985. MRxSmbCscDeleteAfterCloseEpilogue (
  4986. IN OUT PRX_CONTEXT RxContext,
  4987. IN OUT PNTSTATUS Status
  4988. )
  4989. /*++
  4990. Routine Description:
  4991. This routine performs the tail of a delete-after-close operation for CSC.
  4992. Basically, it deletes the file from the cache.
  4993. The status of the operation is passed in case we someday find
  4994. things are so messed up that we want to return a failure even if the
  4995. nonshadowed operations was successful. not today however...
  4996. Arguments:
  4997. RxContext - the RDBSS context
  4998. Return Value:
  4999. Notes:
  5000. --*/
  5001. {
  5002. NTSTATUS LocalStatus=STATUS_UNSUCCESSFUL;
  5003. int iRet = -1;
  5004. ULONG ShadowFileLength;
  5005. RxCaptureFcb;RxCaptureFobx;
  5006. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  5007. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  5008. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  5009. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  5010. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry =
  5011. SmbCeGetAssociatedNetRootEntry(NetRoot);
  5012. BOOLEAN EnteredCriticalSection = FALSE;
  5013. _WIN32_FIND_DATA Find32; //this should not be on the stack CODE.IMPROVEMENT
  5014. BOOLEAN Disconnected;
  5015. ULONG uShadowStatus;
  5016. OTHERINFO sOI;
  5017. if(!MRxSmbIsCscEnabled) {
  5018. return;
  5019. }
  5020. if (fShadow == 0) {
  5021. return;
  5022. }
  5023. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  5024. RxDbgTrace(+1, Dbg,
  5025. ("MRxSmbCscDeleteAfterCloseEpilogue entry %08lx...%08lx on handle %08lx\n",
  5026. RxContext, SrvOpen, smbSrvOpen->hfShadow ));
  5027. if (*Status != STATUS_SUCCESS) {
  5028. RxDbgTrace(0, Dbg,
  5029. ("MRxSmbCscDeleteAfterCloseEpilogue exit(status) w/o deleteing -> %08lx %08lx\n", RxContext, Status ));
  5030. goto FINALLY;
  5031. }
  5032. EnterShadowCritRx(RxContext);
  5033. EnteredCriticalSection = TRUE;
  5034. //if we don't have a shadow...go look for one
  5035. if (smbFcb->hShadow == 0) {
  5036. if (!smbFcb->hShadowRenamed)
  5037. {
  5038. LocalStatus = MRxSmbCscObtainShadowHandles(
  5039. RxContext,
  5040. Status,
  5041. &Find32,
  5042. NULL,
  5043. CREATESHADOW_CONTROL_NOCREATE,
  5044. Disconnected);
  5045. if (LocalStatus != STATUS_SUCCESS) {
  5046. RxDbgTrace(0, Dbg,
  5047. ("MRxSmbCscDeleteAfterCloseEpilogue couldn't get handles-> %08lx %08lx\n",RxContext,LocalStatus ));
  5048. goto FINALLY;
  5049. }
  5050. }
  5051. else
  5052. {
  5053. smbFcb->hShadow = smbFcb->hShadowRenamed;
  5054. smbFcb->hParentDir = smbFcb->hParentDirRenamed;
  5055. }
  5056. if (smbFcb->hShadow == 0) {
  5057. RxDbgTrace(0, Dbg,
  5058. ("MRxSmbCscDeleteAfterCloseEpilogue no handles-> %08lx %08lx\n",RxContext,LocalStatus ));
  5059. goto FINALLY;
  5060. }
  5061. }
  5062. if(GetShadowInfo(smbFcb->hParentDir,
  5063. smbFcb->hShadow,
  5064. &Find32,
  5065. &uShadowStatus, &sOI) < SRET_OK) {
  5066. goto FINALLY;
  5067. }
  5068. if (IsShadowVisible(
  5069. Disconnected,
  5070. Find32.dwFileAttributes,
  5071. uShadowStatus)) {
  5072. BOOLEAN fMarkDeleted = (Disconnected && !mShadowLocallyCreated(uShadowStatus));
  5073. LocalStatus = OkToDeleteObject(smbFcb->hParentDir, smbFcb->hShadow, &Find32, uShadowStatus, Disconnected);
  5074. // If it is not OK to delete, the quit
  5075. if (LocalStatus != STATUS_SUCCESS)
  5076. {
  5077. iRet = -1;
  5078. goto FINALLY;
  5079. }
  5080. if (!fMarkDeleted)
  5081. {
  5082. if (capFcb->OpenCount != 0)
  5083. {
  5084. DbgPrint("Marking for delete hDir=%x hShadow=%x %ws \n\n", smbFcb->hParentDir, smbFcb->hShadow, Find32.cFileName);
  5085. ASSERT(FALSE);
  5086. RxLog(("Marking for delete hDir=%x hShadow=%x %ws \n\n", smbFcb->hParentDir, smbFcb->hShadow, Find32.cFileName));
  5087. // if we are supposed to really delete this file, note this fact on the FCB
  5088. // we will delete it when the FCB is deallocated
  5089. smbFcb->LocalFlags |= FLAG_FDB_DELETE_ON_CLOSE;
  5090. iRet = 0;
  5091. }
  5092. else
  5093. {
  5094. iRet = DeleteShadowHelper(FALSE, smbFcb->hParentDir, smbFcb->hShadow);
  5095. smbFcb->hShadow = 0;
  5096. if (iRet < 0)
  5097. {
  5098. goto FINALLY;
  5099. }
  5100. }
  5101. }
  5102. else
  5103. {
  5104. iRet = DeleteShadowHelper(TRUE, smbFcb->hParentDir, smbFcb->hShadow);
  5105. smbFcb->hShadow = 0;
  5106. }
  5107. if (iRet >= 0)
  5108. {
  5109. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  5110. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  5111. InsertTunnelInfo(smbFcb->hParentDir,
  5112. Find32.cFileName,
  5113. Find32.cAlternateFileName,
  5114. &sOI);
  5115. if (fMarkDeleted) {
  5116. MarkShareDirty(&smbFcb->sCscRootInfo.ShareStatus, smbFcb->sCscRootInfo.hShare);
  5117. }
  5118. // when disconnected, report the change
  5119. if (Disconnected)
  5120. {
  5121. FsRtlNotifyFullReportChange(
  5122. pNetRootEntry->NetRoot.pNotifySync,
  5123. &pNetRootEntry->NetRoot.DirNotifyList,
  5124. (PSTRING)GET_ALREADY_PREFIXED_NAME(NULL,capFcb),
  5125. (USHORT)(GET_ALREADY_PREFIXED_NAME(NULL, capFcb)->Length -
  5126. smbFcb->MinimalCscSmbFcb.LastComponentLength),
  5127. NULL,
  5128. NULL,
  5129. IsFile(Find32.dwFileAttributes)?FILE_NOTIFY_CHANGE_FILE_NAME
  5130. :FILE_NOTIFY_CHANGE_DIR_NAME,
  5131. FILE_ACTION_REMOVED,
  5132. NULL);
  5133. }
  5134. }
  5135. }
  5136. FINALLY:
  5137. if (EnteredCriticalSection) {
  5138. LeaveShadowCritRx(RxContext);
  5139. }
  5140. if (Disconnected) {
  5141. if (iRet < 0) {
  5142. *Status = LocalStatus; //do we need a better error mapping?
  5143. }
  5144. }
  5145. RxDbgTrace(-1, Dbg, ("MRxSmbCscDeleteAfterCloseEpilogue exit-> %08lx %08lx\n", RxContext, Status ));
  5146. return;
  5147. }
  5148. ULONG
  5149. GetPathLevelFromUnicodeString (
  5150. PUNICODE_STRING Name
  5151. )
  5152. /*++
  5153. Routine Description:
  5154. This routine counts the number of L'\\' in a string. It is used to set
  5155. the priority level for a directory on a rename operation.
  5156. Arguments:
  5157. Name -
  5158. Return Value:
  5159. Notes:
  5160. --*/
  5161. {
  5162. PWCHAR t = Name->Buffer;
  5163. LONG l = Name->Length;
  5164. ULONG Count = 1;
  5165. for (;l<2;l--) {
  5166. if (*t++ == L'\\') {
  5167. Count++;
  5168. }
  5169. }
  5170. return(Count);
  5171. }
  5172. VOID
  5173. MRxSmbCscRenameEpilogue (
  5174. IN OUT PRX_CONTEXT RxContext,
  5175. IN OUT PNTSTATUS Status
  5176. )
  5177. /*++
  5178. Routine Description:
  5179. This routine performs the tail of a rename operation for CSC.
  5180. Basically, it renames the file in the record manager datastructures.
  5181. Unfortunately, there is no "basically" to it.
  5182. The status of the operation is passed in case we someday find
  5183. things are so messed up that we want to return a failure even if the
  5184. nonshadowed operations was successful. not today however...
  5185. Arguments:
  5186. RxContext - the RDBSS context
  5187. Return Value:
  5188. Notes:
  5189. The routine does the following operations
  5190. - Get the Inode for the source ie. If \foo.dir\bar.txt is the source, we traverse the path
  5191. to get the inode for bar.txt.
  5192. - If necessary create the destination namespace in the CSC database i.e., if \foo.dir\bar.txt
  5193. is being renamed to \xxx.dir\yyy.dir\abc.txt, then ensure that the hierarchy \xxx.dir\yyy.dir
  5194. exists in the local namespace.
  5195. - If the destination inode exists, then apply the visibility and replace_if_exists logic to it.
  5196. If the operation is still valid, then get all the info about the destination inode and
  5197. delete it. Apply the info on the destination inode to the source.
  5198. - Do a rename
  5199. --*/
  5200. {
  5201. NTSTATUS LocalStatus = STATUS_UNSUCCESSFUL;
  5202. ULONG ShadowFileLength;
  5203. int iRet = -1;
  5204. RxCaptureFcb;RxCaptureFobx;
  5205. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  5206. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  5207. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  5208. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  5209. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry =
  5210. SmbCeGetAssociatedNetRootEntry(NetRoot);
  5211. UNICODE_STRING RenameName={0,0,NULL};
  5212. UNICODE_STRING LastComponentName = {0,0,NULL};
  5213. PFILE_RENAME_INFORMATION RenameInformation = RxContext->Info.Buffer;
  5214. MRX_SMB_FCB CscSmbFcb;
  5215. BOOLEAN EnteredCriticalSection = FALSE;
  5216. _WIN32_FIND_DATA Find32; //this should not be on the stack CODE.IMPROVEMENT
  5217. ULONG ulInheritedHintFlags=0;
  5218. BOOL fDoTunneling = FALSE;
  5219. HSHADOW hDir, hDirTo, hShadow=0, hShadowTo=0;
  5220. ULONG uShadowStatusFrom, uShadowStatusTo, uRenameFlags, attrSav;
  5221. OTHERINFO sOI, sOIFrom;
  5222. LPOTHERINFO lpOI=NULL;
  5223. BOOLEAN Disconnected, fAlreadyStripped = FALSE;
  5224. RETRIEVE_TUNNEL_INFO_RETURNS TunnelType;
  5225. _FILETIME ftLWTime;
  5226. BOOL fFile;
  5227. USHORT *lpcFileNameTuna = NULL, *lpcAlternateFileNameTuna = NULL;
  5228. if(!MRxSmbIsCscEnabled ||
  5229. (fShadow == 0)) {
  5230. RxLog(("RenCSC disabled \n"));
  5231. return;
  5232. }
  5233. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  5234. // an open for rename should never be a local open
  5235. ASSERT(!BooleanFlagOn(
  5236. smbSrvOpen->Flags,
  5237. SMB_SRVOPEN_FLAG_LOCAL_OPEN));
  5238. if (!Disconnected &&
  5239. !pNetRootEntry->NetRoot.CscEnabled) {
  5240. RxLog(("NR %x Not cscenabled %x\n", pNetRootEntry));
  5241. return;
  5242. }
  5243. RxDbgTrace(+1, Dbg,
  5244. ("MRxSmbCscRenameEpilogue entry %08lx...%08lx on handle %08lx\n",
  5245. RxContext, SrvOpen, smbSrvOpen->hfShadow ));
  5246. if (*Status != STATUS_SUCCESS) {
  5247. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue exit(status) w/o deleteing -> %08lx %08lx\n", RxContext, Status ));
  5248. goto FINALLY;
  5249. }
  5250. uRenameFlags = 0;
  5251. EnterShadowCritRx(RxContext);
  5252. EnteredCriticalSection = TRUE;
  5253. //if we don't have a shadow...go look for one
  5254. if (smbFcb->hShadow == 0) {
  5255. LocalStatus = MRxSmbCscObtainShadowHandles(
  5256. RxContext,
  5257. Status,
  5258. &Find32,
  5259. NULL,
  5260. CREATESHADOW_CONTROL_NOCREATE|
  5261. ((capFobx->Flags & FOBX_FLAG_DFS_OPEN)?CREATESHADOW_CONTROL_STRIP_SHARE_NAME:0),
  5262. Disconnected);
  5263. if (LocalStatus != STATUS_SUCCESS) {
  5264. RxDbgTrace(0, Dbg,
  5265. ("MRxSmbCscRenameEpilogue couldn't get handles-> %08lx %08lx\n",RxContext,LocalStatus ));
  5266. goto FINALLY;
  5267. }
  5268. if (smbFcb->hShadow == 0) {
  5269. RxDbgTrace(0, Dbg,
  5270. ("MRxSmbCscRenameEpilogue no handles-> %08lx %08lx\n",RxContext,LocalStatus ));
  5271. goto FINALLY;
  5272. }
  5273. }
  5274. if (GetShadowInfo(
  5275. smbFcb->hParentDir,
  5276. smbFcb->hShadow,
  5277. &Find32,
  5278. &uShadowStatusFrom, &sOIFrom) < SRET_OK) {
  5279. LocalStatus = STATUS_NO_SUCH_FILE;
  5280. goto FINALLY;
  5281. }
  5282. hShadow = smbFcb->hShadow;
  5283. hDir = smbFcb->hParentDir;
  5284. if (!hShadow ||
  5285. !IsShadowVisible(
  5286. Disconnected,
  5287. Find32.dwFileAttributes,
  5288. uShadowStatusFrom)) {
  5289. RxDbgTrace(0, Dbg,
  5290. ("MRxSmbCscRenameEpilogue no shadoworinvisible-> %08lx %08lx\n",RxContext,LocalStatus ));
  5291. LocalStatus = STATUS_NO_SUCH_FILE;
  5292. goto FINALLY;
  5293. }
  5294. // DbgPrint("Renaming %ws ", Find32.cFileName);
  5295. RxLog(("Renaming hDir=%x hShadow=%x %ws ", hDir, hShadow, Find32.cFileName));
  5296. fFile = IsFile(Find32.dwFileAttributes);
  5297. // NB begin temp use of uRenameFlags
  5298. uRenameFlags = (wstrlen(Find32.cFileName)+1)*sizeof(USHORT);
  5299. lpcFileNameTuna = AllocMem(uRenameFlags);
  5300. lpcAlternateFileNameTuna = AllocMem(sizeof(Find32.cAlternateFileName));
  5301. if (!lpcFileNameTuna || ! lpcAlternateFileNameTuna) {
  5302. LocalStatus = STATUS_INSUFFICIENT_RESOURCES;
  5303. goto FINALLY; //bailout;
  5304. }
  5305. // save the alternate filename for tunnelling purposes
  5306. memcpy(lpcAlternateFileNameTuna,
  5307. Find32.cAlternateFileName,
  5308. sizeof(Find32.cAlternateFileName));
  5309. memcpy(lpcFileNameTuna, Find32.cFileName, uRenameFlags);
  5310. // end temp use of uRenameFlags
  5311. uRenameFlags = 0;
  5312. // Save the last write time
  5313. ftLWTime = Find32.ftLastWriteTime;
  5314. if (Disconnected) {
  5315. // if this is a file and we are trying to delete it
  5316. // without permissions, then bail
  5317. if (fFile &&
  5318. !(FILE_WRITE_DATA & smbSrvOpen->MaximalAccessRights)&&
  5319. !(FILE_WRITE_DATA & smbSrvOpen->GuestMaximalAccessRights))
  5320. {
  5321. LocalStatus = STATUS_ACCESS_DENIED;
  5322. RxLog(("No rights to rename %x in dcon Status=%x\n", smbFcb->hShadow, LocalStatus));
  5323. HookKdPrint(BADERRORS, ("No rights to rename %x in dcon Status=%x\n", smbFcb->hShadow, LocalStatus));
  5324. goto FINALLY; //bailout;
  5325. }
  5326. // In disconnected state we don't allow directory renames on
  5327. // remotely obtained directories
  5328. // This is consistent with not allowing delete on these directories
  5329. if (!fFile && !mShadowLocallyCreated(uShadowStatusFrom)) {
  5330. LocalStatus = STATUS_ONLY_IF_CONNECTED;
  5331. goto FINALLY; //bailout;
  5332. }
  5333. if (!mShadowLocallyCreated(uShadowStatusFrom)) { // remote object
  5334. // Ask RenameShadow to mark the source as deleted, it will have to
  5335. // be reintegrated later
  5336. uRenameFlags |= RNMFLGS_MARK_SOURCE_DELETED;
  5337. // if this is the copy of the original,
  5338. // ie. it has not gone through delete/create cycles,
  5339. // we need to save it's value in the new shadow structure
  5340. // so that while reintegrating, we can do rename operations
  5341. // before merging.
  5342. // The SHADOW_REUSE flag is set in CreateShadowFromPath, and
  5343. // in his routine while dealing with hShadowTo
  5344. // when the shadow of a remote object that has been marked deleted
  5345. // is reused during disconnected operation.
  5346. // When a reused object is renamed, the new object is NOT a
  5347. // true alias of the original object on the Share
  5348. if (!mShadowReused(uShadowStatusFrom)) {
  5349. // not been reused, give his rename alias, if any, to the new one
  5350. uRenameFlags |= RNMFLGS_SAVE_ALIAS;
  5351. }
  5352. }
  5353. else
  5354. { // locally created
  5355. // This is a locally created shadow that is being renamed
  5356. // we wan't to retain it's alias, if any, so we know if it
  5357. // was renamed from a remote object or was created locally
  5358. uRenameFlags |= RNMFLGS_RETAIN_ALIAS;
  5359. }
  5360. }
  5361. // Let us create the directory hierarchy in which the file/directory
  5362. // is to be renamed
  5363. // ASSERT((RenameInformation->FileName[0] == L'\\') || (RenameInformation->FileName[0] == L':'))
  5364. RenameName.Buffer = &RenameInformation->FileName[0];
  5365. RenameName.Length = (USHORT)RenameInformation->FileNameLength;
  5366. if (smbFcb->uniDfsPrefix.Buffer)
  5367. {
  5368. UNICODE_STRING DfsName;
  5369. if (capFobx->Flags & FOBX_FLAG_DFS_OPEN)
  5370. {
  5371. LocalStatus = CscDfsStripLeadingServerShare(&RenameName);
  5372. if (LocalStatus != STATUS_SUCCESS)
  5373. {
  5374. RenameName.Buffer = NULL;
  5375. goto FINALLY;
  5376. }
  5377. fAlreadyStripped = TRUE;
  5378. }
  5379. if(CscDfsDoDfsNameMapping(&smbFcb->uniDfsPrefix,
  5380. &smbFcb->uniActualPrefix,
  5381. &RenameName,
  5382. TRUE, //fResolvedNameToDFSName
  5383. &DfsName
  5384. ) != STATUS_SUCCESS)
  5385. {
  5386. LocalStatus = STATUS_INSUFFICIENT_RESOURCES;
  5387. RenameName.Buffer = NULL;
  5388. goto FINALLY;
  5389. }
  5390. RenameName = DfsName;
  5391. }
  5392. RtlZeroMemory(&CscSmbFcb, sizeof(CscSmbFcb));
  5393. CscSmbFcb.MinimalCscSmbFcb.sCscRootInfo = smbFcb->sCscRootInfo;
  5394. MRxSmbCscCreateShadowFromPath(
  5395. &RenameName,
  5396. &CscSmbFcb.MinimalCscSmbFcb.sCscRootInfo,
  5397. &Find32,
  5398. NULL,
  5399. (CREATESHADOW_CONTROL_NOREVERSELOOKUP |
  5400. CREATESHADOW_CONTROL_NOCREATELEAF|
  5401. ((!fAlreadyStripped && (capFobx->Flags & FOBX_FLAG_DFS_OPEN))?CREATESHADOW_CONTROL_STRIP_SHARE_NAME:0)
  5402. ),
  5403. &CscSmbFcb.MinimalCscSmbFcb,
  5404. RxContext,
  5405. Disconnected,
  5406. &ulInheritedHintFlags
  5407. );
  5408. hDirTo = CscSmbFcb.MinimalCscSmbFcb.hParentDir;
  5409. hShadowTo = CscSmbFcb.MinimalCscSmbFcb.hShadow;
  5410. uShadowStatusTo = CscSmbFcb.MinimalCscSmbFcb.ShadowStatus;
  5411. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...000=%08lx %08lx %08lx\n",
  5412. hDirTo,hShadowTo,uShadowStatusTo));
  5413. if (!hDirTo) {
  5414. HookKdPrint(BADERRORS, ("Cannot rename root %x in dcon \n", hShadowTo));
  5415. LocalStatus = STATUS_ACCESS_DENIED;
  5416. goto FINALLY; //bailout;
  5417. }
  5418. //
  5419. // allocate a buffer that's the right size: one extra char is
  5420. // for a trailing null....this buffer is used to get the tunnelling
  5421. // information
  5422. LastComponentName.Length = CscSmbFcb.MinimalCscSmbFcb.LastComponentLength;
  5423. LastComponentName.Buffer = (PWCHAR)RxAllocatePoolWithTag(
  5424. PagedPool,
  5425. LastComponentName.Length + (1 * sizeof(WCHAR)),
  5426. RX_MISC_POOLTAG);
  5427. if (LastComponentName.Buffer==NULL) {
  5428. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue -> noalloc\n"));
  5429. } else {
  5430. PWCHAR t;
  5431. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...lastcomponentinhex=%08lx\n",LastComponentName.Buffer));
  5432. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...renamebuffer=%08lx\n",RenameName.Buffer));
  5433. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...lcofff=%08lx,%08lx\n",
  5434. CscSmbFcb.MinimalCscSmbFcb.LastComponentOffset,CscSmbFcb.MinimalCscSmbFcb.LastComponentLength));
  5435. RtlCopyMemory(
  5436. LastComponentName.Buffer,
  5437. RenameName.Buffer + CscSmbFcb.MinimalCscSmbFcb.LastComponentOffset,
  5438. LastComponentName.Length);
  5439. t = (PWCHAR)( ((PBYTE)(LastComponentName.Buffer)) + LastComponentName.Length );
  5440. *t = 0;
  5441. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...lastcomponent=%ws (%08lx)\n",
  5442. LastComponentName.Buffer,LastComponentName.Buffer));
  5443. }
  5444. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 1111=(%08lx)\n", hDirTo));
  5445. // Do we have a destination shadow for rename?
  5446. if (hShadowTo) {
  5447. BOOLEAN fDestShadowVisible = FALSE;
  5448. if (IsShadowVisible(
  5449. Disconnected,
  5450. Find32.dwFileAttributes,
  5451. uShadowStatusTo))
  5452. {
  5453. fDestShadowVisible = TRUE;
  5454. }
  5455. // If it is visible and this is not a replace_if_exists operation
  5456. // then this is an illegal rename
  5457. if (fDestShadowVisible && !RxContext->Info.ReplaceIfExists)
  5458. {
  5459. LocalStatus = STATUS_OBJECT_NAME_COLLISION;
  5460. goto FINALLY; //bailout;
  5461. }
  5462. if (!Disconnected) {// connected
  5463. if (!RxContext->Info.ReplaceIfExists)
  5464. {
  5465. // When we are connected, we are doing rename in caching mode
  5466. // If the renameTo exists and needs reintegration,
  5467. // we protect it by nuking the renameFrom and succeeding
  5468. // the rename
  5469. KdPrint(("SfnRename:unary op %x, \r\n", hShadow));
  5470. ASSERT(mShadowOutofSync(uShadowStatusTo));
  5471. ASSERT(!fFile || !mShadowOutofSync(uShadowStatusFrom));
  5472. ASSERT(!mShadowBusy(uShadowStatusFrom));
  5473. if(DeleteShadow(hDir, hShadow) < SRET_OK) {
  5474. LocalStatus = STATUS_UNSUCCESSFUL;
  5475. } else {
  5476. iRet = 0;
  5477. smbFcb->hShadow = 0;
  5478. }
  5479. goto FINALLY; //bailout;
  5480. }
  5481. }
  5482. // Nuke the renameTo shadow
  5483. if(DeleteShadow(hDirTo, hShadowTo) < SRET_OK) {
  5484. LocalStatus = STATUS_UNSUCCESSFUL;
  5485. goto FINALLY; //bailout;
  5486. } else {
  5487. //hunt up the fcb, if any and zero the hshadow
  5488. PFDB smbLookedUpFdbTo;
  5489. PMRX_SMB_FCB smbFcbTo;
  5490. smbLookedUpFdbTo = PFindFdbFromHShadow(hShadowTo);
  5491. if (smbLookedUpFdbTo!=NULL) {
  5492. smbFcbTo = MRxSmbCscRecoverMrxFcbFromFdb(smbLookedUpFdbTo);
  5493. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue lookups -> %08lx %08lx %08lx\n",
  5494. smbFcbTo,
  5495. smbLookedUpFdbTo,
  5496. hShadowTo ));
  5497. ASSERT((smbFcbTo->hShadow == hShadowTo)||(smbFcbTo->hShadowRenamed == hShadowTo));
  5498. smbFcbTo->hShadow = 0;
  5499. }
  5500. }
  5501. if (Disconnected && !mShadowLocallyCreated(uShadowStatusTo)) {
  5502. // When the renameTo is a remote object
  5503. // it is possible for two remote objects to get crosslinked, ie. be each others
  5504. // aliases. The reintegrator needs to deal with this case.
  5505. // Cleanup the locally created status of the hShadowFrom if it
  5506. // did exist because it is being renamed to a remote object
  5507. mClearBits(uShadowStatusFrom, SHADOW_LOCALLY_CREATED);
  5508. // Mark the original object as having been reused so a rename
  5509. // on it will not point back to this object.
  5510. // Also set all the CHANGE attributes to indicate that this is a
  5511. // spanking new object. Actually doesn't SHADOW_REUSED flag do that
  5512. // already?
  5513. mSetBits(uShadowStatusFrom, SHADOW_REUSED|SHADOW_DIRTY|SHADOW_ATTRIB_CHANGE);
  5514. }
  5515. }
  5516. if (!hShadowTo)
  5517. {
  5518. if (Disconnected) {
  5519. // we don't have a renameTo. If we are in disconnected state, let us
  5520. // mark it as locally created, which it is.
  5521. mSetBits(uShadowStatusFrom, SHADOW_LOCALLY_CREATED);
  5522. }
  5523. }
  5524. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 3333= (%08lx)\n", hDirTo));
  5525. ASSERT(hDir && hShadow && hDirTo);
  5526. if (!Disconnected) {// connected
  5527. //get the names and attributes from the Share
  5528. MRxSmbGetFileInfoFromServer(RxContext,&RenameName,&Find32,NULL,NULL);
  5529. } else {// disconnected
  5530. if (hShadowTo) {
  5531. // Find32 contains the orgtime of hShadowTo
  5532. // we tell the RenameShadow routine to reuse it.
  5533. Find32.ftLastWriteTime = ftLWTime;
  5534. uRenameFlags |= RNMFLGS_USE_FIND32_TIMESTAMPS;
  5535. } else {
  5536. Find32.cFileName[0] = 0;
  5537. Find32.cAlternateFileName[0] = 0;
  5538. }
  5539. }
  5540. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 4444= (%08lx)\n", hDirTo));
  5541. if (!fFile) {
  5542. // We set the reference priority of the directories to their level
  5543. // in the hierarchiy starting 1 for the root. That way we
  5544. // walk the PQ in reverse priority order for directories. to create
  5545. // all the direcotry objects hierarchically. But with hints
  5546. // this is going to be a problem.
  5547. Find32.dwReserved0 = GetPathLevelFromUnicodeString(&RenameName);
  5548. }
  5549. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 5555= (%08lx)\n", hDirTo));
  5550. // If there is any tunnelling info then use it to create this guy
  5551. if (LastComponentName.Buffer &&
  5552. (TunnelType = RetrieveTunnelInfo(
  5553. hDirTo, // directory where the renames are happenieng
  5554. LastComponentName.Buffer, // potential SFN
  5555. (Disconnected)? &Find32:NULL, // get LFN only when disconnected
  5556. &sOI))) {
  5557. lpOI = &sOI;
  5558. }
  5559. if (Disconnected) {
  5560. //muck with the names.......
  5561. switch (TunnelType) {
  5562. case TUNNEL_RET_SHORTNAME_TUNNEL:
  5563. //we tunneled on the shortname.....retrievetunnelinfo did the copies....
  5564. break;
  5565. case TUNNEL_RET_NOTFOUND:
  5566. //no tunnel. use the name passed as the long name
  5567. RtlCopyMemory( &Find32.cFileName[0],
  5568. LastComponentName.Buffer,
  5569. LastComponentName.Length + sizeof(WCHAR) );
  5570. //lack of break intentional;
  5571. case TUNNEL_RET_LONGNAME_TUNNEL:
  5572. //if we tunneled on the longname....retrievetunnelinfo did the copies....
  5573. //but we may still need a shortname
  5574. MRxSmbCscGenerate83NameAsNeeded(hDirTo,
  5575. &Find32.cFileName[0],
  5576. &Find32.cAlternateFileName[0]);
  5577. break;
  5578. }
  5579. }
  5580. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 6666=(%08lx)\n", hDirTo));
  5581. if (RenameShadow(
  5582. hDir,
  5583. hShadow,
  5584. hDirTo,
  5585. &Find32,
  5586. uShadowStatusFrom,
  5587. lpOI,
  5588. uRenameFlags,
  5589. &hShadowTo) < SRET_OK)
  5590. {
  5591. LocalStatus = STATUS_UNSUCCESSFUL;
  5592. goto FINALLY; //bailout;
  5593. }
  5594. smbFcb->hShadow = 0;
  5595. ASSERT(hShadowTo);
  5596. smbFcb->hShadowRenamed = hShadowTo;
  5597. smbFcb->hParentDirRenamed = hDirTo;
  5598. fDoTunneling = TRUE;
  5599. RxDbgTrace(0, Dbg, ("MRxSmbCscRenameEpilogue...hdirto 7777= (%08lx)\n", hDirTo));
  5600. if (Disconnected) {
  5601. // Mark it on the Share, so reintegration can proceed
  5602. MarkShareDirty(&smbFcb->sCscRootInfo.ShareStatus,
  5603. (ULONG)(smbFcb->sCscRootInfo.hShare));
  5604. }
  5605. if (mPinInheritFlags(ulInheritedHintFlags))
  5606. {
  5607. RxDbgTrace(0, Dbg, ("RenameEpilogue: Setting inherited hintflags on hShadow=%x \n", hShadowTo));
  5608. if(GetShadowInfo(hDirTo, hShadowTo, NULL, NULL, &sOI) >= SRET_OK)
  5609. {
  5610. if (ulInheritedHintFlags & FLAG_CSC_HINT_PIN_INHERIT_USER) {
  5611. sOI.ulHintFlags |= FLAG_CSC_HINT_PIN_USER;
  5612. }
  5613. if (ulInheritedHintFlags & FLAG_CSC_HINT_PIN_INHERIT_SYSTEM) {
  5614. sOI.ulHintFlags |= FLAG_CSC_HINT_PIN_SYSTEM;
  5615. }
  5616. SetShadowInfoEx(hDirTo, hShadowTo, NULL, 0, SHADOW_FLAGS_OR, &sOI, NULL, NULL);
  5617. }
  5618. }
  5619. iRet = 0;
  5620. // This effectively bumps up the version number of the current CSC namespace
  5621. // if this share is a remoteboot share and is being merged, then the reintegration code will
  5622. // backoff
  5623. IncrementActivityCountForShare(smbFcb->sCscRootInfo.hShare);
  5624. FINALLY:
  5625. if (fDoTunneling) {
  5626. // We succeeded the rename, let use keep the tunneling info for the source
  5627. InsertTunnelInfo(
  5628. hDir,
  5629. lpcFileNameTuna,
  5630. lpcAlternateFileNameTuna,
  5631. &sOIFrom);
  5632. }
  5633. if (EnteredCriticalSection) {
  5634. LeaveShadowCritRx(RxContext);
  5635. }
  5636. if (LastComponentName.Buffer) {
  5637. RxFreePool(LastComponentName.Buffer);
  5638. }
  5639. if (lpcFileNameTuna) {
  5640. FreeMem(lpcFileNameTuna);
  5641. }
  5642. if (lpcAlternateFileNameTuna) {
  5643. FreeMem(lpcAlternateFileNameTuna);
  5644. }
  5645. if (Disconnected) {
  5646. if (iRet!=0) {
  5647. *Status = LocalStatus;
  5648. }
  5649. else
  5650. {
  5651. // when disconnected, report the change
  5652. // we can be smart about this and report only once if this is not across
  5653. // directories
  5654. FsRtlNotifyFullReportChange(
  5655. pNetRootEntry->NetRoot.pNotifySync,
  5656. &pNetRootEntry->NetRoot.DirNotifyList,
  5657. (PSTRING)GET_ALREADY_PREFIXED_NAME(NULL,capFcb),
  5658. (USHORT)(GET_ALREADY_PREFIXED_NAME(NULL, capFcb)->Length -
  5659. smbFcb->MinimalCscSmbFcb.LastComponentLength),
  5660. NULL,
  5661. NULL,
  5662. (fFile)?FILE_NOTIFY_CHANGE_FILE_NAME:FILE_NOTIFY_CHANGE_DIR_NAME,
  5663. FILE_ACTION_RENAMED_OLD_NAME,
  5664. NULL);
  5665. // upcase it so change notification will get it right
  5666. UniToUpper(RenameName.Buffer, RenameName.Buffer, RenameName.Length);
  5667. FsRtlNotifyFullReportChange(
  5668. pNetRootEntry->NetRoot.pNotifySync,
  5669. &pNetRootEntry->NetRoot.DirNotifyList,
  5670. (PSTRING)&RenameName,
  5671. (USHORT)(RenameName.Length -
  5672. CscSmbFcb.MinimalCscSmbFcb.LastComponentLength),
  5673. NULL,
  5674. NULL,
  5675. (fFile)?FILE_NOTIFY_CHANGE_FILE_NAME:FILE_NOTIFY_CHANGE_DIR_NAME,
  5676. FILE_ACTION_RENAMED_NEW_NAME,
  5677. NULL);
  5678. }
  5679. }
  5680. if (smbFcb->uniDfsPrefix.Buffer && RenameName.Buffer)
  5681. {
  5682. RxFreePool(RenameName.Buffer);
  5683. }
  5684. // DbgPrint("to %ws\n", Find32.cFileName);
  5685. RxLog(("to hDirTo=%x hShadowTo=%x %ws uShadowStatusFrom=%x\n", hDirTo, hShadowTo, Find32.cFileName, uShadowStatusFrom));
  5686. RxLog(("Status=%x \n\n", *Status));
  5687. RxDbgTrace(-1, Dbg, ("MRxSmbCscRenameEpilogue exit-> %08lx %08lx\n", RxContext, *Status ));
  5688. return;
  5689. }
  5690. VOID
  5691. MRxSmbCscCloseShadowHandle (
  5692. IN OUT PRX_CONTEXT RxContext
  5693. )
  5694. /*++
  5695. Routine Description:
  5696. This routine closes the filehandle opened for CSC.
  5697. Arguments:
  5698. RxContext - the RDBSS context
  5699. Return Value:
  5700. NTSTATUS - The return status for the operation
  5701. Notes:
  5702. --*/
  5703. {
  5704. RxCaptureFcb;RxCaptureFobx;
  5705. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  5706. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  5707. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  5708. // DbgPrint("MRxSmbCscCloseShadowHandle %x\n", smbSrvOpen->hfShadow);
  5709. ASSERT(smbSrvOpen->hfShadow != 0);
  5710. CloseFileLocal((CSCHFILE)(smbSrvOpen->hfShadow));
  5711. smbSrvOpen->hfShadow = 0;
  5712. if (smbSrvOpen->Flags & SMB_SRVOPEN_FLAG_LOCAL_OPEN)
  5713. {
  5714. ASSERT(smbFcb->cntLocalOpens);
  5715. smbFcb->cntLocalOpens--;
  5716. }
  5717. RxDbgTrace(0, Dbg, ("MRxSmbCscCloseShadowHandle\n"));
  5718. }
  5719. NTSTATUS
  5720. MRxSmbCscFixupFindFirst (
  5721. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  5722. )
  5723. /*++
  5724. Routine Description:
  5725. This routine is called from the simplesyncT2 builder/sender to fixup
  5726. the t2 request before it's sent. the deal is that the parameters section
  5727. has to be built up in part but i don't want to preallocate. so, i pass in
  5728. a dummy (but valid pointer) and then drop in the actual parameters
  5729. here.
  5730. Arguments:
  5731. Return Value:
  5732. Notes:
  5733. We will use the smbbuf for everything here. First, we use it for sending
  5734. and receiving. at the end of receiving, the FILE_BOTH_INFORMATION will be
  5735. in the buffer and this will be recomposed into a w32_find buffer in the
  5736. same buffer. if we find for any reason that we can't do this (buffer too
  5737. small, send/rcv doesn't work, whatever) then we'll nuke the shadow and it
  5738. will have to be reloaded.
  5739. --*/
  5740. {
  5741. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  5742. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  5743. PSMB_HEADER SmbHeader = (PSMB_HEADER)StufferState->BufferBase;
  5744. PREQ_TRANSACTION TransactRequest = (PREQ_TRANSACTION)(SmbHeader+1);
  5745. ULONG ParameterCount = SmbGetUshort(&TransactRequest->ParameterCount);
  5746. ULONG ParameterOffset = SmbGetUshort(&TransactRequest->ParameterOffset);
  5747. PBYTE Parameters = ((PBYTE)(SmbHeader))+ParameterOffset;
  5748. REQ_FIND_FIRST2 FindFirst;
  5749. NTSTATUS Status=STATUS_SUCCESS;
  5750. PSMBCE_SERVER pServer = NULL;
  5751. RxDbgTrace(0, Dbg, ("MRxSmbCscFixupFindFirst %08lx %08lx %08lx %08lx\n",
  5752. OrdinaryExchange,ParameterCount,ParameterOffset,Parameters));
  5753. // SearchAttributes is hardcoded to the magic number 0x16
  5754. FindFirst.SearchAttributes = (SMB_FILE_ATTRIBUTE_DIRECTORY |
  5755. SMB_FILE_ATTRIBUTE_SYSTEM |
  5756. SMB_FILE_ATTRIBUTE_HIDDEN);
  5757. FindFirst.SearchCount = 1;
  5758. FindFirst.Flags = (SMB_FIND_CLOSE_AFTER_REQUEST |
  5759. SMB_FIND_CLOSE_AT_EOS |
  5760. SMB_FIND_RETURN_RESUME_KEYS);
  5761. FindFirst.InformationLevel = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
  5762. FindFirst.SearchStorageType = 0;
  5763. RtlCopyMemory (
  5764. Parameters,
  5765. &FindFirst,
  5766. FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0]));
  5767. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  5768. ASSERT(pServer);
  5769. if (FlagOn(pServer->DialectFlags,DF_UNICODE))
  5770. {
  5771. ASSERT(FlagOn(SmbHeader->Flags2,SMB_FLAGS2_UNICODE));
  5772. RtlCopyMemory(
  5773. Parameters + FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0]),
  5774. OrdinaryExchange->pPathArgument1->Buffer,
  5775. OrdinaryExchange->pPathArgument1->Length);
  5776. SmbPutUshort(
  5777. (Parameters +
  5778. FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0]) +
  5779. OrdinaryExchange->pPathArgument1->Length),
  5780. 0); //traiing null
  5781. }
  5782. else
  5783. {
  5784. OEM_STRING OemString;
  5785. OemString.Length =
  5786. OemString.MaximumLength =
  5787. (USHORT)( StufferState->BufferLimit - Parameters - sizeof(CHAR));
  5788. OemString.Buffer = (Parameters + FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0]));
  5789. if (FlagOn(SmbHeader->Flags,SMB_FLAGS_CASE_INSENSITIVE) &&
  5790. !FlagOn(SmbHeader->Flags2,SMB_FLAGS2_KNOWS_LONG_NAMES)) {
  5791. Status = RtlUpcaseUnicodeStringToOemString(
  5792. &OemString,
  5793. OrdinaryExchange->pPathArgument1,
  5794. FALSE);
  5795. } else {
  5796. Status = RtlUnicodeStringToOemString(
  5797. &OemString,
  5798. OrdinaryExchange->pPathArgument1,
  5799. FALSE);
  5800. }
  5801. if (!NT_SUCCESS(Status)) {
  5802. ASSERT(!"BufferOverrun");
  5803. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  5804. }
  5805. OemString.Length = (USHORT)RtlxUnicodeStringToOemSize(OrdinaryExchange->pPathArgument1);
  5806. ASSERT(OemString.Length);
  5807. *(Parameters + FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0])+OemString.Length-1) = 0;
  5808. }
  5809. return(Status);
  5810. }
  5811. typedef FILE_BOTH_DIR_INFORMATION SMB_UNALIGNED *MRXSMBCSC_FILE_BOTH_DIR_INFORMATION;
  5812. VOID
  5813. MRxSmbCscLocateAndFillFind32WithinSmbbuf(
  5814. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  5815. )
  5816. /*++
  5817. Routine Description:
  5818. When this routine is called, the associated smbbuf contains a findfirst
  5819. response with the FILE_BOTH_INFORMATION aboard. This routine first locates
  5820. a position in the smbbuf to hold a find32. Then, the information is
  5821. converted from the NT format for use with the shadow routines.
  5822. Arguments:
  5823. Return Value:
  5824. Find32 - The ptr to the find32 (actually, the smbbuf!)
  5825. Notes:
  5826. --*/
  5827. {
  5828. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  5829. PSMB_HEADER SmbHeader = (PSMB_HEADER)StufferState->BufferBase;
  5830. PRESP_TRANSACTION TransactResponse = (PRESP_TRANSACTION)(SmbHeader+1);
  5831. ULONG DataOffset,FileNameLength,ShortNameLength;
  5832. _WIN32_FIND_DATA *Find32;
  5833. PBYTE AlternateName;
  5834. MRXSMBCSC_FILE_BOTH_DIR_INFORMATION BothDirInfo;
  5835. PSMBCE_SERVER pServer = NULL;
  5836. //first, we have to get a potentially unaligned ptr to the bothdirinfo
  5837. DataOffset = SmbGetUshort(&TransactResponse->DataOffset);
  5838. AlternateName = ((PBYTE)SmbHeader);
  5839. BothDirInfo = (MRXSMBCSC_FILE_BOTH_DIR_INFORMATION)(((PBYTE)SmbHeader)+DataOffset);
  5840. FileNameLength = SmbGetUlong(&BothDirInfo->FileNameLength);
  5841. ShortNameLength = BothDirInfo->ShortNameLength;
  5842. RxDbgTrace(0, Dbg, ("MRxSmbCscLocateAndFillFind32WithinSmbbuf offset=%08lx %08lx %08lx\n",
  5843. DataOffset,FileNameLength,ShortNameLength));
  5844. //save the alternate name info in the very beginning of the buffer..that
  5845. //way, the copy of the full name will not destroy it
  5846. if (ShortNameLength != 0) {
  5847. RtlCopyMemory(
  5848. AlternateName,
  5849. &BothDirInfo->ShortName[0],
  5850. ShortNameLength);
  5851. }
  5852. Find32 = (_WIN32_FIND_DATA *)(AlternateName + LongAlign(sizeof(Find32->cAlternateFileName)));
  5853. Find32->dwFileAttributes = SmbGetUlong(&BothDirInfo->FileAttributes);
  5854. Find32->ftCreationTime.dwLowDateTime = SmbGetUlong(&BothDirInfo->CreationTime.LowPart);
  5855. Find32->ftCreationTime.dwHighDateTime = SmbGetUlong(&BothDirInfo->CreationTime.HighPart);
  5856. Find32->ftLastAccessTime.dwLowDateTime = SmbGetUlong(&BothDirInfo->LastAccessTime.LowPart);
  5857. Find32->ftLastAccessTime.dwHighDateTime = SmbGetUlong(&BothDirInfo->LastAccessTime.HighPart);
  5858. Find32->ftLastWriteTime.dwLowDateTime = SmbGetUlong(&BothDirInfo->LastWriteTime.LowPart);
  5859. Find32->ftLastWriteTime.dwHighDateTime = SmbGetUlong(&BothDirInfo->LastWriteTime.HighPart);
  5860. Find32->nFileSizeLow = SmbGetUlong(&BothDirInfo->EndOfFile.LowPart);
  5861. Find32->nFileSizeHigh = SmbGetUlong(&BothDirInfo->EndOfFile.HighPart);
  5862. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  5863. ASSERT(pServer);
  5864. if (FlagOn(pServer->DialectFlags,DF_UNICODE))
  5865. {
  5866. //copy the full name....don't forget the NULL
  5867. RtlCopyMemory (
  5868. &Find32->cFileName[0],
  5869. &BothDirInfo->FileName[0],
  5870. FileNameLength );
  5871. Find32->cFileName[FileNameLength/sizeof(WCHAR)] = 0;
  5872. //finally, copy the shortname...don't forget the null
  5873. RtlCopyMemory(
  5874. &Find32->cAlternateFileName[0],
  5875. AlternateName,
  5876. ShortNameLength );
  5877. Find32->cAlternateFileName[ShortNameLength/sizeof(WCHAR)] = 0;
  5878. }
  5879. else
  5880. {
  5881. UNICODE_STRING strUni;
  5882. OEM_STRING strOem;
  5883. NTSTATUS Status;
  5884. strOem.Length = strOem.MaximumLength = (USHORT)FileNameLength;
  5885. strOem.Buffer = (PBYTE)&BothDirInfo->FileName[0];
  5886. strUni.Length = (USHORT)RtlxOemStringToUnicodeSize(&strOem);
  5887. strUni.MaximumLength = (USHORT)sizeof(Find32->cFileName);
  5888. strUni.Buffer = Find32->cFileName;
  5889. Status = RtlOemStringToUnicodeString(&strUni, &strOem, FALSE);
  5890. ASSERT(Status == STATUS_SUCCESS);
  5891. Find32->cFileName[strUni.Length/sizeof(WCHAR)];
  5892. strOem.Length = strOem.MaximumLength = (USHORT)ShortNameLength;
  5893. strOem.Buffer = AlternateName;
  5894. strUni.Length = (USHORT)RtlxOemStringToUnicodeSize(&strOem);
  5895. strUni.MaximumLength = (USHORT)sizeof(Find32->cAlternateFileName);
  5896. strUni.Buffer = Find32->cAlternateFileName;
  5897. Status = RtlOemStringToUnicodeString(&strUni, &strOem, FALSE);
  5898. if (Status != STATUS_SUCCESS)
  5899. {
  5900. DbgPrint("oem=%x, uni=%x Status=%x\n", &strUni, &strOem, Status);
  5901. ASSERT(FALSE);
  5902. }
  5903. Find32->cAlternateFileName[strUni.Length/sizeof(WCHAR)];
  5904. ASSERT(Find32->cFileName[0]);
  5905. }
  5906. OrdinaryExchange->Find32WithinSmbbuf = Find32;
  5907. RxDbgTrace(0, Dbg, ("MRxSmbCscLocateAndFillFind32WithinSmbbuf size,name=%08lx %ws\n",
  5908. Find32->nFileSizeLow, &Find32->cFileName[0]));
  5909. return;
  5910. }
  5911. NTSTATUS
  5912. MRxSmbCscGetFileInfoFromServerWithinExchange (
  5913. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  5914. PUNICODE_STRING FileName OPTIONAL
  5915. )
  5916. /*++
  5917. Routine Description:
  5918. This routine reads information about a file; it may have been locally
  5919. modified or it may be in the process of having a showdow created. in any
  5920. case, the info is returned as a pointer to a Find32 structure. The find32
  5921. structure is contained within the smbbuf of the exchange.
  5922. Arguments:
  5923. RxContext - the RDBSS context
  5924. Return Value:
  5925. NTSTATUS - The return status for the operation
  5926. Notes:
  5927. We will use the smbbuf for everything here. First, we use it for sending
  5928. and receiving. at the end of receiving, the FILE_BOTH_INFORMATION will be
  5929. in the buffer and this will be recomposed into a w32_find buffer in the
  5930. same buffer. if we find for any reason that we can't do this (buffer too
  5931. small, send/rcv doesn't work, whatever) then we'll nuke the shadow and it
  5932. will have to be reloaded.
  5933. --*/
  5934. {
  5935. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  5936. ULONG ParameterLength, TotalLength;
  5937. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  5938. if (FileName!=NULL) {
  5939. OrdinaryExchange->pPathArgument1 = FileName; //so it can be found later
  5940. } else {
  5941. ASSERT(OrdinaryExchange->pPathArgument1 != NULL);
  5942. FileName = OrdinaryExchange->pPathArgument1;
  5943. }
  5944. ParameterLength = FileName->Length + sizeof(WCHAR);
  5945. ParameterLength += FIELD_OFFSET(REQ_FIND_FIRST2,Buffer[0]);
  5946. TotalLength = sizeof(SMB_HEADER) + FIELD_OFFSET(REQ_TRANSACTION,Buffer[0]); //basic
  5947. TotalLength += sizeof(WORD); //bytecount
  5948. TotalLength = LongAlign(TotalLength); //move past pad
  5949. TotalLength += LongAlign(ParameterLength);
  5950. RxDbgTrace(+1, Dbg, ("MRxSmbCscGetFileInfoFromServerWithinExchange %08lx %08lx %08lx\n",
  5951. RxContext,TotalLength,ParameterLength));
  5952. if (TotalLength > OrdinaryExchange->SmbBufSize) {
  5953. goto FINALLY;
  5954. }
  5955. //note that the parameter buffer is not the actual parameters BUT
  5956. //it is a valid buffer. CODE.IMPROVEMENT perhaps the called routine
  5957. //should take cognizance of the passed fixup routine and not require
  5958. //a valid param buffer and not do the copy.
  5959. Status = __MRxSmbSimpleSyncTransact2(
  5960. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  5961. SMBPSE_OETYPE_T2_FOR_ONE_FILE_DIRCTRL,
  5962. TRANS2_FIND_FIRST2,
  5963. StufferState->ActualBufferBase,ParameterLength,
  5964. NULL,0,
  5965. MRxSmbCscFixupFindFirst
  5966. );
  5967. if (Status!=STATUS_SUCCESS) {
  5968. goto FINALLY;
  5969. }
  5970. MRxSmbCscLocateAndFillFind32WithinSmbbuf(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  5971. FINALLY:
  5972. RxDbgTrace(-1, Dbg, ("MRxSmbCscGetFileInfoFromServerWithinExchange %08lx %08lx\n",
  5973. RxContext,Status));
  5974. return(Status);
  5975. }
  5976. VOID
  5977. MRxSmbCscUpdateShadowFromClose (
  5978. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  5979. )
  5980. /*++
  5981. Routine Description:
  5982. This routine updates the shadow information after a close.
  5983. Arguments:
  5984. RxContext - the RDBSS context
  5985. Return Value:
  5986. NTSTATUS - The return status for the operation
  5987. Notes:
  5988. If anything every goes wrong, we just don't update. this will cause
  5989. the shadow to be reload later.
  5990. --*/
  5991. {
  5992. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  5993. RxCaptureFcb;RxCaptureFobx;
  5994. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  5995. _WIN32_FIND_DATA *Find32 = NULL;
  5996. ULONG uStatus;
  5997. int TruncateRetVal = -1;
  5998. _WIN32_FIND_DATA *AllocatedFind32 = NULL;
  5999. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  6000. PSMBCEDB_SERVER_ENTRY pServerEntry;
  6001. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  6002. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  6003. BOOLEAN Disconnected;
  6004. RxDbgTrace(+1, Dbg, ("MRxSmbCscUpdateShadowFromClose %08lx\n",
  6005. RxContext));
  6006. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  6007. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  6008. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  6009. if (smbFcb->hShadow==0) {
  6010. if (Disconnected) {
  6011. if (smbSrvOpen->hfShadow != 0){
  6012. MRxSmbCscCloseShadowHandle(RxContext);
  6013. }
  6014. }
  6015. RxDbgTrace(-1, Dbg,
  6016. ("MRxSmbCscUpdateShadowFromClose shadowzero %08lx\n",RxContext));
  6017. return;
  6018. }
  6019. if (smbFcb->ContainingFcb->FcbState & FCB_STATE_ORPHANED)
  6020. {
  6021. if (smbSrvOpen->hfShadow != 0){
  6022. MRxSmbCscCloseShadowHandle(RxContext);
  6023. }
  6024. RxDbgTrace(-1, Dbg,
  6025. ("MRxSmbCscUpdateShadowFromClose Orphaned FCB %x\n", smbFcb->ContainingFcb));
  6026. return;
  6027. }
  6028. EnterShadowCritRx(RxContext);
  6029. if (!Disconnected) {
  6030. // If the file has been modified, we need to get the new timestamp
  6031. // from the server. By the time we come here the file has already been
  6032. // closed on the server, so we can safely get the new timestamp.
  6033. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SHADOW_DATA_MODIFIED)){
  6034. NTSTATUS LocalStatus;
  6035. LeaveShadowCritRx(RxContext);
  6036. LocalStatus = MRxSmbCscGetFileInfoFromServerWithinExchange(
  6037. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  6038. GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext));
  6039. if (LocalStatus == STATUS_SUCCESS) {
  6040. Find32 = OrdinaryExchange->Find32WithinSmbbuf;
  6041. RxLog(("Fromclose hShadow=%x l=%x h=%x\n", smbFcb->hShadow, Find32->ftLastWriteTime.dwLowDateTime, Find32->ftLastWriteTime.dwHighDateTime));
  6042. } else {
  6043. RxLog(("MRxSmbCscGetFileInfoFromServerWithinExchange returned LocalStatus\n"));
  6044. }
  6045. EnterShadowCritRx(RxContext);
  6046. }
  6047. if(GetShadowInfo(smbFcb->hParentDir,
  6048. smbFcb->hShadow,
  6049. NULL,
  6050. &uStatus, NULL) < SRET_OK)
  6051. {
  6052. goto FINALLY;
  6053. }
  6054. // in connected mode for a sparsely filled file that is not corrupt
  6055. // ie. no writes have failed on it, if the original size and the
  6056. // current size match, remove the sparse marking
  6057. // This optimization was added for notepad case in which when the app
  6058. // opens the file it reads the entire file. Therefore CSC does not need
  6059. // to fill the file and therefore we should clear the SPARSE flag. - NavjotV
  6060. //WinSE Bug- 25843
  6061. // We want to do this only if file is not Truncated in an earlier
  6062. // create. When we truncate the file we want it to stay SPARSE till
  6063. // we actually fill the file - NavjotV
  6064. if((NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE) &&
  6065. !smbFcb->ShadowIsCorrupt &&
  6066. !FlagOn(smbFcb->MFlags, SMB_FCB_FLAG_CSC_TRUNCATED_SHADOW) &&
  6067. (uStatus & SHADOW_SPARSE))
  6068. {
  6069. LARGE_INTEGER liTemp;
  6070. if(GetSizeHSHADOW(
  6071. smbFcb->hShadow,
  6072. &(liTemp.HighPart),
  6073. &(liTemp.LowPart))>=0)
  6074. {
  6075. if ((liTemp.HighPart == smbFcb->OriginalShadowSize.HighPart)&&
  6076. (liTemp.LowPart == smbFcb->OriginalShadowSize.LowPart))
  6077. {
  6078. uStatus &= ~SHADOW_SPARSE;
  6079. smbFcb->ShadowStatus &= ~SHADOW_SPARSE;
  6080. // RxDbgTrace(0, Dbg, ("hShadow=%x unsparsed\r\n", smbFcb->hShadow));
  6081. RxLog(("hShadow=%x unsparsed\r\n", smbFcb->hShadow));
  6082. }
  6083. }
  6084. }
  6085. } else {
  6086. // disconnected operation
  6087. if (smbFcb->hParentDir==0xffffffff) {
  6088. goto FINALLY;
  6089. }
  6090. AllocatedFind32 = (_WIN32_FIND_DATA *)RxAllocatePoolWithTag(
  6091. PagedPool | POOL_COLD_ALLOCATION,
  6092. sizeof(_WIN32_FIND_DATA),
  6093. RX_MISC_POOLTAG);
  6094. if (AllocatedFind32==NULL) {
  6095. goto FINALLY;
  6096. }
  6097. Find32 = AllocatedFind32;
  6098. if (GetShadowInfo(
  6099. smbFcb->hParentDir,
  6100. smbFcb->hShadow,
  6101. Find32,
  6102. &uStatus,
  6103. NULL) < SRET_OK) {
  6104. goto FINALLY; //bailout;
  6105. }
  6106. if (IsFile(Find32->dwFileAttributes))
  6107. {
  6108. GetSizeHSHADOW(
  6109. smbFcb->hShadow,
  6110. &(Find32->nFileSizeHigh),
  6111. &(Find32->nFileSizeLow));
  6112. }
  6113. else
  6114. {
  6115. Find32->nFileSizeHigh = Find32->nFileSizeLow = 0;
  6116. }
  6117. }
  6118. // If the shadow has become stale due to write errors
  6119. // or has become dirty because of writes on a complete file
  6120. // or sparse because of writes beyond what we have cached
  6121. // we need to mark it as such
  6122. uStatus |= (smbFcb->ShadowStatus & SHADOW_MODFLAGS);
  6123. if (Disconnected && FlagOn(smbSrvOpen->Flags, SMB_SRVOPEN_FLAG_SHADOW_DATA_MODIFIED))
  6124. {
  6125. uStatus |= SHADOW_DIRTY;
  6126. }
  6127. if (Disconnected && FlagOn(smbFcb->LocalFlags, FLAG_FDB_SHADOW_SNAPSHOTTED))
  6128. {
  6129. uStatus |= SHADOW_DIRTY;
  6130. }
  6131. if (Find32) {
  6132. smbFcb->OriginalShadowSize.LowPart = Find32->nFileSizeLow;
  6133. smbFcb->OriginalShadowSize.HighPart = Find32->nFileSizeHigh;
  6134. }
  6135. if (smbFcb->ShadowIsCorrupt) {
  6136. TruncateRetVal = TruncateDataHSHADOW(smbFcb->hParentDir, smbFcb->hShadow);
  6137. if (TruncateRetVal>=SRET_OK) {
  6138. // Set status flags to indicate sparse file
  6139. uStatus |= SHADOW_SPARSE;
  6140. }
  6141. }
  6142. if (Disconnected &&
  6143. FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SHADOW_DATA_MODIFIED) &&
  6144. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SHADOW_LWT_MODIFIED))
  6145. {
  6146. GetSystemTime(&(Find32->ftLastWriteTime));
  6147. }
  6148. if (SetShadowInfo(
  6149. smbFcb->hParentDir,
  6150. smbFcb->hShadow,
  6151. Find32,
  6152. uStatus,
  6153. ( SHADOW_FLAGS_ASSIGN |
  6154. ((Disconnected) ?
  6155. SHADOW_FLAGS_DONT_UPDATE_ORGTIME :
  6156. 0)
  6157. )) < SRET_OK) {
  6158. goto FINALLY;
  6159. }
  6160. if (TruncateRetVal>=SRET_OK) {
  6161. smbFcb->ShadowIsCorrupt = FALSE;
  6162. }
  6163. if (Disconnected) {
  6164. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SHADOW_MODIFIED)) {
  6165. MarkShareDirty(&smbFcb->sCscRootInfo.ShareStatus, smbFcb->sCscRootInfo.hShare);
  6166. }
  6167. if (smbSrvOpen->hfShadow != 0){
  6168. MRxSmbCscCloseShadowHandle(RxContext);
  6169. }
  6170. }
  6171. FINALLY:
  6172. LeaveShadowCritRx(RxContext);
  6173. if (AllocatedFind32!=NULL) {
  6174. RxFreePool(AllocatedFind32);
  6175. }
  6176. RxDbgTrace(-1, Dbg, ("MRxSmbCscUpdateShadowFromClose %08lx\n",
  6177. RxContext));
  6178. }
  6179. VOID
  6180. MRxSmbCscDeallocateForFcb (
  6181. IN OUT PMRX_FCB pFcb
  6182. )
  6183. /*++
  6184. Routine Description:
  6185. This routine tears down the Csc part of a netroot. Currently, all it does is
  6186. to pull the netroot out of the list of csc netroots.
  6187. Arguments:
  6188. pNetRootEntry -
  6189. Return Value:
  6190. Notes:
  6191. --*/
  6192. {
  6193. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(pFcb);
  6194. PMRX_NET_ROOT NetRoot = pFcb->pNetRoot;
  6195. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = NULL;
  6196. if(!MRxSmbIsCscEnabled ||
  6197. (fShadow == 0)
  6198. ) {
  6199. pFcb->fMiniInited = FALSE; // clean it up on shutdown
  6200. return;
  6201. }
  6202. if( !(NodeType(pFcb)== RDBSS_NTC_STORAGE_TYPE_DIRECTORY ||
  6203. NodeType(pFcb)== RDBSS_NTC_STORAGE_TYPE_FILE ||
  6204. NodeType(pFcb)== RDBSS_NTC_STORAGE_TYPE_UNKNOWN))
  6205. {
  6206. return;
  6207. }
  6208. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  6209. if (pNetRootEntry->NetRoot.NetRootType != NET_ROOT_DISK)
  6210. {
  6211. return;
  6212. }
  6213. EnterShadowCrit();
  6214. #if defined(BITCOPY)
  6215. if (smbFcb && smbFcb->lpDirtyBitmap) {
  6216. LPSTR strmName;
  6217. // Save Bitmap to disk and Delete Bitmap
  6218. strmName = FormAppendNameString(lpdbShadow,
  6219. smbFcb->hShadow,
  6220. CscBmpAltStrmName);
  6221. if (strmName != NULL) {
  6222. if (smbFcb->hShadow >= 0x80000000) {
  6223. // Write only to file inodes
  6224. CscBmpWrite(smbFcb->lpDirtyBitmap, strmName);
  6225. }
  6226. CscBmpDelete(&((LPCSC_BITMAP)(smbFcb->lpDirtyBitmap)));
  6227. ExFreePool(strmName);
  6228. }
  6229. }
  6230. #endif // defined(BITCOPY)
  6231. try
  6232. {
  6233. if (smbFcb->ShadowReverseTranslationLinks.Flink != 0) {
  6234. RxDbgTrace(+1, Dbg, ("MRxSmbCscDeallocateForFcb...%08lx %08lx %08lx %08lx\n",
  6235. pFcb,
  6236. smbFcb->hShadow,
  6237. smbFcb->hParentDir,
  6238. smbFcb->ShadowReverseTranslationLinks.Flink ));
  6239. ValidateSmbFcbList();
  6240. ASSERT(pFcb->fMiniInited);
  6241. pFcb->fMiniInited = FALSE;
  6242. MRxSmbCscRemoveReverseFcbTranslation(smbFcb);
  6243. RxDbgTrace(-1, Dbg, ("MRxSmbCscDeallocateForFcb exit\n"));
  6244. } else {
  6245. ASSERT(smbFcb->ShadowReverseTranslationLinks.Flink == 0);
  6246. }
  6247. if(FlagOn(smbFcb->LocalFlags, FLAG_FDB_DELETE_ON_CLOSE))
  6248. {
  6249. RxLog(("Dealloc: Deleting hShadow=%x %x %x \n", smbFcb->hShadow, pFcb, smbFcb));
  6250. DeleteShadowHelper(FALSE, smbFcb->hParentDir, smbFcb->hShadow);
  6251. smbFcb->hParentDir = smbFcb->hShadow = 0;
  6252. }
  6253. // if there are any Dfs reverse mapping structures, free them
  6254. if (smbFcb->uniDfsPrefix.Buffer)
  6255. {
  6256. FreeMem(smbFcb->uniDfsPrefix.Buffer);
  6257. ASSERT(smbFcb->uniActualPrefix.Buffer);
  6258. FreeMem(smbFcb->uniActualPrefix.Buffer);
  6259. }
  6260. }
  6261. except(EXCEPTION_EXECUTE_HANDLER)
  6262. {
  6263. if(pFcb->fMiniInited)
  6264. {
  6265. DbgPrint("CSCFcbList messed up \n");
  6266. ASSERT(FALSE);
  6267. }
  6268. goto FINALLY;
  6269. }
  6270. FINALLY:
  6271. LeaveShadowCrit();
  6272. return;
  6273. }
  6274. PMRX_SMB_FCB
  6275. MRxSmbCscRecoverMrxFcbFromFdb (
  6276. IN PFDB Fdb
  6277. )
  6278. /*++
  6279. Routine Description:
  6280. Arguments:
  6281. Return Value:
  6282. Notes:
  6283. --*/
  6284. {
  6285. if (Fdb==NULL) {
  6286. return NULL;
  6287. }
  6288. return CONTAINING_RECORD(
  6289. &Fdb->usFlags,
  6290. MRX_SMB_FCB,
  6291. ShadowStatus
  6292. );
  6293. }
  6294. PFDB MRxSmbCscFindFdbFromHShadow (
  6295. IN HSHADOW hShadow
  6296. )
  6297. /*++
  6298. Routine Description:
  6299. This routine looks thru the current open mrxsmbfcbs and returns a mrxsmbfcb
  6300. that corresponds to the HSHADOW passed. In the interest of not mucking with
  6301. the w95 code, we cast this pointer into a PFDB in such a way that
  6302. the the shadowstatus in the mrxsmbfcb lines up with the usFlags in PFDB.
  6303. Arguments:
  6304. Return Value:
  6305. Notes:
  6306. --*/
  6307. {
  6308. PLIST_ENTRY pListEntry;
  6309. DbgDoit(ASSERT(vfInShadowCrit));
  6310. pListEntry = xCscFcbsList.Flink;
  6311. while (pListEntry != &xCscFcbsList) {
  6312. PMRX_SMB_FCB smbFcb;
  6313. smbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  6314. pListEntry,
  6315. MRX_SMB_FCB,
  6316. ShadowReverseTranslationLinks);
  6317. if (((smbFcb->hShadow == hShadow)||(smbFcb->hShadowRenamed == hShadow)) &&
  6318. (!(smbFcb->ContainingFcb->FcbState & FCB_STATE_ORPHANED)))
  6319. {
  6320. PFDB Fdb;
  6321. PUSHORT pShadowStatus = &smbFcb->ShadowStatus;
  6322. ASSERT ( sizeof(Fdb->usFlags) == sizeof (USHORT) );
  6323. Fdb = CONTAINING_RECORD(pShadowStatus,FDB,usFlags);
  6324. return Fdb;
  6325. }
  6326. pListEntry = pListEntry->Flink;
  6327. }
  6328. return NULL;
  6329. }
  6330. PRESOURCE
  6331. MRxSmbCscFindResourceFromHandlesWithModify (
  6332. IN HSHARE hShare,
  6333. IN HSHADOW hRoot,
  6334. IN USHORT usLocalFlagsIncl,
  6335. IN USHORT usLocalFlagsExcl,
  6336. OUT PULONG ShareStatus,
  6337. OUT PULONG DriveMap,
  6338. IN ULONG uStatus,
  6339. IN ULONG uOp
  6340. )
  6341. /*++
  6342. Routine Description:
  6343. This routine looks thru the currently connected netrootentries and
  6344. returns the one that corresponds EITHER to the HSHADOW passed or to
  6345. the HSHARE passed. In the interest of not mucking with the w95 code,
  6346. we cast this pointer into a PRESOURCE. we also return the share
  6347. status as well as the drivemap.....we dont know the drivemap
  6348. but we could get it by walking the list of vnetroots. It is not used anywhere by the UI
  6349. If the uOp is not 0xffffffff, then we modify the status as well as
  6350. returning it.
  6351. Arguments:
  6352. IN HSHARE hShare - the share handle to look for
  6353. IN HSHADOW hRoot - the rootdir handle to look for
  6354. IN USHORT usLocalFlagsIncl - make sure that some of these flags are included (0xffff mean
  6355. include any flags)
  6356. IN USHORT usLocalFlagsExcl - make sure that none of these flags are included
  6357. OUT PULONG ShareStatus - a pointer to where we will store the status
  6358. OUT PULONG DriveMap - a pointer to where we will store the drivemap info
  6359. IN ULONG uStatus - input status to use in the "bit operations"
  6360. IN ULONG uOp - which operation
  6361. Return Value:
  6362. Notes:
  6363. The flags passed here are used in one ioctl to either exclude or include
  6364. connected or disconnected resources as appropriate.
  6365. --*/
  6366. {
  6367. PRESOURCE pResource = NULL;
  6368. BOOLEAN TableLockHeld = FALSE;
  6369. PLIST_ENTRY ListEntry;
  6370. RxDbgTrace(+1, Dbg, ("MRxSmbCscFindResourceFromRoot...%08lx\n",hRoot));
  6371. DbgDoit(ASSERT(vfInShadowCrit));
  6372. if ((hRoot==0) && (hShare==0)) {
  6373. return NULL;
  6374. }
  6375. //we can't hold this....sigh
  6376. LeaveShadowCrit();
  6377. try {
  6378. RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE);
  6379. TableLockHeld = TRUE;
  6380. if (IsListEmpty( &RxNetNameTable.MemberQueue )) {
  6381. try_return(pResource = NULL);
  6382. }
  6383. if (ShareStatus)
  6384. {
  6385. *ShareStatus = 0;
  6386. }
  6387. ListEntry = RxNetNameTable.MemberQueue.Flink;
  6388. for (;ListEntry != &RxNetNameTable.MemberQueue;) {
  6389. PVOID Container;
  6390. PRX_PREFIX_ENTRY PrefixEntry;
  6391. PMRX_NET_ROOT NetRoot;
  6392. PMRX_V_NET_ROOT VNetRoot;
  6393. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  6394. PSMBCEDB_SERVER_ENTRY pServerEntry;
  6395. PUSHORT ThisShareStatus;
  6396. PrefixEntry = CONTAINING_RECORD( ListEntry,
  6397. RX_PREFIX_ENTRY,
  6398. MemberQLinks );
  6399. ListEntry = ListEntry->Flink;
  6400. ASSERT (NodeType(PrefixEntry) == RDBSS_NTC_PREFIX_ENTRY);
  6401. Container = PrefixEntry->ContainingRecord;
  6402. RxDbgTrace(0, Dbg,
  6403. ("---> ListE PfxE Container Name %08lx %08lx %08lx %wZ\n",
  6404. ListEntry, PrefixEntry, Container, &PrefixEntry->Prefix));
  6405. switch (NodeType(Container)) {
  6406. case RDBSS_NTC_NETROOT :
  6407. NetRoot = (PMRX_NET_ROOT)Container;
  6408. RxDbgTrace(0, Dbg,
  6409. ("NetRoot->pSrvCall=0x%x, NetRoot->Type=%d, NetRoot->Context=0x%x, NetRoot->pSrvCall->RxDeviceObject=0x%x\n",
  6410. NetRoot->pSrvCall, NetRoot->Type, NetRoot->Context, NetRoot->pSrvCall->RxDeviceObject));
  6411. if ((NetRoot->pSrvCall == NULL) ||
  6412. (NetRoot->Type != NET_ROOT_DISK) ||
  6413. (NetRoot->Context == NULL) ||
  6414. (NetRoot->pSrvCall->RxDeviceObject != MRxSmbDeviceObject)) {
  6415. RxDbgTrace(0, Dbg,("Skipping \n"));
  6416. continue;
  6417. }
  6418. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  6419. ThisShareStatus = &pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus;
  6420. pServerEntry = SmbCeGetAssociatedServerEntry(NetRoot->pSrvCall);
  6421. RxDbgTrace(0, Dbg,
  6422. ("pNetRootEntry->NetRoot.CscEnabled=%d, pNetRootEntry->NetRoot.sCscRootInfo.hRootDir=0x%x, pNetRootEntry->NetRoot.sCscRootInfo.hShare=0x%x\n",
  6423. pNetRootEntry->NetRoot.CscEnabled, pNetRootEntry->NetRoot.sCscRootInfo.hRootDir, pNetRootEntry->NetRoot.sCscRootInfo.hShare
  6424. ));
  6425. if ((hRoot!=0xffffffff)||(hShare != 0xffffffff))
  6426. {
  6427. if (pNetRootEntry->NetRoot.CscEnabled &&
  6428. ((pNetRootEntry->NetRoot.sCscRootInfo.hRootDir == hRoot) ||
  6429. (pNetRootEntry->NetRoot.sCscRootInfo.hShare == hShare) )) {
  6430. if (*ThisShareStatus & usLocalFlagsExcl) {
  6431. RxDbgTrace(0, Dbg,("Skipping *ThisShareStatus=\n", *ThisShareStatus));
  6432. continue;
  6433. }
  6434. if ((usLocalFlagsIncl==0xffff)
  6435. || (*ThisShareStatus & usLocalFlagsIncl)) {
  6436. switch (mBitOpShadowFlags(uOp)) {
  6437. case SHADOW_FLAGS_ASSIGN:
  6438. *ThisShareStatus = (USHORT)uStatus;
  6439. break;
  6440. case SHADOW_FLAGS_OR:
  6441. *ThisShareStatus |= (USHORT)uStatus;
  6442. break;
  6443. case SHADOW_FLAGS_AND:
  6444. *ThisShareStatus &= (USHORT)uStatus;
  6445. break;
  6446. }
  6447. *ShareStatus |= (*ThisShareStatus | SHARE_CONNECTED);
  6448. if(SmbCeIsServerInDisconnectedMode(pServerEntry))
  6449. {
  6450. *ShareStatus |= SHARE_DISCONNECTED_OP;
  6451. }
  6452. if (pServerEntry->Server.IsPinnedOffline == TRUE)
  6453. *ShareStatus |= SHARE_PINNED_OFFLINE;
  6454. RxDbgTrace(0, Dbg,("Count of srvopens=%d\n", pServerEntry->Server.NumberOfSrvOpens));
  6455. *DriveMap = 0; //not used anywhere
  6456. try_return (pResource = (PRESOURCE)pNetRootEntry);
  6457. }
  6458. }
  6459. }
  6460. else // hShare and hRoot are 0xffffffff, this means we are looping
  6461. {
  6462. if (mBitOpShadowFlags(uOp) == SHADOW_FLAGS_AND)
  6463. {
  6464. if (pNetRootEntry->NetRoot.sCscRootInfo.hRootDir)
  6465. {
  6466. pNetRootEntry->NetRoot.sCscRootInfo.hRootDir = 0;
  6467. pNetRootEntry->NetRoot.sCscRootInfo.hShare = 0;
  6468. }
  6469. }
  6470. }
  6471. continue;
  6472. case RDBSS_NTC_SRVCALL :
  6473. continue;
  6474. case RDBSS_NTC_V_NETROOT :
  6475. VNetRoot = (PMRX_V_NET_ROOT)Container;
  6476. // NTRAID#455236-1/31/2000-shishirp we should'nt be using this field here, it is strictly meant
  6477. // for the wrapper
  6478. if (((PV_NET_ROOT)Container)->Condition == Condition_Good)
  6479. {
  6480. if (VNetRoot->Context != NULL) {
  6481. pNetRootEntry = ((PSMBCE_V_NET_ROOT_CONTEXT)VNetRoot->Context)->pNetRootEntry;
  6482. RxDbgTrace(0, Dbg,("RDBSS_NTC_V_NETROOT: VNetRoot=%x, pNetRootEntry=%x\r\n",
  6483. VNetRoot, pNetRootEntry));
  6484. if ((hRoot!=0xffffffff)||(hShare != 0xffffffff))
  6485. {
  6486. if ((pNetRootEntry != NULL) &&
  6487. pNetRootEntry->NetRoot.CscEnabled &&
  6488. ((pNetRootEntry->NetRoot.sCscRootInfo.hRootDir == hRoot) ||
  6489. (pNetRootEntry->NetRoot.sCscRootInfo.hShare == hShare))) {
  6490. }
  6491. }
  6492. else
  6493. {
  6494. if (pNetRootEntry->NetRoot.sCscRootInfo.hRootDir)
  6495. {
  6496. pNetRootEntry->NetRoot.sCscRootInfo.hRootDir = 0;
  6497. pNetRootEntry->NetRoot.sCscRootInfo.hShare = 0;
  6498. }
  6499. }
  6500. }
  6501. }
  6502. default:
  6503. continue;
  6504. }
  6505. }
  6506. try_return(pResource = NULL);
  6507. try_exit:NOTHING;
  6508. } finally {
  6509. if (TableLockHeld) {
  6510. RxReleasePrefixTableLock( &RxNetNameTable );
  6511. }
  6512. EnterShadowCrit();
  6513. if (pResource && ((hShare != 0xffffffff) || (hRoot != 0xffffffff)))
  6514. {
  6515. if (ShareStatus)
  6516. {
  6517. SetOfflineOpenStatusForShare(hShare, hRoot, ShareStatus);
  6518. }
  6519. }
  6520. }
  6521. RxDbgTrace(-1, Dbg, ("MRxSmbCscFindResourceFromRoot...%08lx\n",pResource));
  6522. return(pResource);
  6523. }
  6524. #undef GetShadowInfo
  6525. #undef SetShadowInfo
  6526. // this is just a simple wrapper function except that we pick off the rootdir case.
  6527. // ...see the recordmanager code for args
  6528. int PUBLIC
  6529. MRxSmbCscWrappedGetShadowInfo(
  6530. HSHADOW hDir,
  6531. HSHADOW hNew,
  6532. LPFIND32 lpFind32,
  6533. ULONG far *lpuFlags,
  6534. LPOTHERINFO lpOI)
  6535. {
  6536. if (hDir != -1) {
  6537. return(GetShadowInfo(hDir, hNew, lpFind32, lpuFlags, lpOI));
  6538. }
  6539. //otherwise....just make it up...........
  6540. RtlZeroMemory(
  6541. lpFind32,
  6542. sizeof(*lpFind32));
  6543. lpFind32->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  6544. *lpuFlags = SHADOW_SPARSE;
  6545. return(SRET_OK);
  6546. }
  6547. // this is just a simple wrapper function except that we pick off the rootdir case.
  6548. // ...see the recordmanager code for args
  6549. int PUBLIC
  6550. MRxSmbCscWrappedSetShadowInfo(
  6551. HSHADOW hDir,
  6552. HSHADOW hNew,
  6553. LPFIND32 lpFind32,
  6554. ULONG uFlags,
  6555. ULONG uOp)
  6556. {
  6557. if (hDir == -1) {
  6558. return(SRET_OK);
  6559. }
  6560. return(SetShadowInfo(hDir, hNew, lpFind32, uFlags, uOp));
  6561. }
  6562. USHORT *
  6563. MRxSmbCscFindLocalFlagsFromFdb(
  6564. PFDB pFdb
  6565. )
  6566. /*++
  6567. Routine Description:
  6568. Arguments:
  6569. Return Value:
  6570. Notes:
  6571. --*/
  6572. {
  6573. PMRX_SMB_FCB smbFcb;
  6574. PUSHORT pShadowStatus = &(pFdb->usFlags);
  6575. DbgDoit(ASSERT(vfInShadowCrit));
  6576. smbFcb = CONTAINING_RECORD(pShadowStatus,MRX_SMB_FCB,ShadowStatus);
  6577. return (&(smbFcb->LocalFlags));
  6578. }
  6579. NTSTATUS
  6580. MRxSmbCscSetSecurityPrologue (
  6581. IN OUT PRX_CONTEXT RxContext
  6582. )
  6583. /*++
  6584. Routine Description:
  6585. This routine is called when a set security call is made. It tries
  6586. to set the ACL on the CSC cached version of the file.
  6587. Arguments:
  6588. RxContext - the RDBSS context
  6589. Return Value:
  6590. NTSTATUS - The return status for the operation
  6591. Notes:
  6592. --*/
  6593. {
  6594. #if defined(REMOTE_BOOT)
  6595. RxCaptureFcb;
  6596. _WIN32_FIND_DATA Find32;
  6597. PMRX_SMB_FCB smbFcb;
  6598. NTSTATUS Status;
  6599. //
  6600. // First we need to set the security descriptor on the CSC
  6601. // version of the file, if one exists.
  6602. //
  6603. smbFcb = MRxSmbGetFcbExtension(capFcb);
  6604. EnterShadowCritRx(RxContext);
  6605. Status = MRxSmbCscCreateShadowFromPath(
  6606. GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),
  6607. SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot),
  6608. &Find32,
  6609. NULL,
  6610. CREATESHADOW_CONTROL_NOCREATE,
  6611. &smbFcb->MinimalCscSmbFcb,
  6612. RxContext,
  6613. FALSE,
  6614. NULL
  6615. ); // not disconnected
  6616. LeaveShadowCritRx(RxContext);
  6617. if (Status == STATUS_SUCCESS) {
  6618. Status = MRxSmbCscSetSecurityOnShadow(
  6619. smbFcb->MinimalCscSmbFcb.hShadow,
  6620. RxContext->SetSecurity.SecurityInformation,
  6621. RxContext->SetSecurity.SecurityDescriptor);
  6622. if (!NT_SUCCESS(Status)) {
  6623. KdPrint(("MRxSmbCscSetSecurityPrologue: Could not set security (%lx) for %wZ: %lx\n", RxContext,
  6624. GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext), Status));
  6625. }
  6626. } else {
  6627. //
  6628. //
  6629. Status = STATUS_SUCCESS;
  6630. }
  6631. return Status;
  6632. #else
  6633. return STATUS_SUCCESS;
  6634. #endif
  6635. }
  6636. VOID
  6637. MRxSmbCscSetSecurityEpilogue (
  6638. IN OUT PRX_CONTEXT RxContext,
  6639. IN OUT PNTSTATUS Status
  6640. )
  6641. /*++
  6642. Routine Description:
  6643. This routine performs the tail of a set security operation for CSC.
  6644. If the set failed, it tries to restore the old ACL on the file.
  6645. Arguments:
  6646. RxContext - the RDBSS context
  6647. Status - the overall status of the open
  6648. Return Value:
  6649. Notes:
  6650. --*/
  6651. {
  6652. return;
  6653. }
  6654. // Table off which the parameter validation is driven
  6655. // there is some redundancy in this table, specifically, we could have only the flags
  6656. // and get rid of the other two fields.
  6657. CSC_IOCTL_ENTRY rgCscIoctlTable[] =
  6658. {
  6659. {IOCTL_SHADOW_GETVERSION, 0, 0},
  6660. {IOCTL_SHADOW_REGISTER_AGENT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6661. {IOCTL_SHADOW_UNREGISTER_AGENT, 0, 0},
  6662. {IOCTL_SHADOW_GET_UNC_PATH, FLAG_CSC_IOCTL_COPYPARAMS, sizeof(COPYPARAMS)},
  6663. {IOCTL_SHADOW_BEGIN_PQ_ENUM, FLAG_CSC_IOCTL_PQPARAMS, sizeof(PQPARAMS)},
  6664. {IOCTL_SHADOW_END_PQ_ENUM, FLAG_CSC_IOCTL_PQPARAMS, sizeof(PQPARAMS)},
  6665. {IOCTL_SHADOW_NEXT_PRI_SHADOW, FLAG_CSC_IOCTL_PQPARAMS, sizeof(PQPARAMS)},
  6666. {IOCTL_SHADOW_PREV_PRI_SHADOW, FLAG_CSC_IOCTL_PQPARAMS, sizeof(PQPARAMS)},
  6667. {IOCTL_SHADOW_GET_SHADOW_INFO, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6668. {IOCTL_SHADOW_SET_SHADOW_INFO, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6669. {IOCTL_SHADOW_CHK_UPDT_STATUS, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6670. {IOCTL_DO_SHADOW_MAINTENANCE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6671. {IOCTL_SHADOW_COPYCHUNK, FLAG_CSC_IOCTL_COPYCHUNKCONTEXT, sizeof(COPYCHUNKCONTEXT)},
  6672. {IOCTL_SHADOW_BEGIN_REINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6673. {IOCTL_SHADOW_END_REINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6674. {IOCTL_SHADOW_CREATE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6675. {IOCTL_SHADOW_DELETE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6676. {IOCTL_GET_SHARE_STATUS, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6677. {IOCTL_SET_SHARE_STATUS, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6678. {IOCTL_ADDUSE, 0, 0}, // not applicable on NT
  6679. {IOCTL_DELUSE, 0, 0}, // not applicable on NT
  6680. {IOCTL_GETUSE, 0, 0}, // not applicable on NT
  6681. {IOCTL_SWITCHES, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6682. {IOCTL_GETSHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6683. {IOCTL_GETGLOBALSTATUS, FLAG_CSC_IOCTL_GLOBALSTATUS,sizeof(GLOBALSTATUS)},
  6684. {IOCTL_FINDOPEN_SHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6685. {IOCTL_FINDNEXT_SHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6686. {IOCTL_FINDCLOSE_SHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6687. {IOCTL_GETPRIORITY_SHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6688. {IOCTL_SETPRIORITY_SHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6689. {IOCTL_ADD_HINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6690. {IOCTL_DELETE_HINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6691. {IOCTL_FINDOPEN_HINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6692. {IOCTL_FINDNEXT_HINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6693. {IOCTL_FINDCLOSE_HINT, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6694. {IOCTL_GET_IH_PRIORITY, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6695. {IOCTL_GETALIAS_HSHADOW, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6696. {_SHADOW_IOCTL_CODE(37), 0, 0}, // hole in the ioctl range
  6697. {_SHADOW_IOCTL_CODE(38), 0, 0}, // hole in the ioctl range
  6698. {_SHADOW_IOCTL_CODE(39), 0, 0}, // hole in the ioctl range
  6699. {IOCTL_OPENFORCOPYCHUNK, FLAG_CSC_IOCTL_COPYCHUNKCONTEXT, sizeof(COPYCHUNKCONTEXT)},
  6700. {IOCTL_CLOSEFORCOPYCHUNK, FLAG_CSC_IOCTL_COPYCHUNKCONTEXT, sizeof(COPYCHUNKCONTEXT)},
  6701. {IOCTL_IS_SERVER_OFFLINE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6702. {IOCTL_TRANSITION_SERVER_TO_ONLINE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6703. {IOCTL_TRANSITION_SERVER_TO_OFFLINE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6704. {IOCTL_TAKE_SERVER_OFFLINE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6705. {IOCTL_NAME_OF_SERVER_GOING_OFFLINE, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)},
  6706. {IOCTL_SHAREID_TO_SHARENAME, FLAG_CSC_IOCTL_SHADOWINFO, sizeof(SHADOWINFO)}
  6707. };
  6708. NTSTATUS
  6709. CaptureInputBufferIfNecessaryAndProbe(
  6710. IN DWORD IoControlCode,
  6711. IN PRX_CONTEXT pRxContext,
  6712. IN PBYTE InputBuffer,
  6713. IN LPCAPTURE_BUFFERS lpCapBuff,
  6714. OUT PBYTE *ppAuxBuf,
  6715. OUT PBYTE *ppOrgBuf,
  6716. OUT PBYTE *ppReturnBuffer
  6717. )
  6718. /*++
  6719. Routine Description:
  6720. This routine does the capturing if necessary and probing of the buffers.
  6721. Note that because the csc ioctls are always called with METHOD_NEITHER
  6722. buffering mode, we always execute the code below.
  6723. Arguments:
  6724. IoControlCode Ioctl code
  6725. pRxContext context which has all the info of the original ioctl call for IO subsystem
  6726. InputBuffer Input Buffer
  6727. lpCapBuff capture buffer passed in by the caller. If this ioctl needs capturing
  6728. then this buffer is used to capture the input buffer.
  6729. We use this in case of SHADOWINFO and COPYPARAMS structures being passed in
  6730. as only in these two case there are embedded pointers
  6731. ppAuxBuf if we needed to capture another part of the buffer (lpFind32 or lpBuffer),
  6732. this routine will allocate a buffer which will be passed back here, and
  6733. must be freed by the caller.
  6734. ppReturnBuffer either the input buffer itself, or lpCapBuff (if inputbuffer is captured)
  6735. Return Value:
  6736. Notes:
  6737. --*/
  6738. {
  6739. int indx;
  6740. BOOL fRet = FALSE;
  6741. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  6742. KPROCESSOR_MODE requestorMode;
  6743. indx = ((IoControlCode >> 2) & 0xfff) - SHADOW_IOCTL_ENUM_BASE;
  6744. if((indx >=0 ) && (indx < sizeof(rgCscIoctlTable)/sizeof(CSC_IOCTL_ENTRY)))
  6745. {
  6746. *ppReturnBuffer = InputBuffer;
  6747. if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_COPYCHUNKCONTEXT)
  6748. {
  6749. return(ValidateCopyChunkContext(pRxContext, IoControlCode));
  6750. }
  6751. if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_BUFFERTYPE_MASK)
  6752. {
  6753. try
  6754. {
  6755. ProbeForRead(InputBuffer,
  6756. rgCscIoctlTable[indx].dwLength,
  6757. 1);
  6758. ProbeForWrite(InputBuffer,
  6759. rgCscIoctlTable[indx].dwLength,
  6760. 1);
  6761. if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_COPYPARAMS)
  6762. {
  6763. lpCapBuff->sCP = *(LPCOPYPARAMS)InputBuffer;
  6764. *ppReturnBuffer = (PBYTE)&(lpCapBuff->sCP);
  6765. Status = ValidateCopyParams(&(lpCapBuff->sCP));
  6766. }
  6767. else if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_SHADOWINFO)
  6768. {
  6769. lpCapBuff->sSI = *(LPSHADOWINFO)InputBuffer;
  6770. *ppReturnBuffer = (PBYTE)&(lpCapBuff->sSI);
  6771. Status = ValidateShadowInfo(
  6772. IoControlCode,
  6773. &(lpCapBuff->sSI),
  6774. ppAuxBuf,
  6775. ppOrgBuf);
  6776. }
  6777. else
  6778. {
  6779. Status = STATUS_SUCCESS;
  6780. }
  6781. }
  6782. except(EXCEPTION_EXECUTE_HANDLER )
  6783. {
  6784. Status = STATUS_INVALID_PARAMETER;
  6785. }
  6786. }
  6787. else
  6788. {
  6789. Status = STATUS_SUCCESS;
  6790. }
  6791. }
  6792. return Status;
  6793. }
  6794. NTSTATUS
  6795. ValidateCopyParams(
  6796. LPCOPYPARAMS lpCP
  6797. )
  6798. /*++
  6799. Routine Description:
  6800. Arguments:
  6801. Return Value:
  6802. Notes:
  6803. --*/
  6804. {
  6805. if((CscProbeForReadWrite((PBYTE)lpCP->lpLocalPath, MAX_PATH*sizeof(USHORT)) == STATUS_SUCCESS)&&
  6806. (CscProbeForReadWrite((PBYTE)lpCP->lpRemotePath, MAX_PATH*sizeof(USHORT)) == STATUS_SUCCESS)&&
  6807. (CscProbeForReadWrite((PBYTE)lpCP->lpSharePath, MAX_SERVER_SHARE_NAME_FOR_CSC*2) == STATUS_SUCCESS))
  6808. {
  6809. return STATUS_SUCCESS;
  6810. }
  6811. return STATUS_INVALID_PARAMETER;
  6812. }
  6813. NTSTATUS
  6814. ValidateShadowInfo(
  6815. DWORD IoControlCode,
  6816. LPSHADOWINFO lpSI,
  6817. LPBYTE *ppAuxBuf,
  6818. LPBYTE *ppOrgBuf
  6819. )
  6820. /*++
  6821. Routine Description:
  6822. Arguments:
  6823. Return Value:
  6824. Notes:
  6825. --*/
  6826. {
  6827. NTSTATUS Status;
  6828. // by the time we get here, the SHADOWINFO strucuture has already been
  6829. // probed
  6830. // IOCTL_DO_SHADOW_MAINTENANCE has multiple suboperations, so we
  6831. // deal them seperately.
  6832. if (IoControlCode == IOCTL_DO_SHADOW_MAINTENANCE)
  6833. {
  6834. // DbgPrint("SHADOW_OP:0x%x\n", lpSI->uOp);
  6835. switch(lpSI->uOp)
  6836. {
  6837. case SHADOW_REDUCE_REFPRI: // 2
  6838. // case SHADOW_RECALC_IHPRI: // 5
  6839. case SHADOW_PER_THREAD_DISABLE: // 7
  6840. case SHADOW_PER_THREAD_ENABLE: // 8
  6841. case SHADOW_ADDHINT_FROM_INODE: // 10
  6842. case SHADOW_DELETEHINT_FROM_INODE: // 11
  6843. case SHADOW_BEGIN_INODE_TRANSACTION: // 13
  6844. case SHADOW_END_INODE_TRANSACTION: // 14
  6845. case SHADOW_TRANSITION_SERVER_TO_OFFLINE: // 19
  6846. case SHADOW_CHANGE_HANDLE_CACHING_STATE: // 20
  6847. case SHADOW_RECREATE: // 21
  6848. case SHADOW_SPARSE_STALE_DETECTION_COUNTER: // 23
  6849. case SHADOW_DISABLE_CSC_FOR_USER: // 25
  6850. case SHADOW_SET_DATABASE_STATUS: // 26
  6851. case SHADOW_MANUAL_FILE_DETECTION_COUNTER: // 28
  6852. return STATUS_SUCCESS;
  6853. case SHADOW_FIND_CREATE_PRINCIPAL_ID: // 15
  6854. case SHADOW_GET_SECURITY_INFO: // 16
  6855. case SHADOW_SET_EXCLUSION_LIST: // 17
  6856. case SHADOW_SET_BW_CONSERVE_LIST: // 18
  6857. case SHADOW_GET_SPACE_STATS: // 5
  6858. if (!lpSI->lpBuffer || !lpSI->cbBufferSize)
  6859. {
  6860. return STATUS_INVALID_PARAMETER;
  6861. }
  6862. else
  6863. {
  6864. Status = CscProbeAndCaptureForReadWrite(
  6865. lpSI->lpBuffer,
  6866. lpSI->cbBufferSize,
  6867. ppAuxBuf);
  6868. if (Status == STATUS_SUCCESS) {
  6869. *ppOrgBuf =(PBYTE) lpSI->lpBuffer;
  6870. lpSI->lpBuffer = (PBYTE) *ppAuxBuf;
  6871. }
  6872. return Status;
  6873. }
  6874. case SHADOW_REINIT_DATABASE: // 9
  6875. case SHADOW_MAKE_SPACE: // 1
  6876. case SHADOW_ADD_SPACE: // 3
  6877. case SHADOW_FREE_SPACE: // 4
  6878. case SHADOW_SET_MAX_SPACE: // 6
  6879. case SHADOW_COPY_INODE_FILE: // 12
  6880. case SHADOW_RENAME: // 22
  6881. case SHADOW_ENABLE_CSC_FOR_USER: // 24
  6882. case SHADOW_PURGE_UNPINNED_FILES: // 27
  6883. Status = CscProbeAndCaptureForReadWrite(
  6884. (PBYTE)(lpSI->lpFind32),
  6885. sizeof(WIN32_FIND_DATA),
  6886. ppAuxBuf);
  6887. if (Status == STATUS_SUCCESS) {
  6888. *ppOrgBuf =(PBYTE) lpSI->lpFind32;
  6889. lpSI->lpFind32 = (LPFIND32) *ppAuxBuf;
  6890. }
  6891. return Status;
  6892. default:
  6893. return STATUS_INVALID_PARAMETER;
  6894. }
  6895. } else if (
  6896. IoControlCode == IOCTL_GET_SHARE_STATUS
  6897. ||
  6898. IoControlCode == IOCTL_SET_SHARE_STATUS
  6899. ) {
  6900. Status = CscProbeAndCaptureForReadWrite(
  6901. (PBYTE)(lpSI->lpFind32),
  6902. sizeof(SHAREINFOW),
  6903. ppAuxBuf);
  6904. if (Status == STATUS_SUCCESS) {
  6905. *ppOrgBuf =(PBYTE) lpSI->lpFind32;
  6906. lpSI->lpFind32 = (LPFIND32) *ppAuxBuf;
  6907. }
  6908. return Status;
  6909. } else if (
  6910. IoControlCode == IOCTL_IS_SERVER_OFFLINE
  6911. ||
  6912. IoControlCode == IOCTL_TAKE_SERVER_OFFLINE
  6913. ||
  6914. IoControlCode == IOCTL_NAME_OF_SERVER_GOING_OFFLINE
  6915. ||
  6916. IoControlCode == IOCTL_SHAREID_TO_SHARENAME
  6917. ) {
  6918. Status = CscProbeAndCaptureForReadWrite(
  6919. lpSI->lpBuffer,
  6920. lpSI->cbBufferSize,
  6921. ppAuxBuf);
  6922. if (Status == STATUS_SUCCESS) {
  6923. *ppOrgBuf =(PBYTE) lpSI->lpBuffer;
  6924. lpSI->lpBuffer = (PBYTE) *ppAuxBuf;
  6925. }
  6926. return Status;
  6927. }
  6928. // for all other ioctls which take SHADOWINFO structure, there may be an embedded
  6929. // find32 structure, which must be probed
  6930. ASSERT(IoControlCode != IOCTL_DO_SHADOW_MAINTENANCE);
  6931. Status = CscProbeAndCaptureForReadWrite(
  6932. (PBYTE)(lpSI->lpFind32),
  6933. sizeof(WIN32_FIND_DATA),
  6934. ppAuxBuf);
  6935. if (Status == STATUS_SUCCESS) {
  6936. *ppOrgBuf =(PBYTE) lpSI->lpFind32;
  6937. lpSI->lpFind32 = (LPFIND32) *ppAuxBuf;
  6938. }
  6939. return Status;
  6940. }
  6941. NTSTATUS
  6942. ValidateCopyChunkContext(
  6943. PRX_CONTEXT RxContext,
  6944. DWORD IoControlCode
  6945. )
  6946. /*++
  6947. Routine Description:
  6948. Arguments:
  6949. Return Value:
  6950. Notes:
  6951. --*/
  6952. {
  6953. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  6954. // on open, validate the name
  6955. if (IoControlCode == IOCTL_OPENFORCOPYCHUNK)
  6956. {
  6957. PBYTE FileName = (PBYTE)LowIoContext->ParamsFor.IoCtl.pInputBuffer;
  6958. ULONG FileNameLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength - 1;
  6959. // let us varify that the name passed in is within our limits
  6960. if ((FileNameLength > ((MAX_PATH+MAX_SERVER_SHARE_NAME_FOR_CSC)*sizeof(USHORT)))||
  6961. CscProbeForReadWrite(FileName, FileNameLength) != STATUS_SUCCESS)
  6962. {
  6963. return STATUS_INVALID_PARAMETER;
  6964. }
  6965. return STATUS_SUCCESS;
  6966. }
  6967. else
  6968. {
  6969. // on copychunk or close we need to validate the chunk structure.
  6970. // we don't need to validate the handle in it because the
  6971. // object manager does that in MrxSmbCscCopyChunk and MrxSmbCscCloseForCopyChunk
  6972. // routines
  6973. COPYCHUNKCONTEXT *CopyChunkContext =
  6974. (COPYCHUNKCONTEXT *)(LowIoContext->ParamsFor.IoCtl.pOutputBuffer);
  6975. if (!CopyChunkContext)
  6976. {
  6977. return STATUS_INVALID_PARAMETER;
  6978. }
  6979. // for all copychunk calls, validate the copychunkcontext buffer
  6980. return CscProbeForReadWrite((PBYTE)CopyChunkContext, sizeof(COPYCHUNKCONTEXT));
  6981. }
  6982. }
  6983. NTSTATUS
  6984. CscProbeForReadWrite(
  6985. PBYTE pBuffer,
  6986. DWORD dwSize
  6987. )
  6988. /*++
  6989. Routine Description:
  6990. Arguments:
  6991. Return Value:
  6992. Notes:
  6993. --*/
  6994. {
  6995. NTSTATUS Status = STATUS_SUCCESS;
  6996. try
  6997. {
  6998. if (pBuffer != NULL) {
  6999. ProbeForRead(
  7000. pBuffer,
  7001. dwSize,
  7002. 1);
  7003. ProbeForWrite(
  7004. pBuffer,
  7005. dwSize,
  7006. 1);
  7007. }
  7008. }
  7009. except(EXCEPTION_EXECUTE_HANDLER)
  7010. {
  7011. Status=STATUS_INVALID_PARAMETER;
  7012. }
  7013. return Status;
  7014. }
  7015. NTSTATUS
  7016. CscProbeAndCaptureForReadWrite(
  7017. PBYTE pBuffer,
  7018. DWORD dwSize,
  7019. PBYTE *ppAuxBuf
  7020. )
  7021. /*++
  7022. Routine Description:
  7023. Arguments:
  7024. Return Value:
  7025. Notes:
  7026. --*/
  7027. {
  7028. NTSTATUS Status = STATUS_SUCCESS;
  7029. PBYTE pBuf = NULL;
  7030. try {
  7031. if (pBuffer != NULL && dwSize > 0) {
  7032. ProbeForRead(pBuffer, dwSize, 1);
  7033. ProbeForWrite(pBuffer, dwSize, 1);
  7034. pBuf = RxAllocatePoolWithTag(PagedPool, dwSize, 'xXRM');
  7035. if (pBuf != NULL) {
  7036. RtlCopyMemory(pBuf, pBuffer, dwSize);
  7037. *ppAuxBuf = pBuf;
  7038. } else {
  7039. Status = STATUS_INSUFFICIENT_RESOURCES;
  7040. }
  7041. }
  7042. } except(EXCEPTION_EXECUTE_HANDLER) {
  7043. Status = STATUS_INVALID_PARAMETER;
  7044. }
  7045. if (Status != STATUS_SUCCESS && pBuf != NULL) {
  7046. RxFreePool(pBuf);
  7047. }
  7048. return Status;
  7049. }
  7050. VOID
  7051. CopyBackIfNecessary(
  7052. IN DWORD IoControlCode,
  7053. IN OUT PBYTE InputBuffer,
  7054. IN LPCAPTURE_BUFFERS lpCapBuff,
  7055. IN PBYTE pAuxBuf,
  7056. IN PBYTE pOrgBuf,
  7057. BOOL fSuccess
  7058. )
  7059. /*++
  7060. Routine Description:
  7061. This routine copies back the capture buffer to the inout buffer, in ioctls which
  7062. expect output.
  7063. Arguments:
  7064. Return Value:
  7065. Notes:
  7066. --*/
  7067. {
  7068. int indx;
  7069. BOOL fRet = FALSE;
  7070. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  7071. LPSHADOWINFO lpSI = NULL;
  7072. indx = ((IoControlCode >> 2) & 0xfff) - SHADOW_IOCTL_ENUM_BASE;
  7073. ASSERT((indx >=0 ) && (indx < sizeof(rgCscIoctlTable)/sizeof(CSC_IOCTL_ENTRY)));
  7074. if (fSuccess)
  7075. {
  7076. if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_SHADOWINFO) {
  7077. *(LPSHADOWINFO)InputBuffer = lpCapBuff->sSI;
  7078. lpSI = &lpCapBuff->sSI;
  7079. if (pAuxBuf != NULL && pOrgBuf != NULL) {
  7080. //
  7081. // Some ioctls have embedded pointers. We have to copy the 2nd buffer
  7082. // back, too, and set the embedded pointer back to that buffer.
  7083. //
  7084. if (IoControlCode == IOCTL_DO_SHADOW_MAINTENANCE) {
  7085. // DbgPrint("SHADOW_OP(2):0x%x\n", lpSI->uOp);
  7086. switch(lpSI->uOp) {
  7087. case SHADOW_FIND_CREATE_PRINCIPAL_ID: // 15
  7088. case SHADOW_GET_SECURITY_INFO: // 16
  7089. case SHADOW_SET_EXCLUSION_LIST: // 17
  7090. case SHADOW_SET_BW_CONSERVE_LIST: // 18
  7091. case SHADOW_GET_SPACE_STATS: // 5
  7092. RtlMoveMemory(pOrgBuf, pAuxBuf, lpSI->cbBufferSize);
  7093. lpSI->lpBuffer = (PBYTE) pOrgBuf;
  7094. break;
  7095. case SHADOW_REINIT_DATABASE: // 9
  7096. case SHADOW_MAKE_SPACE: // 1
  7097. case SHADOW_ADD_SPACE: // 3
  7098. case SHADOW_FREE_SPACE: // 4
  7099. case SHADOW_SET_MAX_SPACE: // 6
  7100. case SHADOW_COPY_INODE_FILE: // 12
  7101. case SHADOW_RENAME: // 22
  7102. case SHADOW_ENABLE_CSC_FOR_USER: // 24
  7103. case SHADOW_PURGE_UNPINNED_FILES: // 27
  7104. RtlMoveMemory(pOrgBuf, pAuxBuf, sizeof(WIN32_FIND_DATA));
  7105. lpSI->lpFind32 = (LPFIND32) pOrgBuf;
  7106. break;
  7107. }
  7108. } else if (
  7109. IoControlCode == IOCTL_GET_SHARE_STATUS
  7110. ||
  7111. IoControlCode == IOCTL_SET_SHARE_STATUS
  7112. ) {
  7113. RtlMoveMemory(pOrgBuf, pAuxBuf, sizeof(SHAREINFOW));
  7114. lpSI->lpFind32 = (LPFIND32) pOrgBuf;
  7115. } else if (
  7116. IoControlCode == IOCTL_IS_SERVER_OFFLINE
  7117. ||
  7118. IoControlCode == IOCTL_TAKE_SERVER_OFFLINE
  7119. ||
  7120. IoControlCode == IOCTL_NAME_OF_SERVER_GOING_OFFLINE
  7121. ||
  7122. IoControlCode == IOCTL_SHAREID_TO_SHARENAME
  7123. ) {
  7124. RtlMoveMemory(pOrgBuf, pAuxBuf, lpSI->cbBufferSize);
  7125. lpSI->lpBuffer = (PBYTE) pOrgBuf;
  7126. } else {
  7127. RtlMoveMemory(pOrgBuf, pAuxBuf, sizeof(WIN32_FIND_DATA));
  7128. lpSI->lpFind32 = (LPFIND32) pOrgBuf;
  7129. }
  7130. }
  7131. }
  7132. } else {
  7133. if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_SHADOWINFO) {
  7134. ((LPSHADOWINFO)InputBuffer)->dwError = lpCapBuff->sSI.dwError;
  7135. } else if (rgCscIoctlTable[indx].dwFlags & FLAG_CSC_IOCTL_COPYPARAMS) {
  7136. ((LPCOPYPARAMS)InputBuffer)->dwError = lpCapBuff->sCP.dwError;
  7137. }
  7138. }
  7139. }
  7140. VOID ValidateSmbFcbList(
  7141. VOID)
  7142. /*++
  7143. Routine Description:
  7144. This routine validates the smbfcb reverse lookup list
  7145. Arguments:
  7146. Return Value:
  7147. Notes:
  7148. This validation code must be called from within the shadow critical section
  7149. --*/
  7150. {
  7151. PLIST_ENTRY pListEntry;
  7152. DWORD cntFlink, cntBlink;
  7153. DbgDoit(ASSERT(vfInShadowCrit));
  7154. cntFlink = cntBlink = 0;
  7155. // check forward list validity
  7156. pListEntry = xCscFcbsList.Flink;
  7157. while (pListEntry != &xCscFcbsList) {
  7158. PMRX_SMB_FCB smbFcb;
  7159. smbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  7160. pListEntry,
  7161. MRX_SMB_FCB,
  7162. ShadowReverseTranslationLinks);
  7163. try
  7164. {
  7165. if((NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_FILE) &&
  7166. (NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)&&
  7167. (NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN)
  7168. )
  7169. {
  7170. DbgPrint("ValidateSmbFcbList:Invalid nodetype %x fcb=%x smbfcb=%x\n",
  7171. NodeType(smbFcb->ContainingFcb),smbFcb->ContainingFcb, smbFcb);
  7172. // DbgBreakPoint();
  7173. }
  7174. }
  7175. except(EXCEPTION_EXECUTE_HANDLER)
  7176. {
  7177. DbgPrint("ValidateSmbFcbList:Invalid smbFcb %x \n", smbFcb);
  7178. //Bug - 578682
  7179. //DbgBreakPoint();
  7180. }
  7181. ++cntFlink;
  7182. pListEntry = pListEntry->Flink;
  7183. }
  7184. // check backward list validity
  7185. pListEntry = xCscFcbsList.Blink;
  7186. while (pListEntry != &xCscFcbsList) {
  7187. PMRX_SMB_FCB smbFcb;
  7188. smbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  7189. pListEntry,
  7190. MRX_SMB_FCB,
  7191. ShadowReverseTranslationLinks);
  7192. try
  7193. {
  7194. if((NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_FILE) &&
  7195. (NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)&&
  7196. (NodeType(smbFcb->ContainingFcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN))
  7197. {
  7198. DbgPrint("ValidateSmbFcbList:Invalid nodetype %x fcb=%x smbfcb=%x\n",
  7199. NodeType(smbFcb->ContainingFcb),smbFcb->ContainingFcb, smbFcb);
  7200. // DbgBreakPoint();
  7201. }
  7202. }
  7203. except(EXCEPTION_EXECUTE_HANDLER)
  7204. {
  7205. DbgPrint("ValidateSmbFcbList:Invalid smbFcb %x \n", smbFcb);
  7206. // DbgBreakPoint();
  7207. }
  7208. ++cntBlink;
  7209. pListEntry = pListEntry->Blink;
  7210. }
  7211. // both counts should be the same
  7212. ASSERT(cntFlink == cntBlink);
  7213. }
  7214. BOOL SetOfflineOpenStatusForShare(
  7215. CSC_SHARE_HANDLE hShare,
  7216. CSC_SHADOW_HANDLE hRootDir,
  7217. OUT PULONG pShareStatus
  7218. )
  7219. /*++
  7220. Routine Description:
  7221. Arguments:
  7222. Return Value:
  7223. Notes:
  7224. --*/
  7225. {
  7226. PLIST_ENTRY pListEntry;
  7227. DbgDoit(ASSERT(vfInShadowCrit));
  7228. if ((hRootDir==0) && (hShare==0)) {
  7229. return 0;
  7230. }
  7231. ASSERT((hShare!=0xffffffff) || (hRootDir!=0xffffffff));
  7232. pListEntry = xCscFcbsList.Flink;
  7233. while (pListEntry != &xCscFcbsList) {
  7234. PMRX_SMB_FCB smbFcb;
  7235. smbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  7236. pListEntry,
  7237. MRX_SMB_FCB,
  7238. ShadowReverseTranslationLinks);
  7239. if (((smbFcb->sCscRootInfo.hShare == hShare)
  7240. ||(smbFcb->sCscRootInfo.hRootDir == hRootDir)))
  7241. {
  7242. if(smbFcb->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  7243. {
  7244. *pShareStatus |= SHARE_FINDS_IN_PROGRESS;
  7245. }
  7246. else
  7247. {
  7248. *pShareStatus |= SHARE_FILES_OPEN;
  7249. }
  7250. }
  7251. pListEntry = pListEntry->Flink;
  7252. }
  7253. return FALSE;
  7254. }
  7255. VOID
  7256. EnterShadowCritRx(
  7257. PRX_CONTEXT pRxContext
  7258. )
  7259. {
  7260. EnterShadowCrit();
  7261. #if DBG
  7262. if (pRxContext)
  7263. {
  7264. ASSERT( !pRxContext->ShadowCritOwner );
  7265. pRxContext->ShadowCritOwner = GetCurThreadHandle();
  7266. }
  7267. #endif
  7268. }
  7269. VOID
  7270. LeaveShadowCritRx(
  7271. PRX_CONTEXT pRxContext
  7272. )
  7273. {
  7274. #if DBG
  7275. if (pRxContext)
  7276. {
  7277. ASSERT( pRxContext->ShadowCritOwner );
  7278. pRxContext->ShadowCritOwner = 0;
  7279. }
  7280. #endif
  7281. LeaveShadowCrit();
  7282. }
  7283. NTSTATUS
  7284. CscInitializeServerEntryDfsRoot(
  7285. PRX_CONTEXT pRxContext,
  7286. PSMBCEDB_SERVER_ENTRY pServerEntry
  7287. )
  7288. {
  7289. PDFS_NAME_CONTEXT pDfsNameContext = NULL;
  7290. NTSTATUS Status = STATUS_SUCCESS;
  7291. UNICODE_STRING ServerPath;
  7292. if (pRxContext &&
  7293. pRxContext->CurrentIrpSp &&
  7294. (pRxContext->CurrentIrpSp->MajorFunction == IRP_MJ_CREATE)) {
  7295. pDfsNameContext = CscIsValidDfsNameContext(pRxContext->Create.NtCreateParameters.DfsNameContext);
  7296. if (pDfsNameContext){
  7297. Status = CscDfsParseDfsPath(
  7298. &pDfsNameContext->UNCFileName,
  7299. &ServerPath,
  7300. NULL,
  7301. NULL);
  7302. if (Status == STATUS_SUCCESS) {
  7303. if (pServerEntry->DfsRootName.Buffer == NULL) {
  7304. pServerEntry->DfsRootName.Buffer = RxAllocatePoolWithTag(
  7305. NonPagedPool,
  7306. ServerPath.Length,
  7307. RX_MISC_POOLTAG);
  7308. if (pServerEntry->DfsRootName.Buffer == NULL)
  7309. {
  7310. return STATUS_INSUFFICIENT_RESOURCES;
  7311. }
  7312. RtlCopyMemory(pServerEntry->DfsRootName.Buffer,
  7313. ServerPath.Buffer,
  7314. ServerPath.Length);
  7315. pServerEntry->DfsRootName.MaximumLength = ServerPath.Length;
  7316. pServerEntry->DfsRootName.Length = ServerPath.Length;
  7317. // DbgPrint("Initialized %x with DfsRoot %wZ\n", pServerEntry, &pServerEntry->DfsRootName);
  7318. }
  7319. }
  7320. }
  7321. }
  7322. return Status;
  7323. }
  7324. NTSTATUS
  7325. MRxSmbCscLocalFileOpen(
  7326. IN OUT PRX_CONTEXT RxContext
  7327. )
  7328. /*++
  7329. Routine Description:
  7330. This routine performs the conserving bandwidth for remote boot client. The bandwidth
  7331. is saved by the way of reducing the files opened on the boot server, instead the local
  7332. copy of the file on CSC is used.
  7333. There is a set the rules that the file has to meet in order to be opened locally.
  7334. * file tried to open on VDO share
  7335. * a local copy of the file has been created on CSC, which is not sparse
  7336. * the write or name space operations have to go through the server except
  7337. * Only execute operations are allowed through
  7338. The routine checks the file whether it meets those rules. The actual open happens on
  7339. MRxSmbCscCreateEpilogue.
  7340. Arguments:
  7341. RxContext - the RDBSS context
  7342. Return Value:
  7343. Status - we return the local open status
  7344. Notes:
  7345. --*/
  7346. {
  7347. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  7348. NTSTATUS LocalStatus;
  7349. RxCaptureFcb;
  7350. PMRX_SMB_FCB smbFcb;
  7351. PMRX_SRV_OPEN SrvOpen;
  7352. PMRX_SMB_SRV_OPEN smbSrvOpen;
  7353. PMRX_NET_ROOT NetRoot;
  7354. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  7355. PSMBCEDB_SERVER_ENTRY pServerEntry;
  7356. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  7357. ULONG CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;
  7358. ULONG CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
  7359. ACCESS_MASK DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess;
  7360. BOOLEAN CreatedShadow = FALSE;
  7361. ULONG uShadowStatus;
  7362. _WIN32_FIND_DATA Find32, CscFind32;
  7363. PUNICODE_STRING PathName;
  7364. int iRet;
  7365. int EarlyOut = 0;
  7366. LARGE_INTEGER CurrentTime;
  7367. LARGE_INTEGER DeadLine;
  7368. BOOL fLocalOpens = FALSE;
  7369. NetRoot = capFcb->pNetRoot;
  7370. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  7371. SrvOpen = RxContext->pRelevantSrvOpen;
  7372. smbFcb = MRxSmbGetFcbExtension(capFcb);
  7373. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  7374. PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  7375. pServerEntry = SmbCeGetAssociatedServerEntry(NetRoot->pSrvCall);
  7376. // don't do local open if the share is either in disconnected state
  7377. // or the share is not a VDO share
  7378. if (SmbCeIsServerInDisconnectedMode(pServerEntry) ||
  7379. (pNetRootEntry->NetRoot.CscFlags != SMB_CSC_CACHE_VDO))
  7380. {
  7381. RxDbgTrace( 0, Dbg, ("Server disconnected or not VDO share, CscFlags=%x\n", pNetRootEntry->NetRoot.CscFlags));
  7382. return Status;
  7383. }
  7384. EnterShadowCritRx(RxContext);
  7385. LocalStatus = MRxSmbCscObtainShadowHandles(
  7386. RxContext,
  7387. &Status,
  7388. &CscFind32,
  7389. &CreatedShadow,
  7390. CREATESHADOW_CONTROL_NOCREATE,
  7391. FALSE);
  7392. if (LocalStatus != STATUS_SUCCESS) {
  7393. EarlyOut = 1;
  7394. goto FINALLY;
  7395. }
  7396. if ((smbFcb->hShadow == 0) ||
  7397. (smbFcb->ShadowStatus == SHADOW_SPARSE) ||
  7398. (smbFcb->ShadowStatus & SHADOW_MODFLAGS) ||
  7399. (CscFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  7400. // if no local copy or file is sparse, or modified, or it is a directory,
  7401. // file cannot open locally
  7402. EarlyOut = 2;
  7403. goto FINALLY;
  7404. }
  7405. LeaveShadowCritRx(RxContext);
  7406. fLocalOpens = CSCCheckLocalOpens(RxContext);
  7407. EnterShadowCritRx(RxContext);
  7408. if (DesiredAccess &
  7409. ( GENERIC_WRITE |
  7410. FILE_WRITE_EA |
  7411. FILE_ADD_FILE |
  7412. FILE_WRITE_DATA |
  7413. FILE_APPEND_DATA |
  7414. FILE_DELETE_CHILD |
  7415. FILE_ADD_SUBDIRECTORY)) { // FILE_WRITE_ATTRIBUTE is OK
  7416. if (fLocalOpens)
  7417. {
  7418. HookKdPrint(BADERRORS, ("VDO not allowed for this desired access %x %x\n", smbFcb->hShadow, DesiredAccess));
  7419. Status = STATUS_ACCESS_DENIED;
  7420. }
  7421. EarlyOut = 3;
  7422. goto FINALLY;
  7423. }
  7424. if (CreateOptions & FILE_DELETE_ON_CLOSE)
  7425. {
  7426. if (fLocalOpens)
  7427. {
  7428. HookKdPrint(BADERRORS, ("DeletOnClose not allowed %x %x\n", smbFcb->hShadow, DesiredAccess));
  7429. Status = STATUS_ACCESS_DENIED;
  7430. EarlyOut = 30;
  7431. goto FINALLY;
  7432. }
  7433. }
  7434. if (CreateDisposition != FILE_OPEN)
  7435. {
  7436. // name space operations should go to the server
  7437. if (fLocalOpens)
  7438. {
  7439. Status = STATUS_SHARING_VIOLATION;
  7440. }
  7441. EarlyOut = 4;
  7442. goto FINALLY;
  7443. }
  7444. if (!(DesiredAccess & FILE_EXECUTE))
  7445. {
  7446. // DbgPrint("FILE_EXECUTE not set (0x%x) on %wZ\n", DesiredAccess, PathName);
  7447. EarlyOut = 5;
  7448. goto FINALLY;
  7449. }
  7450. #if 0
  7451. KeQuerySystemTime( &CurrentTime );
  7452. // system time is based on 100ns
  7453. DeadLine.QuadPart = smbFcb->LastSyncTime.QuadPart + (LONGLONG) (CscSyncInterval * 10 * 1000 * 1000);
  7454. if (CurrentTime.QuadPart < DeadLine.QuadPart) {
  7455. Status = STATUS_SUCCESS;
  7456. goto FINALLY;
  7457. }
  7458. #endif
  7459. // do a check on the server only when there is no outstanding local open
  7460. if (!fLocalOpens)
  7461. {
  7462. LeaveShadowCritRx(RxContext);
  7463. LocalStatus = MRxSmbGetFileInfoFromServer(RxContext,PathName,&Find32,SrvOpen,NULL);
  7464. EnterShadowCritRx(RxContext);
  7465. if (LocalStatus != STATUS_SUCCESS) {
  7466. // if cannot get file information from the server, file cannot open locally
  7467. EarlyOut = 6;
  7468. goto FINALLY;
  7469. }
  7470. iRet = RefreshShadow(
  7471. smbFcb->hParentDir,
  7472. smbFcb->hShadow,
  7473. &Find32,
  7474. &uShadowStatus
  7475. );
  7476. if (iRet < SRET_OK) {
  7477. // if refresh shadow fails, file cannot open locally
  7478. EarlyOut = 7;
  7479. goto FINALLY;
  7480. } else {
  7481. SetShadowInfo(smbFcb->hParentDir,
  7482. smbFcb->hShadow,
  7483. NULL,
  7484. 0,
  7485. SHADOW_FLAGS_OR|SHADOW_FLAGS_SET_REFRESH_TIME);
  7486. }
  7487. if (uShadowStatus == SHADOW_SPARSE) {
  7488. // if the file is sparse, it cannot open locally
  7489. EarlyOut = 8;
  7490. goto FINALLY;
  7491. } else {
  7492. // no more rule, file can open locally
  7493. Status = STATUS_SUCCESS;
  7494. }
  7495. }
  7496. else
  7497. {
  7498. Status = STATUS_SUCCESS;
  7499. }
  7500. FINALLY:
  7501. if (Status == STATUS_SUCCESS) {
  7502. SetFlag(smbSrvOpen->Flags, SMB_SRVOPEN_FLAG_LOCAL_OPEN);
  7503. smbFcb->cntLocalOpens++;
  7504. //RxDbgTrace(0, Dbg, ("Local : %wZ\n",PathName));
  7505. RxLog(("Local Open %lx %lx %lx\n",smbFcb->hParentDir, smbFcb->hShadow, capFcb));
  7506. RxDbgTrace( 0, Dbg,
  7507. ("MRxSmbCscLocalFileOpen hdir/hshadow= %08lx %08lx\n",
  7508. smbFcb->hParentDir, smbFcb->hShadow));
  7509. } else {
  7510. RxDbgTrace(0, Dbg, ("Remote: %d %wZ\n",EarlyOut,PathName));
  7511. }
  7512. LeaveShadowCritRx(RxContext);
  7513. return Status;
  7514. }
  7515. BOOL
  7516. CSCCheckLocalOpens(
  7517. IN PRX_CONTEXT RxContext
  7518. )
  7519. /*++
  7520. Routine Description:
  7521. The routine checks whether there is any fcb in the fcb list which has our inode.
  7522. The reason why this has to be done is because of rename.
  7523. Thus if a file cat.exe is opened the smbFcb->hShadow field had the inode.
  7524. Then if a rename to dog.exe is done while the file is open, the smbfcb->hShadow field is
  7525. set to 0 and smbFcb->hShadowRename is set to the inode value.
  7526. After that when a delete comes through, RDBSS cannot check the sharing violation because
  7527. it doesn'nt change the name in the FCB to dog.exe. So it creates a new FCB for dog.exe.
  7528. Yet we do have to give sharing violation in this scenario. We accomplish this
  7529. by detecting just such a scenario in the routine below.
  7530. It essentially goes though the FCB reverselookup list and if it finds an FCB which
  7531. has the same hShadow or hShadowRenamed as this one, and it's cntLocalOpens is
  7532. non-zero, then it gives sharing violation.
  7533. Arguments:
  7534. RxContext - the RDBSS context
  7535. Status - miniredir status
  7536. Return Value:
  7537. Status - Passed in status, or STATUS_SHARING_VILOATION
  7538. Notes:
  7539. --*/
  7540. {
  7541. BOOL fRet = FALSE;
  7542. RxCaptureFcb;
  7543. PMRX_SMB_FCB smbFcb, pSmbFcbT;
  7544. PMRX_NET_ROOT NetRoot;
  7545. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  7546. CSC_SHADOW_HANDLE hShadow;
  7547. PLIST_ENTRY pListEntry;
  7548. NetRoot = capFcb->pNetRoot;
  7549. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  7550. smbFcb = MRxSmbGetFcbExtension(capFcb);
  7551. hShadow = (smbFcb->hShadow)?smbFcb->hShadow:smbFcb->hShadowRenamed;
  7552. if (!hShadow || (pNetRootEntry->NetRoot.CscFlags != SMB_CSC_CACHE_VDO))
  7553. {
  7554. return FALSE;
  7555. }
  7556. EnterShadowCritRx(RxContext);
  7557. pListEntry = xCscFcbsList.Flink;
  7558. while (pListEntry != &xCscFcbsList) {
  7559. pSmbFcbT = (PMRX_SMB_FCB)CONTAINING_RECORD(
  7560. pListEntry,
  7561. MRX_SMB_FCB,
  7562. ShadowReverseTranslationLinks);
  7563. if ((pSmbFcbT->hShadow==smbFcb->hShadow) ||
  7564. (pSmbFcbT->hShadowRenamed==smbFcb->hShadow))
  7565. {
  7566. if (pSmbFcbT->cntLocalOpens)
  7567. {
  7568. RxLog(("smbfcb=%x has local opens for hShadow=%x\n", pSmbFcbT, smbFcb->hShadow));
  7569. fRet = TRUE;
  7570. break;
  7571. }
  7572. }
  7573. pListEntry = pListEntry->Flink;
  7574. }
  7575. LeaveShadowCritRx(RxContext);
  7576. return fRet;
  7577. }
  7578. BOOL
  7579. IsCSCBusy(
  7580. VOID
  7581. )
  7582. /*++
  7583. Routine Description:
  7584. This routine checks whether any files are being shadowed by CSC
  7585. Arguments:
  7586. None
  7587. Return Value:
  7588. TRUE if any files are being shadowed, FALSE otherwise
  7589. Notes:
  7590. Used by the diableCSC ioctl
  7591. --*/
  7592. {
  7593. DbgDoit(ASSERT(vfInShadowCrit));
  7594. return (xCscFcbsList.Flink != &xCscFcbsList);
  7595. }
  7596. VOID
  7597. ClearCSCStateOnRedirStructures(
  7598. VOID
  7599. )
  7600. /*++
  7601. Routine Description:
  7602. This routine clears the csc state on netroots
  7603. Arguments:
  7604. None
  7605. Return Value:
  7606. None
  7607. Notes:
  7608. Used by the diableCSC ioctl
  7609. --*/
  7610. {
  7611. DbgDoit(ASSERT(vfInShadowCrit));
  7612. ASSERT(!IsCSCBusy());
  7613. ClearAllResourcesOfShadowingState();
  7614. DbgDoit(ASSERT(vfInShadowCrit));
  7615. CscTransitionServerToOnline(0); // transition all servers
  7616. }
  7617. BOOL
  7618. CscDfsShareIsInReint(
  7619. IN PRX_CONTEXT RxContext
  7620. )
  7621. /*++
  7622. Routine Description:
  7623. Arguments:
  7624. Return Value:
  7625. Notes:
  7626. --*/
  7627. {
  7628. PDFS_NAME_CONTEXT pDfsNameContext = NULL;
  7629. UNICODE_STRING SharePath;
  7630. NTSTATUS LocalStatus;
  7631. CSC_SHARE_HANDLE CscShareHandle;
  7632. ULONG ulRootHintFlags;
  7633. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  7634. pDfsNameContext = CscIsValidDfsNameContext(RxContext->Create.NtCreateParameters.DfsNameContext);
  7635. if (pDfsNameContext)
  7636. {
  7637. LocalStatus = CscDfsParseDfsPath(
  7638. &pDfsNameContext->UNCFileName,
  7639. NULL,
  7640. &SharePath,
  7641. NULL);
  7642. if (LocalStatus == STATUS_SUCCESS)
  7643. {
  7644. GetHShareFromUNCString(
  7645. SharePath.Buffer,
  7646. SharePath.Length,
  7647. 1,
  7648. TRUE,
  7649. &CscShareHandle,
  7650. &ulRootHintFlags);
  7651. if (CscShareHandle && (CscShareHandle == hShareReint))
  7652. {
  7653. return TRUE;
  7654. }
  7655. }
  7656. }
  7657. }
  7658. return FALSE;
  7659. }
  7660. LONG CSCBeginReint(
  7661. IN OUT PRX_CONTEXT RxContext,
  7662. IN OUT LPSHADOWINFO lpSI
  7663. )
  7664. /*++
  7665. Routine Description:
  7666. begins merge. This routine needs to be in pagelocked memory because
  7667. it takes cancel spinlock.
  7668. We pend the Irp that issued the beginreint ioctl and set our cancel routine in it.
  7669. If the thread doing the merge dies for some reason, the Ps code calls our cancel routine
  7670. to cacncel this irp, this is when we cleanup the merge state.
  7671. Arguments:
  7672. RxContext
  7673. lpSI Buffer passed down by the caller
  7674. Return Value:
  7675. None.
  7676. --*/
  7677. {
  7678. LONG ShadowIRet;
  7679. KIRQL CancelIrql;
  7680. BOOL fCancelled = FALSE;
  7681. ShadowIRet = IoctlBeginReint(lpSI);
  7682. if (ShadowIRet >= 1)
  7683. {
  7684. CloseOpenFiles(lpSI->hShare, NULL, 0);
  7685. IoAcquireCancelSpinLock( &CancelIrql);
  7686. if (RxContext->CurrentIrp->Cancel)
  7687. {
  7688. vIrpReint = NULL;
  7689. IoReleaseCancelSpinLock( CancelIrql );
  7690. IoctlEndReint(lpSI);
  7691. }
  7692. else
  7693. {
  7694. // succeeded begin merge on this share
  7695. vIrpReint = RxContext->CurrentIrp;
  7696. IoSetCancelRoutine( RxContext->CurrentIrp, CSCCancelReint );
  7697. IoReleaseCancelSpinLock( CancelIrql );
  7698. // Returning STATUS_PENDING
  7699. IoMarkIrpPending( RxContext->CurrentIrp );
  7700. // as we hijacked the Irp, let us make sure that rdbss gets rid of the rxcontext
  7701. RxCompleteRequest_Real( RxContext, NULL, STATUS_PENDING );
  7702. }
  7703. }
  7704. return ShadowIRet;
  7705. }
  7706. ULONG CSCEndReint(
  7707. LPSHADOWINFO lpSI
  7708. )
  7709. /*++
  7710. Routine Description:
  7711. ends merge. This routine needs to be in pagelocked memory because it takes cancel spinlock
  7712. This is normal termination. We cleanup our merge state and complete the irp we pended
  7713. during begin
  7714. Arguments:
  7715. lpSI
  7716. Return Value:
  7717. None.
  7718. --*/
  7719. {
  7720. int ShadowIRet=-1;
  7721. KIRQL CancelIrql;
  7722. PIRP pIrp;
  7723. // check if reint was actualy going on on this share
  7724. ShadowIRet = IoctlEndReint(lpSI);
  7725. if (ShadowIRet >= 0)
  7726. {
  7727. IoAcquireCancelSpinLock( &CancelIrql);
  7728. pIrp = vIrpReint;
  7729. vIrpReint = NULL;
  7730. if (pIrp)
  7731. {
  7732. pIrp->IoStatus.Status = STATUS_SUCCESS;
  7733. pIrp->IoStatus.Information = 0;
  7734. IoSetCancelRoutine(pIrp, NULL);
  7735. }
  7736. IoReleaseCancelSpinLock( CancelIrql );
  7737. if (pIrp)
  7738. {
  7739. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  7740. }
  7741. }
  7742. return ShadowIRet;
  7743. }
  7744. VOID CSCCancelReint(
  7745. IN PDEVICE_OBJECT DeviceObject,
  7746. IN PIRP ThisIrp
  7747. )
  7748. /*++
  7749. Routine Description:
  7750. Cancels a merge begun by the user. This routine needs to be in pagelocked memory because
  7751. it takes cancel spinlock.
  7752. Arguments:
  7753. DeviceObject - Ignored.
  7754. ThisIrp - This is the Irp to cancel.
  7755. Return Value:
  7756. None.
  7757. --*/
  7758. {
  7759. SHADOWINFO sSI;
  7760. memset(&sSI, 0, sizeof(sSI));
  7761. sSI.hShare = hShareReint;
  7762. IoSetCancelRoutine( ThisIrp, NULL );
  7763. vIrpReint = NULL;
  7764. IoReleaseCancelSpinLock( ThisIrp->CancelIrql );
  7765. ThisIrp->IoStatus.Status = STATUS_SUCCESS;
  7766. ThisIrp->IoStatus.Information = 0;
  7767. IoCompleteRequest(ThisIrp, IO_NO_INCREMENT);
  7768. IoctlEndReint(&sSI);
  7769. }
  7770. BOOL
  7771. CloseOpenFiles(
  7772. HSHARE hShare,
  7773. PUNICODE_STRING pServerName,
  7774. int lenSkip
  7775. )
  7776. /*++
  7777. Routine Description:
  7778. Closes all open files for CSC. Does this by issuing a foceclose on the vneteroot
  7779. This an equivalent of wnetcancelconnection on a share with forced close of files
  7780. Arguments:
  7781. hShare CSC handle to the share to close, ignored if pServerName is non-NULL
  7782. pServerName All open files on on shares belonging to this server
  7783. lenskip #of backslashes in servername (usually one)
  7784. Return Value:
  7785. Whether atleast one open file was found
  7786. --*/
  7787. {
  7788. BOOL fFoundAtleastOne=FALSE, fFound;
  7789. PLIST_ENTRY pListEntry;
  7790. SHAREINFOW sSR;
  7791. UNICODE_STRING uniShare;
  7792. EnterShadowCrit();
  7793. pListEntry = xCscFcbsList.Flink;
  7794. while (pListEntry != &xCscFcbsList) {
  7795. PMRX_SMB_FCB smbFcb;
  7796. smbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  7797. pListEntry,
  7798. MRX_SMB_FCB,
  7799. ShadowReverseTranslationLinks);
  7800. fFound = FALSE;
  7801. if (pServerName)
  7802. {
  7803. ASSERT(smbFcb->sCscRootInfo.hShare);
  7804. GetShareInfo(smbFcb->sCscRootInfo.hShare, &sSR, NULL);
  7805. uniShare.Buffer = sSR.rgSharePath+lenSkip;
  7806. uniShare.Length = uniShare.MaximumLength = pServerName->Length;
  7807. // DbgPrint("matching %wZ with Servername\n", &uniShare);
  7808. if(RtlEqualUnicodeString(pServerName, &uniShare, TRUE)&&
  7809. (uniShare.Buffer[pServerName->Length/sizeof(WCHAR)]==(WCHAR)'\\'))
  7810. {
  7811. // DbgPrint("matched \n");
  7812. fFound=TRUE;
  7813. }
  7814. }
  7815. else if ((smbFcb->sCscRootInfo.hShare == hShare))
  7816. {
  7817. fFound = TRUE;
  7818. }
  7819. if (fFound)
  7820. {
  7821. if (!(smbFcb->ContainingFcb->FcbState & FCB_STATE_ORPHANED))
  7822. {
  7823. PNET_ROOT pNetRoot = (PNET_ROOT)((PFCB)(smbFcb->ContainingFcb))->pNetRoot;
  7824. fFoundAtleastOne = TRUE;
  7825. LeaveShadowCrit();
  7826. RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE);
  7827. RxForceFinalizeAllVNetRoots(pNetRoot);
  7828. RxReleasePrefixTableLock( &RxNetNameTable );
  7829. EnterShadowCrit();
  7830. pListEntry = xCscFcbsList.Flink;
  7831. //
  7832. // ...start again
  7833. //
  7834. continue;
  7835. }
  7836. else
  7837. {
  7838. // DbgPrint("Skipping orphaned FCB for hShadow=%x \n", smbFcb->hShadow);
  7839. }
  7840. }
  7841. pListEntry = pListEntry->Flink;
  7842. }
  7843. LeaveShadowCrit();
  7844. return fFoundAtleastOne;
  7845. }
  7846. VOID
  7847. CreateFakeFind32(
  7848. HSHADOW hDir,
  7849. _WIN32_FIND_DATA *Find32,
  7850. PRX_CONTEXT RxContext,
  7851. BOOLEAN LastComponentInName
  7852. )
  7853. /*++
  7854. Routine Description:
  7855. Creates a win32 structure for offline use. This is also created for DFS directories
  7856. Arguments:
  7857. hDir directory inode where the item is to be created
  7858. Find32 win32 data to be fixed up
  7859. RxContext
  7860. LastComponentInname If this is not true, then this must be a directory
  7861. Return Value:
  7862. None.
  7863. --*/
  7864. {
  7865. KeQuerySystemTime(((PLARGE_INTEGER)(&Find32->ftCreationTime)));
  7866. Find32->ftLastAccessTime = Find32->ftLastWriteTime = Find32->ftCreationTime;
  7867. //already zero Find32->nFileSizeHigh = Find32->nFileSizeLow = 0;
  7868. if (!LastComponentInName) {
  7869. // must be a directory....don't know the other attribs without going to get them
  7870. Find32->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  7871. } else {
  7872. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  7873. Find32->dwFileAttributes = cp->FileAttributes;
  7874. Find32->dwFileAttributes &= (FILE_ATTRIBUTE_READONLY |
  7875. FILE_ATTRIBUTE_HIDDEN |
  7876. FILE_ATTRIBUTE_SYSTEM |
  7877. FILE_ATTRIBUTE_ARCHIVE );
  7878. if (FlagOn(cp->CreateOptions,FILE_DIRECTORY_FILE)) {
  7879. Find32->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  7880. }
  7881. }
  7882. MRxSmbCscGenerate83NameAsNeeded(hDir,
  7883. &Find32->cFileName[0],
  7884. &Find32->cAlternateFileName[0]);
  7885. }
  7886. NTSTATUS
  7887. OkToDeleteObject(
  7888. HSHADOW hDir,
  7889. HSHADOW hShadow,
  7890. _WIN32_FIND_DATA *Find32,
  7891. ULONG uShadowStatus,
  7892. BOOLEAN fDisconnected
  7893. )
  7894. /*++
  7895. Routine Description:
  7896. Check to see if the file can be deleted.
  7897. Arguments:
  7898. Return Value:
  7899. STATUS_SUCCESS if Ok to delete, some appropriate status otherwise
  7900. --*/
  7901. {
  7902. BOOLEAN fHasDescendents = FALSE;
  7903. NTSTATUS LocalStatus = STATUS_SUCCESS;
  7904. // in disconnected mode, we don't allow deletions of directories
  7905. // which have been cached while online
  7906. // This automatically takes care of the roots
  7907. if (fDisconnected)
  7908. {
  7909. if (!IsFile(Find32->dwFileAttributes))
  7910. {
  7911. if(!mShadowLocallyCreated(uShadowStatus)) {
  7912. LocalStatus = STATUS_ONLY_IF_CONNECTED;
  7913. goto FINALLY; //bailout;
  7914. }
  7915. }
  7916. ASSERT(hDir);
  7917. }
  7918. // if we are deleting a directory, and it has descendents
  7919. // then fail with appropriate error
  7920. if (!IsFile(Find32->dwFileAttributes))
  7921. {
  7922. if(HasDescendentsHShadow(hDir, hShadow, &fHasDescendents) >= 0)
  7923. {
  7924. if (fHasDescendents)
  7925. {
  7926. LocalStatus = STATUS_DIRECTORY_NOT_EMPTY;
  7927. goto FINALLY; //bailout;
  7928. }
  7929. }
  7930. else
  7931. {
  7932. goto FINALLY; //bailout;
  7933. }
  7934. }
  7935. // don't delete if readonly
  7936. if (Find32->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
  7937. {
  7938. LocalStatus = STATUS_CANNOT_DELETE;
  7939. goto FINALLY; //bailout;
  7940. }
  7941. FINALLY:
  7942. return LocalStatus;
  7943. }
  7944. int IoctlGetGlobalStatus(
  7945. ULONG SessionId,
  7946. LPGLOBALSTATUS lpGS
  7947. )
  7948. /*++
  7949. Routine Description:
  7950. Parameters:
  7951. Return Value:
  7952. Notes:
  7953. --*/
  7954. {
  7955. #if 0
  7956. if (sGS.uFlagsEvents & FLAG_GLOBALSTATUS_NO_NET)
  7957. DbgPrint("IoctlGetGlobalStatus: FLAG_GLOBALSTATUS_NO_NET\r\n");
  7958. if (sGS.uFlagsEvents & FLAG_GLOBALSTATUS_SHARE_DISCONNECTED)
  7959. DbgPrint("IoctlGetGlobalStatus: FLAG_GLOBALSTATUS_SHARE_DISCONNECTED share=%d\r\n",
  7960. sGS.hShareDisconnected);
  7961. #endif
  7962. // DbgPrint("IOCTL_GETGLOBALSTATUS Transitioning 0x%x sess 0x%x vs 0x%x\n",
  7963. // CscServerEntryBeingTransitioned,
  7964. // SessionId,
  7965. // CscSessionIdCausingTransition);
  7966. EnterShadowCrit();
  7967. GetShadowSpaceInfo(&(sGS.sST));
  7968. *lpGS = sGS;
  7969. lpGS->uDatabaseErrorFlags = QueryDatabaseErrorFlags();
  7970. if ((sGS.uFlagsEvents & FLAG_GLOBALSTATUS_SHARE_DISCONNECTED) != 0) {
  7971. // Only the session causing a transition will see the SHARE_DISCONNECT bit, and
  7972. // reset it.
  7973. if (SessionId == CscSessionIdCausingTransition)
  7974. sGS.uFlagsEvents = 0;
  7975. else
  7976. lpGS->uFlagsEvents &= ~FLAG_GLOBALSTATUS_SHARE_DISCONNECTED;
  7977. } else {
  7978. sGS.uFlagsEvents = 0;
  7979. }
  7980. LeaveShadowCrit();
  7981. return (1);
  7982. }
  7983. NTSTATUS
  7984. IoctlGetDebugInfo(
  7985. PRX_CONTEXT RxContext,
  7986. PBYTE InputBuffer,
  7987. ULONG InputBufferLength,
  7988. PBYTE OutputBuffer,
  7989. ULONG OutputBufferLength)
  7990. {
  7991. ULONG Cmd = 0;
  7992. NTSTATUS NtStatus = STATUS_SUCCESS;
  7993. PIOCTL_GET_DEBUG_INFO_ARG pInfoArg = NULL;
  7994. PBYTE pOutBuf = OutputBuffer;
  7995. KPROCESSOR_MODE RequestorMode;
  7996. // DbgPrint("In IoctlGetDebugInfo(IP=0x%x,IL=0x%x,OP=0x%x,OL=0x%x)\n",
  7997. // InputBuffer,
  7998. // InputBufferLength,
  7999. // OutputBuffer,
  8000. // OutputBufferLength);
  8001. if (
  8002. InputBufferLength < sizeof(ULONG)
  8003. ||
  8004. OutputBufferLength < FIELD_OFFSET(IOCTL_GET_DEBUG_INFO_ARG, ServerEntryObject)
  8005. ) {
  8006. return STATUS_INVALID_PARAMETER;
  8007. }
  8008. RequestorMode = RxContext->CurrentIrp->RequestorMode;
  8009. if (RequestorMode != KernelMode) {
  8010. try {
  8011. ProbeForRead(InputBuffer, InputBufferLength, 1);
  8012. Cmd = *(PULONG)InputBuffer;
  8013. } except(EXCEPTION_EXECUTE_HANDLER) {
  8014. NtStatus = STATUS_INVALID_PARAMETER;
  8015. }
  8016. if (NtStatus != STATUS_SUCCESS)
  8017. return NtStatus;
  8018. pOutBuf = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, OutputBufferLength, RX_MISC_POOLTAG);
  8019. if (pOutBuf == NULL)
  8020. return STATUS_INSUFFICIENT_RESOURCES;
  8021. }
  8022. // DbgPrint("Cmd=%d\n", Cmd);
  8023. if (Cmd == DEBUG_INFO_SERVERLIST) {
  8024. PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
  8025. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = NULL;
  8026. PSMBCEDB_SERVER_ENTRY_ARG pServerEntryArg = NULL;
  8027. PSMBCEDB_NETROOT_ENTRY_ARG pNetRootEntryArg = NULL;
  8028. ULONG Size = 0;
  8029. ULONG ServerEntryCount = 0;
  8030. ULONG NetRootEntryCount = 0;
  8031. PCHAR pCh = NULL;
  8032. ULONG i;
  8033. ULONG j;
  8034. //
  8035. // Two passes - 1st to check size, 2nd to marshal the info in
  8036. //
  8037. SmbCeAcquireResource();
  8038. try {
  8039. Size = 0;
  8040. ServerEntryCount = 0;
  8041. pServerEntry = SmbCeGetFirstServerEntry();
  8042. while (pServerEntry != NULL) {
  8043. ServerEntryCount++;
  8044. Size += pServerEntry->Name.Length + sizeof(WCHAR) +
  8045. pServerEntry->DomainName.Length + sizeof(WCHAR) +
  8046. pServerEntry->DfsRootName.Length + sizeof(WCHAR) +
  8047. pServerEntry->DnsName.Length + sizeof(WCHAR);
  8048. NetRootEntryCount = 0;
  8049. pNetRootEntry = SmbCeGetFirstNetRootEntry(pServerEntry);
  8050. while (pNetRootEntry != NULL) {
  8051. NetRootEntryCount++;
  8052. Size += pNetRootEntry->Name.Length + sizeof(WCHAR);
  8053. pNetRootEntry = SmbCeGetNextNetRootEntry(pServerEntry,pNetRootEntry);
  8054. }
  8055. Size += sizeof(SMBCEDB_NETROOT_ENTRY_ARG) * NetRootEntryCount;
  8056. pServerEntry = SmbCeGetNextServerEntry(pServerEntry);
  8057. }
  8058. } except(EXCEPTION_EXECUTE_HANDLER) {
  8059. NtStatus = STATUS_INVALID_PARAMETER;
  8060. }
  8061. // DbgPrint("Sizecheck1: ServerEntryCount=%d,NtStatus=0x%x\n", ServerEntryCount, NtStatus);
  8062. if (NtStatus != STATUS_SUCCESS || ServerEntryCount == 0) {
  8063. SmbCeReleaseResource();
  8064. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8065. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8066. pInfoArg->Status = NtStatus;
  8067. goto AllDone;
  8068. }
  8069. Size += FIELD_OFFSET(IOCTL_GET_DEBUG_INFO_ARG, ServerEntryObject[ServerEntryCount]);
  8070. // DbgPrint("Sizecheck2: Size=%d(0x%x)\n", Size, Size);
  8071. if (Size > OutputBufferLength) {
  8072. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8073. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8074. NtStatus = STATUS_BUFFER_TOO_SMALL;
  8075. pInfoArg->Status = NtStatus;
  8076. pInfoArg->EntryCount = Size;
  8077. SmbCeReleaseResource();
  8078. goto AllDone;
  8079. }
  8080. //
  8081. // Marshal it in
  8082. //
  8083. // Start of buffer is the array of server entries
  8084. // Middle are the arrays of netroots
  8085. // End contains all the strings
  8086. //
  8087. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8088. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8089. pInfoArg->Status = 0;
  8090. pInfoArg->Version = 4;
  8091. pInfoArg->EntryCount = ServerEntryCount;
  8092. pCh = (PCHAR)(pOutBuf + OutputBufferLength);
  8093. pNetRootEntryArg = (PSMBCEDB_NETROOT_ENTRY_ARG)
  8094. &pInfoArg->ServerEntryObject[ServerEntryCount];
  8095. ServerEntryCount = 0;
  8096. pServerEntry = SmbCeGetFirstServerEntry();
  8097. while (pServerEntry != NULL) {
  8098. pServerEntryArg = &pInfoArg->ServerEntryObject[ServerEntryCount];
  8099. pServerEntryArg->ServerStatus = pServerEntry->ServerStatus;
  8100. pServerEntryArg->SecuritySignaturesEnabled = pServerEntry->SecuritySignaturesEnabled;
  8101. pServerEntryArg->CscState = pServerEntry->Server.CscState;
  8102. pServerEntryArg->IsFakeDfsServerForOfflineUse =
  8103. pServerEntry->Server.IsFakeDfsServerForOfflineUse;
  8104. pServerEntryArg->IsPinnedOffline = pServerEntry->Server.IsPinnedOffline;
  8105. pServerEntryArg->pNetRoots = pNetRootEntryArg;
  8106. pCh -= pServerEntry->Name.Length + sizeof(WCHAR);
  8107. pServerEntryArg->Name = (PWCHAR) pCh;
  8108. RtlCopyMemory(pCh, pServerEntry->Name.Buffer, pServerEntry->Name.Length);
  8109. pCh -= pServerEntry->DomainName.Length + sizeof(WCHAR);
  8110. pServerEntryArg->DomainName = (PWCHAR)pCh;
  8111. RtlCopyMemory(pCh, pServerEntry->DomainName.Buffer, pServerEntry->DomainName.Length);
  8112. pCh -= pServerEntry->DfsRootName.Length + sizeof(WCHAR) + 1;;
  8113. pServerEntryArg->DfsRootName = (PWCHAR)pCh;
  8114. RtlCopyMemory(pCh, pServerEntry->DfsRootName.Buffer, pServerEntry->DfsRootName.Length);
  8115. pCh -= pServerEntry->DnsName.Length + sizeof(WCHAR);
  8116. pServerEntryArg->DnsName = (PWCHAR)pCh;
  8117. RtlCopyMemory(pCh, pServerEntry->DnsName.Buffer, pServerEntry->DnsName.Length);
  8118. NetRootEntryCount = 0;
  8119. pNetRootEntry = SmbCeGetFirstNetRootEntry(pServerEntry);
  8120. while (pNetRootEntry != NULL) {
  8121. pNetRootEntryArg->MaximalAccessRights = pNetRootEntry->MaximalAccessRights;
  8122. pNetRootEntryArg->GuestMaximalAccessRights=pNetRootEntry->GuestMaximalAccessRights;
  8123. pNetRootEntryArg->DfsAware = pNetRootEntry->NetRoot.DfsAware;
  8124. pNetRootEntryArg->hShare = pNetRootEntry->NetRoot.sCscRootInfo.hShare;
  8125. pNetRootEntryArg->hRootDir = pNetRootEntry->NetRoot.sCscRootInfo.hRootDir;
  8126. pNetRootEntryArg->ShareStatus = pNetRootEntry->NetRoot.sCscRootInfo.ShareStatus;
  8127. pNetRootEntryArg->CscEnabled = pNetRootEntry->NetRoot.CscEnabled;
  8128. pNetRootEntryArg->CscFlags = pNetRootEntry->NetRoot.CscFlags;
  8129. pNetRootEntryArg->CscShadowable = pNetRootEntry->NetRoot.CscShadowable;
  8130. pNetRootEntryArg->Disconnected = pNetRootEntry->NetRoot.Disconnected;
  8131. pCh -= pNetRootEntry->Name.Length + sizeof(WCHAR);
  8132. pNetRootEntryArg->Name = (PWCHAR)pCh;
  8133. RtlCopyMemory(pCh, pNetRootEntry->Name.Buffer, pNetRootEntry->Name.Length);
  8134. NetRootEntryCount++;
  8135. pNetRootEntryArg++;
  8136. pNetRootEntry = SmbCeGetNextNetRootEntry(pServerEntry,pNetRootEntry);
  8137. }
  8138. pServerEntryArg->NetRootEntryCount = NetRootEntryCount;
  8139. ServerEntryCount++;
  8140. pServerEntry = SmbCeGetNextServerEntry(pServerEntry);
  8141. }
  8142. SmbCeReleaseResource();
  8143. //
  8144. // Now do fixups
  8145. //
  8146. for (i = 0; i < pInfoArg->EntryCount; i++) {
  8147. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].Name, pOutBuf);
  8148. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].DomainName, pOutBuf);
  8149. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].DfsRootName, pOutBuf);
  8150. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].DnsName, pOutBuf);
  8151. for (j = 0; j < pInfoArg->ServerEntryObject[i].NetRootEntryCount; j++)
  8152. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].pNetRoots[j].Name, pOutBuf);
  8153. POINTER_TO_OFFSET(pInfoArg->ServerEntryObject[i].pNetRoots, pOutBuf);
  8154. }
  8155. } else if (Cmd == DEBUG_INFO_CSCFCBSLIST) {
  8156. PIOCTL_GET_DEBUG_INFO_ARG pInfoArg = NULL;
  8157. PMRX_SMB_FCB_ENTRY_ARG pFcbEntryArg = NULL;
  8158. PMRX_SMB_FCB pSmbFcb = NULL;
  8159. PLIST_ENTRY pListEntry = NULL;
  8160. ULONG Size = 0;
  8161. PCHAR pCh = NULL;
  8162. ULONG FcbCount = 0;
  8163. ULONG i;
  8164. EnterShadowCritRx(RxContext);
  8165. pListEntry = xCscFcbsList.Flink;
  8166. FcbCount = 0;
  8167. while (pListEntry != &xCscFcbsList) {
  8168. FcbCount++;
  8169. pSmbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  8170. pListEntry,
  8171. MRX_SMB_FCB,
  8172. ShadowReverseTranslationLinks);
  8173. Size += pSmbFcb->MinimalCscSmbFcb.uniDfsPrefix.Length + sizeof(WCHAR) +
  8174. pSmbFcb->MinimalCscSmbFcb.uniActualPrefix.Length + sizeof(WCHAR);
  8175. pListEntry = pListEntry->Flink;
  8176. }
  8177. Size += FIELD_OFFSET(IOCTL_GET_DEBUG_INFO_ARG, FcbEntryObject[FcbCount]);
  8178. if (Size > OutputBufferLength) {
  8179. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8180. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8181. NtStatus = STATUS_BUFFER_TOO_SMALL;
  8182. pInfoArg->Status = NtStatus;
  8183. pInfoArg->EntryCount = Size;
  8184. LeaveShadowCritRx(RxContext);
  8185. goto AllDone;
  8186. }
  8187. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8188. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8189. pInfoArg->Status = 0;
  8190. pInfoArg->Version = 1;
  8191. pInfoArg->EntryCount = FcbCount;
  8192. FcbCount = 0;
  8193. pCh = (PCHAR)(pOutBuf + OutputBufferLength);
  8194. pListEntry = xCscFcbsList.Flink;
  8195. while (pListEntry != &xCscFcbsList) {
  8196. pFcbEntryArg = &pInfoArg->FcbEntryObject[FcbCount];
  8197. pSmbFcb = (PMRX_SMB_FCB)CONTAINING_RECORD(
  8198. pListEntry,
  8199. MRX_SMB_FCB,
  8200. ShadowReverseTranslationLinks);
  8201. pFcbEntryArg->MFlags = pSmbFcb->MFlags;
  8202. pFcbEntryArg->Tid = pSmbFcb->Tid;
  8203. pFcbEntryArg->ShadowIsCorrupt = pSmbFcb->ShadowIsCorrupt;
  8204. pFcbEntryArg->hShadow = pSmbFcb->hShadow;
  8205. pFcbEntryArg->hParentDir = pSmbFcb->hParentDir;
  8206. pFcbEntryArg->hShadowRenamed = pSmbFcb->hShadowRenamed;
  8207. pFcbEntryArg->ShadowStatus = pSmbFcb->ShadowStatus;
  8208. pFcbEntryArg->LocalFlags = pSmbFcb->LocalFlags;
  8209. pFcbEntryArg->LastComponentOffset = pSmbFcb->LastComponentOffset;
  8210. pFcbEntryArg->LastComponentLength = pSmbFcb->LastComponentLength;
  8211. pFcbEntryArg->hShare = pSmbFcb->sCscRootInfo.hShare;
  8212. pFcbEntryArg->hRootDir = pSmbFcb->sCscRootInfo.hRootDir;
  8213. pFcbEntryArg->ShareStatus = pSmbFcb->sCscRootInfo.ShareStatus;
  8214. pFcbEntryArg->Flags = pSmbFcb->sCscRootInfo.Flags;
  8215. pCh -= pSmbFcb->MinimalCscSmbFcb.uniDfsPrefix.Length + sizeof(WCHAR);
  8216. pFcbEntryArg->DfsPrefix = (PWCHAR)pCh;
  8217. RtlCopyMemory(
  8218. pCh,
  8219. pSmbFcb->MinimalCscSmbFcb.uniDfsPrefix.Buffer,
  8220. pSmbFcb->MinimalCscSmbFcb.uniDfsPrefix.Length);
  8221. pCh -= pSmbFcb->MinimalCscSmbFcb.uniActualPrefix.Length + sizeof(WCHAR);
  8222. pFcbEntryArg->ActualPrefix = (PWCHAR)pCh;
  8223. RtlCopyMemory(
  8224. pCh,
  8225. pSmbFcb->MinimalCscSmbFcb.uniActualPrefix.Buffer,
  8226. pSmbFcb->MinimalCscSmbFcb.uniActualPrefix.Length);
  8227. FcbCount++;
  8228. pListEntry = pListEntry->Flink;
  8229. }
  8230. LeaveShadowCritRx(RxContext);
  8231. for (i = 0; i < pInfoArg->EntryCount; i++) {
  8232. POINTER_TO_OFFSET(pInfoArg->FcbEntryObject[i].DfsPrefix, pOutBuf);
  8233. POINTER_TO_OFFSET(pInfoArg->FcbEntryObject[i].ActualPrefix, pOutBuf);
  8234. }
  8235. } else {
  8236. RtlZeroMemory(pOutBuf, OutputBufferLength);
  8237. pInfoArg = (PIOCTL_GET_DEBUG_INFO_ARG) pOutBuf;
  8238. NtStatus = STATUS_INVALID_PARAMETER;
  8239. pInfoArg->Status = NtStatus;
  8240. goto AllDone;
  8241. }
  8242. AllDone:
  8243. if (RequestorMode != KernelMode) {
  8244. try {
  8245. ProbeForWrite(OutputBuffer, OutputBufferLength, 1);
  8246. RtlCopyMemory(OutputBuffer, pOutBuf, OutputBufferLength);
  8247. } except(EXCEPTION_EXECUTE_HANDLER) {
  8248. NtStatus = STATUS_INVALID_PARAMETER;
  8249. }
  8250. }
  8251. if (pOutBuf != OutputBuffer)
  8252. RxFreePool(pOutBuf);
  8253. return NtStatus;
  8254. }