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.

531 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. minirdr.c
  5. Abstract:
  6. This module implements minirdr registration functions.
  7. Author:
  8. Joe Linn (JoeLinn) 2-2-95
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, RxRegisterMinirdr)
  15. #pragma alloc_text(PAGE, RxMakeLateDeviceAvailable)
  16. #pragma alloc_text(PAGE, RxpUnregisterMinirdr)
  17. #endif
  18. //
  19. // The debug trace level
  20. //
  21. #define Dbg (0)
  22. #ifdef ALLOC_PRAGMA
  23. #endif
  24. // #define BBT_UPDATE 1
  25. #ifdef BBT_UPDATE
  26. extern VOID RxUpdate(PVOID pContext);
  27. HANDLE RxHandle = INVALID_HANDLE_VALUE;
  28. PETHREAD RxPointer = NULL;
  29. #endif
  30. NTSTATUS
  31. NTAPI
  32. RxRegisterMinirdr(
  33. OUT PRDBSS_DEVICE_OBJECT *DeviceObject,
  34. IN OUT PDRIVER_OBJECT DriverObject, // the minirdr driver object
  35. IN PMINIRDR_DISPATCH MrdrDispatch, // the mini rdr dispatch vector
  36. IN ULONG Controls,
  37. IN PUNICODE_STRING DeviceName,
  38. IN ULONG DeviceExtensionSize,
  39. IN DEVICE_TYPE DeviceType,
  40. IN ULONG DeviceCharacteristics
  41. )
  42. /*++
  43. Routine Description:
  44. The routine adds the registration information to the minirdr registration table. As well, it builds
  45. a device object; the MUP registration is at start time. Also, we fill in the deviceobject so that we are catching
  46. all the calls.
  47. Arguments:
  48. DeviceObject - where the created device object is to be stored
  49. ProtocolMarker - a 4byte marker denoting the FileLevel Protocol
  50. ('LCL ', 'SMB ', 'NCP ', and 'NFS ') are used
  51. MrdrDispatch - the dispatch table for finding the server/netroot discovery routines
  52. Context - whatever PVOID the underlying guy wants
  53. MupAction - whether/how the MUP registration is done
  54. DeviceName,DeviceExtensionSize,DeviceType,DeviceCharacteristics
  55. - the params for the device object that is to be built these are adjusted a bit
  56. bfore they're passed to Io
  57. Return Value:
  58. --
  59. --*/
  60. {
  61. NTSTATUS Status;
  62. PRDBSS_DEVICE_OBJECT RxDeviceObject;
  63. PAGED_CODE();
  64. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), (" RxRegisterMinirdr Name = %wZ", DeviceName));
  65. if (DeviceObject==NULL) {
  66. return STATUS_INVALID_PARAMETER;
  67. }
  68. // Create the device object.
  69. Status = IoCreateDevice(DriverObject,
  70. sizeof(RDBSS_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT) + DeviceExtensionSize,
  71. DeviceName,
  72. DeviceType,
  73. DeviceCharacteristics,
  74. FALSE,
  75. (PDEVICE_OBJECT *)(&RxDeviceObject));
  76. if (Status != STATUS_SUCCESS) {
  77. return(Status);
  78. }
  79. if (RxData.DriverObject == NULL) {
  80. return STATUS_UNSUCCESSFUL;
  81. }
  82. //
  83. // If the Mini-Redir is being built in a monolithic fashion, then the
  84. // device object "RxFileSystemDeviceObject" would not have been created
  85. // in the RxDriverEntry function. Hence we set RxDeviceObject->RDBSSDeviceObject
  86. // to NULL. When the "monolithic" Mini-Redir gets unloaded, a check is done
  87. // to see if RxDeviceObject->RDBSSDeviceObject is NULL. If it is not NULL,
  88. // then the device object is dereferenced. This happens in the function
  89. // RxUnregisterMinirdr.
  90. //
  91. // Don't allow myself to be unloaded.
  92. #ifndef MONOLITHIC_MINIRDR
  93. RxDeviceObject->RDBSSDeviceObject = (PDEVICE_OBJECT)RxFileSystemDeviceObject;
  94. ObReferenceObject((PDEVICE_OBJECT)RxFileSystemDeviceObject);
  95. // Reset the Unload routine. This prevents rdbss from being unloaded individually
  96. RxData.DriverObject->DriverUnload = NULL;
  97. #else
  98. RxDeviceObject->RDBSSDeviceObject = NULL;
  99. RxFileSystemDeviceObject->ReferenceCount++;
  100. #endif
  101. *DeviceObject = RxDeviceObject;
  102. RxDeviceObject->RdbssExports = &RxExports;
  103. RxDeviceObject->Dispatch = MrdrDispatch;
  104. RxDeviceObject->RegistrationControls = Controls;
  105. RxDeviceObject->DeviceName = *DeviceName;
  106. RxDeviceObject->RegisterUncProvider =
  107. !BooleanFlagOn(Controls,RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS);
  108. RxDeviceObject->RegisterMailSlotProvider =
  109. !BooleanFlagOn(Controls,RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS);
  110. {
  111. LONG Index;
  112. for (Index = 0; Index < MaximumWorkQueue; Index++) {
  113. InitializeListHead( &RxDeviceObject->OverflowQueue[Index] );
  114. }
  115. }
  116. KeInitializeSpinLock( &RxDeviceObject->OverflowQueueSpinLock );
  117. RxDeviceObject->NetworkProviderPriority = RxGetNetworkProviderPriority(DeviceName);
  118. RxLog(("RegMini %x %wZ\n",RxDeviceObject->NetworkProviderPriority,DeviceName));
  119. RxWmiLog(LOG,
  120. RxRegisterMinirdr,
  121. LOGULONG(RxDeviceObject->NetworkProviderPriority)
  122. LOGUSTR(*DeviceName));
  123. ExAcquireFastMutexUnsafe(&RxData.MinirdrRegistrationMutex);
  124. InsertTailList(&RxData.RegisteredMiniRdrs,&RxDeviceObject->MiniRdrListLinks);
  125. //no need for interlock.....we're inside the mutex
  126. //InterlockedIncrement(&RxData.NumberOfMinirdrsRegistered);
  127. RxData.NumberOfMinirdrsRegistered++;
  128. ExReleaseFastMutexUnsafe(&RxData.MinirdrRegistrationMutex);
  129. if (!FlagOn(Controls,RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH)) {
  130. RxInitializeMinirdrDispatchTable(DriverObject);
  131. }
  132. if (!FlagOn(Controls,RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER)) {
  133. // Initialize the netname table
  134. RxDeviceObject->pRxNetNameTable = &RxDeviceObject->RxNetNameTableInDeviceObject;
  135. RxInitializePrefixTable( RxDeviceObject->pRxNetNameTable, 0, FALSE);
  136. RxDeviceObject->RxNetNameTableInDeviceObject.IsNetNameTable = TRUE;
  137. // Initialize the scavenger data structures
  138. RxDeviceObject->pRdbssScavenger = &RxDeviceObject->RdbssScavengerInDeviceObject;
  139. RxInitializeRdbssScavenger(RxDeviceObject->pRdbssScavenger);
  140. }
  141. RxDeviceObject->pAsynchronousRequestsCompletionEvent = NULL;
  142. #ifdef BBT_UPDATE
  143. if (RxHandle == INVALID_HANDLE_VALUE) {
  144. NTSTATUS Status;
  145. Status = PsCreateSystemThread(
  146. &RxHandle,
  147. PROCESS_ALL_ACCESS,
  148. NULL,
  149. NULL,
  150. NULL,
  151. RxUpdate,
  152. NULL);
  153. if (Status == STATUS_SUCCESS) {
  154. Status = ObReferenceObjectByHandle(
  155. RxHandle,
  156. THREAD_ALL_ACCESS,
  157. NULL,
  158. KernelMode,
  159. &RxPointer,
  160. NULL);
  161. if (Status != STATUS_SUCCESS) {
  162. RxPointer = NULL;
  163. }
  164. ZwClose(RxHandle);
  165. } else {
  166. RxHandle = INVALID_HANDLE_VALUE;
  167. }
  168. }
  169. #endif
  170. return((STATUS_SUCCESS));
  171. }
  172. VOID
  173. NTAPI
  174. RxMakeLateDeviceAvailable(
  175. IN PRDBSS_DEVICE_OBJECT RxDeviceObject
  176. )
  177. /*++
  178. Routine Description:
  179. The routine diddles the device object to make a "late device" available.
  180. A late device is one that is not created in the driver's load routine.
  181. Non-late devices are diddled by the driverload code in the io subsystem; but
  182. for late devices we have to do this by hand. This is a routine instead of a
  183. macro in order that other stuff might have to be done here....it's only
  184. executed once per device object.
  185. Arguments:
  186. DeviceObject - where the created device object is to be stored
  187. Return Value:
  188. --
  189. --*/
  190. {
  191. PAGED_CODE();
  192. RxDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  193. return;
  194. }
  195. VOID
  196. RxpUnregisterMinirdr(
  197. IN PRDBSS_DEVICE_OBJECT RxDeviceObject
  198. )
  199. /*++
  200. Routine Description:
  201. Arguments:
  202. Return Value:
  203. --
  204. --*/
  205. {
  206. PAGED_CODE();
  207. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), (" RxUnregisterMinirdr Name = %wZ\n",&RxDeviceObject->DeviceName));
  208. ExAcquireFastMutexUnsafe(&RxData.MinirdrRegistrationMutex);
  209. RemoveEntryList(&RxDeviceObject->MiniRdrListLinks);
  210. //no need for interlock.....we're inside the mutex
  211. //InterlockedDecrement(&RxData.NumberOfMinirdrsRegistered);
  212. RxData.NumberOfMinirdrsRegistered--;
  213. if (RxData.NumberOfMinirdrsRegistered == 0) {
  214. // Allow rdbss being unloaded after mini rdr driver is unregistered
  215. RxData.DriverObject->DriverUnload = RxUnload;
  216. }
  217. ExReleaseFastMutexUnsafe(&RxData.MinirdrRegistrationMutex);
  218. if (!FlagOn(RxDeviceObject->RegistrationControls,
  219. RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER)) {
  220. RxForceNetTableFinalization(RxDeviceObject);
  221. RxFinalizePrefixTable(&RxDeviceObject->RxNetNameTableInDeviceObject);
  222. //no finalization is defined for scavenger structure
  223. }
  224. RxSpinDownOutstandingAsynchronousRequests(RxDeviceObject);
  225. // Spin down any worker threads associated with this minirdr
  226. RxSpinDownMRxDispatcher(RxDeviceObject);
  227. IoDeleteDevice(&RxDeviceObject->DeviceObject);
  228. #ifdef BBT_UPDATE
  229. if (RxPointer != NULL) {
  230. RxHandle = INVALID_HANDLE_VALUE;
  231. KeWaitForSingleObject(
  232. RxPointer,
  233. Executive,
  234. KernelMode,
  235. FALSE,
  236. NULL);
  237. ASSERT(PsIsThreadTerminating(RxPointer));
  238. ObDereferenceObject(RxPointer);
  239. RxPointer = NULL;
  240. }
  241. #endif
  242. }
  243. VOID
  244. RxSpinDownOutstandingAsynchronousRequests(
  245. PRDBSS_DEVICE_OBJECT RxDeviceObject)
  246. /*++
  247. Routine Description:
  248. This routine spins down all the outstanding requests associated with a
  249. mini redirector before it can be unloaded
  250. Arguments:
  251. RxDeviceObject -- the mini redirector's device object
  252. --*/
  253. {
  254. BOOLEAN WaitForSpinDown = FALSE;
  255. KEVENT SpinDownEvent;
  256. KeInitializeEvent(
  257. &SpinDownEvent,
  258. NotificationEvent,
  259. FALSE);
  260. RxAcquireSerializationMutex();
  261. ASSERT(RxDeviceObject->pAsynchronousRequestsCompletionEvent == NULL);
  262. WaitForSpinDown = (RxDeviceObject->AsynchronousRequestsPending != 0);
  263. RxDeviceObject->pAsynchronousRequestsCompletionEvent = &SpinDownEvent;
  264. RxReleaseSerializationMutex();
  265. if (WaitForSpinDown) {
  266. KeWaitForSingleObject(
  267. &SpinDownEvent,
  268. Executive,
  269. KernelMode,
  270. FALSE,
  271. NULL);
  272. }
  273. }
  274. NTSTATUS
  275. RxRegisterAsynchronousRequest(
  276. PRDBSS_DEVICE_OBJECT RxDeviceObject)
  277. /*++
  278. Routine Description:
  279. This routine registers an asynchronous request. On successful completion
  280. the mini redirector cannot be unloaded till the request completes
  281. Arguments:
  282. RxDeviceObject - the mini redirector device object
  283. Return Value:
  284. STATUS_SUCCESS if successful
  285. --*/
  286. {
  287. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  288. RxAcquireSerializationMutex();
  289. if (RxDeviceObject->pAsynchronousRequestsCompletionEvent == NULL) {
  290. RxDeviceObject->AsynchronousRequestsPending++;
  291. Status = STATUS_SUCCESS;
  292. }
  293. RxReleaseSerializationMutex();
  294. return Status;
  295. }
  296. VOID
  297. RxDeregisterAsynchronousRequest(
  298. PRDBSS_DEVICE_OBJECT RxDeviceObject)
  299. /*++
  300. Routine Description:
  301. This routine signals the completion of an asynchronous request. It resumes
  302. unloading if required.
  303. Arguments:
  304. RxDeviceObject - the mini redirector device object
  305. --*/
  306. {
  307. PKEVENT pEvent = NULL;
  308. RxAcquireSerializationMutex();
  309. RxDeviceObject->AsynchronousRequestsPending--;
  310. if ((RxDeviceObject->AsynchronousRequestsPending == 0) &&
  311. (RxDeviceObject->pAsynchronousRequestsCompletionEvent != NULL)) {
  312. pEvent = RxDeviceObject->pAsynchronousRequestsCompletionEvent;
  313. }
  314. RxReleaseSerializationMutex();
  315. if (pEvent != NULL) {
  316. KeSetEvent(
  317. pEvent,
  318. IO_NO_INCREMENT,
  319. FALSE);
  320. }
  321. }
  322. #ifdef BBT_UPDATE
  323. WCHAR Request_Name[] = L"\\??\\UNC\\landyw-bear\\bbt\\bbt.txt";
  324. VOID
  325. RxUpdate(PVOID pContext)
  326. {
  327. NTSTATUS Status;
  328. OBJECT_ATTRIBUTES ObjectAttributes;
  329. IO_STATUS_BLOCK IoStatusBlock;
  330. UNICODE_STRING RequestName;
  331. RequestName.Buffer = Request_Name;
  332. RequestName.MaximumLength = wcslen(Request_Name) * sizeof(WCHAR);
  333. RequestName.Length = RequestName.MaximumLength;
  334. InitializeObjectAttributes(
  335. &ObjectAttributes,
  336. &RequestName,
  337. OBJ_CASE_INSENSITIVE,
  338. NULL,
  339. NULL);
  340. for (;;) {
  341. PHYSICAL_ADDRESS StartAddress;
  342. LARGE_INTEGER NumberOfBytes;
  343. HANDLE FileHandle;
  344. struct {
  345. LIST_ENTRY Link;
  346. SIZE_T Size;
  347. CHAR Data[];
  348. } *Request;
  349. NumberOfBytes.QuadPart = 0x2;
  350. StartAddress.QuadPart = 0;
  351. MmAddPhysicalMemory(
  352. &StartAddress,
  353. &NumberOfBytes);
  354. Request = (PVOID)(StartAddress.QuadPart);
  355. if (Request != NULL) {
  356. Status = ZwCreateFile(
  357. &FileHandle,
  358. (FILE_APPEND_DATA | SYNCHRONIZE),
  359. &ObjectAttributes,
  360. &IoStatusBlock,
  361. NULL,
  362. FILE_ATTRIBUTE_NORMAL,
  363. (FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE),
  364. FILE_OPEN,
  365. FILE_NO_INTERMEDIATE_BUFFERING,
  366. NULL,
  367. 0);
  368. if (Status == STATUS_SUCCESS) {
  369. LARGE_INTEGER ByteOffset;
  370. ByteOffset.QuadPart = -1;
  371. Status = ZwWriteFile(
  372. FileHandle,
  373. NULL,
  374. NULL,
  375. NULL,
  376. &IoStatusBlock,
  377. Request->Data,
  378. (ULONG)Request->Size,
  379. &ByteOffset,
  380. NULL);
  381. Status = ZwClose(FileHandle);
  382. }
  383. ExFreePool(Request);
  384. }
  385. if (RxHandle == INVALID_HANDLE_VALUE) {
  386. break;
  387. }
  388. }
  389. PsTerminateSystemThread(STATUS_SUCCESS);
  390. }
  391. #endif