/**************************************************************************** * * File : multimed.c * * Description : * Top level control panel applet code for multimedia for * Windows NT * * Copyright (c) 1993 Microsoft Corporation * *****************************************************************************/ /***************************************************************************** Design This module contains the code and data (apart from the icons for the 3 applets) to support 3 control panel applets for multi-media : sound - Setting system sounds midimap - Midi mapper drivers - Installation and configuration of installable drivers through installable drivers interface The interface in is as for all control panel applets. This (super) applet returns a number of internal applets to the CPL_GETCOUNT message depending on : waveOutGetNumDevs returns non-zero - then sound is supported. midiOutGetNumDevs returns non-zero or midiInGetNumDevs returns non-zero - then midimap is supported. Interface to sub-applets. For packaging and historical reasons the other applets are separate files : sound - sound.dll midimap - midimap.dll - is also a midi driver drivers - drivers.dll When an applet (which is supported for the current configuration of the system as determined above) is run (and ONLY THEN) via the CPL_DBLCLK message we call LoadLibrary for the (sub) applet and call its entry point (usually a 'cut-down' CplApplet). To do this each sub-applet's icon and string have fixed ids defined in multimed.h. *****************************************************************************/ #include #include #include #include #include "multimed.h" // This applet has been neutered to provide only MIDIMAP.DLL's CPL // interface; the others are now supported by MMSYS.CPL. // // #define EXTRA_APPLETS #ifdef EXTRA_APPLETS enum { SoundsApplet = 0, DriversApplet, MidiMapApplet, ACMApplet, NumberOfApplets }; struct { LPCTSTR AppletFileName; DWORD dwHelpContext; HINSTANCE ActiveHandle; APPLET_PROC AppletEntryPoint; BOOL AppInUse; NEWCPLINFO CplInfo; } AppletInfo[] = { { TEXT("sound.dll"), IDH_CHILD_SND }, { TEXT("drivers.dll"), IDH_CHILD_DRIVERS }, { TEXT("midimap.dll"), IDH_CHILD_MIDI }, { TEXT("msacm32.drv"), 0 } }; // No context for ACM #else enum { MidiMapApplet = 0, NumberOfApplets }; struct { LPCTSTR AppletFileName; DWORD dwHelpContext; HINSTANCE ActiveHandle; APPLET_PROC AppletEntryPoint; BOOL AppInUse; NEWCPLINFO CplInfo; } AppletInfo[] = { { TEXT("midimap.dll"), IDH_CHILD_MIDI } }; #endif int IdMapping[NumberOfApplets]; int TotalApplets; BOOL LoadDataPart(int AppletIndex) { UINT OldErrorMode; LPNEWCPLINFO lpCplInfo; HINSTANCE DataOnlyHandle; OldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); DataOnlyHandle = LoadLibraryEx(AppletInfo[AppletIndex].AppletFileName, NULL, DONT_RESOLVE_DLL_REFERENCES); SetErrorMode(OldErrorMode); if (DataOnlyHandle == NULL) { return FALSE; } /* * Cache all Cpl data now so we're not embarrassed by errors later */ lpCplInfo = &AppletInfo[AppletIndex].CplInfo; lpCplInfo->dwSize = sizeof(NEWCPLINFO); lpCplInfo->lData = 0; // Applets we use expect this lpCplInfo->dwHelpContext = AppletInfo[AppletIndex].dwHelpContext; lpCplInfo->hIcon = LoadIcon(DataOnlyHandle, MAKEINTRESOURCE(ID_ICON)); if (lpCplInfo->hIcon == NULL || !LoadString(DataOnlyHandle, IDS_NAME, lpCplInfo->szName, sizeof(lpCplInfo->szName)) || !LoadString(DataOnlyHandle, IDS_INFO, lpCplInfo->szInfo, sizeof(lpCplInfo->szInfo)) || !LoadString(DataOnlyHandle, IDS_CONTROL_HLP, lpCplInfo->szHelpFile, sizeof(lpCplInfo->szHelpFile))) { FreeLibrary(DataOnlyHandle); return FALSE; } FreeLibrary(DataOnlyHandle); return TRUE; } LONG CPlApplet(HWND hCplWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { LONG ReturnCode = 0L; // The default apparently int i; switch (uMsg) { case CPL_INIT: /* * I've no idea why this is a better place to initialize than * CPL_GETCOUNT but why not? * */ /* * Check there's somebody home */ for (i = 0; i < NumberOfApplets; i++) { /* ** Don't put up useless junk! */ if (i == MidiMapApplet && midiOutGetNumDevs() == 0 #ifdef EXTRA_APPLETS || i == ACMApplet && waveOutGetNumDevs() == 0 #endif ) { continue; } if (LoadDataPart(i)) { IdMapping[TotalApplets++] = i; } } /* * Only succeed if we support something */ ReturnCode = TotalApplets != 0; break; case CPL_GETCOUNT: return TotalApplets; break; case CPL_NEWINQUIRE: { LPNEWCPLINFO lpCplInfo; int iApplet; iApplet = IdMapping[lParam1]; lpCplInfo = (LPNEWCPLINFO)lParam2; *lpCplInfo = AppletInfo[iApplet].CplInfo; } break; case CPL_DBLCLK: /* * The job here is to * 1. If the applet is not already loaded * -- load it * -- Pass it a cpl_init message - this will do for our applets(!) * * 2. Pass it a CPL_DBLCLK message with the parameters we got * */ { int iApplet; iApplet = IdMapping[lParam1]; if (AppletInfo[iApplet].ActiveHandle == NULL) { UINT OldErrorMode; OldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); AppletInfo[iApplet].ActiveHandle = LoadLibrary(AppletInfo[iApplet].AppletFileName); SetErrorMode(OldErrorMode); if (AppletInfo[iApplet].ActiveHandle != NULL) { AppletInfo[iApplet].AppletEntryPoint = (APPLET_PROC)GetProcAddress( AppletInfo[iApplet].ActiveHandle, "CPlApplet"); } if (AppletInfo[iApplet].AppletEntryPoint != NULL) { (*AppletInfo[iApplet].AppletEntryPoint) (hCplWnd, CPL_INIT, 0, 0); } } if (AppletInfo[iApplet].AppletEntryPoint != NULL) { (*AppletInfo[iApplet].AppletEntryPoint) (hCplWnd, uMsg, lParam1, lParam2); } } break; case CPL_EXIT: /* * Unload all our friends */ { int i; for (i = 0; i < NumberOfApplets; i++) { if (AppletInfo[i].ActiveHandle != NULL) { if (AppletInfo[i].AppletEntryPoint != NULL) { (*AppletInfo[i].AppletEntryPoint) (hCplWnd, CPL_EXIT, 0, 0); } FreeLibrary(AppletInfo[i].ActiveHandle); } } } break; } return ReturnCode; }