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.

463 lines
12 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: dn.cpp
  4. //
  5. // Description:
  6. //
  7. // DeviceNode Class
  8. //
  9. //@@BEGIN_MSINTERNAL
  10. // Development Team:
  11. // Mike McLaughlin
  12. //
  13. // History: Date Author Comment
  14. //
  15. // To Do: Date Author Comment
  16. //
  17. //@@END_MSINTERNAL
  18. //
  19. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  20. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  22. // PURPOSE.
  23. //
  24. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  25. //
  26. //---------------------------------------------------------------------------
  27. #if defined(_M_IA64)
  28. #define USE_ALLOC_TEXT
  29. #endif
  30. #include "common.h"
  31. #if defined(ALLOC_PRAGMA) && defined(_M_IA64)
  32. #pragma alloc_text(INIT, InitializeDeviceNode)
  33. #endif
  34. //---------------------------------------------------------------------------
  35. //---------------------------------------------------------------------------
  36. ALLOC_PAGEABLE_DATA PLIST_DEVICE_NODE gplstDeviceNode = NULL;
  37. //---------------------------------------------------------------------------
  38. //---------------------------------------------------------------------------
  39. #if !defined(_M_IA64)
  40. #pragma INIT_CODE
  41. #endif
  42. #pragma INIT_DATA
  43. NTSTATUS
  44. InitializeDeviceNode(
  45. )
  46. {
  47. if(gplstDeviceNode == NULL) {
  48. gplstDeviceNode = new LIST_DEVICE_NODE;
  49. if(gplstDeviceNode == NULL) {
  50. return(STATUS_INSUFFICIENT_RESOURCES);
  51. }
  52. }
  53. return(STATUS_SUCCESS);
  54. }
  55. #pragma PAGEABLE_CODE
  56. #pragma PAGEABLE_DATA
  57. VOID
  58. UninitializeDeviceNode(
  59. )
  60. {
  61. delete gplstDeviceNode;
  62. gplstDeviceNode = NULL;
  63. }
  64. //---------------------------------------------------------------------------
  65. CDeviceNode::CDeviceNode(
  66. )
  67. {
  68. ASSERT(gplstDeviceNode != NULL);
  69. AddListEnd(gplstDeviceNode);
  70. DPF1(50, "CDeviceNode: %08x", this);
  71. }
  72. CDeviceNode::~CDeviceNode(
  73. )
  74. {
  75. PFILTER_INSTANCE pFilterInstance;
  76. ULONG i;
  77. Assert(this);
  78. RemoveList();
  79. if (pFilterNode) {
  80. pFilterNode->pDeviceNode = NULL;
  81. }
  82. delete pShingleInstance;
  83. FOR_EACH_LIST_ITEM_DELETE(&lstFilterInstance, pFilterInstance) {
  84. ASSERT(pFilterInstance->GetDeviceNode() == this);
  85. pFilterInstance->SetDeviceNode(NULL);
  86. } END_EACH_LIST_ITEM
  87. if(papVirtualSourceData != NULL) {
  88. for(i = 0; i < cVirtualSourceData; i++) {
  89. delete papVirtualSourceData[i];
  90. }
  91. delete papVirtualSourceData;
  92. }
  93. for(i = 0; i < MAX_SYSAUDIO_DEFAULT_TYPE; i++) {
  94. if(apShingleInstance[i] != NULL) {
  95. if(apShingleInstance[i]->GetDeviceNode() == this) {
  96. apShingleInstance[i]->SetDeviceNode(NULL);
  97. }
  98. }
  99. }
  100. delete pFilterNodeVirtual;
  101. DPF1(50, "~CFilterNode: %08x", this);
  102. }
  103. NTSTATUS
  104. CDeviceNode::Create(
  105. PFILTER_NODE pFilterNode
  106. )
  107. {
  108. NTSTATUS Status = STATUS_SUCCESS;
  109. Assert(this);
  110. Assert(pFilterNode);
  111. this->pFilterNode = pFilterNode;
  112. Status = Update();
  113. if(!NT_SUCCESS(Status)) {
  114. goto exit;
  115. }
  116. pShingleInstance = new SHINGLE_INSTANCE(FLAGS_COMBINE_PINS);
  117. if(pShingleInstance == NULL) {
  118. Status = STATUS_INSUFFICIENT_RESOURCES;
  119. goto exit;
  120. }
  121. Status = pShingleInstance->Create(this, (LPGUID)&KSCATEGORY_AUDIO_DEVICE);
  122. if(!NT_SUCCESS(Status)) {
  123. goto exit;
  124. }
  125. exit:
  126. return(Status);
  127. }
  128. NTSTATUS
  129. CDeviceNode::Update(
  130. )
  131. {
  132. NTSTATUS Status = STATUS_SUCCESS;
  133. PFILTER_NODE pFilterNodeNext;
  134. ULONG i;
  135. Assert(this);
  136. Assert(pFilterNode);
  137. DPF2(50, "CDeviceNode::Update DN %08x %s", this, DumpName());
  138. //
  139. // Cleanup all graph structures.
  140. //
  141. lstGraphNode.DestroyList();
  142. lstLogicalFilterNode.DestroyList();
  143. delete pFilterNodeVirtual;
  144. pFilterNodeVirtual = NULL;
  145. //
  146. // Delete old virtual source lines.
  147. //
  148. if(papVirtualSourceData != NULL) {
  149. for(i = 0; i < cVirtualSourceData; i++) {
  150. delete papVirtualSourceData[i];
  151. }
  152. delete papVirtualSourceData;
  153. papVirtualSourceData = NULL;
  154. }
  155. //
  156. // Create new virtual source lines.
  157. //
  158. if(gcVirtualSources != 0) {
  159. papVirtualSourceData = new PVIRTUAL_SOURCE_DATA[gcVirtualSources];
  160. if(papVirtualSourceData == NULL) {
  161. Trap();
  162. Status = STATUS_INSUFFICIENT_RESOURCES;
  163. goto exit;
  164. }
  165. for(i = 0; i < gcVirtualSources; i++) {
  166. papVirtualSourceData[i] = new VIRTUAL_SOURCE_DATA(this);
  167. if(papVirtualSourceData[i] == NULL) {
  168. Trap();
  169. Status = STATUS_INSUFFICIENT_RESOURCES;
  170. goto exit;
  171. }
  172. }
  173. }
  174. cVirtualSourceData = gcVirtualSources;
  175. Status = AddLogicalFilterNode(pFilterNode);
  176. if(!NT_SUCCESS(Status)) {
  177. Trap();
  178. goto exit;
  179. }
  180. FOR_EACH_LIST_ITEM(&pFilterNode->lstConnectedFilterNode, pFilterNodeNext) {
  181. Status = AddLogicalFilterNode(pFilterNodeNext);
  182. if(!NT_SUCCESS(Status)) {
  183. Trap();
  184. goto exit;
  185. }
  186. } END_EACH_LIST_ITEM
  187. Status = CreateVirtualMixer(this);
  188. if(!NT_SUCCESS(Status)) {
  189. Trap();
  190. goto exit;
  191. }
  192. if(pShingleInstance != NULL) {
  193. Status = pShingleInstance->SetDeviceNode(this);
  194. if(!NT_SUCCESS(Status)) {
  195. Trap();
  196. goto exit;
  197. }
  198. }
  199. exit:
  200. return(Status);
  201. }
  202. NTSTATUS
  203. CDeviceNode::AddLogicalFilterNode(
  204. PFILTER_NODE pFilterNode
  205. )
  206. {
  207. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  208. NTSTATUS Status = STATUS_SUCCESS;
  209. Status = VirtualizeTopology(this, pFilterNode);
  210. if(!NT_SUCCESS(Status)) {
  211. Trap();
  212. goto exit;
  213. }
  214. FOR_EACH_LIST_ITEM(
  215. &pFilterNode->lstLogicalFilterNode,
  216. pLogicalFilterNode) {
  217. DPF2(60, "AddLogicalFilterNode: %08x, DN: %08x",
  218. pLogicalFilterNode,
  219. this);
  220. Status = pLogicalFilterNode->AddList(&lstLogicalFilterNode);
  221. if(!NT_SUCCESS(Status)) {
  222. Trap();
  223. goto exit;
  224. }
  225. pLogicalFilterNode->RemoveList(gplstLogicalFilterNode);
  226. } END_EACH_LIST_ITEM
  227. exit:
  228. return(Status);
  229. }
  230. NTSTATUS
  231. CDeviceNode::CreateGraphNodes(
  232. )
  233. {
  234. PGRAPH_NODE pGraphNode, pGraphNodeMixer;
  235. NTSTATUS Status = STATUS_SUCCESS;
  236. Assert(this);
  237. if(lstGraphNode.IsLstEmpty()) {
  238. pGraphNode = new GRAPH_NODE(this, 0);
  239. if(pGraphNode == NULL) {
  240. Status = STATUS_INSUFFICIENT_RESOURCES;
  241. Trap();
  242. goto exit;
  243. }
  244. Status = pGraphNode->Create();
  245. if(!NT_SUCCESS(Status)) {
  246. Trap();
  247. goto exit;
  248. }
  249. //
  250. // Create a special GraphNode that points to the same renderer or
  251. // capturer, but is marked with the "mixer topology" flag so the
  252. // pins and topology created for this GraphNode is the virtual mixer
  253. // topology for the mixer driver.
  254. //
  255. pGraphNodeMixer = new GRAPH_NODE(this, FLAGS_MIXER_TOPOLOGY);
  256. if(pGraphNodeMixer == NULL) {
  257. Status = STATUS_INSUFFICIENT_RESOURCES;
  258. Trap();
  259. goto exit;
  260. }
  261. Status = pGraphNodeMixer->Create();
  262. if(!NT_SUCCESS(Status)) {
  263. Trap();
  264. goto exit;
  265. }
  266. }
  267. exit:
  268. if(!NT_SUCCESS(Status)) {
  269. Trap();
  270. lstGraphNode.DestroyList();
  271. }
  272. return(Status);
  273. }
  274. NTSTATUS
  275. CDeviceNode::GetIndexByDevice(
  276. OUT PULONG pIndex
  277. )
  278. {
  279. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  280. PDEVICE_NODE pDeviceNode;
  281. UINT iDevice = 0;
  282. if(this == NULL) {
  283. ASSERT(Status == STATUS_INVALID_DEVICE_REQUEST);
  284. goto exit;
  285. }
  286. ASSERT(pIndex);
  287. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  288. if(pDeviceNode == this) { // This is the one!
  289. *pIndex = iDevice;
  290. Status = STATUS_SUCCESS;
  291. goto exit;
  292. }
  293. iDevice++;
  294. } END_EACH_LIST_ITEM
  295. ASSERT(Status == STATUS_INVALID_DEVICE_REQUEST);
  296. exit:
  297. return(Status);
  298. }
  299. //=============================================================================
  300. // SetPreferredStatus.
  301. //
  302. // This function is designed to let the drivers know about the preferred
  303. // device changes.
  304. // A usbaudio device can reserve bandwidth based on this property. If it is
  305. // the preferred device, it will reserve a larger bandwidth.
  306. //
  307. // As of 02/20/02 (WinXP) there are no drivers implementing this property.
  308. //
  309. // This code is to support any future changes in external bus class drivers
  310. // related to bus reservation.
  311. //
  312. VOID
  313. CDeviceNode::SetPreferredStatus(
  314. KSPROPERTY_SYSAUDIO_DEFAULT_TYPE DeviceType,
  315. BOOL Enable
  316. )
  317. {
  318. PFILTER_NODE_INSTANCE pFilterNodeInstance=NULL;
  319. KSAUDIO_PREFERRED_STATUS PreferredStatus;
  320. PFILE_OBJECT pFileObject;
  321. KSPROPERTY PreferredStatusProperty;
  322. NTSTATUS Status;
  323. ULONG BytesReturned;
  324. Status = CFilterNodeInstance::Create(&pFilterNodeInstance, this->pFilterNode);
  325. if (!NT_SUCCESS(Status)) {
  326. DPF1(5, "SetPreferredStatus : Create filterinstance failed with status = 0x%08x", Status);
  327. goto exit;
  328. }
  329. pFileObject = pFilterNodeInstance->pFileObject;
  330. ASSERT(pFileObject);
  331. //
  332. // Form the IOCTL packet & send it down
  333. //
  334. PreferredStatusProperty.Set = KSPROPSETID_Audio;
  335. PreferredStatusProperty.Id = KSPROPERTY_AUDIO_PREFERRED_STATUS;
  336. PreferredStatusProperty.Flags = KSPROPERTY_TYPE_SET;
  337. PreferredStatus.Enable = Enable;
  338. PreferredStatus.DeviceType = DeviceType;
  339. PreferredStatus.Flags = 0;
  340. PreferredStatus.Reserved = 0;
  341. DPF(60,"Sending preferred Status to:");
  342. DPF1(60," FriendlyName = %s", DbgUnicode2Sz(this->pFilterNode->GetFriendlyName()));
  343. DPF1(60," DI = %s", DbgUnicode2Sz(this->pFilterNode->GetDeviceInterface()));
  344. DPF1(60," Enable = 0x%08x", Enable);
  345. DPF1(60," DeviceType = 0x%08x", DeviceType);
  346. //
  347. // We actually throw away the status we got back from the device.
  348. // Even if this failed we will still continue setting the device to be the
  349. // preferred device
  350. //
  351. Status = KsSynchronousIoControlDevice(pFileObject,
  352. KernelMode,
  353. IOCTL_KS_PROPERTY,
  354. &PreferredStatusProperty,
  355. sizeof(PreferredStatusProperty),
  356. &PreferredStatus,
  357. sizeof(PreferredStatus),
  358. &BytesReturned);
  359. exit:
  360. if (pFilterNodeInstance) {
  361. pFilterNodeInstance->Destroy();
  362. }
  363. }
  364. NTSTATUS
  365. GetDeviceByIndex(
  366. IN UINT Index,
  367. OUT PDEVICE_NODE *ppDeviceNode
  368. )
  369. {
  370. PDEVICE_NODE pDeviceNode;
  371. NTSTATUS Status;
  372. UINT iDevice = 0;
  373. ASSERT(ppDeviceNode);
  374. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  375. if(iDevice++ == Index) { // This is the one!
  376. *ppDeviceNode = pDeviceNode;
  377. Status = STATUS_SUCCESS;
  378. goto exit;
  379. }
  380. } END_EACH_LIST_ITEM
  381. Status = STATUS_INVALID_DEVICE_REQUEST;
  382. exit:
  383. return(Status);
  384. }
  385. //---------------------------------------------------------------------------
  386. VOID
  387. DestroyAllGraphs(
  388. )
  389. {
  390. PDEVICE_NODE pDeviceNode;
  391. DPF(50, "DestroyAllGraphs");
  392. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  393. pDeviceNode->lstGraphNode.DestroyList();
  394. } END_EACH_LIST_ITEM
  395. }
  396. //---------------------------------------------------------------------------