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.

657 lines
24 KiB

  1. /********************************************************************************
  2. ** Copyright (c) 1999-2000 Microsoft Corporation. All Rights Reserved.
  3. ********************************************************************************/
  4. #include <windows.h>
  5. #include <devioctl.h>
  6. #include <ks.h>
  7. #include <ksmedia.h>
  8. #include <setupapi.h>
  9. #include "resource.h"
  10. #include "prvprop.h"
  11. HINSTANCE ghInstance;
  12. #if (DBG)
  13. /////////////////////////////////////////////////////////////////////////////////
  14. // dbgError
  15. /////////////////////////////////////////////////////////////////////////////////
  16. // This function prints an error message.
  17. // It prints first the string passed and then the error that it gets with
  18. // GetLastError as a string.
  19. //
  20. // Arguments:
  21. // szMsg - message to print.
  22. //
  23. // Return Value:
  24. // None.
  25. void dbgError (LPCTSTR szMsg)
  26. {
  27. LPTSTR errorMessage;
  28. DWORD count;
  29. // Get the error message from the system.
  30. count = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
  31. FORMAT_MESSAGE_FROM_SYSTEM |
  32. FORMAT_MESSAGE_IGNORE_INSERTS,
  33. NULL,
  34. GetLastError (),
  35. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  36. (LPTSTR)&errorMessage,
  37. 0,
  38. NULL);
  39. // Print the msg + error + \n\r.
  40. if (count)
  41. {
  42. OutputDebugString (szMsg);
  43. OutputDebugString (errorMessage);
  44. OutputDebugString (TEXT("\n\r"));
  45. // This is for those without a debugger.
  46. // MessageBox (NULL, szErrorMessage, szMsg, MB_OK | MB_ICONSTOP);
  47. LocalFree (errorMessage);
  48. }
  49. else
  50. {
  51. OutputDebugString (TEXT("AC97 Property Page"));
  52. OutputDebugString (TEXT(": Low memory condition. Cannot ")
  53. TEXT("print error message.\n\r"));
  54. }
  55. }
  56. #else
  57. #define dbgError(a) 0;
  58. #endif
  59. /////////////////////////////////////////////////////////////////////////////////
  60. // DllMain
  61. /////////////////////////////////////////////////////////////////////////////////
  62. // Main enty point of the DLL.
  63. // We safe only the instance handle that we need for the creation of the
  64. // property sheet. There is nothing else to do.
  65. //
  66. // Arguments:
  67. // hModule - instance data, is equal to module handle
  68. // ul_reason_for_call - the reason for the call
  69. // lpReserved - some additional parameter.
  70. //
  71. // Return Value:
  72. // BOOL: FALSE if DLL should fail, TRUE on success
  73. BOOL APIENTRY DllMain
  74. (
  75. HANDLE hModule,
  76. DWORD ul_reason_for_call,
  77. LPVOID lpReserved
  78. )
  79. {
  80. ghInstance = (HINSTANCE) hModule;
  81. return TRUE;
  82. }
  83. /////////////////////////////////////////////////////////////////////////////////
  84. // SetDlgControls
  85. /////////////////////////////////////////////////////////////////////////////////
  86. // This function gets called when the property sheet page gets created by
  87. // "AC97PropPage_OnInitDialog". It initializes the different dialog controls that
  88. // get displayed.
  89. // By default all dlg items are set to "Yes", so we only change to "No" if it
  90. // applies.
  91. //
  92. //
  93. // Arguments:
  94. // hWnd - handle to the dialog window
  95. // pAC97Features - pointer to AC97Features structure
  96. //
  97. // Return Value:
  98. // None.
  99. void SetDlgControls (HWND hWnd, tAC97Features *pAC97Features)
  100. {
  101. const TCHAR No[4] = TEXT("No");
  102. const TCHAR NA[4] = TEXT("N/A");
  103. // DAC or ADC resolution
  104. const TCHAR R18[4] = TEXT("18");
  105. const TCHAR R20[4] = TEXT("20");
  106. // The different 3D Technologies.
  107. const TCHAR T[][40] = {TEXT("No 3D Stereo Enhancement"), TEXT("Analog Devices Phat Stereo"),
  108. TEXT("Creative Stereo Enhancement"), TEXT("National Semi 3D Stereo Enhancement"),
  109. TEXT("Yamaha Ymersion"), TEXT("BBE 3D Stereo Enhancement"),
  110. TEXT("Crystal Semi 3D Stereo Enhancement"), TEXT("Qsound QXpander"),
  111. TEXT("Spatializer 3D Stereo Enhancement"), TEXT("SRS 3D Stereo Enhancement"),
  112. TEXT("Platform Tech 3D Stereo Enhancement"), TEXT("AKM 3D Audio"),
  113. TEXT("Aureal Stereo Enhancement"), TEXT("Aztech 3D Enhancement"),
  114. TEXT("Binaura 3D Audio Enhancement"), TEXT("ESS Technology (stereo enhancement)"),
  115. TEXT("Harman International VMAx"), TEXT("Nvidea 3D Stereo Enhancement"),
  116. TEXT("Philips Incredible Sound"), TEXT("Texas Instrument 3D Stereo Enhancement"),
  117. TEXT("VLSI Technology 3D Stereo Enhancement"), TEXT("TriTech 3D Stereo Enhancement"),
  118. TEXT("Realtek 3D Stereo Enhancement"), TEXT("Samsung 3D Stereo Enhancement"),
  119. TEXT("Wolfson Microelectronics 3D Enhancement"), TEXT("Delta Integration 3D Enhancement"),
  120. TEXT("SigmaTel 3D Enhancement"), TEXT("Rockwell 3D Stereo Enhancement"),
  121. TEXT("Unknown"), TEXT("Unknown"), TEXT("Unknown"), TEXT("Unknown")};
  122. //
  123. // Set the Volume information.
  124. //
  125. if (hWnd == NULL)
  126. return;
  127. // Set the Yes/No flags.
  128. if (pAC97Features->MasterVolume == Volume5bit)
  129. SetWindowText (GetDlgItem (hWnd, IDC_6BIT_MASTER_OUT), No);
  130. if (pAC97Features->HeadphoneVolume == Volume5bit)
  131. SetWindowText (GetDlgItem (hWnd, IDC_6BIT_HEADPHONE), No);
  132. if (pAC97Features->MonoOutVolume == Volume5bit)
  133. SetWindowText (GetDlgItem (hWnd, IDC_6BIT_MONO_OUT), No);
  134. // Evtl disable controls if they are not there.
  135. if (pAC97Features->HeadphoneVolume == VolumeDisabled)
  136. {
  137. SetWindowText (GetDlgItem (hWnd, IDC_6BIT_HEADPHONE), NA);
  138. EnableWindow (GetDlgItem (hWnd, IDC_6BIT_HEADPHONE), FALSE);
  139. EnableWindow (GetDlgItem (hWnd, IDC_HEADPHONE_TEXT), FALSE);
  140. }
  141. if (pAC97Features->MonoOutVolume == VolumeDisabled)
  142. {
  143. SetWindowText (GetDlgItem (hWnd, IDC_6BIT_MONO_OUT), NA);
  144. EnableWindow (GetDlgItem (hWnd, IDC_6BIT_MONO_OUT), FALSE);
  145. EnableWindow (GetDlgItem (hWnd, IDC_MONOOUT_TEXT), FALSE);
  146. }
  147. //
  148. // Set the ConverterResolution. The fields are set be default to "16".
  149. //
  150. if (pAC97Features->DAC == Resolution18bit)
  151. SetWindowText (GetDlgItem (hWnd, IDC_DAC_RESOLUTION), R18);
  152. else if (pAC97Features->DAC == Resolution20bit)
  153. SetWindowText (GetDlgItem (hWnd, IDC_DAC_RESOLUTION), R20);
  154. if (pAC97Features->ADC == Resolution18bit)
  155. SetWindowText (GetDlgItem (hWnd, IDC_ADC_RESOLUTION), R18);
  156. else if (pAC97Features->ADC == Resolution20bit)
  157. SetWindowText (GetDlgItem (hWnd, IDC_ADC_RESOLUTION), R20);
  158. //
  159. // Set the 3D Technique.
  160. //
  161. SetWindowText (GetDlgItem (hWnd, IDC_3D_TECHNIQUE), T[pAC97Features->n3DTechnique & 0x1F]);
  162. // Evtl. disable the text box ...
  163. if (pAC97Features->n3DTechnique == 0)
  164. {
  165. EnableWindow (GetDlgItem (hWnd, IDC_3D_TECHNIQUE), FALSE);
  166. EnableWindow (GetDlgItem (hWnd, IDC_3D_TECHNIQUE_BOX), FALSE);
  167. }
  168. //
  169. // Set the variable sample rate support. Set to "Yes" by default.
  170. //
  171. if (!pAC97Features->bVSRPCM)
  172. SetWindowText (GetDlgItem (hWnd, IDC_VSR_PCM), No);
  173. if (!pAC97Features->bDSRPCM)
  174. SetWindowText (GetDlgItem (hWnd, IDC_DSR_PCM), No);
  175. if (!pAC97Features->bVSRMIC)
  176. SetWindowText (GetDlgItem (hWnd, IDC_VSR_MIC), No);
  177. // Evtl. disable MicIn sample rate text.
  178. if (!pAC97Features->bMicInPresent)
  179. {
  180. SetWindowText (GetDlgItem (hWnd, IDC_VSR_MIC), NA);
  181. EnableWindow (GetDlgItem (hWnd, IDC_VSR_MIC), FALSE);
  182. EnableWindow (GetDlgItem (hWnd, IDC_VSRMIC_TEXT), FALSE);
  183. }
  184. //
  185. // Set the additional DACs support. Default is "Yes".
  186. //
  187. if (!pAC97Features->bCenterDAC)
  188. SetWindowText (GetDlgItem (hWnd, IDC_CENTER_DAC), No);
  189. if (!pAC97Features->bSurroundDAC)
  190. SetWindowText (GetDlgItem (hWnd, IDC_SURROUND_DAC), No);
  191. if (!pAC97Features->bLFEDAC)
  192. SetWindowText (GetDlgItem (hWnd, IDC_LFE_DAC), No);
  193. }
  194. /////////////////////////////////////////////////////////////////////////////////
  195. // AC97PropPage_OnInitDialog
  196. /////////////////////////////////////////////////////////////////////////////////
  197. // This function gets called when the property sheet page gets created. This
  198. // is the perfect opportunity to initialize the dialog items that get displayed.
  199. //
  200. // Arguments:
  201. // ParentHwnd - handle to the dialog window
  202. // FocusHwnd - handle to the control that would get the focus.
  203. // lParam - initialization parameter (pAC97Features).
  204. //
  205. // Return Value:
  206. // TRUE if focus should be set to FocusHwnd, FALSE if you set the focus yourself.
  207. BOOL AC97PropPage_OnInitDialog (HWND ParentHwnd, HWND FocusHwnd, LPARAM lParam)
  208. {
  209. tAC97Features *pAC97Features;
  210. HCURSOR hCursor;
  211. // Check the parameters (lParam is tAC97Features pointer)
  212. if (!lParam)
  213. return FALSE;
  214. // put up the wait cursor
  215. hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  216. pAC97Features = (tAC97Features *)((LPPROPSHEETPAGE)lParam)->lParam;
  217. SetDlgControls (ParentHwnd, pAC97Features);
  218. // We don't need the private structure anymore.
  219. LocalFree (pAC97Features);
  220. // remove the wait cursor
  221. SetCursor(hCursor);
  222. return TRUE;
  223. }
  224. /////////////////////////////////////////////////////////////////////////////////
  225. // AC97DlgProc
  226. /////////////////////////////////////////////////////////////////////////////////
  227. // This callback function gets called by the system whenever something happens
  228. // with the dialog sheet. Please take a look at the SDK for further information
  229. // on dialog messages.
  230. //
  231. // Arguments:
  232. // hDlg - handle to the dialog window
  233. // uMessage - the message
  234. // wParam - depending on message sent
  235. // lParam - depending on message sent
  236. //
  237. // Return Value:
  238. // int (depends on message).
  239. INT_PTR APIENTRY AC97DlgProc (HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  240. {
  241. switch (uMessage)
  242. {
  243. // We don't do anything for these messages.
  244. case WM_COMMAND:
  245. case WM_CONTEXTMENU:
  246. case WM_HELP:
  247. case WM_NOTIFY:
  248. case WM_DESTROY:
  249. break;
  250. case WM_INITDIALOG:
  251. return AC97PropPage_OnInitDialog (hDlg, (HWND) wParam, lParam);
  252. }
  253. return FALSE;
  254. }
  255. #ifdef PROPERTY_SHOW_SET
  256. /////////////////////////////////////////////////////////////////////////////////
  257. // AC97ShowSet
  258. /////////////////////////////////////////////////////////////////////////////////
  259. // This function gets called by the property page provider (in this module) to
  260. // show how we could set properties in the driver. Note that this is only an
  261. // example and doesn't really do anything useful.
  262. // We pass down a DWORD and the driver will simply print this DWORD out on the
  263. // debugger.
  264. //
  265. // Arguments:
  266. // pDeviceInterfaceDetailData - device interface details (path to device driver)
  267. //
  268. // Return Value:
  269. // None (we don't care).
  270. void AC97ShowSet (PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData)
  271. {
  272. HANDLE hTopology;
  273. KSPROPERTY AC97Property;
  274. ULONG ulBytesReturned;
  275. BOOL fSuccess;
  276. DWORD dwData;
  277. // Open the topology filter.
  278. hTopology = CreateFile (pDeviceInterfaceDetailData->DevicePath,
  279. GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  280. NULL, OPEN_EXISTING, 0, NULL);
  281. // Check for error.
  282. if (hTopology == INVALID_HANDLE_VALUE)
  283. {
  284. dbgError (TEXT("AC97ShowSet: CreateFile: "));
  285. return;
  286. }
  287. // Set the dword to something random.
  288. dwData = GetTickCount ();
  289. // Prepare the property structure sent down.
  290. AC97Property.Set = KSPROPSETID_Private;
  291. AC97Property.Flags = KSPROPERTY_TYPE_SET;
  292. AC97Property.Id = KSPROPERTY_AC97_SAMPLE_SET;
  293. // Make the final call.
  294. fSuccess = DeviceIoControl (hTopology, IOCTL_KS_PROPERTY,
  295. &AC97Property, sizeof (AC97Property),
  296. &dwData, sizeof (dwData),
  297. &ulBytesReturned, NULL);
  298. // We don't need the handle anymore.
  299. CloseHandle (hTopology);
  300. // Check for error.
  301. if (!fSuccess)
  302. {
  303. dbgError (TEXT("AC97ShowSet: DeviceIoControl: "));
  304. }
  305. return; // We don't care about the return value.
  306. }
  307. #endif
  308. /////////////////////////////////////////////////////////////////////////////////
  309. // GetAC97Features
  310. /////////////////////////////////////////////////////////////////////////////////
  311. // This function gets called by the property page provider (in this module) to
  312. // get all the AC97 features that are normally not displayed by the drivers.
  313. // To get the AC97Features structure we pass down the private property. As you
  314. // can see this is fairly easy.
  315. //
  316. // Arguments:
  317. // pDeviceInterfaceDetailData - device interface details (path to device driver)
  318. // pAC97Features - pointer to AC97 features structure.
  319. //
  320. // Return Value:
  321. // BOOL: FALSE if we couldn't get the information, TRUE on success.
  322. BOOL GetAC97Features (PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData,
  323. tAC97Features *pAC97Features)
  324. {
  325. HANDLE hTopology;
  326. KSPROPERTY AC97Property;
  327. ULONG ulBytesReturned;
  328. BOOL fSuccess;
  329. // Open the topology filter.
  330. hTopology = CreateFile (pDeviceInterfaceDetailData->DevicePath,
  331. GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  332. NULL, OPEN_EXISTING, 0, NULL);
  333. // Check for error.
  334. if (hTopology == INVALID_HANDLE_VALUE)
  335. {
  336. dbgError (TEXT("GetAC97Features: CreateFile: "));
  337. return FALSE;
  338. }
  339. // Fill the KSPROPERTY structure.
  340. AC97Property.Set = KSPROPSETID_Private;
  341. AC97Property.Flags = KSPROPERTY_TYPE_GET;
  342. AC97Property.Id = KSPROPERTY_AC97_FEATURES;
  343. fSuccess = DeviceIoControl (hTopology, IOCTL_KS_PROPERTY,
  344. &AC97Property, sizeof (AC97Property),
  345. pAC97Features, sizeof (tAC97Features),
  346. &ulBytesReturned, NULL);
  347. // We don't need the handle anymore.
  348. CloseHandle (hTopology);
  349. // Check for error.
  350. if (!fSuccess)
  351. {
  352. dbgError (TEXT("GetAC97Features: DeviceIoControl: "));
  353. return FALSE;
  354. }
  355. return TRUE;
  356. }
  357. /////////////////////////////////////////////////////////////////////////////////
  358. // GetDeviceInterfaceDetail
  359. /////////////////////////////////////////////////////////////////////////////////
  360. // This function gets called by the property page provider (in this module) to
  361. // get the device interface details. The device interface detail contains a
  362. // path to the device driver that can be used to open the device driver.
  363. // When we parse the driver we look for the topology interface since this
  364. // interface exposes the private property.
  365. //
  366. // Arguments:
  367. // pPropPageRequest - points to SP_PROPSHEETPAGE_REQUEST
  368. // pDeviceInterfaceDetailData - device interface details returned.
  369. //
  370. // Return Value:
  371. // BOOL: FALSE if something went wrong, TRUE on success.
  372. BOOL GetDeviceInterfaceDetail (PSP_PROPSHEETPAGE_REQUEST pPropPageRequest,
  373. PSP_DEVICE_INTERFACE_DETAIL_DATA *ppDeviceInterfaceDetailData)
  374. {
  375. BOOL fSuccess;
  376. ULONG ulDeviceInstanceIdSize = 0;
  377. PTSTR pDeviceInstanceID = NULL;
  378. HDEVINFO hDevInfoWithInterface;
  379. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  380. ULONG ulDeviceInterfaceDetailDataSize = 0;
  381. // Get the device instance id (PnP string). The first call will retrieve
  382. // the buffer length in characters. fSuccess will be FALSE.
  383. fSuccess = SetupDiGetDeviceInstanceId (pPropPageRequest->DeviceInfoSet,
  384. pPropPageRequest->DeviceInfoData,
  385. NULL,
  386. 0,
  387. &ulDeviceInstanceIdSize);
  388. // Check for error.
  389. if ((GetLastError () != ERROR_INSUFFICIENT_BUFFER) || (!ulDeviceInstanceIdSize))
  390. {
  391. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiGetDeviceInstanceId: "));
  392. return FALSE;
  393. }
  394. // Allocate the buffer for the device instance ID (PnP string).
  395. pDeviceInstanceID = (PTSTR)LocalAlloc (LPTR, ulDeviceInstanceIdSize * sizeof (TCHAR));
  396. if (!pDeviceInstanceID)
  397. {
  398. dbgError (TEXT("GetDeviceInterfaceDetail: LocalAlloc: "));
  399. return FALSE;
  400. }
  401. // Now call again, this time with all parameters.
  402. fSuccess = SetupDiGetDeviceInstanceId (pPropPageRequest->DeviceInfoSet,
  403. pPropPageRequest->DeviceInfoData,
  404. pDeviceInstanceID,
  405. ulDeviceInstanceIdSize,
  406. NULL);
  407. // Check for error.
  408. if (!fSuccess)
  409. {
  410. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiGetDeviceInstanceId: "));
  411. LocalFree (pDeviceInstanceID);
  412. return FALSE;
  413. }
  414. // Now we can get the handle to the dev info with interface.
  415. // We parse the device specifically for topology interfaces.
  416. hDevInfoWithInterface = SetupDiGetClassDevs (&KSCATEGORY_TOPOLOGY,
  417. pDeviceInstanceID,
  418. NULL,
  419. DIGCF_DEVICEINTERFACE);
  420. // We don't need pDeviceInstanceID anymore.
  421. LocalFree (pDeviceInstanceID);
  422. // Check for error.
  423. if (hDevInfoWithInterface == INVALID_HANDLE_VALUE)
  424. {
  425. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiGetClassDevs: "));
  426. return FALSE;
  427. }
  428. // Go through the list of topology device interface of this device.
  429. // We assume that there is only one topology device interface and
  430. // we will store the device details in our private structure.
  431. DeviceInterfaceData.cbSize = sizeof (DeviceInterfaceData);
  432. fSuccess = SetupDiEnumDeviceInterfaces (hDevInfoWithInterface,
  433. NULL,
  434. &KSCATEGORY_TOPOLOGY,
  435. 0,
  436. &DeviceInterfaceData);
  437. // Check for error.
  438. if (!fSuccess)
  439. {
  440. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiEnumDeviceInterfaces: "));
  441. SetupDiDestroyDeviceInfoList (hDevInfoWithInterface);
  442. return FALSE;
  443. }
  444. // Get the details for this device interface. The first call will retrieve
  445. // the buffer length in characters. fSuccess will be FALSE.
  446. fSuccess = SetupDiGetDeviceInterfaceDetail (hDevInfoWithInterface,
  447. &DeviceInterfaceData,
  448. NULL,
  449. 0,
  450. &ulDeviceInterfaceDetailDataSize,
  451. NULL);
  452. // Check for error.
  453. if ((GetLastError () != ERROR_INSUFFICIENT_BUFFER) || (!ulDeviceInterfaceDetailDataSize))
  454. {
  455. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiGetDeviceInterfaceDetail: "));
  456. SetupDiDestroyDeviceInfoList (hDevInfoWithInterface);
  457. return FALSE;
  458. }
  459. // Allocate the buffer for the device interface detail data.
  460. if (!(*ppDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
  461. LocalAlloc (LPTR, ulDeviceInterfaceDetailDataSize)))
  462. {
  463. dbgError (TEXT("GetDeviceInterfaceDetail: LocalAlloc: "));
  464. SetupDiDestroyDeviceInfoList (hDevInfoWithInterface);
  465. return FALSE;
  466. }
  467. // The size contains only the structure, not the additional path.
  468. (*ppDeviceInterfaceDetailData)->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
  469. // Get the details for this device interface, this time with all paramters.
  470. fSuccess = SetupDiGetDeviceInterfaceDetail (hDevInfoWithInterface,
  471. &DeviceInterfaceData,
  472. *ppDeviceInterfaceDetailData,
  473. ulDeviceInterfaceDetailDataSize,
  474. NULL,
  475. NULL);
  476. // We don't need the handle anymore.
  477. SetupDiDestroyDeviceInfoList (hDevInfoWithInterface);
  478. if (!fSuccess)
  479. {
  480. dbgError (TEXT("GetDeviceInterfaceDetail: SetupDiGetDeviceInterfaceDetail: "));
  481. LocalFree (*ppDeviceInterfaceDetailData), *ppDeviceInterfaceDetailData = NULL;
  482. return FALSE;
  483. }
  484. return TRUE;
  485. }
  486. /////////////////////////////////////////////////////////////////////////////////
  487. // AC97PropPageProvider
  488. /////////////////////////////////////////////////////////////////////////////////
  489. // This function gets called by the device manager when it asks for additional
  490. // property sheet pages. The parameter fAddFunc is the function that we call to
  491. // add the sheet page to the dialog.
  492. // This routine gets called because the registry entry "EnumPropPage32" tells
  493. // the device manager that there is a dll with a exported function that will add
  494. // a property sheet page.
  495. // Because we want to fail this function (not create the sheet) if the driver
  496. // doesn't support the private property, we have to do all the work here, that
  497. // means we open the device and get all the information, then we close the
  498. // device and return.
  499. //
  500. // Arguments:
  501. // pPropPageRequest - points to SP_PROPSHEETPAGE_REQUEST
  502. // fAddFunc - function ptr to call to add sheet.
  503. // lparam - add sheet functions private data handle.
  504. //
  505. // Return Value:
  506. // BOOL: FALSE if pages could not be added, TRUE on success
  507. BOOL APIENTRY AC97PropPageProvider
  508. (
  509. PSP_PROPSHEETPAGE_REQUEST pPropPageRequest,
  510. LPFNADDPROPSHEETPAGE fAddFunc,
  511. LPARAM lParam
  512. )
  513. {
  514. PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData;
  515. tAC97Features *pAC97Features;
  516. PROPSHEETPAGE PropSheetPage;
  517. HPROPSHEETPAGE hPropSheetPage;
  518. // Check page requested
  519. if (pPropPageRequest->PageRequested != SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
  520. {
  521. return FALSE;
  522. }
  523. // Check device info set and data
  524. if ((!pPropPageRequest->DeviceInfoSet) || (!pPropPageRequest->DeviceInfoData))
  525. {
  526. return FALSE;
  527. }
  528. // Allocate the memory for the AC97 features.
  529. pAC97Features = (tAC97Features *) LocalAlloc (LPTR, sizeof (tAC97Features));
  530. if (!pAC97Features)
  531. {
  532. dbgError (TEXT("AC97PropPageProvider: LocalAlloc: "));
  533. return FALSE;
  534. }
  535. // Get the device interface detail which return a path to the device
  536. // driver that we need to open the device.
  537. if (!GetDeviceInterfaceDetail (pPropPageRequest, &pDeviceInterfaceDetailData))
  538. {
  539. LocalFree (pAC97Features);
  540. return FALSE;
  541. }
  542. // Get the AC97 features through the private property call.
  543. if (!GetAC97Features (pDeviceInterfaceDetailData, pAC97Features))
  544. {
  545. LocalFree (pDeviceInterfaceDetailData);
  546. LocalFree (pAC97Features);
  547. return FALSE;
  548. }
  549. #ifdef PROPERTY_SHOW_SET
  550. // Show how we would set something in the driver
  551. AC97ShowSet (pDeviceInterfaceDetailData);
  552. #endif
  553. // We don't need the device interface details any more, get rid of it now!
  554. LocalFree (pDeviceInterfaceDetailData);
  555. // initialize the property page
  556. PropSheetPage.dwSize = sizeof(PROPSHEETPAGE);
  557. PropSheetPage.dwFlags = 0;
  558. PropSheetPage.hInstance = ghInstance;
  559. PropSheetPage.pszTemplate = MAKEINTRESOURCE(DLG_AC97FEATURES);
  560. PropSheetPage.pfnDlgProc = AC97DlgProc;
  561. PropSheetPage.lParam = (LPARAM)pAC97Features;
  562. PropSheetPage.pfnCallback = NULL;
  563. // create the page and get back a handle
  564. hPropSheetPage = CreatePropertySheetPage (&PropSheetPage);
  565. if (!hPropSheetPage)
  566. {
  567. LocalFree (pAC97Features);
  568. return FALSE;
  569. }
  570. // add the property page
  571. if (!(*fAddFunc)(hPropSheetPage, lParam))
  572. {
  573. DestroyPropertySheetPage (hPropSheetPage);
  574. LocalFree (pAC97Features);
  575. return FALSE;
  576. }
  577. return TRUE;
  578. }