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.

2758 lines
85 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Init.c
  5. Abstract:
  6. This module implements the DRIVER_INITIALIZATION routine for the SMB mini rdr.
  7. Author:
  8. Balan Sethu Raman [SethuR] 7-Mar-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "ntverp.h"
  14. #include "ntbowsif.h"
  15. #include <bowpub.h>
  16. #include "netevent.h"
  17. #include "nvisible.h"
  18. #include <ntddbrow.h>
  19. BOOL IsTerminalServicesServer();
  20. BOOL IsServerSKU();
  21. #define RDBSS_DRIVER_LOAD_STRING L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Rdbss"
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE, DriverEntry)
  24. #pragma alloc_text(PAGE, MRxSmbInitUnwind)
  25. #pragma alloc_text(PAGE, MRxSmbInitUnwindSmb)
  26. #pragma alloc_text(PAGE, MRxSmbInitUnwindBowser)
  27. #pragma alloc_text(PAGE, MRxSmbUnload)
  28. #pragma alloc_text(PAGE, MRxSmbInitializeTables)
  29. #pragma alloc_text(PAGE, MRxSmbStart)
  30. #pragma alloc_text(PAGE, MRxSmbStop)
  31. #pragma alloc_text(PAGE, MRxSmbInitializeSecurity)
  32. #pragma alloc_text(PAGE, MRxSmbUninitializeSecurity)
  33. #pragma alloc_text(PAGE, MRxSmbReadMiscellaneousRegistryParameters)
  34. #pragma alloc_text(PAGE, SmbCeGetConfigurationInformation)
  35. #pragma alloc_text(PAGE, MRxSmbFsdDispatch)
  36. #pragma alloc_text(PAGE, MRxSmbDeallocateForFcb)
  37. #pragma alloc_text(PAGE, MRxSmbDeallocateForFobx)
  38. #pragma alloc_text(PAGE, MRxSmbGetUlongRegistryParameter)
  39. #pragma alloc_text(PAGE, MRxSmbPreUnload)
  40. #pragma alloc_text(PAGE, IsTerminalServicesServer)
  41. #pragma alloc_text(PAGE, IsServerSKU)
  42. #endif
  43. extern ERESOURCE s_SmbCeDbResource;
  44. extern ERESOURCE s_SmbSecuritySignatureResource;
  45. extern int fShadow;
  46. NTSYSAPI
  47. NTSTATUS
  48. NTAPI
  49. ZwLoadDriver(
  50. IN PUNICODE_STRING DriverServiceName
  51. );
  52. //
  53. // Global data declarations .
  54. //
  55. PVOID MRxSmbPoRegistrationState = NULL;
  56. FAST_MUTEX MRxSmbSerializationMutex;
  57. FAST_MUTEX MRxSmbReadWriteMutex;
  58. MRXSMB_CONFIGURATION MRxSmbConfiguration;
  59. MRXSMB_STATE MRxSmbState = MRXSMB_STARTABLE;
  60. SMBCE_CONTEXT SmbCeContext;
  61. PMDL s_pEchoSmbMdl = NULL;
  62. ULONG s_EchoSmbLength = 0;
  63. BOOLEAN EnablePlainTextPassword = FALSE;
  64. BOOLEAN SetupInProgress = FALSE;
  65. BOOLEAN EnableWmiLog = FALSE;
  66. BOOLEAN Win9xSessionRestriction = FALSE;
  67. BOOLEAN MRxSmbEnableOpDirCache = TRUE;
  68. ULONG OffLineFileTimeoutInterval = 1000; // in seconds
  69. ULONG ExtendedSessTimeoutInterval = 1000; // in seconds
  70. ULONG MaxNumOfExchangesForPipelineReadWrite = 8;
  71. #ifdef EXPLODE_POOLTAGS
  72. ULONG MRxSmbExplodePoolTags = 1;
  73. #else
  74. ULONG MRxSmbExplodePoolTags = 0;
  75. #endif
  76. //
  77. // This counts any SMBs sent out which could make the contents of the Get
  78. // File Attributes cache stale.
  79. //
  80. ULONG NameCacheGFAInvalidate;
  81. // local functions forward declarations
  82. NTSTATUS
  83. MRxSmbDeleteRegistryParameter(
  84. HANDLE ParametersHandle,
  85. PWCHAR ParameterName
  86. );
  87. //
  88. // Mini Redirector global variables.
  89. //
  90. struct _MINIRDR_DISPATCH MRxSmbDispatch;
  91. PRDBSS_DEVICE_OBJECT MRxSmbDeviceObject;
  92. MRXSMB_GLOBAL_PADDING MrxSmbCeGlobalPadding;
  93. LIST_ENTRY ExchangesWaitingForServerResponseBuffer;
  94. LONG NumOfBuffersForServerResponseInUse;
  95. BOOLEAN MRxSmbEnableCompression = FALSE;
  96. BOOLEAN MRxSmbSecuritySignaturesRequired = FALSE;
  97. BOOLEAN MRxSmbSecuritySignaturesEnabled = TRUE;
  98. BOOLEAN MRxSmbExtendedSignaturesEnabled = TRUE;
  99. BOOLEAN MRxSmbExtendedSignaturesRequired = FALSE;
  100. BOOLEAN MRxSmbEnableCachingOnWriteOnlyOpens = FALSE;
  101. BOOLEAN MRxSmbDisableShadowLoopback = FALSE;
  102. BOOLEAN MRxSmbEnableDownLevelLogOff = FALSE;
  103. ULONG MRxSmbConnectionIdLevel = 0;
  104. BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
  105. FAST_MUTEX MRxSmbFileInfoCacheLock;
  106. //
  107. // The following variable controls whether clientside cacheing is enabled or not.
  108. // It is the responsibility of the Csc routines themselves to do the right things
  109. // is CSC is not enabled because we will make the calls anyway.
  110. //
  111. BOOLEAN MRxSmbIsCscEnabled = TRUE;
  112. BOOLEAN MRxSmbIsCscEnabledForDisconnected = TRUE;
  113. BOOLEAN MRxSmbCscTransitionEnabledByDefault = FALSE;
  114. BOOLEAN MRxSmbEnableDisconnectedRB = FALSE; // don't transition remoteboot machine to disconnected state
  115. BOOLEAN MRxSmbCscAutoDialEnabled = FALSE;
  116. //
  117. // If this flag is TRUE, we strictly obey the transport binding order. If it is FALSE,
  118. // we can use whatever transport we want to connect to the remote server.
  119. //
  120. BOOLEAN MRxSmbObeyBindingOrder = FALSE;
  121. ULONG MRxSmbBuildNumber = VER_PRODUCTBUILD;
  122. #ifdef RX_PRIVATE_BUILD
  123. ULONG MRxSmbPrivateBuild = 1;
  124. #else
  125. ULONG MRxSmbPrivateBuild = 0;
  126. #endif
  127. //
  128. // MRxSmbSecurityInitialized indicates whether MRxSmbInitializeSecurity
  129. // has been called.
  130. //
  131. BOOLEAN MRxSmbSecurityInitialized = FALSE;
  132. //
  133. // MRxSmbBootedRemotely indicates that the machine did a remote boot.
  134. //
  135. BOOLEAN MRxSmbBootedRemotely = FALSE;
  136. //
  137. // MRxSmbUseKernelSecurity indicates that the machine should use kernel mode security APIs
  138. // during this remote boot boot.
  139. //
  140. BOOLEAN MRxSmbUseKernelModeSecurity = FALSE;
  141. LIST_ENTRY MRxSmbPagingFilesSrvOpenList;
  142. //
  143. // These variables will, in the near future, be passed from the kernel to the
  144. // redirector to tell it which share is the remote boot share and how to log on
  145. // to the server.
  146. //
  147. PKEY_VALUE_PARTIAL_INFORMATION MRxSmbRemoteBootRootValue = NULL;
  148. PKEY_VALUE_PARTIAL_INFORMATION MRxSmbRemoteBootMachineDirectoryValue = NULL;
  149. UNICODE_STRING MRxSmbRemoteBootShare;
  150. UNICODE_STRING MRxSmbRemoteBootPath;
  151. UNICODE_STRING MRxSmbRemoteSetupPath;
  152. UNICODE_STRING MRxSmbRemoteBootMachineName;
  153. UNICODE_STRING MRxSmbRemoteBootMachinePassword;
  154. UNICODE_STRING MRxSmbRemoteBootMachineDomain;
  155. UCHAR MRxSmbRemoteBootMachineSid[RI_SECRET_SID_SIZE];
  156. RI_SECRET MRxSmbRemoteBootSecret;
  157. #if defined(REMOTE_BOOT)
  158. BOOLEAN MRxSmbRemoteBootSecretValid = FALSE;
  159. BOOLEAN MRxSmbRemoteBootDoMachineLogon;
  160. BOOLEAN MRxSmbRemoteBootUsePassword2;
  161. #endif // defined(REMOTE_BOOT)
  162. //
  163. // for LoopBack detection
  164. //
  165. GUID CachedServerGuid;
  166. UNICODE_STRING MRxSmbRemoteBootRedirectionPrefix;
  167. UNICODE_PREFIX_TABLE MRxSmbRemoteBootRedirectionTable;
  168. //declare the shadow debugtrace controlpoints
  169. RXDT_DefineCategory(CREATE);
  170. RXDT_DefineCategory(CLEANUP);
  171. RXDT_DefineCategory(CLOSE);
  172. RXDT_DefineCategory(READ);
  173. RXDT_DefineCategory(WRITE);
  174. RXDT_DefineCategory(LOCKCTRL);
  175. RXDT_DefineCategory(FLUSH);
  176. RXDT_DefineCategory(PREFIX);
  177. RXDT_DefineCategory(FCBSTRUCTS);
  178. RXDT_DefineCategory(DISPATCH);
  179. RXDT_DefineCategory(EA);
  180. RXDT_DefineCategory(DEVFCB);
  181. RXDT_DefineCategory(DISCCODE); //this shouldn't be a shadow
  182. RXDT_DefineCategory(BROWSER); //this shouldn't be a shadow
  183. RXDT_DefineCategory(CONNECT); //this shouldn't be a shadow
  184. typedef enum _MRXSMB_INIT_STATES {
  185. MRXSMBINIT_ALL_INITIALIZATION_COMPLETED,
  186. MRXSMBINIT_STARTED_BROWSER,
  187. MRXSMBINIT_INITIALIZED_FOR_CSC,
  188. MRXSMBINIT_MINIRDR_REGISTERED,
  189. MRXSMBINIT_START
  190. } MRXSMB_INIT_STATES;
  191. NTSTATUS
  192. MRxSmbFsdDispatch (
  193. IN PDEVICE_OBJECT DeviceObject,
  194. IN PIRP Irp
  195. );
  196. NTSTATUS
  197. MRxSmbCheckTransportName(
  198. IN PIRP Irp,
  199. OUT PSMBCEDB_SERVER_ENTRY *ppServerEntry
  200. );
  201. NTSTATUS
  202. SmbCeGetServersWithExtendedSessTimeout();
  203. NTSTATUS
  204. DriverEntry(
  205. IN PDRIVER_OBJECT DriverObject,
  206. IN PUNICODE_STRING RegistryPath
  207. )
  208. /*++
  209. Routine Description:
  210. This is the initialization routine for the SMB mini redirector
  211. Arguments:
  212. DriverObject - Pointer to driver object created by the system.
  213. Return Value:
  214. RXSTATUS - The function value is the final status from the initialization
  215. operation.
  216. --*/
  217. {
  218. NTSTATUS Status;
  219. MRXSMB_INIT_STATES MRxSmbInitState = 0;
  220. UNICODE_STRING SmbMiniRedirectorName;
  221. PAGED_CODE();
  222. #ifdef MONOLITHIC_MINIRDR
  223. DbgPrint("InitWrapper\n");
  224. Status = RxDriverEntry(DriverObject, RegistryPath);
  225. DbgPrint("BackFromInitWrapper %p\n",Status);
  226. if (Status != STATUS_SUCCESS) {
  227. DbgPrint("Wrapper failed to initialize. Status = %08lx\n",Status);
  228. return(Status);
  229. }
  230. #endif
  231. NameCacheGFAInvalidate = 0;
  232. RtlZeroMemory(&MRxSmbStatistics,sizeof(MRxSmbStatistics));
  233. KeQuerySystemTime(&MRxSmbStatistics.StatisticsStartTime);
  234. RtlZeroMemory(&MrxSmbCeGlobalPadding,sizeof(MrxSmbCeGlobalPadding));
  235. MmInitializeMdl(&MrxSmbCeGlobalPadding.Mdl,&MrxSmbCeGlobalPadding.Pad[0],SMBCE_PADDING_DATA_SIZE);
  236. MmBuildMdlForNonPagedPool(&MrxSmbCeGlobalPadding.Mdl);
  237. ExInitializeFastMutex(&MRxSmbSerializationMutex);
  238. ExInitializeFastMutex(&MRxSmbReadWriteMutex);
  239. Status = MRxSmbInitializeTransport();
  240. if (Status != STATUS_SUCCESS) {
  241. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry failed to init transport data structures: %08lx\n", Status ));
  242. return(STATUS_UNSUCCESSFUL);
  243. }
  244. MRxSmbReadMiscellaneousRegistryParameters();
  245. //
  246. // Disable opportunistic directory caching if this is a .NET server.
  247. //
  248. if( IsServerSKU() ) {
  249. MRxSmbEnableOpDirCache = FALSE;
  250. }
  251. try {
  252. //
  253. // Initialize the discardable code functions before doing anything else.
  254. //
  255. RdrInitializeDiscardableCode();
  256. MRxSmbInitState = MRXSMBINIT_START;
  257. RtlInitUnicodeString(&SmbMiniRedirectorName,DD_NFS_DEVICE_NAME_U);
  258. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry: DriverObject =%p\n", DriverObject ));
  259. Status = RxRegisterMinirdr(&MRxSmbDeviceObject,
  260. DriverObject,
  261. &MRxSmbDispatch,
  262. 0, //register with unc and for mailslots
  263. &SmbMiniRedirectorName,
  264. 0, //IN ULONG DeviceExtensionSize,
  265. FILE_DEVICE_NETWORK_FILE_SYSTEM, //IN DEVICE_TYPE DeviceType,
  266. FILE_REMOTE_DEVICE //IN ULONG DeviceCharacteristics
  267. );
  268. if (Status!=STATUS_SUCCESS) {
  269. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry failed: %08lx\n", Status ));
  270. try_return(Status);
  271. }
  272. MRxSmbInitState = MRXSMBINIT_MINIRDR_REGISTERED;
  273. Status = MRxSmbInitializeCSC(&SmbMiniRedirectorName);
  274. if (!NT_SUCCESS( Status )) {
  275. try_return( Status );
  276. }
  277. MRxSmbInitState = MRXSMBINIT_INITIALIZED_FOR_CSC;
  278. // init the browser.....BUT DONT TRUST IT!!!!
  279. try {
  280. // Setup the browser
  281. Status = BowserDriverEntry(DriverObject, RegistryPath);
  282. } except(EXCEPTION_EXECUTE_HANDLER) {
  283. // We had some trouble trying to start up the browser.....sigh.
  284. Status = GetExceptionCode();
  285. DbgPrint("Browser didn't start....%08lx\n", Status);
  286. }
  287. if (!NT_SUCCESS( Status )) {
  288. try_return( Status );
  289. }
  290. MRxSmbInitState = MRXSMBINIT_STARTED_BROWSER;
  291. //for all this stuff, there's no undo.....so no extra state
  292. Status = MRxSmbInitializeTables();
  293. if (!NT_SUCCESS( Status )) {
  294. try_return(Status);
  295. }
  296. RtlInitUnicodeString(&SmbCeContext.ComputerName,NULL);
  297. RtlInitUnicodeString(&SmbCeContext.DomainName,NULL);
  298. RtlInitUnicodeString(&SmbCeContext.OperatingSystem, NULL);
  299. RtlInitUnicodeString(&SmbCeContext.LanmanType, NULL);
  300. RtlInitUnicodeString(&SmbCeContext.Transports, NULL);
  301. RtlInitUnicodeString(&SmbCeContext.ServersWithExtendedSessTimeout, NULL);
  302. RtlInitUnicodeString(&MRxSmbRemoteBootMachineName, NULL);
  303. RtlInitUnicodeString(&MRxSmbRemoteBootMachineDomain, NULL);
  304. RtlInitUnicodeString(&MRxSmbRemoteBootMachinePassword, NULL);
  305. SmbCeGetConfigurationInformation();
  306. SmbCeGetServersWithExtendedSessTimeout();
  307. try_exit: NOTHING;
  308. } finally {
  309. if (Status != STATUS_SUCCESS) {
  310. MRxSmbInitUnwind(DriverObject,MRxSmbInitState);
  311. }
  312. }
  313. if (Status != STATUS_SUCCESS) {
  314. DbgPrint("MRxSmb failed to start with %08lx %08lx\n",Status,MRxSmbInitState);
  315. return(Status);
  316. }
  317. // Do not setup Unload Routine. This prevents mrxsmb from being unloaded individually
  318. //setup the driverdispatch for people who come in here directly....like the browser
  319. //CODE.IMPROVEMENT we should change this code so that the things that aren't examined
  320. // in MRxSmbFsdDispatch are routed directly, i.e. reads and writes
  321. {ULONG i;
  322. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  323. DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)MRxSmbFsdDispatch;
  324. }}
  325. Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)MRxSmbDeviceObject, WMIREG_ACTION_REGISTER);
  326. if (Status != STATUS_SUCCESS) {
  327. DbgPrint("MRxSmb fails to register WMI %lx\n",Status);
  328. } else {
  329. EnableWmiLog = TRUE;
  330. }
  331. //and get out
  332. return STATUS_SUCCESS;
  333. }
  334. VOID
  335. MRxSmbPreUnload(
  336. VOID
  337. )
  338. /*++
  339. Routine Description:
  340. Arguments:
  341. Return Value:
  342. Notes:
  343. --*/
  344. {
  345. PDRIVER_OBJECT DriverObject = ((PDEVICE_OBJECT)MRxSmbDeviceObject)->DriverObject;
  346. PAGED_CODE();
  347. if (EnableWmiLog) {
  348. NTSTATUS Status;
  349. Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)MRxSmbDeviceObject, WMIREG_ACTION_DEREGISTER);
  350. if (Status != STATUS_SUCCESS) {
  351. DbgPrint("MRxSmb fails to deregister WMI %lx\n",Status);
  352. }
  353. }
  354. //ASSERT(!"Starting to unload!");
  355. //RxUnregisterMinirdr(MRxSmbDeviceObject);
  356. MRxSmbInitUnwindSmb(DriverObject, MRXSMBINIT_ALL_INITIALIZATION_COMPLETED);
  357. // free the pool associated with the resource
  358. ExDeleteResource(&s_SmbCeDbResource);
  359. ExDeleteResource(&s_SmbSecuritySignatureResource);
  360. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbPreUnload exit: DriverObject =%p\n", DriverObject) );
  361. }
  362. VOID
  363. MRxSmbInitUnwind(
  364. IN PDRIVER_OBJECT DriverObject,
  365. IN MRXSMB_INIT_STATES MRxSmbInitState
  366. )
  367. /*++
  368. Routine Description:
  369. This routine does the common uninit work for unwinding from a bad driver entry or for unloading.
  370. Arguments:
  371. RxInitState - tells how far we got into the intialization
  372. Return Value:
  373. None
  374. --*/
  375. {
  376. PAGED_CODE();
  377. MRxSmbInitUnwindSmb(DriverObject, MRxSmbInitState);
  378. MRxSmbInitUnwindBowser(DriverObject, MRxSmbInitState);
  379. }
  380. VOID
  381. MRxSmbInitUnwindSmb(
  382. IN PDRIVER_OBJECT DriverObject,
  383. IN MRXSMB_INIT_STATES MRxSmbInitState
  384. )
  385. /*++
  386. Routine Description:
  387. This routine does the common uninit work for SMB for unwinding from a bad driver entry or for unloading.
  388. Arguments:
  389. RxInitState - tells how far we got into the intialization
  390. Return Value:
  391. None
  392. --*/
  393. {
  394. PAGED_CODE();
  395. switch (MRxSmbInitState) {
  396. case MRXSMBINIT_ALL_INITIALIZATION_COMPLETED:
  397. //Nothing extra to do...this is just so that the constant in RxUnload doesn't change.......
  398. //lack of break intentional
  399. #ifdef MRXSMB_BUILD_FOR_CSC
  400. case MRXSMBINIT_INITIALIZED_FOR_CSC:
  401. MRxSmbUninitializeCSC();
  402. //lack of break intentional
  403. #endif
  404. case MRXSMBINIT_MINIRDR_REGISTERED:
  405. RxUnregisterMinirdr(MRxSmbDeviceObject);
  406. //lack of break intentional
  407. }
  408. }
  409. VOID
  410. MRxSmbInitUnwindBowser(
  411. IN PDRIVER_OBJECT DriverObject,
  412. IN MRXSMB_INIT_STATES MRxSmbInitState
  413. )
  414. /*++
  415. Routine Description:
  416. This routine does the common uninit work for bowser for unwinding from a bad driver entry or for unloading.
  417. Arguments:
  418. RxInitState - tells how far we got into the intialization
  419. Return Value:
  420. None
  421. --*/
  422. {
  423. switch (MRxSmbInitState) {
  424. case MRXSMBINIT_ALL_INITIALIZATION_COMPLETED:
  425. case MRXSMBINIT_STARTED_BROWSER:
  426. BowserUnload(DriverObject);
  427. case MRXSMBINIT_START:
  428. RdrUninitializeDiscardableCode();
  429. break;
  430. }
  431. }
  432. VOID
  433. MRxSmbUnload(
  434. IN PDRIVER_OBJECT DriverObject
  435. )
  436. /*++
  437. Routine Description:
  438. This is the unload routine for the SMB mini redirector.
  439. Arguments:
  440. DriverObject - pointer to the driver object for the MRxSmb
  441. Return Value:
  442. None
  443. --*/
  444. {
  445. PAGED_CODE();
  446. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbUnload: DriverObject =%p\n", DriverObject) );
  447. MRxSmbInitUnwindBowser(DriverObject,MRXSMBINIT_ALL_INITIALIZATION_COMPLETED);
  448. }
  449. NTSTATUS
  450. MRxSmbInitializeTables(
  451. void
  452. )
  453. /*++
  454. Routine Description:
  455. This routine sets up the mini redirector dispatch vector and also calls to initialize any other tables needed.
  456. Return Value:
  457. RXSTATUS - The return status for the operation
  458. --*/
  459. {
  460. PAGED_CODE();
  461. // Ensure that the SMB mini redirector context satisfies the size constraints
  462. ASSERT(sizeof(MRXSMB_RX_CONTEXT) <= MRX_CONTEXT_SIZE);
  463. //local minirdr dispatch table init
  464. ZeroAndInitializeNodeType( &MRxSmbDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
  465. // SMB mini redirector extension sizes and allocation policies.
  466. // CODE.IMPROVEMENT -- currently we do not allocate the NET_ROOT and SRV_CALL extensions
  467. // in the wrapper. Except for V_NET_ROOT wherein it is shared across multiple instances in
  468. // the wrapper all the other data structure management should be left to the wrappers
  469. MRxSmbDispatch.MRxFlags = (RDBSS_MANAGE_FCB_EXTENSION |
  470. RDBSS_MANAGE_SRV_OPEN_EXTENSION |
  471. RDBSS_MANAGE_FOBX_EXTENSION);
  472. MRxSmbDispatch.MRxSrvCallSize = 0;
  473. MRxSmbDispatch.MRxNetRootSize = 0;
  474. MRxSmbDispatch.MRxVNetRootSize = 0;
  475. MRxSmbDispatch.MRxFcbSize = sizeof(MRX_SMB_FCB);
  476. MRxSmbDispatch.MRxSrvOpenSize = sizeof(MRX_SMB_SRV_OPEN);
  477. MRxSmbDispatch.MRxFobxSize = sizeof(MRX_SMB_FOBX);
  478. // Mini redirector cancel routine ..
  479. MRxSmbDispatch.MRxCancel = NULL;
  480. // Mini redirector Start/Stop
  481. MRxSmbDispatch.MRxStart = MRxSmbStart;
  482. MRxSmbDispatch.MRxStop = MRxSmbStop;
  483. MRxSmbDispatch.MRxDevFcbXXXControlFile = MRxSmbDevFcbXXXControlFile;
  484. // Mini redirector name resolution
  485. MRxSmbDispatch.MRxCreateSrvCall = MRxSmbCreateSrvCall;
  486. MRxSmbDispatch.MRxSrvCallWinnerNotify = MRxSmbSrvCallWinnerNotify;
  487. MRxSmbDispatch.MRxCreateVNetRoot = MRxSmbCreateVNetRoot;
  488. MRxSmbDispatch.MRxUpdateNetRootState = MRxSmbUpdateNetRootState;
  489. MRxSmbDispatch.MRxExtractNetRootName = MRxSmbExtractNetRootName;
  490. MRxSmbDispatch.MRxFinalizeSrvCall = MRxSmbFinalizeSrvCall;
  491. MRxSmbDispatch.MRxFinalizeNetRoot = MRxSmbFinalizeNetRoot;
  492. MRxSmbDispatch.MRxFinalizeVNetRoot = MRxSmbFinalizeVNetRoot;
  493. // File System Object Creation/Deletion.
  494. MRxSmbDispatch.MRxCreate = MRxSmbCreate;
  495. MRxSmbDispatch.MRxCollapseOpen = MRxSmbCollapseOpen;
  496. MRxSmbDispatch.MRxShouldTryToCollapseThisOpen = MRxSmbShouldTryToCollapseThisOpen;
  497. MRxSmbDispatch.MRxExtendForCache = MRxSmbExtendForCache;
  498. MRxSmbDispatch.MRxExtendForNonCache = MRxSmbExtendForNonCache;
  499. MRxSmbDispatch.MRxTruncate = MRxSmbTruncate;
  500. MRxSmbDispatch.MRxCleanupFobx = MRxSmbCleanupFobx;
  501. MRxSmbDispatch.MRxCloseSrvOpen = MRxSmbCloseSrvOpen;
  502. MRxSmbDispatch.MRxFlush = MRxSmbFlush;
  503. MRxSmbDispatch.MRxForceClosed = MRxSmbForcedClose;
  504. MRxSmbDispatch.MRxDeallocateForFcb = MRxSmbDeallocateForFcb;
  505. MRxSmbDispatch.MRxDeallocateForFobx = MRxSmbDeallocateForFobx;
  506. MRxSmbDispatch.MRxIsLockRealizable = MRxSmbIsLockRealizable;
  507. MRxSmbDispatch.MRxAreFilesAliased = MRxSmbAreFilesAliased;
  508. // File System Objects query/Set
  509. MRxSmbDispatch.MRxQueryDirectory = MRxSmbQueryDirectory;
  510. MRxSmbDispatch.MRxQueryVolumeInfo = MRxSmbQueryVolumeInformation;
  511. MRxSmbDispatch.MRxSetVolumeInfo = MRxSmbSetVolumeInformation;
  512. MRxSmbDispatch.MRxQueryEaInfo = MRxSmbQueryEaInformation;
  513. MRxSmbDispatch.MRxSetEaInfo = MRxSmbSetEaInformation;
  514. MRxSmbDispatch.MRxQuerySdInfo = MRxSmbQuerySecurityInformation;
  515. MRxSmbDispatch.MRxSetSdInfo = MRxSmbSetSecurityInformation;
  516. MRxSmbDispatch.MRxQueryQuotaInfo = MRxSmbQueryQuotaInformation;
  517. MRxSmbDispatch.MRxSetQuotaInfo = MRxSmbSetQuotaInformation;
  518. MRxSmbDispatch.MRxQueryFileInfo = MRxSmbQueryFileInformation;
  519. MRxSmbDispatch.MRxSetFileInfo = MRxSmbSetFileInformation;
  520. MRxSmbDispatch.MRxSetFileInfoAtCleanup
  521. = MRxSmbSetFileInformationAtCleanup;
  522. MRxSmbDispatch.MRxIsValidDirectory= MRxSmbIsValidDirectory;
  523. // Buffering state change
  524. MRxSmbDispatch.MRxComputeNewBufferingState = MRxSmbComputeNewBufferingState;
  525. // New MRX functions
  526. MRxSmbDispatch.MRxPreparseName = MRxSmbPreparseName;
  527. // File System Object I/O
  528. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = MRxSmbRead;
  529. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = MRxSmbWrite;
  530. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = MRxSmbLocks;
  531. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = MRxSmbLocks;
  532. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = MRxSmbLocks;
  533. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = MRxSmbLocks;
  534. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = MRxSmbFsCtl;
  535. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = MRxSmbIoCtl;
  536. //CODE.IMPROVEMENT shouldn't flush come thru lowio???
  537. MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = MRxSmbNotifyChangeDirectory;
  538. //no longer a field MRxSmbDispatch.MRxUnlockRoutine = MRxSmbUnlockRoutine;
  539. // Miscellanous
  540. MRxSmbDispatch.MRxCompleteBufferingStateChangeRequest = MRxSmbCompleteBufferingStateChangeRequest;
  541. MRxSmbDispatch.MRxGetConnectionId = MRxSmbGetConnectionId;
  542. // initialize the paging file list
  543. InitializeListHead(&MRxSmbPagingFilesSrvOpenList);
  544. // The list contains the exchanges waiting on pre-allcate buffer in case of Security
  545. // Signature checking is actived and no more buffer can be allocated
  546. InitializeListHead(&ExchangesWaitingForServerResponseBuffer);
  547. NumOfBuffersForServerResponseInUse = 0;
  548. // initialize the mutex which protect the file info cache expire timer
  549. ExInitializeFastMutex(&MRxSmbFileInfoCacheLock);
  550. //
  551. // now callout to initialize other tables
  552. SmbPseInitializeTables();
  553. return(STATUS_SUCCESS);
  554. }
  555. BOOLEAN AlreadyStarted = FALSE;
  556. NTSTATUS
  557. MRxSmbStart(
  558. PRX_CONTEXT RxContext,
  559. IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
  560. )
  561. /*++
  562. Routine Description:
  563. This routine completes the initialization of the mini redirector fromn the
  564. RDBSS perspective. Note that this is different from the initialization done
  565. in DriverEntry. Any initialization that depends on RDBSS should be done as
  566. part of this routine while the initialization that is independent of RDBSS
  567. should be done in the DriverEntry routine.
  568. Arguments:
  569. RxContext - Supplies the Irp that was used to startup the rdbss
  570. Return Value:
  571. RXSTATUS - The return status for the operation
  572. --*/
  573. {
  574. NTSTATUS Status;
  575. MRXSMB_STATE CurrentState;
  576. PAGED_CODE();
  577. //
  578. // If this is a normal start (from the workstation service), change state from
  579. // START_IN_PROGRESS to STARTED. If this is a remote boot start (from ioinit),
  580. // don't change state. This is necessary to allow the workstation service to
  581. // initialize correctly when it finally comes up.
  582. //
  583. if (RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode == FSCTL_LMR_START) {
  584. CurrentState = (MRXSMB_STATE)
  585. InterlockedCompareExchange(
  586. (PLONG)&MRxSmbState,
  587. MRXSMB_STARTED,
  588. MRXSMB_START_IN_PROGRESS);
  589. } else {
  590. CurrentState = MRXSMB_START_IN_PROGRESS;
  591. }
  592. if (CurrentState == MRXSMB_START_IN_PROGRESS) {
  593. MRxSmbPoRegistrationState = PoRegisterSystemState(
  594. NULL,0);
  595. // Initialize the SMB connection engine data structures
  596. Status = SmbCeDbInit();
  597. if (NT_SUCCESS(Status)) {
  598. //
  599. // If this is a normal start, initialize the security related data
  600. // structures. If this is a remote boot start, we can't initialize
  601. // security yet because user mode hasn't started yet.
  602. //
  603. if (RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode == FSCTL_LMR_START) {
  604. Status = MRxSmbInitializeSecurity();
  605. }
  606. if (NT_SUCCESS(Status)) {
  607. Status = SmbMrxInitializeStufferFacilities();
  608. } else {
  609. RxLogFailure (
  610. MRxSmbDeviceObject,
  611. NULL,
  612. EVENT_RDR_UNEXPECTED_ERROR,
  613. Status);
  614. }
  615. if (NT_SUCCESS(Status)) {
  616. Status = MRxSmbInitializeRecurrentServices();
  617. } else {
  618. RxLogFailure (
  619. MRxSmbDeviceObject,
  620. NULL,
  621. EVENT_RDR_UNEXPECTED_ERROR,
  622. Status);
  623. }
  624. if (Status == STATUS_SUCCESS) {
  625. if (Status != STATUS_SUCCESS) {
  626. RxLogFailure (
  627. MRxSmbDeviceObject,
  628. NULL,
  629. EVENT_RDR_UNEXPECTED_ERROR,
  630. Status);
  631. }
  632. } else {
  633. RxLogFailure (
  634. MRxSmbDeviceObject,
  635. NULL,
  636. EVENT_RDR_UNEXPECTED_ERROR,
  637. Status);
  638. }
  639. Status = SeRegisterLogonSessionTerminatedRoutine(
  640. (PSE_LOGON_SESSION_TERMINATED_ROUTINE)
  641. MRxSmbLogonSessionTerminationHandler);
  642. }
  643. } else if (MRxSmbState == MRXSMB_STARTED) {
  644. Status = STATUS_REDIRECTOR_STARTED;
  645. } else {
  646. Status = STATUS_UNSUCCESSFUL;
  647. }
  648. return Status;
  649. }
  650. NTSTATUS
  651. MRxSmbStop(
  652. PRX_CONTEXT RxContext,
  653. IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
  654. )
  655. /*++
  656. Routine Description:
  657. This routine is used to activate the mini redirector from the RDBSS perspective
  658. Arguments:
  659. RxContext - the context that was used to start the mini redirector
  660. pContext - the SMB mini rdr context passed in at registration time.
  661. Return Value:
  662. RXSTATUS - The return status for the operation
  663. --*/
  664. {
  665. NTSTATUS Status;
  666. PAGED_CODE();
  667. PoUnregisterSystemState(
  668. MRxSmbPoRegistrationState);
  669. Status = MRxSmbUninitializeSecurity();
  670. if (NT_SUCCESS(Status)) {
  671. Status = SmbMrxFinalizeStufferFacilities();
  672. }
  673. ASSERT(NT_SUCCESS(Status));
  674. SeUnregisterLogonSessionTerminatedRoutine(
  675. (PSE_LOGON_SESSION_TERMINATED_ROUTINE)
  676. MRxSmbLogonSessionTerminationHandler);
  677. // tear down the recurrent services
  678. MRxSmbTearDownRecurrentServices();
  679. // Tear down the connection engine database
  680. SmbCeDbTearDown();
  681. // Tear down the registration for notifications
  682. MRxSmbDeregisterForPnpNotifications();
  683. // Wait for all the work items to be processed
  684. RxSpinDownMRxDispatcher(MRxSmbDeviceObject);
  685. // Deallocate the configuration strings ....
  686. if (SmbCeContext.ComputerName.Buffer != NULL) {
  687. RxFreePool(SmbCeContext.ComputerName.Buffer);
  688. SmbCeContext.ComputerName.Buffer = NULL;
  689. }
  690. if (SmbCeContext.OperatingSystem.Buffer != NULL) {
  691. RxFreePool(SmbCeContext.OperatingSystem.Buffer);
  692. SmbCeContext.OperatingSystem.Buffer = NULL;
  693. }
  694. if (SmbCeContext.LanmanType.Buffer != NULL) {
  695. RxFreePool(SmbCeContext.LanmanType.Buffer);
  696. SmbCeContext.LanmanType.Buffer = NULL;
  697. }
  698. if (SmbCeContext.DomainName.Buffer != NULL) {
  699. RxFreePool(SmbCeContext.DomainName.Buffer);
  700. SmbCeContext.DomainName.Buffer = NULL;
  701. }
  702. if (SmbCeContext.Transports.Buffer != NULL) {
  703. // the transports buffer is at the end of a larger buffer (by 12 bytes)
  704. // allocated to read the value from the registry. recover the original buffer
  705. // pointer in orer to free.
  706. PKEY_VALUE_PARTIAL_INFORMATION TransportsValueFromRegistry;
  707. TransportsValueFromRegistry = CONTAINING_RECORD(
  708. SmbCeContext.Transports.Buffer,
  709. KEY_VALUE_PARTIAL_INFORMATION,
  710. Data[0]
  711. );
  712. //DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
  713. RxFreePool(TransportsValueFromRegistry);
  714. SmbCeContext.Transports.Buffer = NULL;
  715. SmbCeContext.Transports.Length = 0;
  716. SmbCeContext.Transports.MaximumLength = 0;
  717. }
  718. if (SmbCeContext.ServersWithExtendedSessTimeout.Buffer != NULL) {
  719. // the transports buffer is at the end of a larger buffer (by 12 bytes)
  720. // allocated to read the value from the registry. recover the original buffer
  721. // pointer in orer to free.
  722. PKEY_VALUE_PARTIAL_INFORMATION ServersValueFromRegistry;
  723. ServersValueFromRegistry = CONTAINING_RECORD(
  724. SmbCeContext.ServersWithExtendedSessTimeout.Buffer,
  725. KEY_VALUE_PARTIAL_INFORMATION,
  726. Data[0]
  727. );
  728. //DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
  729. RxFreePool(ServersValueFromRegistry);
  730. SmbCeContext.ServersWithExtendedSessTimeout.Buffer = NULL;
  731. SmbCeContext.ServersWithExtendedSessTimeout.Length = 0;
  732. SmbCeContext.ServersWithExtendedSessTimeout.MaximumLength = 0;
  733. }
  734. RtlFreeUnicodeString(&MRxSmbRemoteBootMachineName);
  735. RtlFreeUnicodeString(&MRxSmbRemoteBootMachineDomain);
  736. RtlFreeUnicodeString(&MRxSmbRemoteBootMachinePassword);
  737. // MRxSmbUninitializeCSC();
  738. if (s_pNegotiateSmb != NULL) {
  739. RxFreePool(s_pNegotiateSmb - TRANSPORT_HEADER_SIZE);
  740. s_pNegotiateSmb = NULL;
  741. }
  742. if (s_pNegotiateSmbRemoteBoot != NULL) {
  743. RxFreePool(s_pNegotiateSmbRemoteBoot - TRANSPORT_HEADER_SIZE);
  744. s_pNegotiateSmbRemoteBoot = NULL;
  745. }
  746. return(STATUS_SUCCESS);
  747. }
  748. NTSTATUS
  749. MRxSmbInitializeSecurity (VOID)
  750. /*++
  751. Routine Description:
  752. This routine initializes the SMB miniredirector security .
  753. Arguments:
  754. None.
  755. Return Value:
  756. None.
  757. Note:
  758. This API can only be called from a FS process.
  759. --*/
  760. {
  761. NTSTATUS Status = STATUS_SUCCESS;
  762. PAGED_CODE();
  763. #ifndef WIN9X
  764. // DbgBreakPoint();
  765. if (MRxSmbSecurityInitialized)
  766. return STATUS_SUCCESS;
  767. if ( NULL == InitSecurityInterfaceW() ) {
  768. ASSERT(FALSE);
  769. Status = STATUS_INVALID_PARAMETER;
  770. } else {
  771. MRxSmbSecurityInitialized = TRUE;
  772. Status = STATUS_SUCCESS;
  773. }
  774. #endif
  775. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  776. return Status;
  777. }
  778. NTSTATUS
  779. MRxSmbUninitializeSecurity(VOID)
  780. /*++
  781. Routine Description:
  782. Arguments:
  783. None.
  784. Return Value:
  785. None.
  786. Note:
  787. This API can only be called from a FS process.
  788. --*/
  789. {
  790. NTSTATUS Status = STATUS_SUCCESS;
  791. PAGED_CODE();
  792. return Status;
  793. }
  794. //
  795. // Remote boot needs to use the ComputerName value, not ActiveComputerName, because
  796. // ActiveComputerName is volatile and is set relatively late in system initialization.
  797. //
  798. #define SMBMRX_CONFIG_COMPUTER_NAME \
  799. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"
  800. #define SMBMRX_CONFIG_COMPUTER_NAME_NONVOLATILE \
  801. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
  802. #define COMPUTERNAME L"ComputerName"
  803. #define SMBMRX_CONFIG_TRANSPORTS \
  804. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Linkage"
  805. #define TRANSPORT_BINDINGS L"Bind"
  806. #define SMB_SERVER_PARAMETERS \
  807. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters"
  808. BOOL
  809. IsTerminalServicesServer()
  810. /*++
  811. Routine Description:
  812. This routine determines whether this is a TS machine, and that we should enable
  813. the per-user connectivity for multiplexing
  814. Arguments:
  815. None
  816. Return Value:
  817. TRUE for machines that are SERVER or better, and are running non-single-user TS.
  818. FALSE for all others.
  819. --*/
  820. {
  821. RTL_OSVERSIONINFOEXW Osvi;
  822. DWORD TypeMask;
  823. DWORDLONG ConditionMask;
  824. // First make sure that its a TS machine
  825. memset(&Osvi, 0, sizeof(OSVERSIONINFOEX));
  826. Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  827. Osvi.wSuiteMask = VER_SUITE_TERMINAL;
  828. TypeMask = VER_SUITENAME;
  829. ConditionMask = 0;
  830. VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
  831. if( NT_SUCCESS(RtlVerifyVersionInfo(&Osvi, TypeMask, ConditionMask)) )
  832. {
  833. // Now make sure this isn't single-user TS
  834. Osvi.wSuiteMask = VER_SUITE_SINGLEUSERTS;
  835. TypeMask = VER_SUITENAME;
  836. ConditionMask = 0;
  837. VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
  838. return !NT_SUCCESS(RtlVerifyVersionInfo(&Osvi, TypeMask, ConditionMask));
  839. }
  840. else
  841. {
  842. return FALSE;
  843. }
  844. }
  845. BOOL
  846. IsServerSKU()
  847. /*++
  848. Routine Description:
  849. This routine determines whether this is a server SKU
  850. Arguments:
  851. None
  852. Return Value:
  853. TRUE for machines that are SERVER or better.
  854. FALSE for all others.
  855. --*/
  856. {
  857. RTL_OSVERSIONINFOEXW Osvi;
  858. DWORD TypeMask;
  859. DWORDLONG ConditionMask;
  860. // First make sure that its a TS machine
  861. memset(&Osvi, 0, sizeof(OSVERSIONINFOEX));
  862. Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  863. Osvi.wProductType = VER_NT_DOMAIN_CONTROLLER;
  864. TypeMask = VER_PRODUCT_TYPE;
  865. ConditionMask = 0;
  866. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_GREATER_EQUAL);
  867. if( NT_SUCCESS(RtlVerifyVersionInfo(&Osvi, TypeMask, ConditionMask)) )
  868. {
  869. return TRUE;
  870. }
  871. else
  872. {
  873. return FALSE;
  874. }
  875. }
  876. VOID
  877. MRxSmbReadMiscellaneousRegistryParameters()
  878. {
  879. NTSTATUS Status;
  880. OBJECT_ATTRIBUTES ObjectAttributes;
  881. UNICODE_STRING UnicodeString;
  882. UNICODE_STRING WorkStationParametersRegistryKeyName;
  883. HANDLE ParametersHandle;
  884. ULONG Temp;
  885. KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
  886. #if defined(REMOTE_BOOT)
  887. PKEY_VALUE_PARTIAL_INFORMATION RbrListFromRegistry;
  888. ULONG AllocationLength;
  889. PWCHAR RbrList;
  890. PWCHAR redirectionEntry;
  891. UNICODE_STRING prefix;
  892. PRBR_PREFIX prefixEntry;
  893. ULONG prefixEntryLength;
  894. PWCHAR DefaultRbrList =
  895. L"L\\pagefile.sys\0"
  896. L"L\\temp\0"
  897. L"L\\tmp\0"
  898. L"R\\\0"
  899. ;
  900. #endif // defined(REMOTE_BOOT)
  901. PAGED_CODE();
  902. RtlInitUnicodeString(&UnicodeString, SMBMRX_MINIRDR_PARAMETERS);
  903. InitializeObjectAttributes(
  904. &ObjectAttributes,
  905. &UnicodeString,
  906. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  907. NULL,
  908. NULL
  909. );
  910. Status = ZwOpenKey (&ParametersHandle, KEY_READ, &ObjectAttributes);
  911. if (NT_SUCCESS(Status)) {
  912. if (0) {
  913. MRxSmbGetUlongRegistryParameter(
  914. ParametersHandle,
  915. L"NoPreciousServerSetup",
  916. (PULONG)&Temp,
  917. FALSE
  918. );
  919. }
  920. Status = MRxSmbGetUlongRegistryParameter(
  921. ParametersHandle,
  922. L"DeferredOpensEnabled",
  923. (PULONG)&Temp,
  924. FALSE );
  925. if (NT_SUCCESS(Status))
  926. MRxSmbDeferredOpensEnabled = (BOOLEAN)Temp;
  927. Status = MRxSmbGetUlongRegistryParameter(
  928. ParametersHandle,
  929. L"OplocksDisabled",
  930. (PULONG)&Temp,
  931. FALSE );
  932. if (NT_SUCCESS(Status))
  933. MRxSmbOplocksDisabled = (BOOLEAN)Temp;
  934. MRxSmbIsCscEnabled = TRUE;
  935. //this should be a macro......
  936. Status = MRxSmbGetUlongRegistryParameter(
  937. ParametersHandle,
  938. L"CscEnabled",
  939. (PULONG)&Temp,
  940. FALSE );
  941. if (NT_SUCCESS(Status)) {
  942. MRxSmbIsCscEnabled = (BOOLEAN)Temp;
  943. }
  944. //this would be the end of the macro.......
  945. if (MRxSmbIsCscEnabled) {
  946. //this should be a macro......
  947. Status = MRxSmbGetUlongRegistryParameter(
  948. ParametersHandle,
  949. L"CscEnabledDCON",
  950. (PULONG)&Temp,
  951. FALSE );
  952. if (NT_SUCCESS(Status))
  953. MRxSmbIsCscEnabledForDisconnected = (BOOLEAN)Temp;
  954. //this would be the end of the macro.......
  955. Status = MRxSmbGetUlongRegistryParameter(
  956. ParametersHandle,
  957. L"CscEnableTransitionByDefault",
  958. (PULONG)&Temp,
  959. FALSE );
  960. if (NT_SUCCESS(Status))
  961. MRxSmbCscTransitionEnabledByDefault = (BOOLEAN)Temp;
  962. Status = MRxSmbGetUlongRegistryParameter(
  963. ParametersHandle,
  964. L"CscEnableAutoDial",
  965. (PULONG)&Temp,
  966. FALSE );
  967. if (NT_SUCCESS(Status))
  968. MRxSmbCscAutoDialEnabled = (BOOLEAN)Temp;
  969. } else {
  970. MRxSmbIsCscEnabledForDisconnected = FALSE;
  971. }
  972. #if 0
  973. Status = MRxSmbGetUlongRegistryParameter(
  974. ParametersHandle,
  975. L"EnableCompression",
  976. (PULONG)&Temp,
  977. FALSE);
  978. if (NT_SUCCESS(Status) &&
  979. (Temp != 0)) {
  980. MRxSmbEnableCompression = TRUE;
  981. }
  982. #endif
  983. Status = MRxSmbGetUlongRegistryParameter(
  984. ParametersHandle,
  985. L"DisableShadowLoopback",
  986. (PULONG)&Temp,
  987. FALSE);
  988. if (NT_SUCCESS(Status) &&
  989. (Temp != 0)) {
  990. MRxSmbDisableShadowLoopback = TRUE;
  991. }
  992. Status = MRxSmbGetUlongRegistryParameter(
  993. ParametersHandle,
  994. L"IgnoreBindingOrder",
  995. (PULONG)&Temp,
  996. FALSE);
  997. if (NT_SUCCESS(Status)) {
  998. MRxSmbObeyBindingOrder = !((BOOLEAN)Temp);
  999. }
  1000. #if defined(REMOTE_BOOT)
  1001. RbrList = DefaultRbrList;
  1002. RtlInitUnicodeString(&UnicodeString, L"RemoteBootRedirectionList");
  1003. Status = ZwQueryValueKey(
  1004. ParametersHandle,
  1005. &UnicodeString,
  1006. KeyValuePartialInformation,
  1007. &InitialPartialInformationValue,
  1008. sizeof(InitialPartialInformationValue),
  1009. &Temp);
  1010. if (Status== STATUS_BUFFER_OVERFLOW) {
  1011. Status = STATUS_SUCCESS;
  1012. }
  1013. if (NT_SUCCESS(Status)) {
  1014. AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
  1015. + InitialPartialInformationValue.DataLength;
  1016. RbrListFromRegistry = RxAllocatePoolWithTag(
  1017. PagedPool,
  1018. AllocationLength,
  1019. MRXSMB_MISC_POOLTAG);
  1020. if (RbrListFromRegistry != NULL) {
  1021. Status = ZwQueryValueKey(
  1022. ParametersHandle,
  1023. &UnicodeString,
  1024. KeyValuePartialInformation,
  1025. RbrListFromRegistry,
  1026. AllocationLength,
  1027. &Temp);
  1028. if (NT_SUCCESS(Status) &&
  1029. (RbrListFromRegistry->DataLength > 0) &&
  1030. (RbrListFromRegistry->Type == REG_MULTI_SZ)) {
  1031. RbrList = (PWCHAR)(&RbrListFromRegistry->Data[0]);
  1032. }
  1033. }
  1034. }
  1035. RtlInitializeUnicodePrefix( &MRxSmbRemoteBootRedirectionTable );
  1036. for ( redirectionEntry = RbrList; *redirectionEntry != 0; ) {
  1037. BOOLEAN redirect;
  1038. if ( *redirectionEntry == L'L' ) {
  1039. redirect = TRUE;
  1040. redirectionEntry++;
  1041. } else if ( *redirectionEntry == L'R' ) {
  1042. redirect = FALSE;
  1043. redirectionEntry++;
  1044. } else {
  1045. redirect = TRUE;
  1046. }
  1047. RtlInitUnicodeString( &prefix, redirectionEntry );
  1048. redirectionEntry = (PWCHAR)((PCHAR)redirectionEntry + prefix.MaximumLength);
  1049. prefixEntryLength = sizeof(RBR_PREFIX) + prefix.MaximumLength;
  1050. prefixEntry = RxAllocatePoolWithTag(
  1051. PagedPool,
  1052. prefixEntryLength,
  1053. MRXSMB_MISC_POOLTAG
  1054. );
  1055. if ( prefixEntry != NULL ) {
  1056. prefixEntry->Redirect = redirect;
  1057. prefixEntry->Prefix.Buffer = (PWCH)(prefixEntry + 1);
  1058. prefixEntry->Prefix.MaximumLength = prefix.Length + sizeof(WCHAR);
  1059. RtlCopyUnicodeString( &prefixEntry->Prefix, &prefix );
  1060. if ( !RtlInsertUnicodePrefix(
  1061. &MRxSmbRemoteBootRedirectionTable,
  1062. &prefixEntry->Prefix,
  1063. &prefixEntry->TableEntry
  1064. ) ) {
  1065. //
  1066. // The prefix is already in the table. Ignore the duplicate.
  1067. //
  1068. RxFreePool( prefixEntry );
  1069. }
  1070. }
  1071. }
  1072. #endif // defined(REMOTE_BOOT)
  1073. ZwClose(ParametersHandle);
  1074. }
  1075. // For server terminal services machines, we multiplex based on LUID.
  1076. if( IsTerminalServicesServer() && !(fShadow && MRxSmbIsCscEnabled) )
  1077. {
  1078. MRxSmbConnectionIdLevel = 2;
  1079. }
  1080. RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, SMBMRX_WORKSTATION_PARAMETERS);
  1081. InitializeObjectAttributes(
  1082. &ObjectAttributes,
  1083. &WorkStationParametersRegistryKeyName,
  1084. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1085. NULL,
  1086. NULL
  1087. );
  1088. Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
  1089. if (NT_SUCCESS(Status)) {
  1090. // RequireSecuritySignature
  1091. MRxSmbSecuritySignaturesRequired = FALSE;
  1092. Status = MRxSmbGetUlongRegistryParameter(
  1093. ParametersHandle,
  1094. L"RequireSecuritySignature",
  1095. (PULONG)&Temp,
  1096. FALSE);
  1097. if (NT_SUCCESS(Status) && (Temp != 0)) {
  1098. MRxSmbSecuritySignaturesRequired = TRUE;
  1099. }
  1100. // EnableSecuritySignature
  1101. MRxSmbSecuritySignaturesEnabled = TRUE;
  1102. Status = MRxSmbGetUlongRegistryParameter(
  1103. ParametersHandle,
  1104. L"EnableSecuritySignature",
  1105. (PULONG)&Temp,
  1106. FALSE);
  1107. if (NT_SUCCESS(Status) && (Temp == 0)) {
  1108. MRxSmbSecuritySignaturesEnabled = FALSE;
  1109. }
  1110. // RequireExtendedSignature
  1111. MRxSmbExtendedSignaturesRequired = FALSE;
  1112. Status = MRxSmbGetUlongRegistryParameter(
  1113. ParametersHandle,
  1114. L"RequireExtendedSignature",
  1115. (PULONG)&Temp,
  1116. FALSE);
  1117. if (NT_SUCCESS(Status) && (Temp != 0)) {
  1118. MRxSmbExtendedSignaturesRequired = TRUE;
  1119. }
  1120. // EnableExtendedSignature
  1121. MRxSmbExtendedSignaturesEnabled = MRxSmbSecuritySignaturesEnabled;
  1122. Status = MRxSmbGetUlongRegistryParameter(
  1123. ParametersHandle,
  1124. L"EnableExtendedSignature",
  1125. (PULONG)&Temp,
  1126. FALSE);
  1127. if (NT_SUCCESS(Status)) {
  1128. if( Temp == 0 )
  1129. {
  1130. MRxSmbExtendedSignaturesEnabled = FALSE;
  1131. }
  1132. else
  1133. {
  1134. MRxSmbExtendedSignaturesEnabled = TRUE;
  1135. }
  1136. }
  1137. // Precedence settings
  1138. // RequireExtended implies RequireSignatures and EnableExtended
  1139. if( MRxSmbExtendedSignaturesRequired )
  1140. {
  1141. MRxSmbSecuritySignaturesRequired = TRUE;
  1142. MRxSmbExtendedSignaturesEnabled = TRUE;
  1143. }
  1144. // EnableExtended implies EnableSignatures
  1145. if( MRxSmbExtendedSignaturesEnabled ) {
  1146. MRxSmbSecuritySignaturesEnabled = TRUE;
  1147. }
  1148. // RequireSignature implies EnableSignature
  1149. if( MRxSmbSecuritySignaturesRequired )
  1150. {
  1151. MRxSmbSecuritySignaturesEnabled = TRUE;
  1152. }
  1153. Status = MRxSmbGetUlongRegistryParameter(
  1154. ParametersHandle,
  1155. L"EnablePlainTextPassword",
  1156. (PULONG)&Temp,
  1157. FALSE );
  1158. if (NT_SUCCESS(Status))
  1159. EnablePlainTextPassword = (BOOLEAN)Temp;
  1160. Status = MRxSmbGetUlongRegistryParameter(
  1161. ParametersHandle,
  1162. L"OffLineFileTimeoutIntervalInSeconds",
  1163. (PULONG)&Temp,
  1164. FALSE );
  1165. if (NT_SUCCESS(Status))
  1166. OffLineFileTimeoutInterval = (ULONG)Temp;
  1167. Status = MRxSmbGetUlongRegistryParameter(
  1168. ParametersHandle,
  1169. L"ExtendedSessTimeout",
  1170. (PULONG)&Temp,
  1171. FALSE );
  1172. if (NT_SUCCESS(Status))
  1173. ExtendedSessTimeoutInterval = (ULONG)Temp;
  1174. Status = MRxSmbGetUlongRegistryParameter(
  1175. ParametersHandle,
  1176. L"MaxNumOfExchangesForPipelineReadWrite",
  1177. (PULONG)&Temp,
  1178. FALSE );
  1179. if (NT_SUCCESS(Status))
  1180. MaxNumOfExchangesForPipelineReadWrite = (ULONG)Temp;
  1181. Status = MRxSmbGetUlongRegistryParameter(
  1182. ParametersHandle,
  1183. L"Win9xSessionRestriction",
  1184. (PULONG)&Temp,
  1185. FALSE );
  1186. if (NT_SUCCESS(Status))
  1187. Win9xSessionRestriction = (BOOLEAN)Temp;
  1188. Status = MRxSmbGetUlongRegistryParameter(
  1189. ParametersHandle,
  1190. L"EnableCachingOnWriteOnlyOpens",
  1191. (PULONG)&Temp,
  1192. FALSE );
  1193. if (NT_SUCCESS(Status))
  1194. MRxSmbEnableCachingOnWriteOnlyOpens = (BOOLEAN)Temp;
  1195. Status = MRxSmbGetUlongRegistryParameter(
  1196. ParametersHandle,
  1197. L"DisableByteRangeLockingOnReadOnlyFiles",
  1198. (PULONG)&Temp,
  1199. FALSE );
  1200. if (NT_SUCCESS(Status))
  1201. DisableByteRangeLockingOnReadOnlyFiles = (BOOLEAN)Temp;
  1202. //
  1203. // Modified LOGOFF behavior for downlevel servers.
  1204. //
  1205. MRxSmbEnableDownLevelLogOff = FALSE;
  1206. Status = MRxSmbGetUlongRegistryParameter(
  1207. ParametersHandle,
  1208. L"EnableDownLevelLogOff",
  1209. (PULONG)&Temp,
  1210. FALSE);
  1211. if ( NT_SUCCESS( Status ) ) {
  1212. if( Temp != 0 )
  1213. {
  1214. MRxSmbEnableDownLevelLogOff = TRUE;
  1215. }
  1216. }
  1217. ZwClose(ParametersHandle);
  1218. }
  1219. // Detect if system setup in progress
  1220. RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, SYSTEM_SETUP_PARAMETERS);
  1221. InitializeObjectAttributes(
  1222. &ObjectAttributes,
  1223. &WorkStationParametersRegistryKeyName,
  1224. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1225. NULL,
  1226. NULL
  1227. );
  1228. Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
  1229. if (NT_SUCCESS(Status)) {
  1230. Status = MRxSmbGetUlongRegistryParameter(
  1231. ParametersHandle,
  1232. L"SystemSetupInProgress",
  1233. (PULONG)&Temp,
  1234. FALSE );
  1235. if (NT_SUCCESS(Status))
  1236. SetupInProgress = (BOOLEAN)Temp;
  1237. ZwClose(ParametersHandle);
  1238. }
  1239. // initialize event log parameter so that it can translate dos error into text description
  1240. RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, EVENTLOG_MRXSMB_PARAMETERS);
  1241. InitializeObjectAttributes(
  1242. &ObjectAttributes,
  1243. &WorkStationParametersRegistryKeyName,
  1244. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1245. NULL,
  1246. NULL
  1247. );
  1248. Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
  1249. if (NT_SUCCESS(Status)) {
  1250. ULONG Storage[16];
  1251. PKEY_VALUE_PARTIAL_INFORMATION Value;
  1252. ULONG ValueSize;
  1253. NTSTATUS Status;
  1254. ULONG BytesRead;
  1255. RtlInitUnicodeString(&UnicodeString, L"ParameterMessageFile");
  1256. Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
  1257. ValueSize = sizeof(Storage);
  1258. Status = ZwQueryValueKey(
  1259. ParametersHandle,
  1260. &UnicodeString,
  1261. KeyValuePartialInformation,
  1262. Value,
  1263. ValueSize,
  1264. &BytesRead);
  1265. if (Status != STATUS_SUCCESS || Value->Type != REG_EXPAND_SZ) {
  1266. UNICODE_STRING UnicodeString1;
  1267. RtlInitUnicodeString(&UnicodeString1, L"%SystemRoot%\\System32\\kernel32.dll");
  1268. Status = ZwSetValueKey(
  1269. ParametersHandle,
  1270. &UnicodeString,
  1271. 0,
  1272. REG_EXPAND_SZ,
  1273. UnicodeString1.Buffer,
  1274. UnicodeString1.Length+sizeof(NULL));
  1275. }
  1276. ZwClose(ParametersHandle);
  1277. }
  1278. //
  1279. // Get Server GUID for Loopback Detection
  1280. // Server Restart updates cached GUID ????
  1281. //
  1282. RtlInitUnicodeString( &UnicodeString, SMB_SERVER_PARAMETERS );
  1283. InitializeObjectAttributes(
  1284. &ObjectAttributes,
  1285. &UnicodeString,
  1286. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1287. NULL,
  1288. NULL);
  1289. Status = ZwOpenKey( &ParametersHandle, KEY_READ, &ObjectAttributes );
  1290. if( NT_SUCCESS( Status ) ) {
  1291. ULONG BytesRead;
  1292. ULONG regValue[ sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( GUID ) ];
  1293. ULONG regValueSize = sizeof( regValue );
  1294. RtlInitUnicodeString( &UnicodeString, L"Guid" );
  1295. Status = ZwQueryValueKey( ParametersHandle,
  1296. &UnicodeString,
  1297. KeyValuePartialInformation,
  1298. (PKEY_VALUE_PARTIAL_INFORMATION)&regValue,
  1299. regValueSize,
  1300. &BytesRead
  1301. );
  1302. RtlCopyMemory(&CachedServerGuid,
  1303. ((PKEY_VALUE_PARTIAL_INFORMATION)&regValue)->Data,
  1304. sizeof(GUID));
  1305. ZwClose(ParametersHandle);
  1306. }
  1307. }
  1308. NTSTATUS
  1309. SmbCeGetConfigurationInformation()
  1310. {
  1311. ULONG Storage[256];
  1312. UNICODE_STRING UnicodeString;
  1313. HANDLE hRegistryKey;
  1314. NTSTATUS Status;
  1315. ULONG BytesRead;
  1316. OBJECT_ATTRIBUTES ObjectAttributes;
  1317. PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
  1318. KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
  1319. ULONG AllocationLength;
  1320. PKEY_VALUE_PARTIAL_INFORMATION TransportsValueFromRegistry;
  1321. PAGED_CODE();
  1322. IF_NOT_MRXSMB_CSC_ENABLED {
  1323. MRxSmbReadMiscellaneousRegistryParameters();
  1324. }
  1325. // Obtain the list of transports associated with SMB redirector. This is stored
  1326. // as a multivalued string and is used subsequently to weed out the
  1327. // appropriate transports. This is a two step process; first we try to find out
  1328. // how much space we need; then we allocate; then we read in. unfortunately, the kind of
  1329. // structure that we have to use to get the value has a header on it, so we have to offset the
  1330. // returned pointer both here and in the free routine.
  1331. //CODE.IMPROVEMENT we should perhaps get a subroutine going that does all this
  1332. //also, there are no log entries.
  1333. //also, we should be doing partial_infos instead of full
  1334. RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_TRANSPORTS);
  1335. InitializeObjectAttributes(
  1336. &ObjectAttributes,
  1337. &UnicodeString, // name
  1338. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,// attributes
  1339. NULL, // root
  1340. NULL); // security descriptor
  1341. Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
  1342. if (!NT_SUCCESS(Status)) {
  1343. return Status;
  1344. }
  1345. RtlInitUnicodeString(&UnicodeString, TRANSPORT_BINDINGS);
  1346. Status = ZwQueryValueKey(
  1347. hRegistryKey,
  1348. &UnicodeString,
  1349. KeyValuePartialInformation,
  1350. &InitialPartialInformationValue,
  1351. sizeof(InitialPartialInformationValue),
  1352. &BytesRead);
  1353. if (Status== STATUS_BUFFER_OVERFLOW) {
  1354. Status = STATUS_SUCCESS;
  1355. }
  1356. if (!NT_SUCCESS(Status)) {
  1357. ZwClose(hRegistryKey);
  1358. return Status;
  1359. }
  1360. AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
  1361. + InitialPartialInformationValue.DataLength;
  1362. if (AllocationLength > 0xFFFF) {
  1363. //
  1364. // Don't allow registry value to consume too much memory
  1365. //
  1366. ZwClose(hRegistryKey);
  1367. return STATUS_INSUFFICIENT_RESOURCES;
  1368. }
  1369. if (0) {
  1370. DbgPrint("SizeofBindingInfo=%08lx %08lx\n",
  1371. AllocationLength,
  1372. InitialPartialInformationValue.DataLength);
  1373. }
  1374. if (SmbCeContext.Transports.Buffer != NULL) {
  1375. // the transports buffer is at the end of a larger buffer (by 12 bytes)
  1376. // allocated to read the value from the registry. recover the original buffer
  1377. // pointer in orer to free.
  1378. TransportsValueFromRegistry = CONTAINING_RECORD(
  1379. SmbCeContext.Transports.Buffer,
  1380. KEY_VALUE_PARTIAL_INFORMATION,
  1381. Data[0]
  1382. );
  1383. //DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
  1384. RxFreePool(TransportsValueFromRegistry);
  1385. SmbCeContext.Transports.Buffer = NULL;
  1386. SmbCeContext.Transports.Length = 0;
  1387. SmbCeContext.Transports.MaximumLength = 0;
  1388. }
  1389. (PBYTE)TransportsValueFromRegistry = RxAllocatePoolWithTag(
  1390. PagedPool,
  1391. AllocationLength,
  1392. MRXSMB_MISC_POOLTAG);
  1393. if (TransportsValueFromRegistry == NULL) {
  1394. ZwClose(hRegistryKey);
  1395. return(STATUS_INSUFFICIENT_RESOURCES);
  1396. }
  1397. Status = ZwQueryValueKey(
  1398. hRegistryKey,
  1399. &UnicodeString,
  1400. KeyValuePartialInformation,
  1401. TransportsValueFromRegistry,
  1402. AllocationLength,
  1403. &BytesRead);
  1404. if (NT_SUCCESS(Status) &&
  1405. (TransportsValueFromRegistry->DataLength > 0) &&
  1406. (TransportsValueFromRegistry->Type == REG_MULTI_SZ)) {
  1407. SmbCeContext.Transports.MaximumLength =
  1408. SmbCeContext.Transports.Length = (USHORT)TransportsValueFromRegistry->DataLength;
  1409. SmbCeContext.Transports.Buffer = (PWCHAR)(&TransportsValueFromRegistry->Data[0]);
  1410. //DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
  1411. } else {
  1412. RxLog(("Invalid Transport Binding string... using all transports"));
  1413. SmbLog(LOG,
  1414. SmbCeGetConfigurationInformation,
  1415. LOGULONG(Status));
  1416. RxFreePool(TransportsValueFromRegistry);
  1417. TransportsValueFromRegistry = NULL;
  1418. }
  1419. ZwClose(hRegistryKey);
  1420. return Status;
  1421. }
  1422. NTSTATUS
  1423. SmbCeGetComputerName(
  1424. VOID
  1425. )
  1426. {
  1427. ULONG Storage[256];
  1428. UNICODE_STRING UnicodeString;
  1429. HANDLE hRegistryKey;
  1430. NTSTATUS Status;
  1431. ULONG BytesRead;
  1432. OBJECT_ATTRIBUTES ObjectAttributes;
  1433. PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
  1434. KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
  1435. ULONG AllocationLength;
  1436. PAGED_CODE();
  1437. ASSERT(SmbCeContext.ComputerName.Buffer == NULL);
  1438. // Obtain the computer name. This is used in formulating the local NETBIOS address
  1439. RtlInitUnicodeString(&SmbCeContext.ComputerName, NULL);
  1440. if (!MRxSmbBootedRemotely) {
  1441. RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_COMPUTER_NAME);
  1442. } else {
  1443. //
  1444. // For remote boot, we are initializing long before the volatile
  1445. // ActiveComputerNameKey is created, so we need to read from the
  1446. // nonvolatile key instead. This is not a problem, because we know
  1447. // that the computer name hasn't been changed since the computer was
  1448. // booted -- since we're very early in the boot sequence -- so the
  1449. // nonvolatile key has the correct computer name.
  1450. //
  1451. RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_COMPUTER_NAME_NONVOLATILE);
  1452. }
  1453. InitializeObjectAttributes(
  1454. &ObjectAttributes,
  1455. &UnicodeString, // name
  1456. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,// attributes
  1457. NULL, // root
  1458. NULL); // security descriptor
  1459. Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
  1460. if (!NT_SUCCESS(Status)) {
  1461. return Status;
  1462. }
  1463. RtlInitUnicodeString(&UnicodeString, COMPUTERNAME);
  1464. Status = ZwQueryValueKey(
  1465. hRegistryKey,
  1466. &UnicodeString,
  1467. KeyValueFullInformation,
  1468. Value,
  1469. sizeof(Storage),
  1470. &BytesRead);
  1471. if (NT_SUCCESS(Status)) {
  1472. // Rtl conversion routines require NULL char to be excluded from the
  1473. // length.
  1474. SmbCeContext.ComputerName.MaximumLength =
  1475. SmbCeContext.ComputerName.Length = (USHORT)Value->DataLength - sizeof(WCHAR);
  1476. SmbCeContext.ComputerName.Buffer = RxAllocatePoolWithTag(
  1477. PagedPool,
  1478. SmbCeContext.ComputerName.Length,
  1479. MRXSMB_MISC_POOLTAG);
  1480. if (SmbCeContext.ComputerName.Buffer != NULL) {
  1481. RtlCopyMemory(SmbCeContext.ComputerName.Buffer,
  1482. (PCHAR)Value+Value->DataOffset,
  1483. Value->DataLength - sizeof(WCHAR));
  1484. } else {
  1485. Status = STATUS_INSUFFICIENT_RESOURCES;
  1486. }
  1487. }
  1488. ZwClose(hRegistryKey);
  1489. return Status;
  1490. }
  1491. NTSTATUS
  1492. SmbCeGetOperatingSystemInformation(
  1493. VOID
  1494. )
  1495. {
  1496. ULONG Storage[256], Storage2[256], Storage3[256];
  1497. UNICODE_STRING UnicodeString;
  1498. HANDLE hRegistryKey;
  1499. NTSTATUS Status, Status2;
  1500. ULONG BytesRead;
  1501. OBJECT_ATTRIBUTES ObjectAttributes;
  1502. PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
  1503. PKEY_VALUE_FULL_INFORMATION Value2 = (PKEY_VALUE_FULL_INFORMATION)Storage2;
  1504. PKEY_VALUE_FULL_INFORMATION Value3 = (PKEY_VALUE_FULL_INFORMATION)Storage3;
  1505. KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
  1506. ULONG AllocationLength;
  1507. PAGED_CODE();
  1508. ASSERT(SmbCeContext.OperatingSystem.Buffer == NULL);
  1509. ASSERT(SmbCeContext.LanmanType.Buffer == NULL);
  1510. RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_CURRENT_WINDOWS_VERSION);
  1511. InitializeObjectAttributes(
  1512. &ObjectAttributes,
  1513. &UnicodeString, // name
  1514. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,// attributes
  1515. NULL, // root
  1516. NULL); // security descriptor
  1517. Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
  1518. if (!NT_SUCCESS(Status)) {
  1519. return Status;
  1520. }
  1521. RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM);
  1522. Status = ZwQueryValueKey(
  1523. hRegistryKey,
  1524. &UnicodeString,
  1525. KeyValueFullInformation,
  1526. Value,
  1527. sizeof(Storage),
  1528. &BytesRead);
  1529. if (NT_SUCCESS(Status)) {
  1530. RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM_NAME );
  1531. Status = ZwQueryValueKey(
  1532. hRegistryKey,
  1533. &UnicodeString,
  1534. KeyValueFullInformation,
  1535. Value3,
  1536. sizeof(Storage3),
  1537. &BytesRead);
  1538. if( NT_SUCCESS(Status) )
  1539. {
  1540. // Change the data pointers
  1541. PWSTR pProduct = (PWSTR)((PCHAR)Value3 + Value3->DataOffset);
  1542. if( (Value3->DataLength > 20) &&
  1543. (_wcsnicmp( pProduct, L"Microsoft ", 10 ) == 0) )
  1544. {
  1545. Value3->DataLength -= 20;
  1546. Value3->DataOffset += 20;
  1547. }
  1548. // check for existance of Service Pack String
  1549. RtlInitUnicodeString(&UnicodeString, L"CSDVersion");
  1550. Status2 = ZwQueryValueKey(
  1551. hRegistryKey,
  1552. &UnicodeString,
  1553. KeyValueFullInformation,
  1554. Value2,
  1555. sizeof(Storage2),
  1556. &BytesRead);
  1557. SmbCeContext.OperatingSystem.MaximumLength =
  1558. (USHORT)Value->DataLength + (USHORT)Value3->DataLength;
  1559. if(NT_SUCCESS(Status2)) {
  1560. SmbCeContext.OperatingSystem.MaximumLength += (USHORT)Value2->DataLength;
  1561. }
  1562. SmbCeContext.OperatingSystem.Length = SmbCeContext.OperatingSystem.MaximumLength;
  1563. SmbCeContext.OperatingSystem.Buffer = RxAllocatePoolWithTag(
  1564. PagedPool,
  1565. SmbCeContext.OperatingSystem.MaximumLength,
  1566. MRXSMB_MISC_POOLTAG);
  1567. if (SmbCeContext.OperatingSystem.Buffer != NULL) {
  1568. RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer,
  1569. (PCHAR)Value3+Value3->DataOffset,
  1570. Value3->DataLength);
  1571. RtlCopyMemory((SmbCeContext.OperatingSystem.Buffer +
  1572. (Value3->DataLength/sizeof(WCHAR)) - 1),
  1573. L" ",
  1574. sizeof(WCHAR));
  1575. RtlCopyMemory((SmbCeContext.OperatingSystem.Buffer +
  1576. (Value3->DataLength/sizeof(WCHAR))),
  1577. (PCHAR)Value+Value->DataOffset,
  1578. Value->DataLength);
  1579. if(NT_SUCCESS(Status2)) {
  1580. // add a space
  1581. RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer +
  1582. (Value3->DataLength + Value->DataLength)/sizeof(WCHAR) - 1,
  1583. L" ",
  1584. sizeof(WCHAR));
  1585. RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer +
  1586. (Value3->DataLength + Value->DataLength)/sizeof(WCHAR),
  1587. (PCHAR)Value2+Value2->DataOffset,
  1588. Value2->DataLength);
  1589. }
  1590. } else {
  1591. Status = STATUS_INSUFFICIENT_RESOURCES;
  1592. }
  1593. }
  1594. }
  1595. if (NT_SUCCESS(Status)) {
  1596. RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM_VERSION);
  1597. Status = ZwQueryValueKey(
  1598. hRegistryKey,
  1599. &UnicodeString,
  1600. KeyValueFullInformation,
  1601. Value,
  1602. sizeof(Storage),
  1603. &BytesRead);
  1604. if (NT_SUCCESS(Status)) {
  1605. SmbCeContext.LanmanType.MaximumLength =
  1606. SmbCeContext.LanmanType.Length = (USHORT)Value->DataLength +
  1607. (USHORT)Value3->DataLength;
  1608. SmbCeContext.LanmanType.Buffer = RxAllocatePoolWithTag(
  1609. PagedPool,
  1610. SmbCeContext.LanmanType.Length,
  1611. MRXSMB_MISC_POOLTAG);
  1612. if (SmbCeContext.LanmanType.Buffer != NULL) {
  1613. RtlCopyMemory(
  1614. SmbCeContext.LanmanType.Buffer,
  1615. (PCHAR)Value3 + Value3->DataOffset,
  1616. Value3->DataLength);
  1617. RtlCopyMemory(
  1618. (SmbCeContext.LanmanType.Buffer +
  1619. (Value3->DataLength/sizeof(WCHAR)) - 1),
  1620. L" ",
  1621. sizeof(WCHAR));
  1622. RtlCopyMemory(
  1623. (SmbCeContext.LanmanType.Buffer +
  1624. (Value3->DataLength/sizeof(WCHAR))),
  1625. (PCHAR)Value+Value->DataOffset,
  1626. Value->DataLength);
  1627. } else {
  1628. Status = STATUS_INSUFFICIENT_RESOURCES;
  1629. }
  1630. }
  1631. }
  1632. ZwClose(hRegistryKey);
  1633. return Status;
  1634. }
  1635. NTSTATUS
  1636. MRxSmbPnpIrpCompletion(
  1637. PDEVICE_OBJECT pDeviceObject,
  1638. PIRP pIrp,
  1639. PVOID pContext)
  1640. /*++
  1641. Routine Description:
  1642. This routine completes the PNP irp for SMB mini redirector.
  1643. Arguments:
  1644. DeviceObject - Supplies the device object for the packet being processed.
  1645. pIrp - Supplies the Irp being processed
  1646. pContext - the completion context
  1647. --*/
  1648. {
  1649. PKEVENT pCompletionEvent = pContext;
  1650. KeSetEvent(
  1651. pCompletionEvent,
  1652. IO_NO_INCREMENT,
  1653. FALSE);
  1654. return STATUS_MORE_PROCESSING_REQUIRED;
  1655. }
  1656. NTSTATUS
  1657. MRxSmbProcessPnpIrp(
  1658. PIRP pIrp)
  1659. /*++
  1660. Routine Description:
  1661. This routine initiates the processing of PNP irps for SMB mini redirector.
  1662. Arguments:
  1663. pIrp - Supplies the Irp being processed
  1664. Notes:
  1665. The query target device relation is the only call that is implemented
  1666. currently. This is done by returing the PDO associated with the transport
  1667. connection object. In any case this routine assumes the responsibility of
  1668. completing the IRP and return STATUS_PENDING.
  1669. This routine also writes an error log entry when the underlying transport
  1670. fails the request. This should help us isolate the responsibility.
  1671. --*/
  1672. {
  1673. NTSTATUS Status;
  1674. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( pIrp );
  1675. IoMarkIrpPending(pIrp);
  1676. if ((IrpSp->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) &&
  1677. (IrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation)) {
  1678. PIRP pAssociatedIrp;
  1679. PFILE_OBJECT pConnectionFileObject = NULL;
  1680. PMRX_FCB pFcb = NULL;
  1681. PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
  1682. BOOLEAN ServerTransportReferenced = FALSE;
  1683. // Locate the transport connection object for the associated file object
  1684. // and forward the query to that device.
  1685. if ((IrpSp->FileObject != NULL) &&
  1686. ((pFcb = IrpSp->FileObject->FsContext) != NULL) &&
  1687. (NodeTypeIsFcb(pFcb))) {
  1688. PMRX_SRV_CALL pSrvCall;
  1689. PMRX_NET_ROOT pNetRoot;
  1690. if (((pNetRoot = pFcb->pNetRoot) != NULL) &&
  1691. ((pSrvCall = pNetRoot->pSrvCall) != NULL)) {
  1692. pServerEntry = pSrvCall->Context;
  1693. if (pServerEntry != NULL) {
  1694. SmbCeAcquireResource();
  1695. Status = SmbCeReferenceServerTransport(&pServerEntry->pTransport);
  1696. if (Status == STATUS_SUCCESS) {
  1697. pConnectionFileObject = SmbCepReferenceEndpointFileObject(
  1698. pServerEntry->pTransport);
  1699. ServerTransportReferenced = TRUE;
  1700. }
  1701. SmbCeReleaseResource();
  1702. }
  1703. }
  1704. }
  1705. if (pConnectionFileObject != NULL) {
  1706. PDEVICE_OBJECT pRelatedDeviceObject;
  1707. PIO_STACK_LOCATION pIrpStackLocation,
  1708. pAssociatedIrpStackLocation;
  1709. pRelatedDeviceObject = IoGetRelatedDeviceObject(pConnectionFileObject);
  1710. pAssociatedIrp = IoAllocateIrp(
  1711. pRelatedDeviceObject->StackSize,
  1712. FALSE);
  1713. if (pAssociatedIrp != NULL) {
  1714. KEVENT CompletionEvent;
  1715. KeInitializeEvent( &CompletionEvent,
  1716. SynchronizationEvent,
  1717. FALSE );
  1718. // Fill up the associated IRP and call the underlying driver.
  1719. pAssociatedIrpStackLocation = IoGetNextIrpStackLocation(pAssociatedIrp);
  1720. pIrpStackLocation = IoGetCurrentIrpStackLocation(pIrp);
  1721. *pAssociatedIrpStackLocation = *pIrpStackLocation;
  1722. pAssociatedIrpStackLocation->FileObject = pConnectionFileObject;
  1723. pAssociatedIrpStackLocation->DeviceObject = pRelatedDeviceObject;
  1724. IoSetCompletionRoutine(
  1725. pAssociatedIrp,
  1726. MRxSmbPnpIrpCompletion,
  1727. &CompletionEvent,
  1728. TRUE,TRUE,TRUE);
  1729. pAssociatedIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1730. Status = IoCallDriver(pRelatedDeviceObject,pAssociatedIrp);
  1731. if (Status == STATUS_PENDING) {
  1732. (VOID) KeWaitForSingleObject(
  1733. &CompletionEvent,
  1734. Executive,
  1735. KernelMode,
  1736. FALSE,
  1737. (PLARGE_INTEGER) NULL );
  1738. }
  1739. pIrp->IoStatus = pAssociatedIrp->IoStatus;
  1740. Status = pIrp->IoStatus.Status;
  1741. if (!NT_SUCCESS(Status)) {
  1742. MRxSmbLogTransportError(
  1743. &pServerEntry->pTransport->pTransport->RxCeTransport.Name,
  1744. &SmbCeContext.DomainName,
  1745. Status,
  1746. EVENT_RDR_CONNECTION);
  1747. }
  1748. ObDereferenceObject(pConnectionFileObject);
  1749. IoFreeIrp(pAssociatedIrp);
  1750. } else {
  1751. Status = STATUS_INSUFFICIENT_RESOURCES;
  1752. }
  1753. } else {
  1754. Status = STATUS_INVALID_DEVICE_REQUEST;
  1755. }
  1756. if (ServerTransportReferenced) {
  1757. SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
  1758. }
  1759. } else {
  1760. Status = STATUS_INVALID_DEVICE_REQUEST;
  1761. }
  1762. if (Status != STATUS_PENDING) {
  1763. pIrp->IoStatus.Status = Status;
  1764. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  1765. Status = STATUS_PENDING;
  1766. }
  1767. return STATUS_PENDING;
  1768. }
  1769. WML_CONTROL_GUID_REG MRxSmb_ControlGuids[] = {
  1770. { // 8fc7e81a-f733-42e0-9708-cfdae07ed969 MRxSmb
  1771. 0x8fc7e81a,0xf733,0x42e0,{0x97,0x08,0xcf,0xda,0xe0,0x7e,0xd9,0x69},
  1772. { // eab93e5c-02ce-4e33-9419-901d82868816
  1773. {0xeab93e5c,0x02ce,0x4e33,{0x94,0x19,0x90,0x1d,0x82,0x86,0x88,0x16},},
  1774. // 56a0dee7-be12-4cf1-b7e0-976b0d174944
  1775. {0x56a0dee7,0xbe12,0x4cf1,{0xb7,0xe0,0x97,0x6b,0x0d,0x17,0x49,0x44},},
  1776. // ecabc730-60bf-481e-b92b-2749f8272d9d
  1777. {0xecabc730,0x60bf,0x481e,{0xb9,0x2b,0x27,0x49,0xf8,0x27,0x2d,0x9d},}
  1778. },
  1779. },
  1780. };
  1781. #define MRxSmb_ControlGuids_len 1
  1782. NTSTATUS
  1783. MRxSmbProcessSystemControlIrp(
  1784. IN PDEVICE_OBJECT DeviceObject,
  1785. IN PIRP Irp
  1786. )
  1787. /*++
  1788. Routine Description:
  1789. This is the common routine for doing System control operations called
  1790. by both the fsd and fsp threads
  1791. Arguments:
  1792. Irp - Supplies the Irp to process
  1793. InFsp - Indicates if this is the fsp thread or someother thread
  1794. Return Value:
  1795. RXSTATUS - The return status for the operation
  1796. --*/
  1797. {
  1798. NTSTATUS Status;
  1799. WML_TINY_INFO Info;
  1800. UNICODE_STRING RegPath;
  1801. PAGED_CODE();
  1802. if (EnableWmiLog) {
  1803. RtlInitUnicodeString (&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\MRxSmb");
  1804. RtlZeroMemory (&Info, sizeof(Info));
  1805. Info.ControlGuids = MRxSmb_ControlGuids;
  1806. Info.GuidCount = MRxSmb_ControlGuids_len;
  1807. Info.DriverRegPath = &RegPath;
  1808. Status = WmlTinySystemControl(&Info,DeviceObject,Irp);
  1809. if (Status != STATUS_SUCCESS) {
  1810. //DbgPrint("MRxSmb WMI control return %lx\n", Status);
  1811. }
  1812. } else {
  1813. Status = STATUS_INVALID_DEVICE_REQUEST;
  1814. Irp->IoStatus.Status = Status;
  1815. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1816. }
  1817. return Status;
  1818. }
  1819. extern LONG BowserDebugTraceLevel;
  1820. NTSTATUS
  1821. MRxSmbFsdDispatch (
  1822. IN PDEVICE_OBJECT DeviceObject,
  1823. IN PIRP Irp
  1824. )
  1825. /*++
  1826. Routine Description:
  1827. This routine implements the FSD dispatch for the smbmini DRIVER object.
  1828. Arguments:
  1829. DeviceObject - Supplies the device object for the packet being processed.
  1830. Irp - Supplies the Irp being processed
  1831. Return Value:
  1832. RXSTATUS - The Fsd status for the Irp
  1833. Notes:
  1834. This routine centralizes the logic required to dela with special cases in
  1835. handling various requests directed to the redirector.
  1836. 1) The Browser is built as part of the redirector driver ( mrxsmb.sys ) for
  1837. historical reasons ( carryover effect from the old redirector ). Hence this
  1838. routine serves as the switching point for redirecting requests to the browser
  1839. or the redirector depending on the device object.
  1840. 2) The browser occasionally specifies a transport name in its open requests.
  1841. This is a request by the browser to override the transport priority
  1842. otherwise specified. In such cases this routine invokes the appropriate
  1843. preprocessing before passing on the request to the wrapper.
  1844. 3) The DFS driver also specifies additional parameters in its open requests.
  1845. In such cases this routine invokes the appropriate preprocessing routine.
  1846. 4) The PNP IRP for returning device relations are subverted by the mini
  1847. redirector for SMB
  1848. (2) (3) and (4) are legitimate uses of the wrapper architecture in which each
  1849. mini redirector is given the ability to customize the response to IRPs
  1850. passed in by the I/O subsystem. This is typically done by overiding the
  1851. dispatch vector.
  1852. --*/
  1853. {
  1854. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); //ok4ioget
  1855. UCHAR MajorFunctionCode = IrpSp->MajorFunction;
  1856. ULONG MinorFunctionCode = IrpSp->MinorFunction;
  1857. BOOLEAN ForwardRequestToWrapper = TRUE;
  1858. PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
  1859. NTSTATUS Status;
  1860. PAGED_CODE();
  1861. if (DeviceObject == (PDEVICE_OBJECT)BowserDeviceObject) {
  1862. switch (MajorFunctionCode) {
  1863. case IRP_MJ_DEVICE_CONTROL:
  1864. {
  1865. ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  1866. Status = BowserFsdDeviceIoControlFile(BowserDeviceObject, Irp);
  1867. if ((Status == STATUS_SUCCESS) &&
  1868. (MinorFunctionCode == IRP_MN_USER_FS_REQUEST) &&
  1869. (IoControlCode == IOCTL_LMDR_START)) {
  1870. MRxSmbRegisterForPnpNotifications();
  1871. }
  1872. }
  1873. return Status;
  1874. case IRP_MJ_QUERY_INFORMATION:
  1875. return BowserFsdQueryInformationFile(BowserDeviceObject, Irp);
  1876. case IRP_MJ_CREATE:
  1877. return BowserFsdCreate(BowserDeviceObject, Irp);
  1878. case IRP_MJ_CLEANUP:
  1879. return BowserFsdCleanup(BowserDeviceObject, Irp);
  1880. case IRP_MJ_CLOSE:
  1881. return BowserFsdClose(BowserDeviceObject, Irp);
  1882. default:
  1883. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  1884. Irp->IoStatus.Information = 0;
  1885. IoCompleteRequest(Irp, IO_NO_INCREMENT );
  1886. return (STATUS_NOT_IMPLEMENTED);
  1887. }
  1888. }
  1889. ASSERT(DeviceObject==(PDEVICE_OBJECT)MRxSmbDeviceObject);
  1890. if (DeviceObject!=(PDEVICE_OBJECT)MRxSmbDeviceObject) {
  1891. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  1892. Irp->IoStatus.Information = 0;
  1893. IoCompleteRequest(Irp, IO_NO_INCREMENT );
  1894. return (STATUS_INVALID_DEVICE_REQUEST);
  1895. }
  1896. if (IrpSp->MajorFunction == IRP_MJ_SYSTEM_CONTROL) {
  1897. return MRxSmbProcessSystemControlIrp(DeviceObject,Irp);
  1898. }
  1899. Status = STATUS_SUCCESS;
  1900. FsRtlEnterFileSystem();
  1901. if (IrpSp->MajorFunction == IRP_MJ_PNP) {
  1902. ForwardRequestToWrapper = FALSE;
  1903. Status = MRxSmbProcessPnpIrp(Irp);
  1904. } else {
  1905. if (IrpSp->MajorFunction == IRP_MJ_CREATE) {
  1906. Status = CscPreProcessCreateIrp(Irp);
  1907. }
  1908. if (Status == STATUS_SUCCESS) {
  1909. Status = MRxSmbCheckTransportName(Irp, &pServerEntry);
  1910. }
  1911. }
  1912. FsRtlExitFileSystem();
  1913. if ((Status == STATUS_SUCCESS) &&
  1914. ForwardRequestToWrapper){
  1915. Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)MRxSmbDeviceObject,Irp);
  1916. } else if (Status != STATUS_PENDING) {
  1917. Irp->IoStatus.Status = Status;
  1918. Irp->IoStatus.Information = 0;
  1919. IoCompleteRequest(Irp, IO_NO_INCREMENT );
  1920. }
  1921. if (pServerEntry != NULL ) {
  1922. FsRtlEnterFileSystem();
  1923. pServerEntry->TransportSpecifiedByUser = 0;
  1924. SmbCeDereferenceServerEntry(pServerEntry);
  1925. FsRtlExitFileSystem();
  1926. }
  1927. return Status;
  1928. }
  1929. NTSTATUS
  1930. MRxSmbDeallocateForFcb (
  1931. IN OUT PMRX_FCB pFcb
  1932. )
  1933. {
  1934. PAGED_CODE();
  1935. MRxSmbCscDeallocateForFcb(pFcb);
  1936. return(STATUS_SUCCESS);
  1937. }
  1938. NTSTATUS
  1939. MRxSmbDeallocateForFobx (
  1940. IN OUT PMRX_FOBX pFobx
  1941. )
  1942. {
  1943. PAGED_CODE();
  1944. IF_DEBUG {
  1945. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(pFobx);
  1946. PMRX_SRV_OPEN SrvOpen = pFobx->pSrvOpen;
  1947. PMRX_FCB Fcb = SrvOpen->pFcb;
  1948. if (smbFobx && FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_LOUD_FINALIZE)) {
  1949. DbgPrint("Finalizobx side buffer %p %p %p %pon %wZ\n",
  1950. 0, 0, // sidebuffer, count
  1951. smbFobx,pFobx,GET_ALREADY_PREFIXED_NAME(SrvOpen,Fcb)
  1952. );
  1953. }
  1954. }
  1955. return(STATUS_SUCCESS);
  1956. }
  1957. NTSTATUS
  1958. MRxSmbDeleteRegistryParameter(
  1959. HANDLE ParametersHandle,
  1960. PWCHAR ParameterName
  1961. )
  1962. {
  1963. UNICODE_STRING UnicodeString;
  1964. NTSTATUS Status;
  1965. PAGED_CODE(); //INIT
  1966. RtlInitUnicodeString(&UnicodeString, ParameterName);
  1967. Status = ZwDeleteValueKey(ParametersHandle,
  1968. &UnicodeString);
  1969. ASSERT(NT_SUCCESS(Status));
  1970. return(Status);
  1971. }
  1972. NTSTATUS
  1973. MRxSmbGetUlongRegistryParameter(
  1974. HANDLE ParametersHandle,
  1975. PWCHAR ParameterName,
  1976. PULONG ParamUlong,
  1977. BOOLEAN LogFailure
  1978. )
  1979. {
  1980. ULONG Storage[16];
  1981. PKEY_VALUE_PARTIAL_INFORMATION Value;
  1982. ULONG ValueSize;
  1983. UNICODE_STRING UnicodeString;
  1984. NTSTATUS Status;
  1985. ULONG BytesRead;
  1986. PAGED_CODE(); //INIT
  1987. Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
  1988. ValueSize = sizeof(Storage);
  1989. RtlInitUnicodeString(&UnicodeString, ParameterName);
  1990. Status = ZwQueryValueKey(ParametersHandle,
  1991. &UnicodeString,
  1992. KeyValuePartialInformation,
  1993. Value,
  1994. ValueSize,
  1995. &BytesRead);
  1996. if (NT_SUCCESS(Status)) {
  1997. if (Value->Type == REG_DWORD) {
  1998. PULONG ConfigValue = (PULONG)&Value->Data[0];
  1999. *ParamUlong = *((PULONG)ConfigValue);
  2000. return(STATUS_SUCCESS);
  2001. } else {
  2002. Status = STATUS_INVALID_PARAMETER;
  2003. }
  2004. }
  2005. if (!LogFailure) { return Status; }
  2006. RxLogFailureWithBuffer(
  2007. MRxSmbDeviceObject,
  2008. NULL,
  2009. EVENT_RDR_CANT_READ_REGISTRY,
  2010. Status,
  2011. ParameterName,
  2012. (USHORT)(wcslen(ParameterName)*sizeof(WCHAR))
  2013. );
  2014. return Status;
  2015. }
  2016. NTSTATUS
  2017. SmbCeGetServersWithExtendedSessTimeout()
  2018. {
  2019. ULONG Storage[256];
  2020. UNICODE_STRING UnicodeString;
  2021. HANDLE hRegistryKey;
  2022. NTSTATUS Status;
  2023. ULONG BytesRead;
  2024. OBJECT_ATTRIBUTES ObjectAttributes;
  2025. PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
  2026. KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
  2027. ULONG AllocationLength;
  2028. PKEY_VALUE_PARTIAL_INFORMATION ServersValueFromRegistry;
  2029. PAGED_CODE();
  2030. // Obtain the list of servers associated with extended session timeout.
  2031. // This is required by third party server which handles SMB sessions with different processes.
  2032. // The time to process requests on different sessions can be varied dramatically.
  2033. RtlInitUnicodeString(&UnicodeString, SMBMRX_WORKSTATION_PARAMETERS);
  2034. InitializeObjectAttributes(
  2035. &ObjectAttributes,
  2036. &UnicodeString, // name
  2037. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,// attributes
  2038. NULL, // root
  2039. NULL); // security descriptor
  2040. Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
  2041. if (!NT_SUCCESS(Status)) {
  2042. //DbgPrint("SmbCeGetServersWithExtendedSessTimeout ZwOpenKey failed %x\n",Status);
  2043. return Status;
  2044. }
  2045. RtlInitUnicodeString(&UnicodeString, L"ServersWithExtendedSessTimeout");
  2046. Status = ZwQueryValueKey(
  2047. hRegistryKey,
  2048. &UnicodeString,
  2049. KeyValuePartialInformation,
  2050. &InitialPartialInformationValue,
  2051. sizeof(InitialPartialInformationValue),
  2052. &BytesRead);
  2053. if (Status== STATUS_BUFFER_OVERFLOW) {
  2054. Status = STATUS_SUCCESS;
  2055. }
  2056. if (!NT_SUCCESS(Status)) {
  2057. ZwClose(hRegistryKey);
  2058. return Status;
  2059. }
  2060. AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
  2061. + InitialPartialInformationValue.DataLength;
  2062. if (AllocationLength > 0xFFFF) {
  2063. //
  2064. // Don't allow registry value to consume too much memory
  2065. //
  2066. ZwClose(hRegistryKey);
  2067. return STATUS_INSUFFICIENT_RESOURCES;
  2068. }
  2069. if (0) {
  2070. DbgPrint("SizeofBindingInfo=%08lx %08lx\n",
  2071. AllocationLength,
  2072. InitialPartialInformationValue.DataLength);
  2073. }
  2074. ASSERT(SmbCeContext.ServersWithExtendedSessTimeout.Buffer == NULL);
  2075. (PBYTE)ServersValueFromRegistry = RxAllocatePoolWithTag(
  2076. PagedPool,
  2077. AllocationLength,
  2078. MRXSMB_MISC_POOLTAG);
  2079. if (ServersValueFromRegistry == NULL) {
  2080. ZwClose(hRegistryKey);
  2081. return(STATUS_INSUFFICIENT_RESOURCES);
  2082. }
  2083. Status = ZwQueryValueKey(
  2084. hRegistryKey,
  2085. &UnicodeString,
  2086. KeyValuePartialInformation,
  2087. ServersValueFromRegistry,
  2088. AllocationLength,
  2089. &BytesRead);
  2090. if (NT_SUCCESS(Status) &&
  2091. (ServersValueFromRegistry->DataLength > 0) &&
  2092. (ServersValueFromRegistry->Type == REG_MULTI_SZ)) {
  2093. SmbCeContext.ServersWithExtendedSessTimeout.MaximumLength =
  2094. SmbCeContext.ServersWithExtendedSessTimeout.Length = (USHORT)ServersValueFromRegistry->DataLength;
  2095. SmbCeContext.ServersWithExtendedSessTimeout.Buffer = (PWCHAR)(&ServersValueFromRegistry->Data[0]);
  2096. //DbgPrint("b1 %08lx b2 %08lx\n", ServersValueFromRegistry,SmbCeContext.ServersWithExtendedSessTimeout.Buffer);
  2097. } else {
  2098. RxLog(("Invalid Transport Binding string... using all transports"));
  2099. SmbLog(LOG,
  2100. SmbCeGetConfigurationInformation,
  2101. LOGULONG(Status));
  2102. RxFreePool(ServersValueFromRegistry);
  2103. ServersValueFromRegistry = NULL;
  2104. }
  2105. ZwClose(hRegistryKey);
  2106. return Status;
  2107. }