3 * PROJECT: ReactOS Multimedia Control Panel
4 * FILE: dll/cpl/mmsys/mmsys.c
5 * PURPOSE: ReactOS Multimedia Control Panel
6 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
7 * Dmitry Chapyshev <dmitry@reactos.org>
25 HWPD_STANDARDLIST
= 0,
27 HWPD_MAX
= HWPD_LARGELIST
28 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
45 static EVENT_LABEL_ITEM EventLabels
[] =
67 static SYSTEM_SCHEME_ITEM SystemSchemes
[] =
72 IDS_REACTOS_DEFAULT_SCHEME
87 DeviceCreateHardwarePageEx(HWND hWndParent
,
90 HWPAGE_DISPLAYMODE DisplayMode
);
92 typedef BOOL (WINAPI
*UpdateDriverForPlugAndPlayDevicesProto
)(IN OPTIONAL HWND hwndParent
,
93 IN LPCTSTR HardwareId
,
94 IN LPCTSTR FullInfPath
,
95 IN DWORD InstallFlags
,
96 OUT OPTIONAL PBOOL bRebootRequired
99 #define UPDATEDRIVERFORPLUGANDPLAYDEVICES "UpdateDriverForPlugAndPlayDevicesW"
100 #define NUM_APPLETS (1)
103 HINSTANCE hApplet
= 0;
106 const APPLET Applets
[NUM_APPLETS
] =
108 {IDI_CPLICON
, IDS_CPLNAME
, IDS_CPLDESCRIPTION
, MmSysApplet
},
113 DllCanUnloadNow(VOID
)
115 DPRINT1("DllCanUnloadNow() stubs\n");
120 DllGetClassObject(REFCLSID rclsid
,
124 DPRINT1("DllGetClassObject() stubs\n");
130 ShowDriverSettingsAfterForkW(HWND hwnd
,
135 DPRINT1("ShowDriverSettingsAfterForkW() stubs\n");
139 ShowDriverSettingsAfterForkA(HWND hwnd
,
144 DPRINT1("ShowDriverSettingsAfterForkA() stubs\n");
148 ShowDriverSettingsAfterFork(HWND hwnd
,
153 DPRINT1("ShowDriverSettingsAfterFork() stubs\n");
157 ShowMMCPLPropertySheet(HWND hwnd
,
162 DPRINT1("ShowMMCPLPropertySheet() stubs\n");
167 ShowAudioPropertySheet(HWND hwnd
,
172 DPRINT1("ShowAudioPropertySheet() stubs\n");
176 mmseRunOnceW(HWND hwnd
,
181 DPRINT1("mmseRunOnceW() stubs\n");
185 mmseRunOnceA(HWND hwnd
,
190 DPRINT1("mmseRunOnceA() stubs\n");
194 mmseRunOnce(HWND hwnd
,
199 DPRINT1("mmseRunOnce() stubs\n");
203 MediaPropPageProvider(LPVOID Info
,
204 LPFNADDPROPSHEETPAGE PropSheetPage
,
207 DPRINT1("MediaPropPageProvider() stubs\n");
212 ShowFullControlPanel(HWND hwnd
,
217 DPRINT1("ShowFullControlPanel() stubs\n");
221 InstallSystemSoundLabels(HKEY hKey
)
229 if (RegCreateKeyExW(hKey
, EventLabels
[i
].LabelName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
231 RegSetValueExW(hSubKey
, NULL
, 0, REG_SZ
, (LPBYTE
)EventLabels
[i
].DefaultName
, (wcslen(EventLabels
[i
].DefaultName
)+1) * sizeof(WCHAR
));
232 swprintf(Buffer
, L
"@mmsys.cpl,-%u", EventLabels
[i
].LocalizedResId
);
233 RegSetValueExW(hSubKey
, L
"DispFileName", 0, REG_SZ
, (LPBYTE
)Buffer
, (wcslen(Buffer
)+1) * sizeof(WCHAR
));
235 RegCloseKey(hSubKey
);
238 }while(EventLabels
[i
].LabelName
);
242 InstallSystemSoundSchemeNames(HKEY hKey
)
249 if (RegCreateKeyExW(hKey
, SystemSchemes
[i
].LabelName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
251 RegSetValueExW(hSubKey
, NULL
, 0, REG_SZ
, (LPBYTE
)SystemSchemes
[i
].DefaultName
, (wcslen(SystemSchemes
[i
].DefaultName
)+1) * sizeof(WCHAR
));
252 RegCloseKey(hSubKey
);
255 }while(SystemSchemes
[i
].LabelName
);
259 InstallDefaultSystemSoundScheme(HKEY hRootKey
)
262 WCHAR Path
[MAX_PATH
];
265 if (RegCreateKeyExW(hRootKey
, L
".Default", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
268 RegSetValueExW(hKey
, NULL
, 0, REG_SZ
, (LPBYTE
)SystemSchemes
[0].DefaultName
, (wcslen(SystemSchemes
[0].DefaultName
)+1) * sizeof(WCHAR
));
269 swprintf(Path
, L
"@mmsys.cpl,-%u", SystemSchemes
[0].IconId
);
270 RegSetValueExW(hKey
, L
"DispFileName", 0, REG_SZ
, (LPBYTE
)Path
, (wcslen(Path
)+1) * sizeof(WCHAR
));
274 if (RegCreateKeyExW(hKey
, EventLabels
[i
].LabelName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
278 swprintf(Path
, L
"%%SystemRoot%%\\media\\%s", EventLabels
[i
].FileName
);
279 if (RegCreateKeyExW(hSubKey
, L
".Current", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hScheme
, NULL
) == ERROR_SUCCESS
)
281 RegSetValueExW(hScheme
, NULL
, 0, REG_EXPAND_SZ
, (LPBYTE
)Path
, (wcslen(Path
)+1) * sizeof(WCHAR
));
282 RegCloseKey(hScheme
);
285 if (RegCreateKeyExW(hSubKey
, L
".Default", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hScheme
, NULL
) == ERROR_SUCCESS
)
287 RegSetValueExW(hScheme
, NULL
, 0, REG_EXPAND_SZ
, (LPBYTE
)Path
, (wcslen(Path
)+1) * sizeof(WCHAR
));
288 RegCloseKey(hScheme
);
290 RegCloseKey(hSubKey
);
293 }while(EventLabels
[i
].LabelName
);
300 InstallSystemSoundScheme()
305 if (RegCreateKeyExW(HKEY_CURRENT_USER
, L
"AppEvents", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
308 if (RegCreateKeyExW(hKey
, L
"EventLabels", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
310 InstallSystemSoundLabels(hSubKey
);
311 RegCloseKey(hSubKey
);
314 if (RegCreateKeyExW(hKey
, L
"Schemes", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hSubKey
, &dwDisposition
) == ERROR_SUCCESS
)
318 if (RegCreateKeyExW(hSubKey
, L
"Names", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hNames
, NULL
) == ERROR_SUCCESS
)
320 InstallSystemSoundSchemeNames(hNames
);
324 if (RegCreateKeyExW(hSubKey
, L
"Apps", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hNames
, NULL
) == ERROR_SUCCESS
)
326 InstallDefaultSystemSoundScheme(hNames
);
328 if (dwDisposition
& REG_CREATED_NEW_KEY
)
331 RegSetValueExW(hSubKey
, NULL
, 0, REG_SZ
, (LPBYTE
)L
".Default", (wcslen(L
".Default")+1) * sizeof(WCHAR
));
335 RegCloseKey(hSubKey
);
342 IsSoftwareBusPnpEnumeratorInstalled()
345 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData
;
346 GUID SWBusGuid
= {STATIC_BUSID_SoftwareDeviceEnumerator
};
347 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
;
349 hDevInfo
= SetupDiGetClassDevsW(&SWBusGuid
, NULL
, NULL
, DIGCF_DEVICEINTERFACE
| DIGCF_PRESENT
);
356 DeviceInterfaceData
.cbSize
= sizeof(SP_DEVICE_INTERFACE_DATA
);
357 if (!SetupDiEnumDeviceInterfaces(hDevInfo
, NULL
, &SWBusGuid
, 0, &DeviceInterfaceData
))
360 SetupDiDestroyDeviceInfoList(hDevInfo
);
364 DeviceInterfaceDetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
));
365 if (!DeviceInterfaceDetailData
)
368 SetupDiDestroyDeviceInfoList(hDevInfo
);
372 DeviceInterfaceDetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
373 if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo
, &DeviceInterfaceData
, DeviceInterfaceDetailData
,MAX_PATH
* sizeof(WCHAR
) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
), NULL
, NULL
))
376 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData
);
377 SetupDiDestroyDeviceInfoList(hDevInfo
);
380 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData
);
381 SetupDiDestroyDeviceInfoList(hDevInfo
);
386 InstallSoftwareBusPnpEnumerator(LPWSTR InfPath
, LPCWSTR HardwareIdList
)
388 HDEVINFO DeviceInfoSet
= INVALID_HANDLE_VALUE
;
389 SP_DEVINFO_DATA DeviceInfoData
;
393 HMODULE hModule
= NULL
;
394 UpdateDriverForPlugAndPlayDevicesProto UpdateProc
;
398 if (!SetupDiGetINFClass(InfPath
,&ClassGUID
,ClassName
,sizeof(ClassName
)/sizeof(ClassName
[0]),0))
403 DeviceInfoSet
= SetupDiCreateDeviceInfoList(&ClassGUID
,0);
404 if(DeviceInfoSet
== INVALID_HANDLE_VALUE
)
409 DeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
410 if (!SetupDiCreateDeviceInfo(DeviceInfoSet
, ClassName
, &ClassGUID
, NULL
, 0, DICD_GENERATE_ID
, &DeviceInfoData
))
412 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
416 if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet
, &DeviceInfoData
, SPDRP_HARDWAREID
, (LPBYTE
)HardwareIdList
, (lstrlen(HardwareIdList
)+1+1)*sizeof(TCHAR
)))
418 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
422 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE
, DeviceInfoSet
, &DeviceInfoData
))
424 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
428 if(GetFileAttributes(InfPath
)==(DWORD
)(-1)) {
429 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
433 flags
|= INSTALLFLAG_FORCE
;
434 hModule
= LoadLibraryW(L
"newdev.dll");
436 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
440 UpdateProc
= (UpdateDriverForPlugAndPlayDevicesProto
)GetProcAddress(hModule
,UPDATEDRIVERFORPLUGANDPLAYDEVICES
);
443 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
444 FreeLibrary(hModule
);
448 if(!UpdateProc(NULL
, HardwareIdList
, InfPath
, flags
, &reboot
))
450 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
451 FreeLibrary(hModule
);
455 FreeLibrary(hModule
);
456 SetupDiDestroyDeviceInfoList(DeviceInfoSet
);
461 MMSYS_InstallDevice(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
465 WCHAR szBuffer
[MAX_PATH
];
469 SC_HANDLE hSCManager
, hService
;
475 if (!IsEqualIID(&pspDevInfoData
->ClassGuid
, &GUID_DEVCLASS_SOUND
) &&
476 !IsEqualIID(&pspDevInfoData
->ClassGuid
, &GUID_DEVCLASS_MEDIA
))
477 return ERROR_DI_DO_DEFAULT
;
479 Length
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
480 if (!Length
|| Length
>= MAX_PATH
- 14)
482 return ERROR_GEN_FAILURE
;
485 pBuffer
= PathAddBackslashW(szBuffer
);
488 return ERROR_GEN_FAILURE
;
491 wcscpy(pBuffer
, L
"inf\\audio.inf");
493 hInf
= SetupOpenInfFileW(szBuffer
,
498 if (hInf
== INVALID_HANDLE_VALUE
)
500 return ERROR_GEN_FAILURE
;
503 Context
= SetupInitDefaultQueueCallback(NULL
);
506 SetupCloseInfFile(hInf
);
507 return ERROR_GEN_FAILURE
;
510 Result
= SetupInstallFromInfSectionW(NULL
,
517 SetupDefaultQueueCallbackW
,
524 Result
= SetupInstallServicesFromInfSectionW(hInf
,
525 L
"Audio_Inst.NT.Services",
529 SetupTermDefaultQueueCallback(Context
);
530 SetupCloseInfFile(hInf
);
532 if (!IsSoftwareBusPnpEnumeratorInstalled())
534 Length
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
535 if (!Length
|| Length
>= MAX_PATH
- 14)
537 return ERROR_GEN_FAILURE
;
540 pBuffer
= PathAddBackslashW(szBuffer
);
543 return ERROR_GEN_FAILURE
;
546 wcscpy(pBuffer
, L
"inf\\machine.inf");
547 InstallSoftwareBusPnpEnumerator(szBuffer
, L
"ROOT\\SWENUM\0");
550 hSCManager
= OpenSCManager(NULL
, NULL
, SC_MANAGER_CONNECT
);
553 return ERROR_DI_DO_DEFAULT
;
556 hService
= OpenService(hSCManager
, L
"RosAudioSrv", SERVICE_ALL_ACCESS
);
559 /* Make RosAudioSrv start automatically */
560 ChangeServiceConfig(hService
, SERVICE_NO_CHANGE
, SERVICE_AUTO_START
, SERVICE_NO_CHANGE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
562 StartService(hService
, 0, NULL
);
563 CloseServiceHandle(hService
);
565 CloseServiceHandle(hSCManager
);
567 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32", 0, GENERIC_READ
| GENERIC_WRITE
, &hKey
) == ERROR_SUCCESS
)
569 szBuffer
[Length
] = '\0';
570 pBuffer
= PathAddBackslashW(szBuffer
);
571 wcscpy(pBuffer
, L
"system32\\wdmaud.drv");
573 for(Index
= 1; Index
<= 4; Index
++)
575 swprintf(WaveName
, L
"wave%u", Index
);
576 if (RegQueryValueExW(hKey
, WaveName
, 0, NULL
, NULL
, &BufferSize
) != ERROR_MORE_DATA
)
578 /* Store new audio driver entry */
579 RegSetValueExW(hKey
, WaveName
, 0, REG_SZ
, (LPBYTE
)szBuffer
, (wcslen(szBuffer
)+1) * sizeof(WCHAR
));
584 WCHAR Buffer
[MAX_PATH
];
585 BufferSize
= sizeof(Buffer
);
587 if (RegQueryValueExW(hKey
, WaveName
, 0, NULL
, (LPBYTE
)Buffer
, &BufferSize
) == ERROR_SUCCESS
)
589 /* Make sure the buffer is zero terminated */
590 Buffer
[MAX_PATH
-1] = L
'\0';
592 if (!wcsicmp(Buffer
, szBuffer
))
594 /* An entry already exists */
602 InstallSystemSoundScheme();
604 return ERROR_DI_DO_DEFAULT
;
609 MMSYS_RemoveDevice(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
611 return ERROR_DI_DO_DEFAULT
;
615 MMSYS_AllowInstallDevice(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
617 return ERROR_DI_DO_DEFAULT
;
621 MMSYS_SelectDevice(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
623 return ERROR_DI_DO_DEFAULT
;
627 MMSYS_DetectDevice(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
629 return ERROR_DI_DO_DEFAULT
;
633 MMSYS_SelectBestCompatDRV(HDEVINFO hDevInfo
, PSP_DEVINFO_DATA pspDevInfoData
)
635 return ERROR_DI_DO_DEFAULT
;
639 MediaClassInstaller(IN DI_FUNCTION diFunction
,
640 IN HDEVINFO hDevInfo
,
641 IN PSP_DEVINFO_DATA pspDevInfoData OPTIONAL
)
645 case DIF_INSTALLDEVICE
:
646 return MMSYS_InstallDevice(hDevInfo
, pspDevInfoData
);
648 return MMSYS_RemoveDevice(hDevInfo
, pspDevInfoData
);
649 case DIF_ALLOW_INSTALL
:
650 return MMSYS_AllowInstallDevice(hDevInfo
, pspDevInfoData
);
651 case DIF_SELECTDEVICE
:
652 return MMSYS_SelectDevice(hDevInfo
, pspDevInfoData
);
654 return MMSYS_DetectDevice(hDevInfo
, pspDevInfoData
);
655 case DIF_SELECTBESTCOMPATDRV
:
656 return MMSYS_SelectBestCompatDRV(hDevInfo
, pspDevInfoData
);
658 return ERROR_DI_DO_DEFAULT
;
663 /* Hardware property page dialog callback */
664 static INT_PTR CALLBACK
665 HardwareDlgProc(HWND hwndDlg
,
670 UNREFERENCED_PARAMETER(lParam
);
671 UNREFERENCED_PARAMETER(wParam
);
677 Guids
[0] = GUID_DEVCLASS_CDROM
;
678 Guids
[1] = GUID_DEVCLASS_MEDIA
;
680 /* Create the hardware page */
681 DeviceCreateHardwarePageEx(hwndDlg
,
683 sizeof(Guids
) / sizeof(Guids
[0]),
693 MmSysApplet(HWND hwnd
,
698 PROPSHEETPAGE psp
[5];
699 PROPSHEETHEADER psh
; // = { 0 };
702 UNREFERENCED_PARAMETER(lParam
);
703 UNREFERENCED_PARAMETER(wParam
);
704 UNREFERENCED_PARAMETER(uMsg
);
706 LoadString(hApplet
, IDS_CPLNAME
, Caption
, _countof(Caption
));
708 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
709 psh
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_PROPTITLE
;
710 psh
.hwndParent
= hwnd
;
711 psh
.hInstance
= hApplet
;
712 psh
.hIcon
= LoadIcon(hApplet
,
713 MAKEINTRESOURCE(IDI_CPLICON
));
714 psh
.pszCaption
= Caption
;
715 psh
.nPages
= sizeof(psp
) / sizeof(PROPSHEETPAGE
);
719 InitPropSheetPage(&psp
[0], IDD_VOLUME
,VolumeDlgProc
);
720 InitPropSheetPage(&psp
[1], IDD_SOUNDS
,SoundsDlgProc
);
721 InitPropSheetPage(&psp
[2], IDD_AUDIO
,AudioDlgProc
);
722 InitPropSheetPage(&psp
[3], IDD_VOICE
,VoiceDlgProc
);
723 InitPropSheetPage(&psp
[4], IDD_HARDWARE
,HardwareDlgProc
);
725 return (LONG
)(PropertySheet(&psh
) != -1);
729 InitPropSheetPage(PROPSHEETPAGE
*psp
,
733 ZeroMemory(psp
, sizeof(PROPSHEETPAGE
));
734 psp
->dwSize
= sizeof(PROPSHEETPAGE
);
735 psp
->dwFlags
= PSP_DEFAULT
;
736 psp
->hInstance
= hApplet
;
737 psp
->pszTemplate
= MAKEINTRESOURCE(idDlg
);
738 psp
->pfnDlgProc
= DlgProc
;
742 /* Control Panel Callback */
744 CPlApplet(HWND hwndCpl
,
759 CPLINFO
*CPlInfo
= (CPLINFO
*)lParam2
;
760 UINT uAppIndex
= (UINT
)lParam1
;
763 CPlInfo
->idIcon
= Applets
[uAppIndex
].idIcon
;
764 CPlInfo
->idName
= Applets
[uAppIndex
].idName
;
765 CPlInfo
->idInfo
= Applets
[uAppIndex
].idDescription
;
771 UINT uAppIndex
= (UINT
)lParam1
;
772 Applets
[uAppIndex
].AppletProc(hwndCpl
,
785 DllMain(HINSTANCE hinstDLL
,
789 UNREFERENCED_PARAMETER(lpReserved
);
792 case DLL_PROCESS_ATTACH
:
794 DisableThreadLibraryCalls(hinstDLL
);