Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

438 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. strtstop.c
  5. Abstract:
  6. This module implements the Start and Stop routines for the wrapper.
  7. Author:
  8. Balan Sethu Raman [SethuR] 27-Jan-1996
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <ntddnfs2.h>
  15. #include <ntddmup.h>
  16. #include "fsctlbuf.h"
  17. #include "prefix.h"
  18. #include "rxce.h"
  19. //
  20. // The local trace mask for this part of the module
  21. //
  22. #define Dbg (DEBUG_TRACE_DEVFCB)
  23. //
  24. // Forward declarations
  25. //
  26. VOID
  27. RxDeregisterUNCProvider(
  28. PRDBSS_DEVICE_OBJECT RxDeviceObject
  29. );
  30. VOID
  31. RxUnstart(
  32. PRX_CONTEXT RxContext,
  33. PRDBSS_DEVICE_OBJECT RxDeviceObject
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE, RxDeregisterUNCProvider)
  37. #pragma alloc_text(PAGE, RxUnstart)
  38. #pragma alloc_text(PAGE, RxSetDomainForMailslotBroadcast)
  39. #endif
  40. //
  41. // There are three states associated with each minirdr w.r.t the Start/Stop sequence.
  42. // These are
  43. // RDBSS_STARTABLE
  44. // - This is the initial state and also the one intowhich a minirdr transitions
  45. // after a successful stop.
  46. //
  47. // RDBSS_STARTED
  48. // - A transition to this state occurs after the startup sequence has been
  49. // successfully completed. This is the state in which the minirdr is active.
  50. //
  51. // RDBSS_STOP_IN_PROGRESS
  52. // - A transition to this state occurs when a shutdown sequence has been initiated.
  53. //
  54. //
  55. // A minirdr can be started and stopped independent of the system by invoking
  56. // the appropriate command through the workstation service. The
  57. // Start/Stop functionality is different from the Load/UnLoad functionality, i.e., it
  58. // is possible to stop a mini redirectors without unloading it.
  59. //
  60. // The data structures associated with the RDBSS can be classified into two categories
  61. // 1) those maintained by the RDBSS and visible to all the mini redirectors or private
  62. // and 2) those that are mainitained by the RDBSS and visible to the I/O subsystem.
  63. // The NET_ROOT,VNET_ROOT, SRV_CALL etc. are examples of the first category while
  64. // FCB's,FOBX's(File Object extensions ) are examples of the second category.
  65. // None of these data structures can be unilaterally destroyed by the RDBSS -- those
  66. // in category 1 must be destroyed in coordination with the mini redirectors while
  67. // those in category 2 must be done in coordination with the I/O subsystem.
  68. //
  69. // The destruction of the data structures can be initiated by the RDBSS while those
  70. // in the second category cannot be initiated by the RDBSS. Hence the shutdown
  71. // sequence has to make provisions for handling them differently.
  72. //
  73. // A shutdown sequence can be successfully completed ( so that the driver can be
  74. // unloaded ) if there are no residual instances in category 2, i.e., there are no
  75. // open file handles or references to file objects from the other system components.
  76. //
  77. // If there are any residual references, the corresponding instances are marked as
  78. // having been orphaned. The only permissible operations on orphaned instances are
  79. // close and cleanup. The mini redirector close/cleanup operations must make special
  80. // provisions for dealing with orphaned instances. All other operations are short
  81. // circuited with an error status by the wrapper.
  82. //
  83. VOID
  84. RxUnstart(
  85. PRX_CONTEXT RxContext,
  86. PRDBSS_DEVICE_OBJECT RxDeviceObject
  87. )
  88. {
  89. PAGED_CODE();
  90. ASSERT(BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP));
  91. if (RxDeviceObject->MupHandle != (HANDLE)0) {
  92. RxDbgTrace(0, Dbg, ("RxDeregisterUNCProvider derigistering from MUP %wZ\n", &RxDeviceObject->DeviceName));
  93. FsRtlDeregisterUncProvider(RxDeviceObject->MupHandle);
  94. RxDeviceObject->MupHandle = (HANDLE)0;
  95. }
  96. if (RxDeviceObject->RegisteredAsFileSystem) {
  97. IoUnregisterFileSystem((PDEVICE_OBJECT)RxDeviceObject);
  98. }
  99. if (RxData.NumberOfMinirdrsStarted==1) {
  100. RxForceNetTableFinalization(RxDeviceObject);
  101. RxData.NumberOfMinirdrsStarted = 0;
  102. // Get rid of buffers that have been allocated.
  103. if (s_PrimaryDomainName.Buffer != NULL) {
  104. RxFreePool(s_PrimaryDomainName.Buffer);
  105. s_PrimaryDomainName.Length = 0;
  106. s_PrimaryDomainName.Buffer = NULL;
  107. }
  108. } else {
  109. InterlockedDecrement(&RxData.NumberOfMinirdrsStarted);
  110. }
  111. }
  112. NTSTATUS
  113. RxSetDomainForMailslotBroadcast (
  114. IN PUNICODE_STRING DomainName
  115. )
  116. {
  117. PAGED_CODE();
  118. if (s_PrimaryDomainName.Buffer!=NULL) {
  119. RxFreePool(s_PrimaryDomainName.Buffer);
  120. }
  121. RxLog(("DomainName=%wZ",DomainName));
  122. RxWmiLog(LOG,
  123. RxSetDomainForMailslotBroadcast_1,
  124. LOGUSTR(*DomainName));
  125. s_PrimaryDomainName.Length = (USHORT)DomainName->Length;
  126. s_PrimaryDomainName.MaximumLength = s_PrimaryDomainName.Length;
  127. if (s_PrimaryDomainName.Length > 0) {
  128. s_PrimaryDomainName.Buffer = RxAllocatePoolWithTag(
  129. PagedPool | POOL_COLD_ALLOCATION,
  130. s_PrimaryDomainName.Length,
  131. RX_MISC_POOLTAG);
  132. if (s_PrimaryDomainName.Buffer == NULL) {
  133. return(STATUS_INSUFFICIENT_RESOURCES);
  134. } else {
  135. RtlCopyMemory(
  136. s_PrimaryDomainName.Buffer,
  137. DomainName->Buffer,
  138. s_PrimaryDomainName.Length);
  139. RxLog(("CapturedDomainName=%wZ",&s_PrimaryDomainName));
  140. RxWmiLog(LOG,
  141. RxSetDomainForMailslotBroadcast_2,
  142. LOGUSTR(s_PrimaryDomainName));
  143. }
  144. } else {
  145. s_PrimaryDomainName.Buffer = NULL;
  146. }
  147. return(STATUS_SUCCESS);
  148. }
  149. NTSTATUS
  150. RxStartMinirdr (
  151. IN PRX_CONTEXT RxContext,
  152. OUT PBOOLEAN PostToFsp
  153. )
  154. /*++
  155. Routine Description:
  156. This routine starts up the calling minirdr by registering as an UNC
  157. provider with the MUP.
  158. Arguments:
  159. RxContext - Describes the Context. the context is used to get the device object and to tell if we're in the fsp.
  160. PostToFsp - set to TRUE if the request has to be posted
  161. Return Value:
  162. RxStatus(SUCCESS) -- the Startup sequence was successfully completed.
  163. any other value indicates the appropriate error in the startup sequence.
  164. --*/
  165. {
  166. NTSTATUS Status;
  167. PRDBSS_DEVICE_OBJECT RxDeviceObject = RxContext->RxDeviceObject;
  168. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  169. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  170. BOOLEAN SuppressUnstart = FALSE;
  171. RxDbgTrace(0, Dbg, ("RxStartMinirdr [Start] -> %08lx\n", 0));
  172. // The startup sequence cannot be completed because there are certain aspects of
  173. // security and transport initialization that require handles. Since handles are
  174. // tied to a process the RDBSS needs to present an anchoring point to all the mini
  175. // redirectors. So the initialization will be completed in the context of the
  176. // FSP ( system process since RDBSS does not have its own FSP)
  177. if (InFSD) {
  178. SECURITY_SUBJECT_CONTEXT SubjectContext;
  179. SeCaptureSubjectContext(&SubjectContext);
  180. RxContext->FsdUid = RxGetUid( &SubjectContext );
  181. SeReleaseSubjectContext(&SubjectContext);
  182. *PostToFsp = TRUE;
  183. return STATUS_PENDING;
  184. }
  185. if (!ExAcquireResourceExclusiveLite(&RxData.Resource, Wait)) {
  186. *PostToFsp = TRUE;
  187. return STATUS_PENDING;
  188. }
  189. if (!RxAcquirePrefixTableLockExclusive( RxContext->RxDeviceObject->pRxNetNameTable, Wait)) {
  190. ASSERT(!"How can the wait fail?????");
  191. ExReleaseResourceLite(&RxData.Resource);
  192. *PostToFsp = TRUE;
  193. return STATUS_PENDING;
  194. }
  195. try {
  196. if (RxDeviceObject->MupHandle != NULL) {
  197. RxDbgTrace(0, Dbg, ("RxStartMinirdr [Already] -> %08lx\n", 0));
  198. SuppressUnstart = TRUE;
  199. try_return(Status = STATUS_REDIRECTOR_STARTED);
  200. }
  201. if (RxDeviceObject->RegisterUncProvider) {
  202. Status = FsRtlRegisterUncProvider(
  203. &RxDeviceObject->MupHandle,
  204. &RxDeviceObject->DeviceName,
  205. RxDeviceObject->RegisterMailSlotProvider
  206. );
  207. if (Status!=STATUS_SUCCESS) {
  208. RxDeviceObject->MupHandle = (HANDLE)0;
  209. try_return(Status);
  210. }
  211. } else {
  212. Status = STATUS_SUCCESS;
  213. }
  214. IoRegisterFileSystem((PDEVICE_OBJECT)RxDeviceObject);
  215. RxDeviceObject->RegisteredAsFileSystem = TRUE;
  216. MINIRDR_CALL(Status,
  217. RxContext,
  218. RxDeviceObject->Dispatch,
  219. MRxStart,
  220. (RxContext,RxDeviceObject));
  221. if (Status == STATUS_SUCCESS) {
  222. RxDeviceObject->StartStopContext.Version++;
  223. RxSetRdbssState(RxDeviceObject,RDBSS_STARTED);
  224. InterlockedIncrement(&RxData.NumberOfMinirdrsStarted);
  225. Status = RxInitializeMRxDispatcher(RxDeviceObject);
  226. }
  227. try_return(Status);
  228. try_exit:NOTHING;
  229. } finally {
  230. if (AbnormalTermination() || !NT_SUCCESS(Status)){
  231. if (!SuppressUnstart) {
  232. RxUnstart(RxContext,RxDeviceObject);
  233. }
  234. }
  235. RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
  236. ExReleaseResourceLite(&RxData.Resource);
  237. }
  238. return Status;
  239. }
  240. NTSTATUS
  241. RxStopMinirdr (
  242. IN PRX_CONTEXT RxContext,
  243. OUT PBOOLEAN PostToFsp
  244. )
  245. /*++
  246. Routine Description:
  247. This routine stops a minirdr....a stopped minirdr will no longer accept new commands.
  248. Arguments:
  249. RxContext - the context
  250. PostToFsp - the flag when set delays processing to the FSP.
  251. Return Value:
  252. the Status of the STOP operaion ...
  253. STATUS_PENDING -- processing delayed to FSP
  254. STATUS_REDIRECTOR_HAS_OPEN_HANDLES -- cannot be stopped at this time
  255. Notes:
  256. When a STOP request is issued to RDBSS there are ongoing requests in the
  257. RDBSS. Some of the requests can be cancelled while the remaining requests
  258. need to be processed to completion.
  259. There are a number of strategies that can be employed to close down the
  260. RDBSS. Currently, the most conservative approach is employed. The
  261. cancellation of those operations that can be cancelled and the STOP
  262. operation is held back till the remaining requests run through to completion.
  263. Subsequently, this will be revised so that the response times to STOP requests
  264. are smaller.
  265. --*/
  266. {
  267. NTSTATUS Status;
  268. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  269. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  270. PRDBSS_DEVICE_OBJECT RxDeviceObject = RxContext->RxDeviceObject;
  271. RxDbgTrace(0, Dbg, ("RxStopMinirdr [Stop] -> %08lx\n", 0));
  272. if (InFSD) {
  273. *PostToFsp = TRUE;
  274. return STATUS_PENDING;
  275. }
  276. if (!ExAcquireResourceExclusiveLite(&RxData.Resource, Wait)) {
  277. *PostToFsp = TRUE;
  278. return STATUS_PENDING;
  279. }
  280. try {
  281. KIRQL SavedIrql;
  282. BOOLEAN fWait;
  283. ASSERT(BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP));
  284. if (RxDeviceObject->StartStopContext.State!=RDBSS_STARTED){
  285. RxDbgTrace(0, Dbg, ("RxStopMinirdr [Notstarted] -> %08lx\n", 0));
  286. try_return ( Status = STATUS_REDIRECTOR_NOT_STARTED );
  287. }
  288. // Wait for all the ongoing requests to be completed. When the RDBSS is
  289. // transitioned to the STOPPED state the last context to be completed
  290. // will complete the wait.
  291. // Terminate all the scavenging operations.
  292. RxTerminateScavenging(RxContext);
  293. RxDbgPrint(("Waiting for all contexts to be flushed\n"));
  294. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  295. RemoveEntryList(&RxContext->ContextListEntry);
  296. RxDeviceObject->StartStopContext.State = RDBSS_STOP_IN_PROGRESS;
  297. RxDeviceObject->StartStopContext.pStopContext = RxContext;
  298. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  299. fWait = (InterlockedDecrement(&RxDeviceObject->NumberOfActiveContexts) != 0);
  300. if (fWait) {
  301. RxWaitSync(RxContext);
  302. }
  303. ASSERT(RxDeviceObject->NumberOfActiveContexts == 0);
  304. RxUnstart(RxContext,RxDeviceObject);
  305. RxSpinDownMRxDispatcher(RxDeviceObject);
  306. MINIRDR_CALL(
  307. Status,
  308. RxContext,
  309. RxDeviceObject->Dispatch,
  310. MRxStop,
  311. (RxContext,RxDeviceObject),
  312. );
  313. // If there are no residual FCB's the driver can be unloaded. If not the
  314. // driver must remain loaded so that close/cleanup operations on ORPHANED
  315. // FCB's can be completed.
  316. if (RxDeviceObject->NumberOfActiveFcbs == 0) {
  317. Status = STATUS_SUCCESS;
  318. } else {
  319. //ASSERT(!"OPENHANDLES!");
  320. Status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
  321. }
  322. RxSpinDownMRxDispatcher(RxDeviceObject);
  323. // All set to startup again.
  324. RxSetRdbssState(RxDeviceObject,RDBSS_STARTABLE);
  325. try_exit: NOTHING;
  326. } finally {
  327. ExReleaseResourceLite( &RxData.Resource );
  328. }
  329. return Status;
  330. }
  331.