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.

359 lines
7.7 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: registry.c
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Mike McLaughlin
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //
  18. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  19. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  21. // PURPOSE.
  22. //
  23. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  24. //
  25. //---------------------------------------------------------------------------
  26. #include "common.h"
  27. //===========================================================================
  28. //===========================================================================
  29. NTSTATUS
  30. GetRegistryDefault(
  31. PSHINGLE_INSTANCE pShingleInstance,
  32. PDEVICE_NODE *ppDeviceNode
  33. )
  34. {
  35. #ifdef REGISTRY_PREFERRED_DEVICE
  36. PKEY_VALUE_FULL_INFORMATION pkvfi = NULL;
  37. PDEVICE_NODE pDeviceNode;
  38. PGRAPH_NODE pGraphNode;
  39. PWSTR pwstrString = NULL;
  40. PWSTR pwstrPath = NULL;
  41. HANDLE hkey = NULL;
  42. NTSTATUS Status;
  43. if(pShingleInstance->pcwstrRegistryPath == NULL ||
  44. pShingleInstance->pcwstrRegistryValue == NULL) {
  45. goto exit;
  46. }
  47. Status = OpenRegistryKey(pShingleInstance->pcwstrRegistryPath, &hkey);
  48. if(!NT_SUCCESS(Status)) {
  49. goto exit;
  50. }
  51. Status = QueryRegistryValue(
  52. hkey,
  53. pShingleInstance->pcwstrRegistryValue,
  54. &pkvfi);
  55. if(!NT_SUCCESS(Status)) {
  56. goto exit;
  57. }
  58. if(pkvfi->Type != REG_SZ) {
  59. Trap();
  60. goto exit;
  61. }
  62. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  63. Status = pDeviceNode->CreateGraphNodes();
  64. if(!NT_SUCCESS(Status)) {
  65. goto exit;
  66. }
  67. FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
  68. if((pGraphNode->ulFlags ^
  69. pShingleInstance->ulFlags) &
  70. FLAGS_MIXER_TOPOLOGY) {
  71. continue;
  72. }
  73. Status = FindFriendlyName(
  74. pShingleInstance,
  75. ppDeviceNode,
  76. pGraphNode,
  77. (PWSTR)(((PUCHAR)pkvfi) + pkvfi->DataOffset));
  78. if(Status != STATUS_CONTINUE) {
  79. goto exit;
  80. }
  81. } END_EACH_LIST_ITEM
  82. } END_EACH_LIST_ITEM
  83. exit:
  84. delete pkvfi;
  85. delete pwstrPath;
  86. delete pwstrString;
  87. if(hkey != NULL) {
  88. ZwClose(hkey);
  89. }
  90. #endif
  91. return(STATUS_SUCCESS);
  92. }
  93. #ifdef REGISTRY_PREFERRED_DEVICE // this registry code doesn't work under NT
  94. // and isn't needed any more
  95. ENUMFUNC
  96. FindFriendlyName(
  97. PSHINGLE_INSTANCE pShingleInstance,
  98. PDEVICE_NODE *ppDeviceNode,
  99. PGRAPH_NODE pGraphNode,
  100. PWSTR pwstr
  101. )
  102. {
  103. NTSTATUS Status = STATUS_SUCCESS;
  104. PSTART_NODE pStartNode;
  105. ULONG c;
  106. // if "Use any available device" (registry key == empty string)
  107. if(wcslen(pwstr) == 0) {
  108. if((pGraphNode->ulFlags &
  109. pShingleInstance->ulFlags &
  110. GN_FLAGS_PREFERRED_MASK) == 0) {
  111. Status = STATUS_CONTINUE;
  112. goto exit;
  113. }
  114. *ppDeviceNode = pGraphNode->pDeviceNode;
  115. ASSERT(NT_SUCCESS(Status));
  116. goto exit;
  117. }
  118. c = wcslen(pGraphNode->pDeviceNode->GetFriendlyName());
  119. DPF2(100, "FindFriendlyName: %s c: %d",
  120. pGraphNode->pDeviceNode->DumpName(),
  121. c);
  122. //
  123. // The device name from the registry needs to be limited to 32 characters
  124. // (include NULL) because "pwstr" has been trunicated to this by
  125. // wdmaud.sys (the getcap structure passed back to winmm has this limit).
  126. //
  127. if(c >= MAXPNAMELEN) {
  128. c = MAXPNAMELEN - 1; // c doesn't include the NULL
  129. }
  130. if(wcsncmp(pwstr, pGraphNode->pDeviceNode->GetFriendlyName(), c) == 0) {
  131. *ppDeviceNode = pGraphNode->pDeviceNode;
  132. ASSERT(NT_SUCCESS(Status));
  133. goto exit;
  134. }
  135. if(pShingleInstance ==
  136. apShingleInstance[KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT]) {
  137. Status = STATUS_CONTINUE;
  138. goto exit;
  139. }
  140. FOR_EACH_LIST_ITEM(&pGraphNode->lstStartNode, pStartNode) {
  141. PPIN_INFO pPinInfo;
  142. Assert(pStartNode);
  143. Assert(pStartNode->pPinNode);
  144. pPinInfo = pStartNode->pPinNode->pPinInfo;
  145. Assert(pPinInfo);
  146. if(pPinInfo->pwstrName == NULL) {
  147. continue;
  148. }
  149. if(pPinInfo->pguidName != NULL) {
  150. Trap();
  151. continue;
  152. }
  153. if(pPinInfo->pguidCategory == NULL) {
  154. Trap();
  155. continue;
  156. }
  157. if(!IsEqualGUID(
  158. &KSCATEGORY_WDMAUD_USE_PIN_NAME,
  159. pPinInfo->pguidCategory)) {
  160. continue;
  161. }
  162. if(wcsncmp(
  163. pwstr,
  164. pPinInfo->pwstrName,
  165. wcslen(pPinInfo->pwstrName)) == 0) {
  166. Status = GetRegistryDefault(
  167. apShingleInstance[KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT],
  168. ppDeviceNode);
  169. goto exit;
  170. }
  171. } END_EACH_LIST_ITEM
  172. Status = STATUS_CONTINUE;
  173. exit:
  174. return(Status);
  175. }
  176. #endif
  177. #ifndef UNDER_NT
  178. NTSTATUS
  179. GetRegistryPlaybackRecordFormat(
  180. PWAVEFORMATEX pWaveFormatEx,
  181. BOOL fPlayback
  182. )
  183. {
  184. PKEY_VALUE_FULL_INFORMATION pkvfiFormatName = NULL;
  185. PKEY_VALUE_FULL_INFORMATION pkvfiFormat = NULL;
  186. HANDLE hkeyAudio = NULL;
  187. HANDLE hkeyFormats = NULL;
  188. NTSTATUS Status;
  189. Status = OpenRegistryKey(
  190. REGSTR_PATH_MULTIMEDIA_AUDIO,
  191. &hkeyAudio);
  192. if(!NT_SUCCESS(Status)) {
  193. goto exit;
  194. }
  195. Status = QueryRegistryValue(
  196. hkeyAudio,
  197. fPlayback ?
  198. REGSTR_VAL_DEFAULT_PLAYBACK_FORMAT :
  199. REGSTR_VAL_DEFAULT_RECORD_FORMAT,
  200. &pkvfiFormatName);
  201. if(!NT_SUCCESS(Status)) {
  202. goto exit;
  203. }
  204. if(pkvfiFormatName->Type != REG_SZ) {
  205. Trap();
  206. Status = STATUS_INVALID_DEVICE_REQUEST;
  207. goto exit;
  208. }
  209. Status = OpenRegistryKey(
  210. REGSTR_PATH_MULTIMEDIA_AUDIO_FORMATS,
  211. &hkeyFormats);
  212. if(!NT_SUCCESS(Status)) {
  213. Trap();
  214. goto exit;
  215. }
  216. Status = QueryRegistryValue(
  217. hkeyFormats,
  218. (PCWSTR)(((PUCHAR)pkvfiFormatName) + pkvfiFormatName->DataOffset),
  219. &pkvfiFormat);
  220. if(!NT_SUCCESS(Status)) {
  221. Trap();
  222. goto exit;
  223. }
  224. if(pkvfiFormat->Type != REG_BINARY) {
  225. Status = STATUS_INVALID_DEVICE_REQUEST;
  226. goto exit;
  227. }
  228. RtlCopyMemory(
  229. pWaveFormatEx,
  230. ((PUCHAR)pkvfiFormat) + pkvfiFormat->DataOffset,
  231. min(pkvfiFormat->DataLength, sizeof(WAVEFORMATEX)));
  232. DPF3(90, "GetRegistryPlayBackRecordFormat: SR: %d CH: %d BPS %d",
  233. pWaveFormatEx->nSamplesPerSec,
  234. pWaveFormatEx->nChannels,
  235. pWaveFormatEx->wBitsPerSample);
  236. exit:
  237. if(hkeyAudio != NULL) {
  238. ZwClose(hkeyAudio);
  239. }
  240. if(hkeyFormats != NULL) {
  241. ZwClose(hkeyFormats);
  242. }
  243. delete pkvfiFormatName;
  244. delete pkvfiFormat;
  245. return(Status);
  246. }
  247. #endif
  248. NTSTATUS
  249. OpenRegistryKey(
  250. PCWSTR pcwstr,
  251. PHANDLE pHandle,
  252. HANDLE hRootDir
  253. )
  254. {
  255. UNICODE_STRING UnicodeDeviceString;
  256. OBJECT_ATTRIBUTES ObjectAttributes;
  257. RtlInitUnicodeString(&UnicodeDeviceString, pcwstr);
  258. InitializeObjectAttributes(
  259. &ObjectAttributes,
  260. &UnicodeDeviceString,
  261. OBJ_CASE_INSENSITIVE,
  262. hRootDir,
  263. NULL);
  264. return(ZwOpenKey(
  265. pHandle,
  266. KEY_READ | KEY_NOTIFY | KEY_WRITE,
  267. &ObjectAttributes));
  268. }
  269. NTSTATUS
  270. QueryRegistryValue(
  271. HANDLE hkey,
  272. PCWSTR pcwstrValueName,
  273. PKEY_VALUE_FULL_INFORMATION *ppkvfi
  274. )
  275. {
  276. UNICODE_STRING ustrValueName;
  277. NTSTATUS Status;
  278. ULONG cbValue;
  279. *ppkvfi = NULL;
  280. RtlInitUnicodeString(&ustrValueName, pcwstrValueName);
  281. Status = ZwQueryValueKey(
  282. hkey,
  283. &ustrValueName,
  284. KeyValueFullInformation,
  285. NULL,
  286. 0,
  287. &cbValue);
  288. if(Status != STATUS_BUFFER_OVERFLOW &&
  289. Status != STATUS_BUFFER_TOO_SMALL) {
  290. goto exit;
  291. }
  292. *ppkvfi = (PKEY_VALUE_FULL_INFORMATION)new BYTE[cbValue];
  293. if(*ppkvfi == NULL) {
  294. Status = STATUS_INSUFFICIENT_RESOURCES;
  295. goto exit;
  296. }
  297. Status = ZwQueryValueKey(
  298. hkey,
  299. &ustrValueName,
  300. KeyValueFullInformation,
  301. *ppkvfi,
  302. cbValue,
  303. &cbValue);
  304. if(!NT_SUCCESS(Status)) {
  305. delete *ppkvfi;
  306. *ppkvfi = NULL;
  307. goto exit;
  308. }
  309. exit:
  310. return(Status);
  311. }