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