[MMSYS] Add the speaker volume dialog.
[reactos.git] / dll / cpl / mmsys / mmsys.c
1 /*
2 *
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>
8 * UPDATE HISTORY:
9 * 2005/11/23 Created
10 */
11
12 #include "mmsys.h"
13
14 #include <winsvc.h>
15 #include <shlwapi.h>
16 #include <debug.h>
17
18 #include <swenum.h>
19 #include <newdev.h>
20 #include <initguid.h>
21 #include <devguid.h>
22
23 typedef enum
24 {
25 HWPD_STANDARDLIST = 0,
26 HWPD_LARGELIST,
27 HWPD_MAX = HWPD_LARGELIST
28 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
29
30 typedef struct
31 {
32 LPWSTR LabelName;
33 LPWSTR DefaultName;
34 UINT LocalizedResId;
35 LPWSTR FileName;
36 }EVENT_LABEL_ITEM;
37
38 typedef struct
39 {
40 LPWSTR LabelName;
41 LPWSTR DefaultName;
42 UINT IconId;
43 }SYSTEM_SCHEME_ITEM;
44
45 static EVENT_LABEL_ITEM EventLabels[] =
46 {
47 {
48 L"WindowsLogon",
49 L"ReactOS Logon",
50 IDS_REACTOS_LOGON,
51 L"ReactOS_Logon.wav"
52 },
53 {
54 L"WindowsLogoff",
55 L"ReactOS Logoff",
56 IDS_REACTOS_LOGOFF,
57 L"ReactOS_Logoff.wav"
58 },
59 {
60 NULL,
61 NULL,
62 0,
63 NULL
64 }
65 };
66
67 static SYSTEM_SCHEME_ITEM SystemSchemes[] =
68 {
69 {
70 L".Default",
71 L"ReactOS Standard",
72 IDS_REACTOS_DEFAULT_SCHEME
73 },
74 {
75 L".None",
76 L"No Sounds",
77 -1
78 },
79 {
80 NULL,
81 NULL
82 }
83 };
84
85
86 HWND WINAPI
87 DeviceCreateHardwarePageEx(HWND hWndParent,
88 LPGUID lpGuids,
89 UINT uNumberOfGuids,
90 HWPAGE_DISPLAYMODE DisplayMode);
91
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
97 );
98
99 #define UPDATEDRIVERFORPLUGANDPLAYDEVICES "UpdateDriverForPlugAndPlayDevicesW"
100 #define NUM_APPLETS (1)
101
102
103 HINSTANCE hApplet = 0;
104
105 /* Applets */
106 const APPLET Applets[NUM_APPLETS] =
107 {
108 {IDI_CPLICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, MmSysApplet},
109 };
110
111
112 HRESULT WINAPI
113 DllCanUnloadNow(VOID)
114 {
115 DPRINT1("DllCanUnloadNow() stubs\n");
116 return S_OK;
117 }
118
119 HRESULT WINAPI
120 DllGetClassObject(REFCLSID rclsid,
121 REFIID riid,
122 LPVOID *ppv)
123 {
124 DPRINT1("DllGetClassObject() stubs\n");
125 return S_OK;
126 }
127
128
129 VOID WINAPI
130 ShowDriverSettingsAfterForkW(HWND hwnd,
131 HINSTANCE hInstance,
132 LPWSTR lpszCmd,
133 int nCmdShow)
134 {
135 DPRINT1("ShowDriverSettingsAfterForkW() stubs\n");
136 }
137
138 VOID WINAPI
139 ShowDriverSettingsAfterForkA(HWND hwnd,
140 HINSTANCE hInstance,
141 LPSTR lpszCmd,
142 int nCmdShow)
143 {
144 DPRINT1("ShowDriverSettingsAfterForkA() stubs\n");
145 }
146
147 VOID WINAPI
148 ShowDriverSettingsAfterFork(HWND hwnd,
149 HINSTANCE hInstance,
150 LPSTR lpszCmd,
151 int nCmdShow)
152 {
153 DPRINT1("ShowDriverSettingsAfterFork() stubs\n");
154 }
155
156 BOOL WINAPI
157 ShowMMCPLPropertySheet(HWND hwnd,
158 LPCSTR pszPropSheet,
159 LPSTR pszName,
160 LPSTR pszCaption)
161 {
162 DPRINT1("ShowMMCPLPropertySheet() stubs\n");
163 return TRUE;
164 }
165
166 VOID WINAPI
167 ShowAudioPropertySheet(HWND hwnd,
168 HINSTANCE hInstance,
169 LPTSTR lpszCmd,
170 int nCmdShow)
171 {
172 DPRINT1("ShowAudioPropertySheet() stubs\n");
173 }
174
175 VOID WINAPI
176 mmseRunOnceW(HWND hwnd,
177 HINSTANCE hInstance,
178 LPWSTR lpszCmd,
179 int nCmdShow)
180 {
181 DPRINT1("mmseRunOnceW() stubs\n");
182 }
183
184 VOID WINAPI
185 mmseRunOnceA(HWND hwnd,
186 HINSTANCE hInstance,
187 LPSTR lpszCmd,
188 int nCmdShow)
189 {
190 DPRINT1("mmseRunOnceA() stubs\n");
191 }
192
193 VOID WINAPI
194 mmseRunOnce(HWND hwnd,
195 HINSTANCE hInstance,
196 LPSTR lpszCmd,
197 int nCmdShow)
198 {
199 DPRINT1("mmseRunOnce() stubs\n");
200 }
201
202 BOOL WINAPI
203 MediaPropPageProvider(LPVOID Info,
204 LPFNADDPROPSHEETPAGE PropSheetPage,
205 LPARAM lParam)
206 {
207 DPRINT1("MediaPropPageProvider() stubs\n");
208 return TRUE;
209 }
210
211 VOID WINAPI
212 ShowFullControlPanel(HWND hwnd,
213 HINSTANCE hInstance,
214 LPSTR lpszCmd,
215 int nCmdShow)
216 {
217 DPRINT1("ShowFullControlPanel() stubs\n");
218 }
219
220 VOID
221 InstallSystemSoundLabels(HKEY hKey)
222 {
223 UINT i = 0;
224 HKEY hSubKey;
225 WCHAR Buffer[40];
226
227 do
228 {
229 if (RegCreateKeyExW(hKey, EventLabels[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
230 {
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));
234
235 RegCloseKey(hSubKey);
236 }
237 i++;
238 }while(EventLabels[i].LabelName);
239 }
240
241 VOID
242 InstallSystemSoundSchemeNames(HKEY hKey)
243 {
244 UINT i = 0;
245 HKEY hSubKey;
246
247 do
248 {
249 if (RegCreateKeyExW(hKey, SystemSchemes[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
250 {
251 RegSetValueExW(hSubKey, NULL, 0, REG_SZ, (LPBYTE)SystemSchemes[i].DefaultName, (wcslen(SystemSchemes[i].DefaultName)+1) * sizeof(WCHAR));
252 RegCloseKey(hSubKey);
253 }
254 i++;
255 }while(SystemSchemes[i].LabelName);
256 }
257
258 VOID
259 InstallDefaultSystemSoundScheme(HKEY hRootKey)
260 {
261 HKEY hKey, hSubKey;
262 WCHAR Path[MAX_PATH];
263 UINT i = 0;
264
265 if (RegCreateKeyExW(hRootKey, L".Default", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
266 return;
267
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));
271
272 do
273 {
274 if (RegCreateKeyExW(hKey, EventLabels[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
275 {
276 HKEY hScheme;
277
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)
280 {
281 RegSetValueExW(hScheme, NULL, 0, REG_EXPAND_SZ, (LPBYTE)Path, (wcslen(Path)+1) * sizeof(WCHAR));
282 RegCloseKey(hScheme);
283 }
284
285 if (RegCreateKeyExW(hSubKey, L".Default", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hScheme, NULL) == ERROR_SUCCESS)
286 {
287 RegSetValueExW(hScheme, NULL, 0, REG_EXPAND_SZ, (LPBYTE)Path, (wcslen(Path)+1) * sizeof(WCHAR));
288 RegCloseKey(hScheme);
289 }
290 RegCloseKey(hSubKey);
291 }
292 i++;
293 }while(EventLabels[i].LabelName);
294
295 RegCloseKey(hKey);
296 }
297
298
299 VOID
300 InstallSystemSoundScheme()
301 {
302 HKEY hKey, hSubKey;
303 DWORD dwDisposition;
304
305 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"AppEvents", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
306 return;
307
308 if (RegCreateKeyExW(hKey, L"EventLabels", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
309 {
310 InstallSystemSoundLabels(hSubKey);
311 RegCloseKey(hSubKey);
312 }
313
314 if (RegCreateKeyExW(hKey, L"Schemes", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisposition) == ERROR_SUCCESS)
315 {
316 HKEY hNames;
317
318 if (RegCreateKeyExW(hSubKey, L"Names", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hNames, NULL) == ERROR_SUCCESS)
319 {
320 InstallSystemSoundSchemeNames(hNames);
321 RegCloseKey(hNames);
322 }
323
324 if (RegCreateKeyExW(hSubKey, L"Apps", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hNames, NULL) == ERROR_SUCCESS)
325 {
326 InstallDefaultSystemSoundScheme(hNames);
327 RegCloseKey(hNames);
328 if (dwDisposition & REG_CREATED_NEW_KEY)
329 {
330 // FIXME
331 RegSetValueExW(hSubKey, NULL, 0, REG_SZ, (LPBYTE)L".Default", (wcslen(L".Default")+1) * sizeof(WCHAR));
332 }
333 }
334
335 RegCloseKey(hSubKey);
336 }
337
338 RegCloseKey(hKey);
339 }
340
341 BOOL
342 IsSoftwareBusPnpEnumeratorInstalled()
343 {
344 HDEVINFO hDevInfo;
345 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
346 GUID SWBusGuid = {STATIC_BUSID_SoftwareDeviceEnumerator};
347 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
348
349 hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
350 if (!hDevInfo)
351 {
352 // failed
353 return FALSE;
354 }
355
356 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
357 if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
358 {
359 // failed
360 SetupDiDestroyDeviceInfoList(hDevInfo);
361 return FALSE;
362 }
363
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)
366 {
367 // failed
368 SetupDiDestroyDeviceInfoList(hDevInfo);
369 return FALSE;
370 }
371
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))
374 {
375 // failed
376 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
377 SetupDiDestroyDeviceInfoList(hDevInfo);
378 return FALSE;
379 }
380 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
381 SetupDiDestroyDeviceInfoList(hDevInfo);
382 return TRUE;
383 }
384
385 DWORD
386 InstallSoftwareBusPnpEnumerator(LPWSTR InfPath, LPCWSTR HardwareIdList)
387 {
388 HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
389 SP_DEVINFO_DATA DeviceInfoData;
390 GUID ClassGUID;
391 TCHAR ClassName[50];
392 int Result = 0;
393 HMODULE hModule = NULL;
394 UpdateDriverForPlugAndPlayDevicesProto UpdateProc;
395 BOOL reboot = FALSE;
396 DWORD flags = 0;
397
398 if (!SetupDiGetINFClass(InfPath,&ClassGUID,ClassName,sizeof(ClassName)/sizeof(ClassName[0]),0))
399 {
400 return -1;
401 }
402
403 DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0);
404 if(DeviceInfoSet == INVALID_HANDLE_VALUE)
405 {
406 return -1;
407 }
408
409 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
410 if (!SetupDiCreateDeviceInfo(DeviceInfoSet, ClassName, &ClassGUID, NULL, 0, DICD_GENERATE_ID, &DeviceInfoData))
411 {
412 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
413 return -1;
414 }
415
416 if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)HardwareIdList, (lstrlen(HardwareIdList)+1+1)*sizeof(TCHAR)))
417 {
418 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
419 return -1;
420 }
421
422 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData))
423 {
424 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
425 return -1;
426 }
427
428 if(GetFileAttributes(InfPath)==(DWORD)(-1)) {
429 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
430 return -1;
431 }
432
433 flags |= INSTALLFLAG_FORCE;
434 hModule = LoadLibraryW(L"newdev.dll");
435 if(!hModule) {
436 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
437 return -1;
438 }
439
440 UpdateProc = (UpdateDriverForPlugAndPlayDevicesProto)GetProcAddress(hModule,UPDATEDRIVERFORPLUGANDPLAYDEVICES);
441 if(!UpdateProc)
442 {
443 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
444 FreeLibrary(hModule);
445 return -1;
446 }
447
448 if(!UpdateProc(NULL, HardwareIdList, InfPath, flags, &reboot))
449 {
450 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
451 FreeLibrary(hModule);
452 return -1;
453 }
454
455 FreeLibrary(hModule);
456 SetupDiDestroyDeviceInfoList(DeviceInfoSet);
457 return Result;
458 }
459
460 DWORD
461 MMSYS_InstallDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
462 {
463 UINT Length;
464 LPWSTR pBuffer;
465 WCHAR szBuffer[MAX_PATH];
466 HINF hInf;
467 PVOID Context;
468 BOOL Result;
469 SC_HANDLE hSCManager, hService;
470 WCHAR WaveName[20];
471 HKEY hKey;
472 DWORD BufferSize;
473 ULONG Index;
474
475 if (!IsEqualIID(&pspDevInfoData->ClassGuid, &GUID_DEVCLASS_SOUND) &&
476 !IsEqualIID(&pspDevInfoData->ClassGuid, &GUID_DEVCLASS_MEDIA))
477 return ERROR_DI_DO_DEFAULT;
478
479 Length = GetWindowsDirectoryW(szBuffer, MAX_PATH);
480 if (!Length || Length >= MAX_PATH - 14)
481 {
482 return ERROR_GEN_FAILURE;
483 }
484
485 pBuffer = PathAddBackslashW(szBuffer);
486 if (!pBuffer)
487 {
488 return ERROR_GEN_FAILURE;
489 }
490
491 wcscpy(pBuffer, L"inf\\audio.inf");
492
493 hInf = SetupOpenInfFileW(szBuffer,
494 NULL,
495 INF_STYLE_WIN4,
496 NULL);
497
498 if (hInf == INVALID_HANDLE_VALUE)
499 {
500 return ERROR_GEN_FAILURE;
501 }
502
503 Context = SetupInitDefaultQueueCallback(NULL);
504 if (Context == NULL)
505 {
506 SetupCloseInfFile(hInf);
507 return ERROR_GEN_FAILURE;
508 }
509
510 Result = SetupInstallFromInfSectionW(NULL,
511 hInf,
512 L"AUDIO_Inst.NT",
513 SPINST_ALL,
514 NULL,
515 NULL,
516 SP_COPY_NEWER,
517 SetupDefaultQueueCallbackW,
518 Context,
519 NULL,
520 NULL);
521
522 if (Result)
523 {
524 Result = SetupInstallServicesFromInfSectionW(hInf,
525 L"Audio_Inst.NT.Services",
526 0);
527 }
528
529 SetupTermDefaultQueueCallback(Context);
530 SetupCloseInfFile(hInf);
531
532 if (!IsSoftwareBusPnpEnumeratorInstalled())
533 {
534 Length = GetWindowsDirectoryW(szBuffer, MAX_PATH);
535 if (!Length || Length >= MAX_PATH - 14)
536 {
537 return ERROR_GEN_FAILURE;
538 }
539
540 pBuffer = PathAddBackslashW(szBuffer);
541 if (!pBuffer)
542 {
543 return ERROR_GEN_FAILURE;
544 }
545
546 wcscpy(pBuffer, L"inf\\machine.inf");
547 InstallSoftwareBusPnpEnumerator(szBuffer, L"ROOT\\SWENUM\0");
548 }
549
550 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
551 if (!hSCManager)
552 {
553 return ERROR_DI_DO_DEFAULT;
554 }
555
556 hService = OpenService(hSCManager, L"RosAudioSrv", SERVICE_ALL_ACCESS);
557 if (hService)
558 {
559 /* Make RosAudioSrv start automatically */
560 ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
561
562 StartService(hService, 0, NULL);
563 CloseServiceHandle(hService);
564 }
565 CloseServiceHandle(hSCManager);
566
567 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32", 0, GENERIC_READ | GENERIC_WRITE, &hKey) == ERROR_SUCCESS)
568 {
569 szBuffer[Length] = '\0';
570 pBuffer = PathAddBackslashW(szBuffer);
571 wcscpy(pBuffer, L"system32\\wdmaud.drv");
572
573 for(Index = 1; Index <= 4; Index++)
574 {
575 swprintf(WaveName, L"wave%u", Index);
576 if (RegQueryValueExW(hKey, WaveName, 0, NULL, NULL, &BufferSize) != ERROR_MORE_DATA)
577 {
578 /* Store new audio driver entry */
579 RegSetValueExW(hKey, WaveName, 0, REG_SZ, (LPBYTE)szBuffer, (wcslen(szBuffer)+1) * sizeof(WCHAR));
580 break;
581 }
582 else
583 {
584 WCHAR Buffer[MAX_PATH];
585 BufferSize = sizeof(Buffer);
586
587 if (RegQueryValueExW(hKey, WaveName, 0, NULL, (LPBYTE)Buffer, &BufferSize) == ERROR_SUCCESS)
588 {
589 /* Make sure the buffer is zero terminated */
590 Buffer[MAX_PATH-1] = L'\0';
591
592 if (!wcsicmp(Buffer, szBuffer))
593 {
594 /* An entry already exists */
595 break;
596 }
597 }
598 }
599 }
600 RegCloseKey(hKey);
601 }
602 InstallSystemSoundScheme();
603
604 return ERROR_DI_DO_DEFAULT;
605
606 }
607
608 DWORD
609 MMSYS_RemoveDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
610 {
611 return ERROR_DI_DO_DEFAULT;
612 }
613
614 DWORD
615 MMSYS_AllowInstallDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
616 {
617 return ERROR_DI_DO_DEFAULT;
618 }
619
620 DWORD
621 MMSYS_SelectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
622 {
623 return ERROR_DI_DO_DEFAULT;
624 }
625
626 DWORD
627 MMSYS_DetectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
628 {
629 return ERROR_DI_DO_DEFAULT;
630 }
631
632 DWORD
633 MMSYS_SelectBestCompatDRV(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
634 {
635 return ERROR_DI_DO_DEFAULT;
636 }
637
638 DWORD WINAPI
639 MediaClassInstaller(IN DI_FUNCTION diFunction,
640 IN HDEVINFO hDevInfo,
641 IN PSP_DEVINFO_DATA pspDevInfoData OPTIONAL)
642 {
643 switch (diFunction)
644 {
645 case DIF_INSTALLDEVICE:
646 return MMSYS_InstallDevice(hDevInfo, pspDevInfoData);
647 case DIF_REMOVE:
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);
653 case DIF_DETECT:
654 return MMSYS_DetectDevice(hDevInfo, pspDevInfoData);
655 case DIF_SELECTBESTCOMPATDRV:
656 return MMSYS_SelectBestCompatDRV(hDevInfo, pspDevInfoData);
657 default:
658 return ERROR_DI_DO_DEFAULT;
659 }
660 }
661
662
663 /* Hardware property page dialog callback */
664 static INT_PTR CALLBACK
665 HardwareDlgProc(HWND hwndDlg,
666 UINT uMsg,
667 WPARAM wParam,
668 LPARAM lParam)
669 {
670 UNREFERENCED_PARAMETER(lParam);
671 UNREFERENCED_PARAMETER(wParam);
672 switch(uMsg)
673 {
674 case WM_INITDIALOG:
675 {
676 GUID Guids[2];
677 Guids[0] = GUID_DEVCLASS_CDROM;
678 Guids[1] = GUID_DEVCLASS_MEDIA;
679
680 /* Create the hardware page */
681 DeviceCreateHardwarePageEx(hwndDlg,
682 Guids,
683 sizeof(Guids) / sizeof(Guids[0]),
684 HWPD_LARGELIST);
685 break;
686 }
687 }
688
689 return FALSE;
690 }
691
692 static int CALLBACK
693 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
694 {
695 // NOTE: This callback is needed to set large icon correctly.
696 HICON hIcon;
697 switch (uMsg)
698 {
699 case PSCB_INITIALIZED:
700 {
701 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDI_CPLICON));
702 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
703 break;
704 }
705 }
706 return 0;
707 }
708
709 LONG APIENTRY
710 MmSysApplet(HWND hwnd,
711 UINT uMsg,
712 LPARAM wParam,
713 LPARAM lParam)
714 {
715 PROPSHEETPAGE psp[5];
716 PROPSHEETHEADER psh; // = { 0 };
717 TCHAR Caption[256];
718
719 UNREFERENCED_PARAMETER(lParam);
720 UNREFERENCED_PARAMETER(wParam);
721 UNREFERENCED_PARAMETER(uMsg);
722
723 LoadString(hApplet, IDS_CPLNAME, Caption, _countof(Caption));
724
725 psh.dwSize = sizeof(PROPSHEETHEADER);
726 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK;
727 psh.hwndParent = hwnd;
728 psh.hInstance = hApplet;
729 psh.pszIcon = MAKEINTRESOURCEW(IDI_CPLICON);
730 psh.pszCaption = Caption;
731 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
732 psh.nStartPage = 0;
733 psh.ppsp = psp;
734 psh.pfnCallback = PropSheetProc;
735
736 InitPropSheetPage(&psp[0], IDD_VOLUME,VolumeDlgProc, 0);
737 InitPropSheetPage(&psp[1], IDD_SOUNDS,SoundsDlgProc, 0);
738 InitPropSheetPage(&psp[2], IDD_AUDIO,AudioDlgProc, 0);
739 InitPropSheetPage(&psp[3], IDD_VOICE,VoiceDlgProc, 0);
740 InitPropSheetPage(&psp[4], IDD_HARDWARE,HardwareDlgProc, 0);
741
742 return (LONG)(PropertySheet(&psh) != -1);
743 }
744
745 VOID
746 InitPropSheetPage(PROPSHEETPAGE *psp,
747 WORD idDlg,
748 DLGPROC DlgProc,
749 LPARAM lParam)
750 {
751 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
752 psp->dwSize = sizeof(PROPSHEETPAGE);
753 psp->dwFlags = PSP_DEFAULT;
754 psp->hInstance = hApplet;
755 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
756 psp->pfnDlgProc = DlgProc;
757 psp->lParam = lParam;
758 }
759
760
761 /* Control Panel Callback */
762 LONG CALLBACK
763 CPlApplet(HWND hwndCpl,
764 UINT uMsg,
765 LPARAM lParam1,
766 LPARAM lParam2)
767 {
768 switch(uMsg)
769 {
770 case CPL_INIT:
771 return TRUE;
772
773 case CPL_GETCOUNT:
774 return NUM_APPLETS;
775
776 case CPL_INQUIRE:
777 {
778 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
779 UINT uAppIndex = (UINT)lParam1;
780
781 CPlInfo->lData = 0;
782 CPlInfo->idIcon = Applets[uAppIndex].idIcon;
783 CPlInfo->idName = Applets[uAppIndex].idName;
784 CPlInfo->idInfo = Applets[uAppIndex].idDescription;
785 break;
786 }
787
788 case CPL_DBLCLK:
789 {
790 UINT uAppIndex = (UINT)lParam1;
791 Applets[uAppIndex].AppletProc(hwndCpl,
792 uMsg,
793 lParam1,
794 lParam2);
795 break;
796 }
797 }
798
799 return FALSE;
800 }
801
802
803 BOOL WINAPI
804 DllMain(HINSTANCE hinstDLL,
805 DWORD dwReason,
806 LPVOID lpReserved)
807 {
808 UNREFERENCED_PARAMETER(lpReserved);
809 switch(dwReason)
810 {
811 case DLL_PROCESS_ATTACH:
812 hApplet = hinstDLL;
813 DisableThreadLibraryCalls(hinstDLL);
814 break;
815 }
816
817 return TRUE;
818 }