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.

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