/* Copyright (c) 1998 Microsoft Corporation */ /* * @Doc DMusic * * @Module DMusic16.c - Startup code | * * 16-bit Dll for DirectMusic sequencing on legacy devices (Win95/Win98 non-WDM drivers) * * This Dll is the 16-bit thunk peer for DMusic32.Dll * * @globalv HINSTANCE | ghInst | The instance handle for the DLL. * */ #include #include #include #include "dmusic16.h" #include "debug.h" HINSTANCE ghInst; HDRVR ghDrvr; UINT guReferenceCount = 0; /* @func LibMain system entry point * * @comm * * This entry point is called when the DLL is first loaded (NOT every time). * * Saves the global instance handle and initializes all the other modules. * */ int PASCAL LibMain( HINSTANCE hInst, /* @parm Instance handle for the DLL */ WORD cbHeap, /* @parm Initial size of the local heap */ LPSTR lpszCmdLine) /* @parm Command-line parameters */ { UINT uLev; char szFilename[260]; if (GetModuleFileName(hInst, szFilename, sizeof(szFilename))) { DPF(2, "%s", (LPSTR)szFilename); } ghDrvr = OpenDriver(szFilename, NULL, 0L); DPF(1, "DMusic16.DLL task %04X hdrvr %04X", GetCurrentTask(), (WORD)ghDrvr); ghInst = hInst; uLev = DbgInitialize(TRUE); DPF(0, "DMusic16: Debug level is %u", uLev); if (uLev > 2) { DPF(0, "DMusic16: Break in LibMain"); DebugBreak(); } DeviceOnLoad(); AllocOnLoad(); MidiOutOnLoad(); #if 0 // This causes problems at terminate time. Find out later if we really need it. // if (!CreateTimerTask()) { DPF(0, "CreateTimerTask() failed"); } if (NULL == (LoadLibrary("dmusic16"))) { DPF(0, "Could not LoadLibrary ourselves!"); } #endif return 1; } /* @func LibExit system call * * @comm * * This entry point is called just before the DLL is unloaded. * * Uninitialize all the other modules */ VOID PASCAL __loadds LibExit(VOID) { DPF(2, "LibExit start"); #if 0 DestroyTimerTask(); #endif MidiOutOnExit(); AllocOnExit(); DPF(2, "LibExit end, going away now."); } extern BOOL FAR PASCAL dmthunk_ThunkConnect16(LPCSTR, LPCSTR, HINSTANCE, DWORD); STATIC char pszDll16[] = "DMUSIC16.DLL"; STATIC char pszDll32[] = "DMUSIC.DLL"; /* @func DLLEntryPoint system entry point * * @comm * * This entry point is called each time the DLL is loaded or unloaded * * It is used here to initialize the peer connection for the thunk layer. */ #define PROCESS_DETACH 0 #define PROCESS_ATTACH 1 BOOL WINAPI DllEntryPoint( DWORD dwReason, /* @parm Is the DLL being loaded or unloaded? */ HINSTANCE hi, /* @parm The instance handle */ HGLOBAL hgDS, /* @parm The global handle of the DLL's (shared) DS */ WORD wHeapSize, /* @parm The initial size of the local heap */ LPCSTR lszCmdLine, /* @parm The command line (always NULL) */ WORD wCmdLine) /* @parm Unused */ { // DllEntryPoint is called before LibEntry in a 4.x dll, so we have to LocalInit here if we're // going to use LocalAlloc // if (guReferenceCount == 0 && wHeapSize) { LocalInit(0, 0, wHeapSize); } switch(dwReason) { case PROCESS_ATTACH: DPF(2, "ProcessAttach task %04X", GetCurrentTask()); ++guReferenceCount; dmthunk_ThunkConnect16(pszDll16, pszDll32, ghInst, 1); break; case PROCESS_DETACH: DPF(2, "ProcessDetach task %04X", GetCurrentTask()); /* Clean up after them if they didn't close handles. We must do this here as well as * in DriverProc because on the last exit, we will go away before the DriverProc cleanup * gets called if the process termination is normal. */ CloseDevicesForTask(GetCurrentTask()); /* NOTE: We close on reference count of 1 since the initial OpenDriver call causes one more PROCESS_ATTACH to happen. */ if (1 == --guReferenceCount) { CloseDriver(ghDrvr, 0, 0); } break; } return TRUE; } /* @func DriverProc entry point for ourselves as a loadable driver. * * @comm This entry points allows us to know when a task has gone away and therefore to clean * up after it even though we don't properly get notified that our thunk peer has gone away. */ LRESULT WINAPI DriverProc( DWORD dwID, HDRVR hdrvr, UINT umsg, LPARAM lParam1, LPARAM lParam2) { // // NOTE DS is not valid here. // switch (umsg) { case DRV_LOAD: return(1L); case DRV_FREE: return(0L); case DRV_OPEN: case DRV_CLOSE: return(1L); case DRV_EXITAPPLICATION: DPF(2, "Cleaning up handles for task %04X", GetCurrentTask()); CloseDevicesForTask(GetCurrentTask()); break; default: return(DefDriverProc(dwID, hdrvr, umsg, lParam1, lParam2)); } } //** DriverProc()