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.

454 lines
11 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: shi.cpp
  4. //
  5. // Description:
  6. //
  7. // Shingle Instance 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. #include "common.h"
  28. //---------------------------------------------------------------------------
  29. //---------------------------------------------------------------------------
  30. const WCHAR cwstrFilterTypeName[] = KSSTRING_Filter;
  31. const WCHAR cwstrPlaybackShingleName[] = L"PLAYBACK";
  32. const WCHAR cwstrRecordShingleName[] = L"RECORD";
  33. const WCHAR cwstrMidiShingleName[] = L"MIDI";
  34. const WCHAR cwstrMixerShingleName[] = L"MIXER";
  35. #ifdef DEBUG
  36. const WCHAR cwstrPinsShingleName[] = L"PINS";
  37. #endif
  38. PSHINGLE_INSTANCE apShingleInstance[] = {
  39. NULL, // KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT
  40. NULL, // KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT
  41. NULL, // KSPROPERTY_SYSAUDIO_RECORD_DEFAULT
  42. NULL, // KSPROPERTY_SYSAUDIO_MIDI_DEFAULT
  43. NULL, // KSPROPERTY_SYSAUDIO_MIXER_DEFAULT
  44. #ifdef DEBUG
  45. NULL,
  46. #endif
  47. };
  48. ULONG aulFlags[] = {
  49. FLAGS_COMBINE_PINS | GN_FLAGS_PLAYBACK | GN_FLAGS_RECORD | GN_FLAGS_MIDI,
  50. FLAGS_COMBINE_PINS | GN_FLAGS_PLAYBACK,
  51. FLAGS_COMBINE_PINS | GN_FLAGS_RECORD,
  52. FLAGS_COMBINE_PINS | GN_FLAGS_MIDI,
  53. FLAGS_MIXER_TOPOLOGY | GN_FLAGS_PLAYBACK | GN_FLAGS_RECORD | GN_FLAGS_MIDI,
  54. #ifdef DEBUG
  55. GN_FLAGS_PLAYBACK,
  56. #endif
  57. };
  58. PCWSTR apcwstrReference[] = {
  59. cwstrFilterTypeName,
  60. cwstrPlaybackShingleName,
  61. cwstrRecordShingleName,
  62. cwstrMidiShingleName,
  63. cwstrMixerShingleName,
  64. #ifdef DEBUG
  65. cwstrPinsShingleName,
  66. #endif
  67. };
  68. //---------------------------------------------------------------------------
  69. //---------------------------------------------------------------------------
  70. NTSTATUS
  71. CShingleInstance::InitializeShingle(
  72. )
  73. {
  74. NTSTATUS Status = STATUS_SUCCESS;
  75. int i;
  76. for(i = 0; i < SIZEOF_ARRAY(apShingleInstance); i++) {
  77. apShingleInstance[i] = new SHINGLE_INSTANCE(aulFlags[i]);
  78. if(apShingleInstance[i] == NULL) {
  79. Status = STATUS_INSUFFICIENT_RESOURCES;
  80. goto exit;
  81. }
  82. Status = apShingleInstance[i]->CreateCreateItem(apcwstrReference[i]);
  83. if(!NT_SUCCESS(Status)) {
  84. goto exit;
  85. }
  86. }
  87. Status = QueueWorkList(
  88. CShingleInstance::InitializeShingleWorker,
  89. NULL,
  90. NULL);
  91. if(!NT_SUCCESS(Status)) {
  92. goto exit;
  93. }
  94. exit:
  95. if(!NT_SUCCESS(Status)) {
  96. UninitializeShingle();
  97. }
  98. return(Status);
  99. }
  100. VOID
  101. CShingleInstance::UninitializeShingle(
  102. )
  103. {
  104. int i;
  105. for(i = 0; i < SIZEOF_ARRAY(apShingleInstance); i++) {
  106. delete apShingleInstance[i];
  107. apShingleInstance[i] = NULL;
  108. }
  109. }
  110. NTSTATUS
  111. CShingleInstance::InitializeShingleWorker(
  112. PVOID pReference1,
  113. PVOID pReference2
  114. )
  115. {
  116. NTSTATUS Status;
  117. Status = apShingleInstance[KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT]->Create(
  118. NULL,
  119. (LPGUID)&KSCATEGORY_PREFERRED_WAVEOUT_DEVICE);
  120. if(!NT_SUCCESS(Status)) {
  121. goto exit;
  122. }
  123. Status = apShingleInstance[KSPROPERTY_SYSAUDIO_RECORD_DEFAULT]->Create(
  124. NULL,
  125. (LPGUID)&KSCATEGORY_PREFERRED_WAVEIN_DEVICE);
  126. if(!NT_SUCCESS(Status)) {
  127. goto exit;
  128. }
  129. Status = apShingleInstance[KSPROPERTY_SYSAUDIO_MIDI_DEFAULT]->Create(
  130. NULL,
  131. (LPGUID)&KSCATEGORY_PREFERRED_MIDIOUT_DEVICE);
  132. if(!NT_SUCCESS(Status)) {
  133. goto exit;
  134. }
  135. exit:
  136. return(Status);
  137. }
  138. //---------------------------------------------------------------------------
  139. CShingleInstance::CShingleInstance(
  140. ULONG ulFlags
  141. )
  142. {
  143. this->ulFlags = ulFlags;
  144. }
  145. CShingleInstance::~CShingleInstance(
  146. )
  147. {
  148. PKSOBJECT_CREATE_ITEM pCreateItem;
  149. DPF1(60, "~CShingleInstance: %08x", this);
  150. ASSERT(this != NULL);
  151. Assert(this);
  152. DestroyDeviceInterface();
  153. FOR_EACH_LIST_ITEM(&lstCreateItem, pCreateItem) {
  154. DestroyCreateItem(pCreateItem);
  155. } END_EACH_LIST_ITEM
  156. }
  157. NTSTATUS
  158. CShingleInstance::Create(
  159. IN PDEVICE_NODE pDeviceNode,
  160. IN LPGUID pguidClass
  161. )
  162. {
  163. NTSTATUS Status = STATUS_SUCCESS;
  164. static ULONG cShingles = 0;
  165. this->pDeviceNode = pDeviceNode;
  166. //
  167. // SECURITY NOTE: ALPERS
  168. // I am not going to switch to strsafe.h just for this.
  169. // This almost has no risk. cShingles represent the number of
  170. // ShingleInstances that have been created. In order for this to overflow
  171. // cShingles has to be larger than 999999.
  172. //
  173. swprintf(wstrReference, L"SAD%d", cShingles++);
  174. Status = CreateCreateItem(wstrReference);
  175. if(!NT_SUCCESS(Status)) {
  176. goto exit;
  177. }
  178. Status = CreateDeviceInterface(pguidClass, wstrReference);
  179. if(!NT_SUCCESS(Status)) {
  180. goto exit;
  181. }
  182. DPF2(60, "CShingleInstance::Create: %08x DN: %08x", this, pDeviceNode);
  183. exit:
  184. return(Status);
  185. }
  186. NTSTATUS
  187. CShingleInstance::SetDeviceNode(
  188. IN PDEVICE_NODE pDeviceNode
  189. )
  190. {
  191. NTSTATUS Status = STATUS_SUCCESS;
  192. DisableDeviceInterface();
  193. this->pDeviceNode = pDeviceNode;
  194. Status = EnableDeviceInterface();
  195. if(!NT_SUCCESS(Status)) {
  196. goto exit;
  197. }
  198. DPF2(60, "CShingleInstance::SetDeviceNode: %08x DN: %08x",
  199. this,
  200. pDeviceNode);
  201. exit:
  202. return(Status);
  203. }
  204. NTSTATUS
  205. CShingleInstance::CreateCreateItem(
  206. IN PCWSTR pcwstrReference
  207. )
  208. {
  209. PKSOBJECT_CREATE_ITEM pCreateItem = NULL;
  210. NTSTATUS Status = STATUS_SUCCESS;
  211. //
  212. // SECURITY NOTE:
  213. // The new operator allocates memory and fills it with zeros.
  214. // Therefore the SECURITY_DESCRIPTOR of KSOBJECT_CREATE_ITEM will
  215. // be NULL.
  216. // That's OK, because we want to apply default security to this object.
  217. //
  218. pCreateItem = new KSOBJECT_CREATE_ITEM;
  219. if(pCreateItem == NULL) {
  220. Status = STATUS_INSUFFICIENT_RESOURCES;
  221. goto exit;
  222. }
  223. pCreateItem->Create = CFilterInstance::FilterDispatchCreate;
  224. pCreateItem->Context = this;
  225. RtlInitUnicodeString(&pCreateItem->ObjectClass, pcwstrReference);
  226. Status = KsAllocateObjectCreateItem(
  227. gpDeviceInstance->pDeviceHeader,
  228. pCreateItem,
  229. FALSE,
  230. NULL);
  231. if(!NT_SUCCESS(Status)) {
  232. //
  233. // This is used in DestroyCreateItem to determine if it is necessary
  234. // to call KsFreeObjectCreateItem.
  235. //
  236. pCreateItem->ObjectClass.Buffer = NULL;
  237. goto exit;
  238. }
  239. Status = lstCreateItem.AddList(pCreateItem);
  240. if(!NT_SUCCESS(Status)) {
  241. goto exit;
  242. }
  243. DPF3(60, "CSHI::CreateItem SHI %08x CI %08x %s",
  244. this,
  245. pCreateItem,
  246. DbgUnicode2Sz((PWSTR)pcwstrReference));
  247. exit:
  248. if(!NT_SUCCESS(Status)) {
  249. DestroyCreateItem(pCreateItem);
  250. }
  251. return(Status);
  252. }
  253. ENUMFUNC
  254. CShingleInstance::DestroyCreateItem(
  255. IN PKSOBJECT_CREATE_ITEM pCreateItem
  256. )
  257. {
  258. if(pCreateItem != NULL) {
  259. if(pCreateItem->ObjectClass.Buffer != NULL) {
  260. KsFreeObjectCreateItem(
  261. gpDeviceInstance->pDeviceHeader,
  262. &pCreateItem->ObjectClass);
  263. }
  264. delete pCreateItem;
  265. }
  266. return(STATUS_CONTINUE);
  267. }
  268. NTSTATUS
  269. CShingleInstance::CreateDeviceInterface(
  270. IN LPGUID pguidClass,
  271. IN PCWSTR pcwstrReference
  272. )
  273. {
  274. UNICODE_STRING ustrReference;
  275. NTSTATUS Status = STATUS_SUCCESS;
  276. ASSERT(gpDeviceInstance != NULL);
  277. ASSERT(gpDeviceInstance->pPhysicalDeviceObject != NULL);
  278. ASSERT(gpDeviceInstance->pDeviceHeader != NULL);
  279. ASSERT(this->ustrSymbolicLinkName.Buffer == NULL);
  280. RtlInitUnicodeString(&ustrReference, pcwstrReference);
  281. Status = IoRegisterDeviceInterface(
  282. gpDeviceInstance->pPhysicalDeviceObject,
  283. pguidClass,
  284. &ustrReference,
  285. &this->ustrSymbolicLinkName);
  286. if(!NT_SUCCESS(Status)) {
  287. goto exit;
  288. }
  289. Status = EnableDeviceInterface();
  290. if(!NT_SUCCESS(Status)) {
  291. goto exit;
  292. }
  293. DPF3(60, "CSHI::CreateDeviceInterface: %08x %s %s",
  294. this,
  295. DbgGuid2Sz(pguidClass),
  296. DbgUnicode2Sz(this->ustrSymbolicLinkName.Buffer));
  297. exit:
  298. return(Status);
  299. }
  300. NTSTATUS
  301. CShingleInstance::EnableDeviceInterface(
  302. )
  303. {
  304. NTSTATUS Status = STATUS_SUCCESS;
  305. PWSTR pwstrFriendlyName = L"";
  306. UNICODE_STRING ustrValueName;
  307. UNICODE_STRING ustrValue;
  308. HANDLE hkey = NULL;
  309. if(this->ustrSymbolicLinkName.Buffer == NULL) {
  310. ASSERT(NT_SUCCESS(Status));
  311. goto exit;
  312. }
  313. //
  314. // Put the proxy's CLSID in the new device interface
  315. //
  316. Status = IoOpenDeviceInterfaceRegistryKey(
  317. &this->ustrSymbolicLinkName,
  318. STANDARD_RIGHTS_ALL,
  319. &hkey);
  320. if(!NT_SUCCESS(Status)) {
  321. goto exit;
  322. }
  323. RtlInitUnicodeString(&ustrValueName, L"CLSID");
  324. RtlInitUnicodeString(&ustrValue, L"{17CCA71B-ECD7-11D0-B908-00A0C9223196}");
  325. Status = ZwSetValueKey(
  326. hkey,
  327. &ustrValueName,
  328. 0,
  329. REG_SZ,
  330. ustrValue.Buffer,
  331. ustrValue.Length);
  332. if(!NT_SUCCESS(Status)) {
  333. goto exit;
  334. }
  335. //
  336. // Set the friendly name into the new device interface
  337. //
  338. if(pDeviceNode != NULL) {
  339. Assert(pDeviceNode);
  340. if(pDeviceNode->GetFriendlyName() != NULL) {
  341. pwstrFriendlyName = pDeviceNode->GetFriendlyName();
  342. }
  343. else {
  344. DPF(5, "CSHI::EnableDeviceInterface no friendly name");
  345. }
  346. }
  347. RtlInitUnicodeString(&ustrValueName, L"FriendlyName");
  348. Status = ZwSetValueKey(
  349. hkey,
  350. &ustrValueName,
  351. 0,
  352. REG_SZ,
  353. pwstrFriendlyName,
  354. (wcslen(pwstrFriendlyName) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
  355. if(!NT_SUCCESS(Status)) {
  356. goto exit;
  357. }
  358. Status = IoSetDeviceInterfaceState(&this->ustrSymbolicLinkName, TRUE);
  359. if(!NT_SUCCESS(Status)) {
  360. goto exit;
  361. }
  362. DPF2(60, "CSHI::EnableDeviceInterface: %08x %s",
  363. this,
  364. DbgUnicode2Sz(this->ustrSymbolicLinkName.Buffer));
  365. exit:
  366. if(hkey != NULL) {
  367. ZwClose(hkey);
  368. }
  369. return(Status);
  370. }
  371. VOID
  372. CShingleInstance::DisableDeviceInterface(
  373. )
  374. {
  375. Assert(this);
  376. DPF1(60, "CSHI::DisableDeviceInterface %08x", this);
  377. if(this->ustrSymbolicLinkName.Buffer != NULL) {
  378. DPF1(60, "CSHI::DisableDeviceInterface %s",
  379. DbgUnicode2Sz(this->ustrSymbolicLinkName.Buffer));
  380. IoSetDeviceInterfaceState(&this->ustrSymbolicLinkName, FALSE);
  381. }
  382. }
  383. VOID
  384. CShingleInstance::DestroyDeviceInterface(
  385. )
  386. {
  387. DisableDeviceInterface();
  388. RtlFreeUnicodeString(&this->ustrSymbolicLinkName);
  389. this->ustrSymbolicLinkName.Buffer = NULL;
  390. }
  391. //---------------------------------------------------------------------------