Synchronize with trunk r58457.
[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: Thoams 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 typedef enum
15 {
16 HWPD_STANDARDLIST = 0,
17 HWPD_LARGELIST,
18 HWPD_MAX = HWPD_LARGELIST
19 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
20
21 typedef struct
22 {
23 LPWSTR LabelName;
24 LPWSTR DefaultName;
25 UINT LocalizedResId;
26 LPWSTR FileName;
27 }EVENT_LABEL_ITEM;
28
29 typedef struct
30 {
31 LPWSTR LabelName;
32 LPWSTR DefaultName;
33 UINT IconId;
34 }SYSTEM_SCHEME_ITEM;
35
36 static EVENT_LABEL_ITEM EventLabels[] =
37 {
38 {
39 L"WindowsLogon",
40 L"ReactOS Logon",
41 IDS_REACTOS_LOGON,
42 L"ReactOS_Logon.wav"
43 },
44 {
45 L"WindowsLogoff",
46 L"ReactOS Logoff",
47 IDS_REACTOS_LOGOFF,
48 L"ReactOS_Logoff.wav"
49 },
50 {
51 NULL,
52 NULL,
53 0,
54 NULL
55 }
56 };
57
58 static SYSTEM_SCHEME_ITEM SystemSchemes[] =
59 {
60 {
61 L".Default",
62 L"ReactOS Standard",
63 IDS_REACTOS_DEFAULT_SCHEME
64 },
65 {
66 L".None",
67 L"No Sounds",
68 -1
69 },
70 {
71 NULL,
72 NULL
73 }
74 };
75
76
77 HWND WINAPI
78 DeviceCreateHardwarePageEx(HWND hWndParent,
79 LPGUID lpGuids,
80 UINT uNumberOfGuids,
81 HWPAGE_DISPLAYMODE DisplayMode);
82
83 #define NUM_APPLETS (1)
84
85
86 HINSTANCE hApplet = 0;
87
88 /* Applets */
89 const APPLET Applets[NUM_APPLETS] =
90 {
91 {IDI_CPLICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, MmSysApplet},
92 };
93
94
95 HRESULT WINAPI
96 DllCanUnloadNow(VOID)
97 {
98 DPRINT1("DllCanUnloadNow() stubs\n");
99 return S_OK;
100 }
101
102 HRESULT WINAPI
103 DllGetClassObject(REFCLSID rclsid,
104 REFIID riid,
105 LPVOID *ppv)
106 {
107 DPRINT1("DllGetClassObject() stubs\n");
108 return S_OK;
109 }
110
111
112 VOID WINAPI
113 ShowDriverSettingsAfterForkW(HWND hwnd,
114 HINSTANCE hInstance,
115 LPWSTR lpszCmd,
116 int nCmdShow)
117 {
118 DPRINT1("ShowDriverSettingsAfterForkW() stubs\n");
119 }
120
121 VOID WINAPI
122 ShowDriverSettingsAfterForkA(HWND hwnd,
123 HINSTANCE hInstance,
124 LPSTR lpszCmd,
125 int nCmdShow)
126 {
127 DPRINT1("ShowDriverSettingsAfterForkA() stubs\n");
128 }
129
130 VOID WINAPI
131 ShowDriverSettingsAfterFork(HWND hwnd,
132 HINSTANCE hInstance,
133 LPSTR lpszCmd,
134 int nCmdShow)
135 {
136 DPRINT1("ShowDriverSettingsAfterFork() stubs\n");
137 }
138
139 BOOL WINAPI
140 ShowMMCPLPropertySheet(HWND hwnd,
141 LPCSTR pszPropSheet,
142 LPSTR pszName,
143 LPSTR pszCaption)
144 {
145 DPRINT1("ShowMMCPLPropertySheet() stubs\n");
146 return TRUE;
147 }
148
149 VOID WINAPI
150 ShowAudioPropertySheet(HWND hwnd,
151 HINSTANCE hInstance,
152 LPTSTR lpszCmd,
153 int nCmdShow)
154 {
155 DPRINT1("ShowAudioPropertySheet() stubs\n");
156 }
157
158 VOID WINAPI
159 mmseRunOnceW(HWND hwnd,
160 HINSTANCE hInstance,
161 LPWSTR lpszCmd,
162 int nCmdShow)
163 {
164 DPRINT1("mmseRunOnceW() stubs\n");
165 }
166
167 VOID WINAPI
168 mmseRunOnceA(HWND hwnd,
169 HINSTANCE hInstance,
170 LPSTR lpszCmd,
171 int nCmdShow)
172 {
173 DPRINT1("mmseRunOnceA() stubs\n");
174 }
175
176 VOID WINAPI
177 mmseRunOnce(HWND hwnd,
178 HINSTANCE hInstance,
179 LPSTR lpszCmd,
180 int nCmdShow)
181 {
182 DPRINT1("mmseRunOnce() stubs\n");
183 }
184
185 BOOL WINAPI
186 MediaPropPageProvider(LPVOID Info,
187 LPFNADDPROPSHEETPAGE PropSheetPage,
188 LPARAM lParam)
189 {
190 DPRINT1("MediaPropPageProvider() stubs\n");
191 return TRUE;
192 }
193
194 VOID WINAPI
195 ShowFullControlPanel(HWND hwnd,
196 HINSTANCE hInstance,
197 LPSTR lpszCmd,
198 int nCmdShow)
199 {
200 DPRINT1("ShowFullControlPanel() stubs\n");
201 }
202
203 VOID
204 InstallSystemSoundLabels(HKEY hKey)
205 {
206 UINT i = 0;
207 HKEY hSubKey;
208 WCHAR Buffer[40];
209
210 do
211 {
212 if (RegCreateKeyExW(hKey, EventLabels[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
213 {
214 RegSetValueExW(hSubKey, NULL, 0, REG_SZ, (LPBYTE)EventLabels[i].DefaultName, (wcslen(EventLabels[i].DefaultName)+1) * sizeof(WCHAR));
215 swprintf(Buffer, L"@mmsys.cpl,-%u", EventLabels[i].LocalizedResId);
216 RegSetValueExW(hSubKey, L"DispFileName", 0, REG_SZ, (LPBYTE)Buffer, (wcslen(Buffer)+1) * sizeof(WCHAR));
217
218 RegCloseKey(hSubKey);
219 }
220 i++;
221 }while(EventLabels[i].LabelName);
222 }
223
224 VOID
225 InstallSystemSoundSchemeNames(HKEY hKey)
226 {
227 UINT i = 0;
228 HKEY hSubKey;
229
230 do
231 {
232 if (RegCreateKeyExW(hKey, SystemSchemes[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
233 {
234 RegSetValueExW(hSubKey, NULL, 0, REG_SZ, (LPBYTE)SystemSchemes[i].DefaultName, (wcslen(SystemSchemes[i].DefaultName)+1) * sizeof(WCHAR));
235 RegCloseKey(hSubKey);
236 }
237 i++;
238 }while(SystemSchemes[i].LabelName);
239 }
240
241 VOID
242 InstallDefaultSystemSoundScheme(HKEY hRootKey)
243 {
244 HKEY hKey, hSubKey;
245 WCHAR Path[MAX_PATH];
246 UINT i = 0;
247
248 if (RegCreateKeyExW(hRootKey, L".Default", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
249 return;
250
251 RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)SystemSchemes[0].DefaultName, (wcslen(SystemSchemes[0].DefaultName)+1) * sizeof(WCHAR));
252 swprintf(Path, L"@mmsys.cpl,-%u", SystemSchemes[0].IconId);
253 RegSetValueExW(hKey, L"DispFileName", 0, REG_SZ, (LPBYTE)Path, (wcslen(Path)+1) * sizeof(WCHAR));
254
255 do
256 {
257 if (RegCreateKeyExW(hKey, EventLabels[i].LabelName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
258 {
259 HKEY hScheme;
260
261 swprintf(Path, L"%%SystemRoot%%\\media\\%s", EventLabels[i].FileName);
262 if (RegCreateKeyExW(hSubKey, L".Current", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hScheme, NULL) == ERROR_SUCCESS)
263 {
264 RegSetValueExW(hScheme, NULL, 0, REG_EXPAND_SZ, (LPBYTE)Path, (wcslen(Path)+1) * sizeof(WCHAR));
265 RegCloseKey(hScheme);
266 }
267
268 if (RegCreateKeyExW(hSubKey, L".Default", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hScheme, NULL) == ERROR_SUCCESS)
269 {
270 RegSetValueExW(hScheme, NULL, 0, REG_EXPAND_SZ, (LPBYTE)Path, (wcslen(Path)+1) * sizeof(WCHAR));
271 RegCloseKey(hScheme);
272 }
273 RegCloseKey(hSubKey);
274 }
275 i++;
276 }while(EventLabels[i].LabelName);
277
278 RegCloseKey(hKey);
279 }
280
281
282 VOID
283 InstallSystemSoundScheme()
284 {
285 HKEY hKey, hSubKey;
286 DWORD dwDisposition;
287
288 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"AppEvents", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
289 return;
290
291 if (RegCreateKeyExW(hKey, L"EventLabels", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
292 {
293 InstallSystemSoundLabels(hSubKey);
294 RegCloseKey(hSubKey);
295 }
296
297 if (RegCreateKeyExW(hKey, L"Schemes", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisposition) == ERROR_SUCCESS)
298 {
299 HKEY hNames;
300
301 if (RegCreateKeyExW(hSubKey, L"Names", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hNames, NULL) == ERROR_SUCCESS)
302 {
303 InstallSystemSoundSchemeNames(hNames);
304 RegCloseKey(hNames);
305 }
306
307 if (RegCreateKeyExW(hSubKey, L"Apps", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hNames, NULL) == ERROR_SUCCESS)
308 {
309 InstallDefaultSystemSoundScheme(hNames);
310 RegCloseKey(hNames);
311 if (dwDisposition & REG_CREATED_NEW_KEY)
312 {
313 // FIXME
314 RegSetValueExW(hSubKey, NULL, 0, REG_SZ, (LPBYTE)L".Default", (wcslen(L".Default")+1) * sizeof(WCHAR));
315 }
316 }
317
318 RegCloseKey(hSubKey);
319 }
320
321 RegCloseKey(hKey);
322 }
323
324
325 DWORD
326 MMSYS_InstallDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
327 {
328 UINT Length;
329 LPWSTR pBuffer;
330 WCHAR szBuffer[MAX_PATH];
331 HINF hInf;
332 PVOID Context;
333 BOOL Result;
334 SC_HANDLE hSCManager, hService;
335 WCHAR WaveName[20];
336 HKEY hKey;
337 DWORD BufferSize;
338 ULONG Index;
339
340 if (!IsEqualIID(&pspDevInfoData->ClassGuid, &GUID_DEVCLASS_SOUND) &&
341 !IsEqualIID(&pspDevInfoData->ClassGuid, &GUID_DEVCLASS_MEDIA))
342 return ERROR_DI_DO_DEFAULT;
343
344 Length = GetWindowsDirectoryW(szBuffer, MAX_PATH);
345 if (!Length || Length >= MAX_PATH - 14)
346 {
347 return ERROR_GEN_FAILURE;
348 }
349
350 pBuffer = PathAddBackslashW(szBuffer);
351 if (!pBuffer)
352 {
353 return ERROR_GEN_FAILURE;
354 }
355
356 wcscpy(pBuffer, L"inf\\audio.inf");
357
358 hInf = SetupOpenInfFileW(szBuffer,
359 NULL,
360 INF_STYLE_WIN4,
361 NULL);
362
363 if (hInf == INVALID_HANDLE_VALUE)
364 {
365 return ERROR_GEN_FAILURE;
366 }
367
368 Context = SetupInitDefaultQueueCallback(NULL);
369 if (Context == NULL)
370 {
371 SetupCloseInfFile(hInf);
372 return ERROR_GEN_FAILURE;
373 }
374
375 Result = SetupInstallFromInfSectionW(NULL,
376 hInf,
377 L"AUDIO_Inst.NT",
378 SPINST_ALL,
379 NULL,
380 NULL,
381 SP_COPY_NEWER,
382 SetupDefaultQueueCallbackW,
383 Context,
384 NULL,
385 NULL);
386
387 if (Result)
388 {
389 Result = SetupInstallServicesFromInfSectionW(hInf,
390 L"Audio_Inst.NT.Services",
391 0);
392 }
393
394 SetupTermDefaultQueueCallback(Context);
395 SetupCloseInfFile(hInf);
396
397
398
399 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
400 if (!hSCManager)
401 {
402 return ERROR_DI_DO_DEFAULT;
403 }
404
405 hService = OpenService(hSCManager, L"RosAudioSrv", SERVICE_ALL_ACCESS);
406 if (hService)
407 {
408 /* Make RosAudioSrv start automatically */
409 ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
410
411 StartService(hService, 0, NULL);
412 CloseServiceHandle(hService);
413 }
414 CloseServiceHandle(hSCManager);
415
416 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32", 0, GENERIC_READ | GENERIC_WRITE, &hKey) == ERROR_SUCCESS)
417 {
418 szBuffer[Length] = '\0';
419 pBuffer = PathAddBackslashW(szBuffer);
420 wcscpy(pBuffer, L"system32\\wdmaud.drv");
421
422 for(Index = 1; Index <= 4; Index++)
423 {
424 swprintf(WaveName, L"wave%u", Index);
425 if (RegQueryValueExW(hKey, WaveName, 0, NULL, NULL, &BufferSize) != ERROR_MORE_DATA)
426 {
427 /* Store new audio driver entry */
428 RegSetValueExW(hKey, WaveName, 0, REG_SZ, (LPBYTE)szBuffer, (wcslen(szBuffer)+1) * sizeof(WCHAR));
429 break;
430 }
431 else
432 {
433 WCHAR Buffer[MAX_PATH];
434 BufferSize = sizeof(Buffer);
435
436 if (RegQueryValueExW(hKey, WaveName, 0, NULL, (LPBYTE)Buffer, &BufferSize) == ERROR_SUCCESS)
437 {
438 /* Make sure the buffer is zero terminated */
439 Buffer[MAX_PATH-1] = L'\0';
440
441 if (!wcsicmp(Buffer, szBuffer))
442 {
443 /* An entry already exists */
444 break;
445 }
446 }
447 }
448 }
449 RegCloseKey(hKey);
450 }
451 InstallSystemSoundScheme();
452
453 return ERROR_DI_DO_DEFAULT;
454
455 }
456
457 DWORD
458 MMSYS_RemoveDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
459 {
460 return ERROR_DI_DO_DEFAULT;
461 }
462
463 DWORD
464 MMSYS_AllowInstallDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
465 {
466 return ERROR_DI_DO_DEFAULT;
467 }
468
469 DWORD
470 MMSYS_SelectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
471 {
472 return ERROR_DI_DO_DEFAULT;
473 }
474
475 DWORD
476 MMSYS_DetectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
477 {
478 return ERROR_DI_DO_DEFAULT;
479 }
480
481 DWORD
482 MMSYS_SelectBestCompatDRV(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
483 {
484 return ERROR_DI_DO_DEFAULT;
485 }
486
487 DWORD WINAPI
488 MediaClassInstaller(IN DI_FUNCTION diFunction,
489 IN HDEVINFO hDevInfo,
490 IN PSP_DEVINFO_DATA pspDevInfoData OPTIONAL)
491 {
492 switch (diFunction)
493 {
494 case DIF_INSTALLDEVICE:
495 return MMSYS_InstallDevice(hDevInfo, pspDevInfoData);
496 case DIF_REMOVE:
497 return MMSYS_RemoveDevice(hDevInfo, pspDevInfoData);
498 case DIF_ALLOW_INSTALL:
499 return MMSYS_AllowInstallDevice(hDevInfo, pspDevInfoData);
500 case DIF_SELECTDEVICE:
501 return MMSYS_SelectDevice(hDevInfo, pspDevInfoData);
502 case DIF_DETECT:
503 return MMSYS_DetectDevice(hDevInfo, pspDevInfoData);
504 case DIF_SELECTBESTCOMPATDRV:
505 return MMSYS_SelectBestCompatDRV(hDevInfo, pspDevInfoData);
506 default:
507 return ERROR_DI_DO_DEFAULT;
508 }
509 }
510
511
512 /* Hardware property page dialog callback */
513 static INT_PTR CALLBACK
514 HardwareDlgProc(HWND hwndDlg,
515 UINT uMsg,
516 WPARAM wParam,
517 LPARAM lParam)
518 {
519 UNREFERENCED_PARAMETER(lParam);
520 UNREFERENCED_PARAMETER(wParam);
521 switch(uMsg)
522 {
523 case WM_INITDIALOG:
524 {
525 GUID Guids[2];
526 Guids[0] = GUID_DEVCLASS_CDROM;
527 Guids[1] = GUID_DEVCLASS_MEDIA;
528
529 /* Create the hardware page */
530 DeviceCreateHardwarePageEx(hwndDlg,
531 Guids,
532 sizeof(Guids) / sizeof(Guids[0]),
533 HWPD_LARGELIST);
534 break;
535 }
536 }
537
538 return FALSE;
539 }
540
541 LONG APIENTRY
542 MmSysApplet(HWND hwnd,
543 UINT uMsg,
544 LPARAM wParam,
545 LPARAM lParam)
546 {
547 PROPSHEETPAGE psp[5];
548 PROPSHEETHEADER psh; // = { 0 };
549 TCHAR Caption[256];
550
551 UNREFERENCED_PARAMETER(lParam);
552 UNREFERENCED_PARAMETER(wParam);
553 UNREFERENCED_PARAMETER(uMsg);
554
555 LoadString(hApplet,
556 IDS_CPLNAME,
557 Caption,
558 sizeof(Caption) / sizeof(TCHAR));
559
560 psh.dwSize = sizeof(PROPSHEETHEADER);
561 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
562 psh.hwndParent = hwnd;
563 psh.hInstance = hApplet;
564 psh.hIcon = LoadIcon(hApplet,
565 MAKEINTRESOURCE(IDI_CPLICON));
566 psh.pszCaption = Caption;
567 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
568 psh.nStartPage = 0;
569 psh.ppsp = psp;
570
571 InitPropSheetPage(&psp[0], IDD_VOLUME,VolumeDlgProc);
572 InitPropSheetPage(&psp[1], IDD_SOUNDS,SoundsDlgProc);
573 InitPropSheetPage(&psp[2], IDD_AUDIO,AudioDlgProc);
574 InitPropSheetPage(&psp[3], IDD_VOICE,VoiceDlgProc);
575 InitPropSheetPage(&psp[4], IDD_HARDWARE,HardwareDlgProc);
576
577 return (LONG)(PropertySheet(&psh) != -1);
578 }
579
580 VOID
581 InitPropSheetPage(PROPSHEETPAGE *psp,
582 WORD idDlg,
583 DLGPROC DlgProc)
584 {
585 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
586 psp->dwSize = sizeof(PROPSHEETPAGE);
587 psp->dwFlags = PSP_DEFAULT;
588 psp->hInstance = hApplet;
589 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
590 psp->pfnDlgProc = DlgProc;
591 }
592
593
594 /* Control Panel Callback */
595 LONG CALLBACK
596 CPlApplet(HWND hwndCpl,
597 UINT uMsg,
598 LPARAM lParam1,
599 LPARAM lParam2)
600 {
601 switch(uMsg)
602 {
603 case CPL_INIT:
604 return TRUE;
605
606 case CPL_GETCOUNT:
607 return NUM_APPLETS;
608
609 case CPL_INQUIRE:
610 {
611 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
612 UINT uAppIndex = (UINT)lParam1;
613
614 CPlInfo->lData = 0;
615 CPlInfo->idIcon = Applets[uAppIndex].idIcon;
616 CPlInfo->idName = Applets[uAppIndex].idName;
617 CPlInfo->idInfo = Applets[uAppIndex].idDescription;
618 break;
619 }
620
621 case CPL_DBLCLK:
622 {
623 UINT uAppIndex = (UINT)lParam1;
624 Applets[uAppIndex].AppletProc(hwndCpl,
625 uMsg,
626 lParam1,
627 lParam2);
628 break;
629 }
630 }
631
632 return FALSE;
633 }
634
635
636 BOOL WINAPI
637 DllMain(HINSTANCE hinstDLL,
638 DWORD dwReason,
639 LPVOID lpReserved)
640 {
641 UNREFERENCED_PARAMETER(lpReserved);
642 switch(dwReason)
643 {
644 case DLL_PROCESS_ATTACH:
645 hApplet = hinstDLL;
646 DisableThreadLibraryCalls(hinstDLL);
647 break;
648 }
649
650 return TRUE;
651 }