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