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.

313 lines
7.9 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: device.c
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // S.Mohanraj
  11. //
  12. // History: Date Author Comment
  13. //
  14. //@@END_MSINTERNAL
  15. //---------------------------------------------------------------------------
  16. //
  17. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  18. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  20. // PURPOSE.
  21. //
  22. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  23. //
  24. //---------------------------------------------------------------------------
  25. #define IRPMJFUNCDESC
  26. //#define TIME_BOMB
  27. #include "common.h"
  28. #ifdef TIME_BOMB
  29. #include <ksdebug.h>
  30. #include "..\timebomb\timebomb.c"
  31. #endif
  32. //---------------------------------------------------------------------------
  33. //---------------------------------------------------------------------------
  34. PDEVICE_INSTANCE gpDeviceInstance = NULL;
  35. DEFINE_KSCREATE_DISPATCH_TABLE(DeviceCreateItems)
  36. {
  37. DEFINE_KSCREATE_ITEMNULL(
  38. CFilterInstance::FilterDispatchCreate,
  39. NULL),
  40. };
  41. //---------------------------------------------------------------------------
  42. //---------------------------------------------------------------------------
  43. #pragma INIT_CODE
  44. #pragma INIT_DATA
  45. NTSTATUS
  46. DriverEntry
  47. (
  48. IN PDRIVER_OBJECT DriverObject,
  49. IN PUNICODE_STRING usRegistryPathName
  50. )
  51. {
  52. NTSTATUS Status = STATUS_SUCCESS;
  53. #ifdef TIME_BOMB
  54. if (HasEvaluationTimeExpired()) {
  55. return STATUS_EVALUATION_EXPIRATION;
  56. }
  57. #endif
  58. KeInitializeMutex(&gMutex, 0);
  59. GrabMutex();
  60. DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
  61. DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
  62. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
  63. DriverObject->DriverUnload = DriverUnload;
  64. DriverObject->DriverExtension->AddDevice = AddDevice;
  65. KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
  66. KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
  67. KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
  68. KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
  69. Status = InitializeUtil();
  70. if(!NT_SUCCESS(Status)) {
  71. Trap();
  72. goto exit;
  73. }
  74. Status = InitializeFilterNode();
  75. if(!NT_SUCCESS(Status)) {
  76. Trap();
  77. goto exit;
  78. }
  79. Status = InitializeDeviceNode();
  80. if(!NT_SUCCESS(Status)) {
  81. Trap();
  82. goto exit;
  83. }
  84. Status = InitializeVirtualSourceLine();
  85. if(!NT_SUCCESS(Status)) {
  86. Trap();
  87. goto exit;
  88. }
  89. InitializeListHead(&gEventQueue);
  90. KeInitializeSpinLock(&gEventLock);
  91. exit:
  92. ReleaseMutex();
  93. return(Status);
  94. }
  95. #pragma PAGEABLE_CODE
  96. #pragma PAGEABLE_DATA
  97. NTSTATUS
  98. DispatchPnp(
  99. IN PDEVICE_OBJECT pDeviceObject,
  100. IN PIRP pIrp
  101. )
  102. {
  103. PIO_STACK_LOCATION pIrpStack;
  104. UNICODE_STRING usLinkName;
  105. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  106. switch(pIrpStack->MinorFunction) {
  107. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  108. //
  109. // Mark the device as not disableable.
  110. //
  111. pIrp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  112. break;
  113. case IRP_MN_REMOVE_DEVICE:
  114. //
  115. // We need to unregister the notifications first before killing the
  116. // worker threads
  117. //
  118. UnregisterForPlugPlayNotifications();
  119. //
  120. // Needs to be outside the mutex because KsUnregisterWorker blocks
  121. // until all worker threads are done
  122. //
  123. UninitializeUtil();
  124. GrabMutex();
  125. CShingleInstance::UninitializeShingle();
  126. UninitializeFilterNode();
  127. UninitializeDeviceNode();
  128. UninitializeVirtualSourceLine();
  129. RtlInitUnicodeString(&usLinkName, STR_LINKNAME);
  130. IoDeleteSymbolicLink(&usLinkName);
  131. gpDeviceInstance = NULL;
  132. UninitializeMemory();
  133. ReleaseMutex();
  134. break;
  135. }
  136. return(KsDefaultDispatchPnp(pDeviceObject, pIrp));
  137. }
  138. VOID
  139. DriverUnload(
  140. IN PDRIVER_OBJECT DriverObject
  141. )
  142. {
  143. #ifdef DEBUG
  144. #ifndef UNDER_NT
  145. #ifdef _X86_
  146. UninitializeDebug();
  147. #endif
  148. #endif
  149. #endif
  150. }
  151. NTSTATUS
  152. AddDevice(
  153. IN PDRIVER_OBJECT DriverObject,
  154. IN PDEVICE_OBJECT PhysicalDeviceObject
  155. )
  156. /*++
  157. Routine Description:
  158. When a new device is detected, PnP calls this entry point with the
  159. new PhysicalDeviceObject (PDO). The driver creates an associated
  160. FunctionalDeviceObject (FDO).
  161. Arguments:
  162. DriverObject -
  163. Pointer to the driver object.
  164. PhysicalDeviceObject -
  165. Pointer to the new physical device object.
  166. Return Values:
  167. STATUS_SUCCESS or an appropriate error condition.
  168. --*/
  169. {
  170. UNICODE_STRING usDeviceName;
  171. UNICODE_STRING usLinkName;
  172. PDEVICE_OBJECT FunctionalDeviceObject = NULL;
  173. NTSTATUS Status;
  174. int i;
  175. GrabMutex();
  176. RtlInitUnicodeString(&usDeviceName, STR_DEVICENAME);
  177. Status = IoCreateDevice(
  178. DriverObject,
  179. sizeof(DEVICE_INSTANCE),
  180. &usDeviceName,
  181. FILE_DEVICE_KS,
  182. 0,
  183. FALSE,
  184. &FunctionalDeviceObject);
  185. if(!NT_SUCCESS(Status)) {
  186. Trap();
  187. goto exit;
  188. }
  189. gpDeviceInstance =
  190. (PDEVICE_INSTANCE)FunctionalDeviceObject->DeviceExtension;
  191. gpDeviceInstance->pPhysicalDeviceObject = PhysicalDeviceObject;
  192. gpDeviceInstance->pFunctionalDeviceObject = FunctionalDeviceObject;
  193. RtlInitUnicodeString(&usLinkName, STR_LINKNAME);
  194. Status = IoCreateSymbolicLink(&usLinkName, &usDeviceName);
  195. if(!NT_SUCCESS(Status)) {
  196. Trap();
  197. goto exit;
  198. }
  199. Status = KsAllocateDeviceHeader(
  200. &gpDeviceInstance->pDeviceHeader,
  201. SIZEOF_ARRAY(DeviceCreateItems),
  202. (PKSOBJECT_CREATE_ITEM)DeviceCreateItems);
  203. if(!NT_SUCCESS(Status)) {
  204. Trap();
  205. goto exit;
  206. }
  207. KsSetDevicePnpAndBaseObject(
  208. gpDeviceInstance->pDeviceHeader,
  209. IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject),
  210. FunctionalDeviceObject);
  211. //
  212. // ISSUE: 05/13/2002 ALPERS
  213. // StackSize Problem
  214. // Note that we may still have StackSize problems with deeper objects.
  215. // The problem will be caught by IO verifier.
  216. // However in real world, we do not expect any problems because usbaudio
  217. // driver will never passes-down requests from Sysaudio. In other words,
  218. // even if DeviceStackSize is deeper than Sysaudio, the IRP will never go
  219. // down-level from Usbaudio.
  220. //
  221. //
  222. // Set the StackSize for deeper device stacks.
  223. // Sysaudio StackSize is normally 2.
  224. // SYSAUDIO - FDO
  225. // SWENUM - PDO
  226. //
  227. // Sysaudio forwards the IRPs to other device stacks which might
  228. // be deeper than 2. In that case IoVerifier will bugcheck.
  229. // An example of this is an upper UsbAudio filter driver forwarding
  230. // IRPs to UsbAudio.
  231. //
  232. // Setting FDO StackSize to DEFAULT_LARGE_IRP_LOCATIONS 8 (iomgr.h)
  233. // guarantees that the IRP comes from large IRP lookaside list in kernel.
  234. // Thus no memory is wasted. The system has a list of IRPs that it recycles.
  235. //
  236. // StackSize 7 will almost guarantee that sysaudio will be deep enough
  237. // for any DeviceStack, even with IoVerifier turned on.
  238. //
  239. if (FunctionalDeviceObject->StackSize < 7) {
  240. FunctionalDeviceObject->StackSize = 7;
  241. }
  242. Status = RegisterForPlugPlayNotifications();
  243. if(!NT_SUCCESS(Status)) {
  244. Trap();
  245. goto exit;
  246. }
  247. Status = CShingleInstance::InitializeShingle();
  248. if(!NT_SUCCESS(Status)) {
  249. Trap();
  250. goto exit;
  251. }
  252. DeviceCreateItems[0].Context =
  253. apShingleInstance[KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT];
  254. FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
  255. FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  256. exit:
  257. ReleaseMutex();
  258. return(Status);
  259. }
  260. //---------------------------------------------------------------------------
  261. // End of File: device.c
  262. //---------------------------------------------------------------------------