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.

1788 lines
51 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. DConnect.c
  5. Abstract:
  6. This module implements the routines by which the a server\share comes
  7. up in a disconnected state.
  8. Author:
  9. Joe Linn [JoeLinn] 5-may-1997
  10. Revision History:
  11. Shishir Pardikar(shishirp) Various bug fixes Aug 1997 onwards
  12. Shishir Pardikar(shishirp) Change Notification In disconnected state 27-aug-1998
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #pragma code_seg("PAGE")
  18. #ifdef MRXSMB_BUILD_FOR_CSC_DCON
  19. extern DEBUG_TRACE_CONTROLPOINT RX_DEBUG_TRACE_MRXSMBCSC;
  20. #define Dbg (DEBUG_TRACE_MRXSMBCSC)
  21. WCHAR wchSingleBackSlash = '\\';
  22. UNICODE_STRING vRootString = {2,2,&wchSingleBackSlash}; // root string for change notification
  23. WCHAR vtzOfflineVolume[] = L"Offline";
  24. typedef struct tagNOTIFYEE_FOBX
  25. {
  26. LIST_ENTRY NextNotifyeeFobx;
  27. MRX_FOBX *pFobx;
  28. }
  29. NOTIFYEE_FOBX, *PNOTIFYEE_FOBX;
  30. PNOTIFYEE_FOBX
  31. PIsFobxInTheList(
  32. PLIST_ENTRY pNotifyeeFobxList,
  33. PMRX_FOBX pFobx
  34. );
  35. BOOL
  36. FCleanupAllNotifyees(
  37. PNOTIFY_SYNC pNotifySync,
  38. PLIST_ENTRY pDirNotifyList,
  39. PLIST_ENTRY pNotifyeeFobxList,
  40. PFAST_MUTEX pNotifyeeFobxListMutex
  41. );
  42. PMRX_SMB_FCB
  43. MRxSmbCscRecoverMrxFcbFromFdb (
  44. IN PFDB Fdb
  45. );
  46. NTSTATUS
  47. MRxSmbCscNegotiateDisconnected(
  48. PSMBCEDB_SERVER_ENTRY pServerEntry
  49. )
  50. /*++
  51. Routine Description:
  52. This routine takes the place of negotiating when the special tranport marker
  53. has been detected in the negotiate routine.
  54. Arguments:
  55. Return Value:
  56. Notes:
  57. --*/
  58. {
  59. NTSTATUS Status;
  60. RxDbgTrace(0,Dbg,("MRxSmbCscNegotiateDisconnected %08lx %08lx\n",
  61. pServerEntry, pServerEntry->pTransport));
  62. if (MRxSmbIsCscEnabledForDisconnected) {
  63. pServerEntry->ServerStatus = STATUS_SUCCESS;
  64. SmbCeUpdateServerEntryState(
  65. pServerEntry,
  66. SMBCEDB_ACTIVE);
  67. //no need for anyting else!
  68. Status = STATUS_SUCCESS;
  69. } else {
  70. Status = STATUS_HOST_UNREACHABLE;
  71. }
  72. return Status;
  73. }
  74. NTSTATUS
  75. MRxSmbCscDisconnectedConnect (
  76. IN OUT PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange
  77. )
  78. /*++
  79. Routine Description:
  80. This routine takes the place of connecting when we're doing disconnected
  81. mode. what we do is to simulate what would happen if the exchange had come thru
  82. ParseSmbHeader.
  83. Arguments:
  84. Return Value:
  85. Notes:
  86. --*/
  87. {
  88. NTSTATUS Status = STATUS_PENDING;
  89. BOOLEAN PostFinalize;
  90. PSMBCEDB_SERVER_ENTRY pServerEntry;
  91. // PSMBCEDB_SESSION_ENTRY pSessionEntry;
  92. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  93. SMBCEDB_OBJECT_STATE SessionState;
  94. SMBCEDB_OBJECT_STATE NetRootState;
  95. PMRX_V_NET_ROOT VNetRoot;
  96. PMRX_NET_ROOT NetRoot;
  97. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  98. CSC_SHARE_HANDLE hShare;
  99. CSC_SHADOW_HANDLE hRootDir,hShadow;
  100. PRX_CONTEXT RxContext = pNetRootExchange->pCreateNetRootContext->RxContext;
  101. VNetRoot = pNetRootExchange->SmbCeContext.pVNetRoot;
  102. NetRoot = VNetRoot->pNetRoot;
  103. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(VNetRoot);
  104. pServerEntry = SmbCeGetExchangeServerEntry(&pNetRootExchange->Exchange);
  105. // pSessionEntry = SmbCeGetExchangeSessionEntry(&pNetRootExchange->Exchange);
  106. pNetRootEntry = SmbCeGetExchangeNetRootEntry(&pNetRootExchange->Exchange);
  107. if ((NetRoot->Type == NET_ROOT_DISK) ||
  108. (NetRoot->Type == NET_ROOT_WILD)) {
  109. ASSERT(MRxSmbIsCscEnabledForDisconnected);
  110. RxDbgTrace(0,Dbg,("MRxSmbCscDisconnectedConnect %08lx %08lx\n",
  111. pServerEntry, pServerEntry->pTransport));
  112. // init netrootentry. This will be inited by the ObtainShareHandles call
  113. pNetRootEntry->NetRoot.CscEnabled = TRUE; // assume csc is enabled
  114. pNetRootEntry->NetRoot.CscShadowable = FALSE; // ACHTUNG, don't set this to TRUE
  115. // otherwise a share will get created
  116. // in disconnectd state
  117. pNetRootEntry->NetRoot.NetRootType = NET_ROOT_DISK;
  118. hShare = pNetRootEntry->NetRoot.sCscRootInfo.hShare;
  119. if (hShare==0) {
  120. NTSTATUS LocalStatus;
  121. EnterShadowCrit();
  122. LocalStatus = MRxSmbCscObtainShareHandles(
  123. NetRoot->pNetRootName,
  124. TRUE,
  125. FALSE,
  126. SmbCeGetAssociatedNetRootEntry(NetRoot)
  127. );
  128. if (LocalStatus != STATUS_SUCCESS) {
  129. RxDbgTrace(0, Dbg,
  130. ("MRxSmbCscDisconnectedConnect no server handle -> %08xl %08lx\n",
  131. RxContext,LocalStatus ));
  132. } else {
  133. hShare = pNetRootEntry->NetRoot.sCscRootInfo.hShare;
  134. }
  135. LeaveShadowCrit();
  136. }
  137. } else {
  138. hShare = 0;
  139. }
  140. //ok, we have to do everything that parsesmbheader would have done
  141. if (hShare==0) {
  142. //can't find it in the table......just fail........
  143. pNetRootExchange->Status = STATUS_BAD_NETWORK_NAME;
  144. // SessionState = SMBCEDB_INVALID;
  145. NetRootState = SMBCEDB_MARKED_FOR_DELETION;
  146. } else {
  147. pNetRootExchange->Status = STATUS_SUCCESS;
  148. pNetRootExchange->SmbStatus = STATUS_SUCCESS;
  149. // SessionState = SMBCEDB_ACTIVE;
  150. //NETROOT STUFF
  151. //some of the netroot stuff is earlier....before the lookup
  152. NetRootState = SMBCEDB_ACTIVE;
  153. }
  154. #if 0
  155. SmbCeUpdateSessionEntryState(
  156. pSessionEntry,
  157. SessionState);
  158. #endif
  159. SmbCeUpdateVNetRootContextState(
  160. pVNetRootContext,
  161. NetRootState);
  162. SmbConstructNetRootExchangeFinalize(
  163. &pNetRootExchange->Exchange,
  164. &PostFinalize);
  165. ASSERT(!PostFinalize);
  166. return Status;
  167. }
  168. typedef struct _MRXSMBCSC_QUERYDIR_INFO {
  169. WCHAR Pattern[2];
  170. FINDSHADOW sFS;
  171. ULONG uShadowStatus;
  172. _WIN32_FIND_DATA Find32;
  173. ULONG NumCallsSoFar;
  174. BOOLEAN IsNonEmpty;
  175. } MRXSMBCSC_QUERYDIR_INFO, *PMRXSMBCSC_QUERYDIR_INFO;
  176. NTSTATUS
  177. MRxSmbCscLoadNextDirectoryEntry(
  178. IN OUT PRX_CONTEXT RxContext,
  179. IN OUT PMRXSMBCSC_QUERYDIR_INFO QuerydirInfo,
  180. OUT LPHSHADOW hShadowp
  181. )
  182. {
  183. NTSTATUS Status;
  184. int iRet;
  185. HSHADOW hTmp=0; //???
  186. if (QuerydirInfo->NumCallsSoFar <= 1)
  187. {
  188. iRet = GetAncestorsHSHADOW(QuerydirInfo->sFS.hDir, &hTmp, NULL);
  189. if (iRet >= SRET_OK)
  190. {
  191. iRet = GetShadowInfo(hTmp,
  192. QuerydirInfo->sFS.hDir,
  193. &QuerydirInfo->Find32,
  194. &QuerydirInfo->uShadowStatus,
  195. NULL
  196. );
  197. if (iRet >= SRET_OK)
  198. {
  199. if (QuerydirInfo->NumCallsSoFar == 0 )
  200. {
  201. QuerydirInfo->Find32.cFileName[0] = (WCHAR)'.';
  202. QuerydirInfo->Find32.cFileName[1] = 0;
  203. QuerydirInfo->Find32.cAlternateFileName[0] = (WCHAR)'.';
  204. QuerydirInfo->Find32.cAlternateFileName[1] = 0;
  205. }
  206. else
  207. {
  208. QuerydirInfo->Find32.cFileName[0] = (WCHAR)'.';
  209. QuerydirInfo->Find32.cFileName[1] = (WCHAR)'.';
  210. QuerydirInfo->Find32.cFileName[2] = 0;
  211. QuerydirInfo->Find32.cAlternateFileName[0] = (WCHAR)'.';
  212. QuerydirInfo->Find32.cAlternateFileName[1] = (WCHAR)'.';
  213. QuerydirInfo->Find32.cAlternateFileName[2] = 0;
  214. }
  215. }
  216. }
  217. }
  218. else if (QuerydirInfo->NumCallsSoFar == 2)
  219. {
  220. iRet = FindOpenHSHADOW(&QuerydirInfo->sFS,
  221. &hTmp,
  222. &QuerydirInfo->Find32,
  223. &QuerydirInfo->uShadowStatus,
  224. NULL);
  225. } else {
  226. iRet = FindNextHSHADOW(&QuerydirInfo->sFS,
  227. &hTmp,
  228. &QuerydirInfo->Find32,
  229. &QuerydirInfo->uShadowStatus,
  230. NULL);
  231. }
  232. if (iRet < SRET_OK)
  233. {
  234. Status = STATUS_UNSUCCESSFUL;
  235. }
  236. else
  237. {
  238. if (QuerydirInfo->NumCallsSoFar >= 2)
  239. {
  240. if (hTmp)
  241. {
  242. *hShadowp = hTmp;
  243. Status = STATUS_SUCCESS;
  244. }
  245. else
  246. {
  247. Status = STATUS_NO_MORE_FILES;
  248. }
  249. }
  250. else
  251. {
  252. *hShadowp = hTmp;
  253. Status = STATUS_SUCCESS;
  254. }
  255. }
  256. QuerydirInfo->NumCallsSoFar++;
  257. QuerydirInfo->IsNonEmpty = (Status==STATUS_SUCCESS);
  258. return(Status);
  259. }
  260. NTSTATUS
  261. MRxSmbDCscQueryDirectory (
  262. IN OUT PRX_CONTEXT RxContext
  263. )
  264. /*++
  265. Routine Description:
  266. Arguments:
  267. RxContext - the RDBSS context
  268. Return Value:
  269. NTSTATUS - The return status for the operation
  270. Notes:
  271. --*/
  272. {
  273. NTSTATUS Status;
  274. RxCaptureFcb;
  275. RxCaptureFobx;
  276. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  277. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  278. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  279. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  280. FILE_INFORMATION_CLASS FileInformationClass;
  281. PBYTE pBuffer;
  282. PULONG pLengthRemaining;
  283. PFILE_DIRECTORY_INFORMATION pPreviousBuffer = NULL;
  284. PMRXSMBCSC_QUERYDIR_INFO QuerydirInfo;
  285. BOOLEAN EnteredCriticalSection = FALSE;
  286. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  287. = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  288. BOOLEAN Disconnected;
  289. ULONG EntriesReturned = 0;
  290. BOOLEAN IsResume = FALSE;
  291. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  292. if (!Disconnected) {
  293. return (STATUS_CONNECTION_DISCONNECTED);
  294. }
  295. // if there is reumeinfo but it is not the one that CSC allocated,
  296. // we want to fail this find.
  297. if (smbFobx->Enumeration.ResumeInfo &&
  298. !FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_IS_CSC_SEARCH))
  299. {
  300. return (STATUS_NO_MORE_FILES);
  301. }
  302. FileInformationClass = RxContext->Info.FileInformationClass;
  303. pBuffer = RxContext->Info.Buffer;
  304. pLengthRemaining = &RxContext->Info.LengthRemaining;
  305. RxDbgTrace(+1, Dbg,
  306. ("MRxSmbDCscQueryDirectory entry(%08lx)...%08lx %08lx %08lx %08lx\n",
  307. RxContext,
  308. FileInformationClass,pBuffer,*pLengthRemaining,
  309. smbFobx->Enumeration.ResumeInfo ));
  310. if (smbFobx->Enumeration.ResumeInfo == NULL) {
  311. PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
  312. if (smbFobx->Enumeration.WildCardsFound = FsRtlDoesNameContainWildCards(Template)){
  313. //we need an upcased template for
  314. RtlUpcaseUnicodeString( Template, Template, FALSE );
  315. }
  316. //allocate and initialize the structure
  317. QuerydirInfo = (PMRXSMBCSC_QUERYDIR_INFO)RxAllocatePoolWithTag(
  318. PagedPool,
  319. sizeof(MRXSMBCSC_QUERYDIR_INFO),
  320. MRXSMB_DIRCTL_POOLTAG);
  321. if (QuerydirInfo==NULL) {
  322. RxDbgTrace(0, Dbg, (" --> Couldn't get the QuerydirInfo!\n"));
  323. Status = STATUS_INSUFFICIENT_RESOURCES;
  324. goto FINALLY;
  325. }
  326. smbFobx->Enumeration.Flags |= SMBFOBX_ENUMFLAG_IS_CSC_SEARCH;
  327. smbFobx->Enumeration.ResumeInfo = (PMRX_SMB_DIRECTORY_RESUME_INFO)QuerydirInfo;
  328. RtlZeroMemory(QuerydirInfo,sizeof(*QuerydirInfo));
  329. QuerydirInfo->Pattern[0] = L'*'; //[1] is already null
  330. QuerydirInfo->sFS.hDir = smbFcb->hShadow;
  331. QuerydirInfo->sFS.uSrchFlags = FLAG_FINDSHADOW_META
  332. |FLAG_FINDSHADOW_ALLOW_NORMAL
  333. |FLAG_FINDSHADOW_NEWSTYLE;
  334. QuerydirInfo->sFS.uAttrib = 0xffffffff;
  335. QuerydirInfo->sFS.lpPattern = &QuerydirInfo->Pattern[0];
  336. QuerydirInfo->sFS.lpfnMMProc = FsobjMMProc;
  337. } else {
  338. QuerydirInfo = (PMRXSMBCSC_QUERYDIR_INFO)(smbFobx->Enumeration.ResumeInfo);
  339. ASSERT(FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_IS_CSC_SEARCH));
  340. IsResume = TRUE;
  341. }
  342. EnterShadowCrit();
  343. EnteredCriticalSection = TRUE;
  344. for (;;) {
  345. NTSTATUS LoadStatus;
  346. BOOLEAN FilterFailure;
  347. UNICODE_STRING FileName,AlternateFileName;
  348. ULONG SpaceNeeded;
  349. PBYTE pRememberBuffer;
  350. _WIN32_FIND_DATA *Find32 = &QuerydirInfo->Find32;
  351. BOOLEAN BufferOverflow;
  352. HSHADOW hShadow = 0;
  353. if (!QuerydirInfo->IsNonEmpty) {
  354. LoadStatus = MRxSmbCscLoadNextDirectoryEntry(RxContext,QuerydirInfo, &hShadow);
  355. if (LoadStatus!=STATUS_SUCCESS) {
  356. smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_IS_CSC_SEARCH;
  357. Status = (EntriesReturned==0)?STATUS_NO_MORE_FILES:STATUS_SUCCESS;
  358. if (EntriesReturned > 0)
  359. Status = STATUS_SUCCESS;
  360. else
  361. Status = (IsResume == TRUE) ? STATUS_NO_MORE_FILES : STATUS_NO_SUCH_FILE;
  362. goto FINALLY;
  363. }
  364. }
  365. RxDbgTrace(0, Dbg,
  366. ("MRxSmbDCscQueryDirectory (%08lx)...qdiryaya <%ws>\n",
  367. RxContext,
  368. &QuerydirInfo->Find32.cFileName[0] ));
  369. RtlInitUnicodeString(&FileName,&QuerydirInfo->Find32.cFileName[0]);
  370. RtlInitUnicodeString(&AlternateFileName,&QuerydirInfo->Find32.cAlternateFileName[0]);
  371. RxDbgTrace(0, Dbg,
  372. ("MRxSmbDCscQueryDirectory (%08lx)...qdiryaya2 <%wZ><%wZ>|<%wZ>\n",
  373. RxContext,
  374. &FileName,&AlternateFileName,
  375. &capFobx->UnicodeQueryTemplate));
  376. FilterFailure = FALSE;
  377. if (smbFobx->Enumeration.WildCardsFound ) {
  378. try
  379. {
  380. FilterFailure = !FsRtlIsNameInExpression(
  381. &capFobx->UnicodeQueryTemplate,
  382. &FileName,
  383. TRUE,
  384. NULL );
  385. }
  386. except(EXCEPTION_EXECUTE_HANDLER)
  387. {
  388. FilterFailure = TRUE;
  389. }
  390. } else {
  391. FilterFailure = !RtlEqualUnicodeString(
  392. &capFobx->UnicodeQueryTemplate,
  393. &FileName,
  394. TRUE ); //case-insensitive
  395. }
  396. //check shortname
  397. if (FilterFailure) {
  398. if (smbFobx->Enumeration.WildCardsFound ) {
  399. try
  400. {
  401. FilterFailure = !FsRtlIsNameInExpression(
  402. &capFobx->UnicodeQueryTemplate,
  403. &AlternateFileName,
  404. TRUE,
  405. NULL );
  406. }
  407. except(EXCEPTION_EXECUTE_HANDLER)
  408. {
  409. FilterFailure = TRUE;
  410. }
  411. } else {
  412. FilterFailure = !RtlEqualUnicodeString(
  413. &capFobx->UnicodeQueryTemplate,
  414. &AlternateFileName,
  415. TRUE ); //case-insensitive
  416. }
  417. }
  418. if (FilterFailure) {
  419. QuerydirInfo->IsNonEmpty = FALSE;
  420. continue;
  421. }
  422. //OK, we have an entry we'd like to return.....see if it will fit.
  423. pRememberBuffer = pBuffer;
  424. if (EntriesReturned != 0) {
  425. pBuffer = (PBYTE)QuadAlignPtr(pBuffer); //assume that this will fit
  426. }
  427. SpaceNeeded = smbFobx->Enumeration.FileNameOffset+FileName.Length;
  428. RxDbgTrace(0, Dbg,
  429. ("MRxSmbDCscQueryDirectory (%08lx)...qdiryaya3 <%wZ><%wZ>|<%wZ> needs %08lx %08lx %08lx %08lx\n",
  430. RxContext,
  431. &FileName,&AlternateFileName,
  432. &capFobx->UnicodeQueryTemplate,
  433. pBuffer,SpaceNeeded,pRememberBuffer,*pLengthRemaining));
  434. if (pBuffer+SpaceNeeded > pRememberBuffer+*pLengthRemaining) {
  435. //buffer overflow on this enrty....
  436. //pBuffer = pRememberBuffer; //rollback
  437. Status = (EntriesReturned==0)?STATUS_BUFFER_OVERFLOW:STATUS_SUCCESS;
  438. goto FINALLY;
  439. } else {
  440. PFILE_DIRECTORY_INFORMATION pThisBuffer = (PFILE_DIRECTORY_INFORMATION)pBuffer;
  441. if (pPreviousBuffer != NULL) {
  442. pPreviousBuffer->NextEntryOffset = (ULONG)(((PBYTE)pThisBuffer)-((PBYTE)pPreviousBuffer));
  443. }
  444. pPreviousBuffer = pThisBuffer;
  445. RtlZeroMemory(pBuffer,smbFobx->Enumeration.FileNameOffset);
  446. RtlCopyMemory(pBuffer+smbFobx->Enumeration.FileNameOffset,
  447. FileName.Buffer,
  448. FileName.Length);
  449. *((PULONG)(pBuffer+smbFobx->Enumeration.FileNameLengthOffset)) = FileName.Length;
  450. //hallucinate the record based on specific return type
  451. switch (FileInformationClass) {
  452. case FileNamesInformation:
  453. break;
  454. case FileBothDirectoryInformation:{
  455. PFILE_BOTH_DIR_INFORMATION pThisBufferAsBOTH
  456. = (PFILE_BOTH_DIR_INFORMATION)pThisBuffer;
  457. //Do not copy more than size of shortname
  458. pThisBufferAsBOTH->ShortNameLength = min(sizeof(pThisBufferAsBOTH->ShortName),(CCHAR)(AlternateFileName.Length));
  459. RtlCopyMemory( &pThisBufferAsBOTH->ShortName[0],
  460. AlternateFileName.Buffer,
  461. pThisBufferAsBOTH->ShortNameLength );
  462. }
  463. //no break intentional
  464. case FileDirectoryInformation:
  465. case FileFullDirectoryInformation:
  466. //just fill what we have...
  467. pThisBuffer->FileAttributes = Find32->dwFileAttributes;
  468. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  469. pThisBuffer->CreationTime,
  470. Find32->ftCreationTime);
  471. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  472. pThisBuffer->LastAccessTime,
  473. Find32->ftLastAccessTime);
  474. COPY_STRUCTFILETIME_TO_LARGEINTEGER(
  475. pThisBuffer->LastWriteTime,
  476. Find32->ftLastWriteTime);
  477. pThisBuffer->EndOfFile.HighPart = Find32->nFileSizeHigh;
  478. pThisBuffer->EndOfFile.LowPart = Find32->nFileSizeLow;
  479. pThisBuffer->AllocationSize = pThisBuffer->EndOfFile;
  480. if (IsLeaf(hShadow)) {
  481. PFDB pFDB = MRxSmbCscFindFdbFromHShadow(hShadow);
  482. if (pFDB != NULL) {
  483. PMRX_SMB_FCB smbFcb = MRxSmbCscRecoverMrxFcbFromFdb(pFDB);
  484. PMRX_FCB mrxFcb = smbFcb->ContainingFcb;
  485. pThisBuffer->EndOfFile = mrxFcb->Header.FileSize;
  486. pThisBuffer->AllocationSize = pThisBuffer->EndOfFile;
  487. }
  488. }
  489. break;
  490. default:
  491. RxDbgTrace( 0, Dbg, ("MRxSmbCoreFileSearch: Invalid FS information class\n"));
  492. ASSERT(!"this can't happen");
  493. Status = STATUS_INVALID_PARAMETER;
  494. goto FINALLY;
  495. }
  496. pBuffer += SpaceNeeded;
  497. *pLengthRemaining -= (ULONG)(pBuffer-pRememberBuffer);
  498. EntriesReturned++;
  499. QuerydirInfo->IsNonEmpty = FALSE;
  500. if (RxContext->QueryDirectory.ReturnSingleEntry) {
  501. Status = STATUS_SUCCESS;
  502. goto FINALLY;
  503. }
  504. }
  505. }
  506. FINALLY:
  507. if (EnteredCriticalSection) {
  508. LeaveShadowCrit();
  509. }
  510. RxDbgTrace(-1, Dbg, ("MRxSmbDCscQueryDirectory exit-> %08lx %08lx\n", RxContext, Status ));
  511. return Status;
  512. }
  513. NTSTATUS
  514. MRxSmbDCscGetFsSizeInfo (
  515. IN OUT PRX_CONTEXT RxContext
  516. )
  517. /*++
  518. Routine Description:
  519. This routine routes a fs size query to the underlying filesystem. It does
  520. this by opening a handle to the priorityqueue inode and uses this to route
  521. call. CODE.IMPROVEMENT.ASHAMED if the system is converted to use relative
  522. opens, then we should just use the relative open fileobject for this passthru.
  523. Arguments:
  524. RxContext - the RDBSS context
  525. Return Value:
  526. NTSTATUS - The return status for the operation
  527. Notes:
  528. --*/
  529. {
  530. NTSTATUS Status = STATUS_SUCCESS;
  531. RxCaptureFcb;
  532. RxCaptureFobx;
  533. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  534. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  535. FS_INFORMATION_CLASS FsInformationClass;
  536. PBYTE pBuffer;
  537. PULONG pLengthRemaining;
  538. ULONG PassedInLength,ReturnedLength;
  539. BOOLEAN CriticalSectionEntered = FALSE;
  540. PNT5CSC_MINIFILEOBJECT MiniFileObject;
  541. FsInformationClass = RxContext->Info.FileInformationClass;
  542. pBuffer = RxContext->Info.Buffer;
  543. pLengthRemaining = &RxContext->Info.LengthRemaining;
  544. RxDbgTrace(+1, Dbg,
  545. ("MRxSmbDCscGetFsSizeInfo entry(%08lx)...%08lx %08lx %08lx\n",
  546. RxContext,
  547. FsInformationClass, pBuffer, *pLengthRemaining ));
  548. EnterShadowCrit();
  549. CriticalSectionEntered = TRUE;
  550. OpenFileHSHADOW(ULID_PQ,
  551. 0,
  552. 0,
  553. (CSCHFILE *)(&MiniFileObject)
  554. );
  555. if (MiniFileObject == NULL) {
  556. Status = STATUS_UNSUCCESSFUL;
  557. goto FINALLY;
  558. }
  559. PassedInLength = *pLengthRemaining;
  560. //DbgBreakPoint();
  561. Status = Nt5CscXxxInformation(
  562. (PCHAR)IRP_MJ_QUERY_VOLUME_INFORMATION,
  563. MiniFileObject,
  564. FsInformationClass,
  565. PassedInLength,
  566. pBuffer,
  567. &ReturnedLength
  568. );
  569. if (!NT_ERROR(Status)) {
  570. *pLengthRemaining -= ReturnedLength;
  571. }
  572. FINALLY:
  573. if (MiniFileObject != NULL) {
  574. CloseFileLocal((CSCHFILE)(MiniFileObject));
  575. }
  576. if (CriticalSectionEntered) {
  577. LeaveShadowCrit();
  578. }
  579. RxDbgTrace(-1, Dbg, ("MRxSmbDCscGetFsSizeInfo exit-> %08lx %08lx %08lx %08lx\n",
  580. RxContext, Status, ReturnedLength, *pLengthRemaining ));
  581. return Status;
  582. }
  583. NTSTATUS
  584. MRxSmbDCscFlush (
  585. IN OUT PRX_CONTEXT RxContext
  586. )
  587. /*++
  588. Routine Description:
  589. This routine just performs a flush in disconnected mode. since we don't send
  590. a flush in disconnected mode and since we dont need to flush the shadow
  591. (since we use all unbuffered writes) we can just return SUCCESS.
  592. Arguments:
  593. RxContext - the RDBSS context
  594. Return Value:
  595. NTSTATUS - The return status for the operation
  596. Notes:
  597. --*/
  598. {
  599. NTSTATUS Status = STATUS_SUCCESS;
  600. RxCaptureFcb;
  601. PSMBCEDB_SERVER_ENTRY pServerEntry;
  602. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  603. if (!SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  604. return(STATUS_MORE_PROCESSING_REQUIRED);
  605. }
  606. return(STATUS_SUCCESS);
  607. }
  608. NTSTATUS
  609. MRxSmbDCscQueryVolumeInformation (
  610. IN OUT PRX_CONTEXT RxContext
  611. )
  612. /*++
  613. Routine Description:
  614. This routine just performs a queryvolume in disconnected mode. it draws on
  615. the same philosphy as downlevel queryvolume.
  616. Arguments:
  617. RxContext - the RDBSS context
  618. Return Value:
  619. NTSTATUS - The return status for the operation
  620. Notes:
  621. --*/
  622. {
  623. NTSTATUS Status = STATUS_SUCCESS;
  624. RxCaptureFcb;
  625. RxCaptureFobx;
  626. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  627. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  628. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  629. FS_INFORMATION_CLASS FsInformationClass;
  630. PBYTE pBuffer;
  631. PULONG pLengthRemaining;
  632. ULONG LengthUsed;
  633. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  634. = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  635. BOOLEAN Disconnected;
  636. PSMBCE_NET_ROOT psmbNetRoot = &pNetRootEntry->NetRoot;
  637. Disconnected = SmbCeIsServerInDisconnectedMode(pServerEntry);
  638. if (!Disconnected) {
  639. return(STATUS_CONNECTION_DISCONNECTED);
  640. }
  641. FsInformationClass = RxContext->Info.FsInformationClass;
  642. pBuffer = RxContext->Info.Buffer;
  643. pLengthRemaining = &RxContext->Info.LengthRemaining;
  644. RxDbgTrace(+1, Dbg,
  645. ("MRxSmbDCscQueryVolumeInformation entry(%08lx)...%08lx %08lx %08lx bytes @ %08lx %08lx %08lx\n",
  646. RxContext,
  647. FsInformationClass, pBuffer, *pLengthRemaining,
  648. smbSrvOpen->hfShadow ));
  649. switch (FsInformationClass) {
  650. case FileFsAttributeInformation:
  651. //here, cause it to return the data from our tableentry in downlvli.c
  652. if (psmbNetRoot->FileSystemNameLength == 0) {
  653. //set our name
  654. psmbNetRoot->FileSystemNameLength = 14;
  655. psmbNetRoot->FileSystemName[0] = '*';
  656. psmbNetRoot->FileSystemName[1] = 'N';
  657. psmbNetRoot->FileSystemName[2] = 'T';
  658. psmbNetRoot->FileSystemName[3] = '5';
  659. psmbNetRoot->FileSystemName[4] = 'C';
  660. psmbNetRoot->FileSystemName[5] = 'S';
  661. psmbNetRoot->FileSystemName[6] = 'C';
  662. }
  663. psmbNetRoot->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
  664. psmbNetRoot->MaximumComponentNameLength = 255;
  665. Status = MRxSmbGetFsAttributesFromNetRoot(RxContext);
  666. goto FINALLY;
  667. //no break needed because of gotofinally
  668. case FileFsVolumeInformation: {
  669. PFILE_FS_VOLUME_INFORMATION FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)pBuffer;
  670. ASSERT(*pLengthRemaining >= sizeof(FILE_FS_VOLUME_INFORMATION));
  671. //here, we have no reliable information....return zeros
  672. FsVolInfo->VolumeCreationTime.QuadPart = 0;
  673. FsVolInfo->VolumeSerialNumber = 0;
  674. FsVolInfo->VolumeLabelLength = 0;
  675. FsVolInfo->SupportsObjects = FALSE;
  676. // calculate the size of the VolumeLabel we have and put it in a temp var
  677. LengthUsed = *pLengthRemaining - FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,VolumeLabel[0]);
  678. LengthUsed = min(LengthUsed, sizeof(vtzOfflineVolume)-2);
  679. memcpy(FsVolInfo->VolumeLabel, vtzOfflineVolume, LengthUsed);
  680. FsVolInfo->VolumeLabelLength = LengthUsed;
  681. *pLengthRemaining -= (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,VolumeLabel[0])+LengthUsed);
  682. }
  683. goto FINALLY;
  684. //no break needed because of gotofinally
  685. case FileFsSizeInformation: case FileFsFullSizeInformation:
  686. //here, we route to the underlying filesystem
  687. Status = MRxSmbDCscGetFsSizeInfo(RxContext);
  688. goto FINALLY;
  689. //no break needed because of gotofinally
  690. case FileFsDeviceInformation:
  691. ASSERT(!"this should have been turned away");
  692. //no break;
  693. default:
  694. Status = STATUS_NOT_IMPLEMENTED;
  695. goto FINALLY;
  696. }
  697. FINALLY:
  698. RxDbgTrace(-1, Dbg, ("MRxSmbDCscQueryVolumeInformation exit(%08lx %08lx)...%08lx %08lx %08lx bytes @ %08lx\n",
  699. RxContext, Status,
  700. FsInformationClass, pBuffer, *pLengthRemaining,
  701. smbSrvOpen->hfShadow ));
  702. return Status;
  703. }
  704. NTSTATUS
  705. MRxSmbDCscQueryFileInfo (
  706. IN OUT PRX_CONTEXT RxContext
  707. )
  708. /*++
  709. Routine Description:
  710. This routine just performs a queryfileinfo in disconnected mode. because info buffering
  711. is enabled, it should never call down here! so we can just return STATUS_DISCONNECTED
  712. all the time!.
  713. Arguments:
  714. RxContext - the RDBSS context
  715. Return Value:
  716. NTSTATUS - The return status for the operation
  717. Notes:
  718. --*/
  719. {
  720. NTSTATUS Status = STATUS_SUCCESS;
  721. RxCaptureFcb;
  722. RxCaptureFobx;
  723. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  724. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  725. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  726. FILE_INFORMATION_CLASS FileInformationClass;
  727. PBYTE pBuffer;
  728. PULONG pLengthRemaining;
  729. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  730. = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  731. BOOLEAN Disconnected;
  732. PSMBCE_NET_ROOT psmbNetRoot = &pNetRootEntry->NetRoot;
  733. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  734. if (!Disconnected) {
  735. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  736. if (pServerEntry->Header.State == SMBCEDB_ACTIVE) {
  737. return(STATUS_MORE_PROCESSING_REQUIRED);
  738. } else {
  739. return(STATUS_CONNECTION_DISCONNECTED);
  740. }
  741. }
  742. FileInformationClass = RxContext->Info.FileInformationClass;
  743. pBuffer = RxContext->Info.Buffer;
  744. pLengthRemaining = &RxContext->Info.LengthRemaining;
  745. RxDbgTrace(+1, Dbg,
  746. ("MRxSmbDCscQueryFileInfo entry(%08lx)...%08lx %08lx %08lx bytes @ %08lx %08lx %08lx\n",
  747. RxContext,
  748. FileInformationClass, pBuffer, *pLengthRemaining,
  749. smbSrvOpen->hfShadow ));
  750. switch (FileInformationClass) {
  751. case FileBasicInformation:
  752. {
  753. PFILE_BASIC_INFORMATION Buffer = (PFILE_BASIC_INFORMATION)pBuffer;
  754. switch (NodeType(capFcb)) {
  755. case RDBSS_NTC_STORAGE_TYPE_DIRECTORY:
  756. case RDBSS_NTC_STORAGE_TYPE_FILE:
  757. //copy in all the stuff that we know....it may be enough.....
  758. Buffer->ChangeTime = pFileInfo->Basic.ChangeTime;
  759. Buffer->CreationTime = pFileInfo->Basic.CreationTime;
  760. Buffer->LastWriteTime = pFileInfo->Basic.LastWriteTime;
  761. Buffer->LastAccessTime = pFileInfo->Basic.LastAccessTime;
  762. Buffer->FileAttributes = pFileInfo->Basic.FileAttributes;
  763. if (FlagOn( capFcb->FcbState, FCB_STATE_TEMPORARY )) {
  764. SetFlag( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
  765. }
  766. RxContext->Info.LengthRemaining -= sizeof(FILE_BASIC_INFORMATION);
  767. break;
  768. default:
  769. Status = STATUS_NOT_IMPLEMENTED;
  770. }
  771. }
  772. break;
  773. case FileStandardInformation:
  774. {
  775. PFILE_STANDARD_INFORMATION Buffer = (PFILE_STANDARD_INFORMATION)pBuffer;
  776. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  777. switch (NodeType(capFcb)) {
  778. case RDBSS_NTC_STORAGE_TYPE_DIRECTORY:
  779. Buffer->Directory = TRUE;
  780. RxContext->Info.LengthRemaining -= sizeof(FILE_STANDARD_INFORMATION);
  781. break;
  782. case RDBSS_NTC_STORAGE_TYPE_FILE:
  783. memset(Buffer, 0, sizeof(FILE_STANDARD_INFORMATION));
  784. Buffer->AllocationSize = smbFcb->NewShadowSize;
  785. Buffer->EndOfFile = smbFcb->NewShadowSize;
  786. RxContext->Info.LengthRemaining -= sizeof(FILE_STANDARD_INFORMATION);
  787. break;
  788. default:
  789. Status = STATUS_NOT_IMPLEMENTED;
  790. }
  791. }
  792. break;
  793. case FileEaInformation:
  794. {
  795. PFILE_EA_INFORMATION EaBuffer = (PFILE_EA_INFORMATION)pBuffer;
  796. EaBuffer->EaSize = 0;
  797. RxContext->Info.LengthRemaining -= sizeof(FILE_EA_INFORMATION);
  798. }
  799. break;
  800. default:
  801. Status = STATUS_NOT_IMPLEMENTED;
  802. }
  803. RxDbgTrace(-1, Dbg,
  804. ("MRxSmbDCscQueryFileInfo exit(%08lx %08lx)...%08lx %08lx %08lx bytes @ %08lx\n",
  805. RxContext, Status,
  806. FileInformationClass, pBuffer, *pLengthRemaining,
  807. smbSrvOpen->hfShadow ));
  808. return Status;
  809. }
  810. NTSTATUS
  811. MRxSmbDCscSetFileInfo (
  812. IN OUT PRX_CONTEXT RxContext
  813. )
  814. /*++
  815. Routine Description:
  816. This routine just performs a querydirectory in disconnected mode. it draws on
  817. the same philosphy as downlevel querydirectory.
  818. Arguments:
  819. RxContext - the RDBSS context
  820. Return Value:
  821. NTSTATUS - The return status for the operation
  822. Notes:
  823. --*/
  824. {
  825. NTSTATUS Status = STATUS_SUCCESS;
  826. RxCaptureFcb;
  827. RxCaptureFobx;
  828. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  829. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  830. FILE_INFORMATION_CLASS FileInformationClass;
  831. PBYTE pBuffer;
  832. PULONG pLengthRemaining;
  833. ULONG DummyReturnedLength;
  834. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  835. = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  836. BOOLEAN Disconnected;
  837. PSMBCE_NET_ROOT psmbNetRoot = &pNetRootEntry->NetRoot;
  838. PNT5CSC_MINIFILEOBJECT MiniFileObject = (PNT5CSC_MINIFILEOBJECT)(smbSrvOpen->hfShadow);
  839. Disconnected = MRxSmbCSCIsDisconnectedOpen(capFcb, smbSrvOpen);
  840. if (!Disconnected) {
  841. return(STATUS_CONNECTION_DISCONNECTED);
  842. }
  843. FileInformationClass = RxContext->Info.FileInformationClass;
  844. pBuffer = RxContext->Info.Buffer;
  845. pLengthRemaining = &RxContext->Info.LengthRemaining;
  846. RxDbgTrace(+1, Dbg,
  847. ("MRxSmbDCscSetFileInfo entry(%08lx)...%08lx %08lx %08lx bytes @ %08lx %08lx %08lx\n",
  848. RxContext,
  849. FileInformationClass, pBuffer, *pLengthRemaining,
  850. smbSrvOpen->hfShadow ));
  851. switch (FileInformationClass) {
  852. case FileEndOfFileInformation:
  853. case FileAllocationInformation:
  854. case FileBasicInformation:
  855. case FileDispositionInformation:
  856. MRxSmbCscSetFileInfoEpilogue(RxContext,&Status);
  857. goto FINALLY;
  858. case FileRenameInformation:
  859. MRxSmbCscRenameEpilogue(RxContext,&Status);
  860. goto FINALLY;
  861. default:
  862. Status = STATUS_NOT_IMPLEMENTED;
  863. goto FINALLY;
  864. }
  865. FINALLY:
  866. RxDbgTrace(-1, Dbg,
  867. ("MRxSmbDCscSetFileInfo exit(%08lx %08lx)...%08lx %08lx %08lx bytes @ %08lx\n",
  868. RxContext, Status,
  869. FileInformationClass, pBuffer, *pLengthRemaining,
  870. smbSrvOpen->hfShadow ));
  871. return Status;
  872. }
  873. NTSTATUS
  874. MRxSmbDCscFsCtl(
  875. IN OUT PRX_CONTEXT RxContext
  876. )
  877. /*++
  878. Routine Description:
  879. This routine just performs a querydirectory in disconnected mode. it draws on
  880. the same philosphy as downlevel querydirectory.
  881. Arguments:
  882. RxContext - the RDBSS context
  883. Return Value:
  884. NTSTATUS - The return status for the operation
  885. Notes:
  886. --*/
  887. {
  888. return STATUS_NOT_SUPPORTED;
  889. }
  890. NTSTATUS
  891. MRxSmbDCscIsValidDirectory(
  892. IN OUT PRX_CONTEXT RxContext,
  893. IN PUNICODE_STRING DirectoryName)
  894. {
  895. NTSTATUS Status;
  896. MRX_SMB_FCB CscSmbFcb;
  897. WIN32_FIND_DATA Find32;
  898. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  899. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(RxContext->Create.pNetRoot);
  900. memset(&(CscSmbFcb.MinimalCscSmbFcb), 0, sizeof(CscSmbFcb.MinimalCscSmbFcb));
  901. if (!pNetRootEntry->NetRoot.sCscRootInfo.hRootDir)
  902. {
  903. return STATUS_BAD_NETWORK_PATH;
  904. }
  905. EnterShadowCrit();
  906. Status = MRxSmbCscCreateShadowFromPath(
  907. DirectoryName,
  908. &(pNetRootEntry->NetRoot.sCscRootInfo),
  909. &Find32,
  910. NULL,
  911. (CREATESHADOW_CONTROL_NOCREATE |
  912. CREATESHADOW_CONTROL_NOREVERSELOOKUP),
  913. &(CscSmbFcb.MinimalCscSmbFcb),
  914. RxContext,
  915. TRUE,
  916. NULL);
  917. if ((Status != STATUS_SUCCESS) ||
  918. !(Find32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  919. Status = STATUS_BAD_NETWORK_PATH;
  920. }
  921. LeaveShadowCrit();
  922. return Status;
  923. }
  924. NTSTATUS
  925. MRxSmbCscNotifyChangeDirectory(
  926. IN OUT PRX_CONTEXT RxContext
  927. )
  928. /*++
  929. Routine Description:
  930. This routine sets a directory notification for a directory in disconnected state
  931. The smbmini makes this call when it notices that the serverentry is in disconnected state
  932. All change notifications are maintained in a list, so that when the server is being transitioned
  933. from offline to online, we can complete all of them.
  934. We use FOBX as the unique key for change notifications.
  935. Arguments:
  936. RxContext - the RDBSS context
  937. Return Value:
  938. NTSTATUS - The return status for the operation
  939. Notes:
  940. If successfully registered a change notify, it returns STATUS_PENDING. It also
  941. hijacks the IRP and reduces the refcount on the RxContext, so that the wrapper
  942. will delete this rxcontext.
  943. --*/
  944. {
  945. NTSTATUS Status;
  946. RxCaptureFcb;
  947. RxCaptureFobx;
  948. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  949. PSMBCEDB_SERVER_ENTRY pServerEntry;
  950. BOOLEAN FcbAcquired = FALSE;
  951. ULONG CompletionFilter;
  952. BOOLEAN WatchTree;
  953. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  954. PUNICODE_STRING pDirName=NULL;
  955. PNOTIFYEE_FOBX pNF = NULL;
  956. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  957. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  958. if (!RxIsFcbAcquiredExclusive(capFcb)) {
  959. ASSERT(!RxIsFcbAcquiredShared(capFcb));
  960. Status = RxAcquireExclusiveFcbResourceInMRx( capFcb );
  961. FcbAcquired = (Status == STATUS_SUCCESS);
  962. }
  963. CompletionFilter = pLowIoContext->ParamsFor.NotifyChangeDirectory.CompletionFilter;
  964. WatchTree = pLowIoContext->ParamsFor.NotifyChangeDirectory.WatchTree;
  965. if (!(((PFCB)capFcb)->PrivateAlreadyPrefixedName).Length)
  966. {
  967. pDirName = &vRootString;
  968. }
  969. else
  970. {
  971. pDirName = &(((PFCB)capFcb)->PrivateAlreadyPrefixedName);
  972. }
  973. //
  974. // Call the Fsrtl package to process the request.
  975. //
  976. pNF = AllocMem(sizeof(NOTIFYEE_FOBX));
  977. if (!pNF)
  978. {
  979. return STATUS_INSUFFICIENT_RESOURCES;
  980. }
  981. pNF->pFobx = capFobx;
  982. SmbCeLog(("chngnotify fobx=%x\n", capFobx));
  983. SmbLog(LOG,
  984. MRxSmbCscNotifyChangeDirectory,
  985. LOGPTR(capFobx));
  986. // DbgPrint("chngnotify %wZ fobx=%x NR=%x DirList=%x\n", pDirName, capFobx, pNetRootEntry, &pNetRootEntry->NetRoot.DirNotifyList);
  987. FsRtlNotifyFullChangeDirectory( pNetRootEntry->NetRoot.pNotifySync,
  988. &pNetRootEntry->NetRoot.DirNotifyList,
  989. capFobx,
  990. (PSTRING)pDirName,
  991. WatchTree,
  992. TRUE,
  993. CompletionFilter,
  994. RxContext->CurrentIrp,
  995. NULL,
  996. NULL
  997. );
  998. // attach this
  999. ExAcquireFastMutex(&pNetRootEntry->NetRoot.NotifyeeFobxListMutex);
  1000. if (!PIsFobxInTheList(&pNetRootEntry->NetRoot.NotifyeeFobxList, capFobx))
  1001. {
  1002. InsertTailList(&pNetRootEntry->NetRoot.NotifyeeFobxList, &pNF->NextNotifyeeFobx);
  1003. }
  1004. else
  1005. {
  1006. FreeMem((PVOID)pNF);
  1007. }
  1008. ExReleaseFastMutex(&pNetRootEntry->NetRoot.NotifyeeFobxListMutex);
  1009. // as we hijacked the Irp, let us make sure that rdbss gets rid of the rxcontext
  1010. RxCompleteRequest_Real( RxContext, NULL, STATUS_PENDING );
  1011. Status = STATUS_PENDING;
  1012. if (FcbAcquired) {
  1013. RxReleaseFcbResourceInMRx(capFcb );
  1014. }
  1015. return Status;
  1016. }
  1017. NTSTATUS
  1018. MRxSmbCscCleanupFobx(
  1019. IN PRX_CONTEXT RxContext)
  1020. /*++
  1021. Routine Description:
  1022. This routine cleans up a file system object.
  1023. For CSC, the only thing we do is to remove changenotification.
  1024. Arguments:
  1025. pRxContext - the RDBSS context
  1026. Return Value:
  1027. RXSTATUS - The return status for the operation
  1028. --*/
  1029. {
  1030. RxCaptureFcb;
  1031. RxCaptureFobx;
  1032. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  1033. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1034. BOOLEAN fInList = FALSE;
  1035. PNOTIFYEE_FOBX pNF = NULL;
  1036. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  1037. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1038. if (MRxSmbCSCIsDisconnectedOpen(capFcb, MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen)))
  1039. {
  1040. ExAcquireFastMutex(&pNetRootEntry->NetRoot.NotifyeeFobxListMutex);
  1041. pNF = PIsFobxInTheList(&pNetRootEntry->NetRoot.NotifyeeFobxList, capFobx);
  1042. if (pNF)
  1043. {
  1044. RemoveEntryList(&pNF->NextNotifyeeFobx);
  1045. FreeMem(pNF);
  1046. pNF = NULL;
  1047. fInList = TRUE;
  1048. }
  1049. ExReleaseFastMutex(&pNetRootEntry->NetRoot.NotifyeeFobxListMutex);
  1050. if (fInList)
  1051. {
  1052. SmbCeLog(("chngnotify cleanup fobx=%x\n", capFobx));
  1053. SmbLog(LOG,
  1054. MRxSmbCscCleanupFobx,
  1055. LOGPTR(capFobx));
  1056. // DbgPrint("chngnotify Cleanup fobx=%x NR=%x DirList=%x\n", capFobx, pNetRootEntry, &pNetRootEntry->NetRoot.DirNotifyList);
  1057. FsRtlNotifyCleanup (
  1058. pNetRootEntry->NetRoot.pNotifySync,
  1059. &pNetRootEntry->NetRoot.DirNotifyList,
  1060. capFobx
  1061. );
  1062. }
  1063. }
  1064. return STATUS_SUCCESS;
  1065. }
  1066. NTSTATUS
  1067. MRxSmbCscInitializeNetRootEntry(
  1068. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. This routine initializes, the change notify structures in the netrootentry
  1073. Arguments:
  1074. Return Value:
  1075. --*/
  1076. {
  1077. NTSTATUS NtStatus = STATUS_SUCCESS;
  1078. try {
  1079. FsRtlNotifyInitializeSync( &pNetRootEntry->NetRoot.pNotifySync );
  1080. } except(EXCEPTION_EXECUTE_HANDLER) {
  1081. NtStatus = GetExceptionCode();
  1082. }
  1083. if (NtStatus == STATUS_SUCCESS) {
  1084. InitializeListHead( &pNetRootEntry->NetRoot.DirNotifyList );
  1085. InitializeListHead( &pNetRootEntry->NetRoot.NotifyeeFobxList);
  1086. ExInitializeFastMutex(&pNetRootEntry->NetRoot.NotifyeeFobxListMutex);
  1087. }
  1088. return NtStatus;
  1089. }
  1090. VOID
  1091. MRxSmbCscUninitializeNetRootEntry(
  1092. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. This routine unitializes, the change notify structures
  1097. Arguments:
  1098. Return Value:
  1099. --*/
  1100. {
  1101. FsRtlNotifyUninitializeSync( &pNetRootEntry->NetRoot.pNotifySync );
  1102. }
  1103. BOOLEAN
  1104. MRxSmbCSCIsDisconnectedOpen(
  1105. PMRX_FCB pFcb,
  1106. PMRX_SMB_SRV_OPEN smbSrvOpen
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. A slightly more involved check to see whether this is a disconnected open.
  1111. Arguments:
  1112. Return Value:
  1113. --*/
  1114. {
  1115. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(pFcb->pNetRoot->pSrvCall);
  1116. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(pFcb);
  1117. if(BooleanFlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DISCONNECTED_OPEN))
  1118. {
  1119. return TRUE;
  1120. }
  1121. // we need to also check that the serverentry is non-NULL. This can happen when
  1122. // you the syetem is about to shut down, or the FCB has been orphaned.
  1123. if (pServerEntry && SmbCeIsServerInDisconnectedMode(pServerEntry))
  1124. {
  1125. if (smbFcb->hShadow || smbFcb->hShadowRenamed)
  1126. {
  1127. // is the shadow visible in disconnected state?
  1128. return(IsShadowVisible(TRUE, smbFcb->dwFileAttributes, smbFcb->ShadowStatus) != 0);
  1129. }
  1130. }
  1131. return FALSE;
  1132. }
  1133. #endif //ifdef MRXSMB_BUILD_FOR_CSC_DCON
  1134. PNOTIFYEE_FOBX
  1135. PIsFobxInTheList(
  1136. PLIST_ENTRY pNotifyeeFobxList,
  1137. PMRX_FOBX pFobx
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This a support routine form change notification. It checks whether an FOBX, which is
  1142. the redir's internal representation of a handle, is a change notification handle
  1143. or not. Note, the shadow crit sect must be held when calling this.
  1144. Arguments:
  1145. Return Value:
  1146. --*/
  1147. {
  1148. PLIST_ENTRY pListEntry;
  1149. pListEntry = pNotifyeeFobxList->Flink;
  1150. if (pListEntry)
  1151. {
  1152. while (pListEntry != pNotifyeeFobxList)
  1153. {
  1154. PNOTIFYEE_FOBX pNF = (PNOTIFYEE_FOBX)CONTAINING_RECORD(pListEntry, NOTIFYEE_FOBX, NextNotifyeeFobx);
  1155. if (pNF->pFobx == pFobx)
  1156. {
  1157. return pNF;
  1158. }
  1159. pListEntry = pListEntry->Flink;
  1160. }
  1161. }
  1162. return NULL;
  1163. }
  1164. BOOL
  1165. FCleanupAllNotifyees(
  1166. PNOTIFY_SYNC pNotifySync,
  1167. PLIST_ENTRY pDirNotifyList,
  1168. PLIST_ENTRY pNotifyeeFobxList,
  1169. PFAST_MUTEX pNotifyeeFobxListMutex
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. This routine completes all outstanding changenotifications for a paricular list of
  1174. notifyees
  1175. Arguments:
  1176. Return Value:
  1177. --*/
  1178. {
  1179. PLIST_ENTRY pListEntry;
  1180. PNOTIFYEE_FOBX pNF;
  1181. BOOL fDoneSome = FALSE;
  1182. ExAcquireFastMutex(pNotifyeeFobxListMutex);
  1183. pListEntry = pNotifyeeFobxList->Flink;
  1184. if (pListEntry)
  1185. {
  1186. while (pListEntry != pNotifyeeFobxList)
  1187. {
  1188. pNF = (PNOTIFYEE_FOBX)CONTAINING_RECORD(pListEntry, NOTIFYEE_FOBX, NextNotifyeeFobx);
  1189. SmbCeLog(("chngnotify cleanup fobx=%x\n", pNF->pFobx));
  1190. SmbLog(LOG,
  1191. FCleanupAllNotifyees,
  1192. LOGPTR(pNF->pFobx));
  1193. // DbgPrint("chngnotify Cleanup fobx=%x DirList=%x\n", pNF->pFobx, pDirNotifyList);
  1194. FsRtlNotifyCleanup (
  1195. pNotifySync,
  1196. pDirNotifyList,
  1197. pNF->pFobx
  1198. );
  1199. RemoveEntryList(&pNF->NextNotifyeeFobx);
  1200. FreeMem(pNF);
  1201. fDoneSome = TRUE;
  1202. pListEntry = pNotifyeeFobxList->Flink;
  1203. }
  1204. }
  1205. ExReleaseFastMutex(pNotifyeeFobxListMutex);
  1206. return fDoneSome;
  1207. }
  1208. VOID
  1209. MRxSmbCSCResumeAllOutstandingOperations(
  1210. PSMBCEDB_SERVER_ENTRY pServerEntry
  1211. )
  1212. /*++
  1213. Routine Description:
  1214. This routine completes all outstanding change notifications on the server.
  1215. This is called when a server is being transitioned from offline to online.
  1216. The caller must make sure that smbceresource is held, so that there are
  1217. no synchronization problems while enumerating.
  1218. Arguments:
  1219. Return Value:
  1220. --*/
  1221. {
  1222. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  1223. pNetRootEntry = SmbCeGetFirstNetRootEntry(pServerEntry);
  1224. while (pNetRootEntry != NULL) {
  1225. if (pNetRootEntry->NetRoot.pNotifySync)
  1226. {
  1227. FCleanupAllNotifyees(pNetRootEntry->NetRoot.pNotifySync,
  1228. &pNetRootEntry->NetRoot.DirNotifyList,
  1229. &pNetRootEntry->NetRoot.NotifyeeFobxList,
  1230. &pNetRootEntry->NetRoot.NotifyeeFobxListMutex
  1231. );
  1232. }
  1233. pNetRootEntry = SmbCeGetNextNetRootEntry(pServerEntry,pNetRootEntry);
  1234. }
  1235. }
  1236. VOID
  1237. MRxSmbCSCObtainRightsForUserOnFile(
  1238. IN PRX_CONTEXT pRxContext,
  1239. HSHADOW hDir,
  1240. HSHADOW hShadow,
  1241. OUT ACCESS_MASK *pMaximalAccessRights,
  1242. OUT ACCESS_MASK *pGuestMaximalAccessRights
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. This routine gets the rights for a specific user. The routine is called during
  1247. a create operation in disconnected state.
  1248. Arguments:
  1249. pRxContext Context for the create operation. We use this to get the user SID
  1250. hDir Directory Inode
  1251. hShadow File Inode
  1252. pMaximalAccessRights Access rights on the file for the user returned to the caller
  1253. pGuestMaximalAccessRights Guest Access rights on the file returned to the caller
  1254. Return Value:
  1255. None
  1256. --*/
  1257. {
  1258. NTSTATUS Status;
  1259. BOOLEAN AccessGranted = FALSE, SidHasAccessMask;
  1260. SID_CONTEXT SidContext;
  1261. int i;
  1262. *pMaximalAccessRights = *pGuestMaximalAccessRights = 0;
  1263. Status = CscRetrieveSid(
  1264. pRxContext,
  1265. &SidContext);
  1266. if (Status == STATUS_SUCCESS) {
  1267. CACHED_SECURITY_INFORMATION CachedSecurityInformation;
  1268. ULONG BytesReturned,SidLength;
  1269. DWORD CscStatus;
  1270. CSC_SID_INDEX SidIndex;
  1271. if (SidContext.pSid != NULL) {
  1272. SidLength = RtlLengthSid(
  1273. SidContext.pSid);
  1274. SidIndex = CscMapSidToIndex(
  1275. SidContext.pSid,
  1276. SidLength);
  1277. } else {
  1278. SidIndex = CSC_INVALID_SID_INDEX;
  1279. }
  1280. if (SidIndex == CSC_INVALID_SID_INDEX) {
  1281. // The sid was not located in the existing Sid mappings
  1282. // Map this Sid to that of a Guest
  1283. SidIndex = CSC_GUEST_SID_INDEX;
  1284. }
  1285. BytesReturned = sizeof(CachedSecurityInformation);
  1286. CscStatus = GetShadowInfoEx(
  1287. hDir,
  1288. hShadow,
  1289. NULL,
  1290. NULL,
  1291. NULL,
  1292. &CachedSecurityInformation,
  1293. &BytesReturned);
  1294. if (CscStatus == ERROR_SUCCESS) {
  1295. if (BytesReturned == sizeof(CACHED_SECURITY_INFORMATION)) {
  1296. // Walk through the cached access rights to determine the
  1297. // maximal permissible access rights.
  1298. for (i = 0; (i < CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES); i++) {
  1299. if(CachedSecurityInformation.AccessRights[i].SidIndex == SidIndex)
  1300. {
  1301. if (CSC_GUEST_SID_INDEX != SidIndex)
  1302. {
  1303. *pMaximalAccessRights = CachedSecurityInformation.AccessRights[i].MaximalRights;
  1304. }
  1305. }
  1306. if (CachedSecurityInformation.AccessRights[i].SidIndex == CSC_GUEST_SID_INDEX)
  1307. {
  1308. *pGuestMaximalAccessRights = CachedSecurityInformation.AccessRights[i].MaximalRights;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. CscDiscardSid(&SidContext);
  1314. }
  1315. }
  1316. VOID
  1317. MRxSmbCscFlushFdb(
  1318. IN PFDB Fdb
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. This routine is called from delete ioctl to flush an open file which is being delay closed.
  1323. Files which are closed by the user but for which the redir hasn't pushed out the
  1324. close, cannot have their cached replicas deleted because these are open too. This
  1325. causes CSCDeleteIoctl to fail, and the user has not idea why.
  1326. This routine must be called with ShadowCritSect held
  1327. Arguments:
  1328. Fdb CSC version of smbfcb.
  1329. Return Value:
  1330. None
  1331. --*/
  1332. {
  1333. PMRX_SMB_FCB pSmbFcb;
  1334. PNET_ROOT pNetRoot;
  1335. pSmbFcb = MRxSmbCscRecoverMrxFcbFromFdb(Fdb);
  1336. pNetRoot = (PNET_ROOT)(pSmbFcb->ContainingFcb->pNetRoot);
  1337. LeaveShadowCrit();
  1338. RxScavengeFobxsForNetRoot(pNetRoot,NULL);
  1339. EnterShadowCrit();
  1340. }