1b4c81c44a2cca31519118d367aececd9d0537bd
[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 RegSetValueExW(hKey, WaveName, 0, REG_SZ, (LPBYTE)szBuffer, (wcslen(szBuffer)+1) * sizeof(WCHAR));
439 }
440 }
441 RegCloseKey(hKey);
442 }
443 InstallSystemSoundScheme();
444
445 return ERROR_DI_DO_DEFAULT;
446
447 }
448
449 DWORD
450 MMSYS_RemoveDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
451 {
452 return ERROR_DI_DO_DEFAULT;
453 }
454
455 DWORD
456 MMSYS_AllowInstallDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
457 {
458 return ERROR_DI_DO_DEFAULT;
459 }
460
461 DWORD
462 MMSYS_SelectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
463 {
464 return ERROR_DI_DO_DEFAULT;
465 }
466
467 DWORD
468 MMSYS_DetectDevice(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
469 {
470 return ERROR_DI_DO_DEFAULT;
471 }
472
473 DWORD
474 MMSYS_SelectBestCompatDRV(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData)
475 {
476 return ERROR_DI_DO_DEFAULT;
477 }
478
479 DWORD WINAPI
480 MediaClassInstaller(IN DI_FUNCTION diFunction,
481 IN HDEVINFO hDevInfo,
482 IN PSP_DEVINFO_DATA pspDevInfoData OPTIONAL)
483 {
484 switch (diFunction)
485 {
486 case DIF_INSTALLDEVICE:
487 return MMSYS_InstallDevice(hDevInfo, pspDevInfoData);
488 case DIF_REMOVE:
489 return MMSYS_RemoveDevice(hDevInfo, pspDevInfoData);
490 case DIF_ALLOW_INSTALL:
491 return MMSYS_AllowInstallDevice(hDevInfo, pspDevInfoData);
492 case DIF_SELECTDEVICE:
493 return MMSYS_SelectDevice(hDevInfo, pspDevInfoData);
494 case DIF_DETECT:
495 return MMSYS_DetectDevice(hDevInfo, pspDevInfoData);
496 case DIF_SELECTBESTCOMPATDRV:
497 return MMSYS_SelectBestCompatDRV(hDevInfo, pspDevInfoData);
498 default:
499 return ERROR_DI_DO_DEFAULT;
500 }
501 }
502
503
504 /* Hardware property page dialog callback */
505 static INT_PTR CALLBACK
506 HardwareDlgProc(HWND hwndDlg,
507 UINT uMsg,
508 WPARAM wParam,
509 LPARAM lParam)
510 {
511 UNREFERENCED_PARAMETER(lParam);
512 UNREFERENCED_PARAMETER(wParam);
513 switch(uMsg)
514 {
515 case WM_INITDIALOG:
516 {
517 GUID Guids[2];
518 Guids[0] = GUID_DEVCLASS_CDROM;
519 Guids[1] = GUID_DEVCLASS_MEDIA;
520
521 /* create the hardware page */
522 DeviceCreateHardwarePageEx(hwndDlg,
523 Guids,
524 sizeof(Guids) / sizeof(Guids[0]),
525 HWPD_LARGELIST);
526 break;
527 }
528 }
529
530 return FALSE;
531 }
532
533 LONG APIENTRY
534 MmSysApplet(HWND hwnd,
535 UINT uMsg,
536 LPARAM wParam,
537 LPARAM lParam)
538 {
539 PROPSHEETPAGE psp[5];
540 PROPSHEETHEADER psh; //= {0};
541 TCHAR Caption[256];
542
543 UNREFERENCED_PARAMETER(lParam);
544 UNREFERENCED_PARAMETER(wParam);
545 UNREFERENCED_PARAMETER(uMsg);
546
547 LoadString(hApplet,
548 IDS_CPLNAME,
549 Caption,
550 sizeof(Caption) / sizeof(TCHAR));
551
552 psh.dwSize = sizeof(PROPSHEETHEADER);
553 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
554 psh.hwndParent = hwnd;
555 psh.hInstance = hApplet;
556 psh.hIcon = LoadIcon(hApplet,
557 MAKEINTRESOURCE(IDI_CPLICON));
558 psh.pszCaption = Caption;
559 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
560 psh.nStartPage = 0;
561 psh.ppsp = psp;
562
563 InitPropSheetPage(&psp[0], IDD_VOLUME,VolumeDlgProc);
564 InitPropSheetPage(&psp[1], IDD_SOUNDS,SoundsDlgProc);
565 InitPropSheetPage(&psp[2], IDD_AUDIO,AudioDlgProc);
566 InitPropSheetPage(&psp[3], IDD_VOICE,VoiceDlgProc);
567 InitPropSheetPage(&psp[4], IDD_HARDWARE,HardwareDlgProc);
568
569 return (LONG)(PropertySheet(&psh) != -1);
570 }
571
572 VOID
573 InitPropSheetPage(PROPSHEETPAGE *psp,
574 WORD idDlg,
575 DLGPROC DlgProc)
576 {
577 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
578 psp->dwSize = sizeof(PROPSHEETPAGE);
579 psp->dwFlags = PSP_DEFAULT;
580 psp->hInstance = hApplet;
581 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
582 psp->pfnDlgProc = DlgProc;
583 }
584
585
586 /* Control Panel Callback */
587 LONG CALLBACK
588 CPlApplet(HWND hwndCpl,
589 UINT uMsg,
590 LPARAM lParam1,
591 LPARAM lParam2)
592 {
593 switch(uMsg)
594 {
595 case CPL_INIT:
596 return TRUE;
597
598 case CPL_GETCOUNT:
599 return NUM_APPLETS;
600
601 case CPL_INQUIRE:
602 {
603 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
604 UINT uAppIndex = (UINT)lParam1;
605
606 CPlInfo->lData = 0;
607 CPlInfo->idIcon = Applets[uAppIndex].idIcon;
608 CPlInfo->idName = Applets[uAppIndex].idName;
609 CPlInfo->idInfo = Applets[uAppIndex].idDescription;
610 break;
611 }
612
613 case CPL_DBLCLK:
614 {
615 UINT uAppIndex = (UINT)lParam1;
616 Applets[uAppIndex].AppletProc(hwndCpl,
617 uMsg,
618 lParam1,
619 lParam2);
620 break;
621 }
622 }
623
624 return FALSE;
625 }
626
627
628 BOOL WINAPI
629 DllMain(HINSTANCE hinstDLL,
630 DWORD dwReason,
631 LPVOID lpReserved)
632 {
633 UNREFERENCED_PARAMETER(lpReserved);
634 switch(dwReason)
635 {
636 case DLL_PROCESS_ATTACH:
637 hApplet = hinstDLL;
638 DisableThreadLibraryCalls(hinstDLL);
639 break;
640 }
641
642 return TRUE;
643 }