Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

723 lines
17 KiB

/*==========================================================================
*
* Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
*
* File: w95hack.c
* Content: Win95 hack-o-rama code
* This is a HACK to handle the fact that Win95 doesn't notify
* a DLL when a process is destroyed.
* History:
* Date By Reason
* ==== == ======
* 28-mar-95 craige initial implementation
* 01-apr-95 craige happy fun joy updated header file
* 06-apr-95 craige reworked for new ddhelp
* 09-may-95 craige loading any DLL
* 16-sep-95 craige bug 1117: must UnmapViewOfFile before closing handle
* 29-nov-95 angusm added HelperCreateDSFocusThread
* 18-jul-96 andyco added Helper(Add/)DeleteDPlayServer
* 12-oct-96 colinmc added new service to get DDHELP to get its own handle
* for communicating with the DirectSound VXD
* 22-jan-97 kipo return an HRESULT from HelperAddDPlayServer()
* 29-jan-97 colinmc vxd handling stuff is no longer win16 lock specific
*
***************************************************************************/
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#include "w95help.h"
#include "dpf.h"
#undef E_FAIL
#define E_FAIL 0x80004005L
//extern DWORD * pdwHelperPid;
//extern HANDLE * phModule; // must be defined
extern DWORD dwHelperPid;
extern HINSTANCE hModule; // must be defined
/*
* sendRequest
*
* communicate a request to DDHELP
*/
static BOOL sendRequest( LPDDHELPDATA req_phd )
{
LPDDHELPDATA phd;
HANDLE hmem;
HANDLE hmutex;
HANDLE hackevent;
HANDLE hstartevent;
BOOL rc;
/*
* get events start/ack events
*/
hstartevent = CreateEvent( NULL, FALSE, FALSE, DDHELP_EVENT_NAME );
if( hstartevent == NULL )
{
return FALSE;
}
hackevent = CreateEvent( NULL, FALSE, FALSE, DDHELP_ACK_EVENT_NAME );
if( hackevent == NULL )
{
CloseHandle( hstartevent );
return FALSE;
}
/*
* create shared memory area
*/
hmem = CreateFileMapping( (HANDLE) 0xffffffff, NULL,
PAGE_READWRITE, 0, sizeof( DDHELPDATA ),
DDHELP_SHARED_NAME );
if( hmem == NULL )
{
DPF( 1, "Could not create file mapping!" );
CloseHandle( hstartevent );
CloseHandle( hackevent );
return FALSE;
}
phd = (LPDDHELPDATA) MapViewOfFile( hmem, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
if( phd == NULL )
{
DPF( 1, "Could not create view of file!" );
CloseHandle( hmem );
CloseHandle( hstartevent );
CloseHandle( hackevent );
return FALSE;
}
/*
* wait for access to the shared memory
*/
hmutex = OpenMutex( SYNCHRONIZE, FALSE, DDHELP_MUTEX_NAME );
if( hmutex == NULL )
{
DPF( 1, "Could not create mutex!" );
UnmapViewOfFile( phd );
CloseHandle( hmem );
CloseHandle( hstartevent );
CloseHandle( hackevent );
return FALSE;
}
WaitForSingleObject( hmutex, INFINITE );
/*
* wake up DDHELP with our request
*/
memcpy( phd, req_phd, sizeof( DDHELPDATA ) );
phd->req_id = hModule;
if( SetEvent( hstartevent ) )
{
WaitForSingleObject( hackevent, INFINITE );
memcpy( req_phd, phd, sizeof( DDHELPDATA ) );
rc = TRUE;
}
else
{
DPF( 1, "Could not signal event to notify DDHELP" );
rc = FALSE;
}
/*
* done with things
*/
ReleaseMutex( hmutex );
CloseHandle( hmutex );
CloseHandle( hstartevent );
CloseHandle( hackevent );
UnmapViewOfFile( phd );
CloseHandle( hmem );
return rc;
} /* sendRequest */
/*
* DoneWithHelperProcess
*/
void DoneWithHelperProcess( void )
{
DDHELPDATA hd;
if( dwHelperPid == 0 )
{
return;
}
hd.req = DDHELPREQ_FREEDCLIST;
sendRequest( &hd );
} /* DoneWithHelperProcess */
/*
* WaitForHelperStartup
*/
BOOL WaitForHelperStartup( void )
{
HANDLE hevent;
DWORD rc;
hevent = CreateEvent( NULL, TRUE, FALSE, DDHELP_STARTUP_EVENT_NAME );
if( hevent == NULL )
{
return FALSE;
}
DPF( 3, "Wait DDHELP startup event to be triggered" );
rc = WaitForSingleObject( hevent, 100000 ); // fail if this doesn't work within 100 seconds
CloseHandle( hevent );
if( rc == WAIT_TIMEOUT )
{
return FALSE;
}
return TRUE;
} /* WaitForHelperStartup */
/*
* HelperLoadDLL
*
* get the helper to load a DLL for us.
*/
DWORD HelperLoadDLL( LPSTR dllname, LPSTR fnname, DWORD context )
{
DDHELPDATA hd;
DWORD rc = 0;
if( dllname != NULL )
{
hd.req = DDHELPREQ_LOADDLL;
lstrcpy( hd.fname, dllname );
if( fnname != NULL )
{
strcpy( hd.func, fnname );
hd.context = context;
DPF( 3, "Context=%08lx", context );
}
else
{
hd.func[0] = 0;
}
DPF( 3, "Asking DDHELP to load DLL %s", dllname );
sendRequest( &hd );
rc = (DWORD)hd.dwReturn;
}
return rc;
} /* HelperLoadDLL */
/*
* HelperCreateThread
*/
void HelperCreateThread( void )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_CREATEHELPERTHREAD;
sendRequest( &hd );
} /* HelperCreateThread */
/*
* SignalNewProcess
*
* Signal DDHELP that a new process has arrived. This is called with the
* DLL lock taken, so global vars are safe
*/
void SignalNewProcess( DWORD pid, LPHELPNOTIFYPROC proc )
{
DDHELPDATA hd;
if( pid == dwHelperPid )
{
DPF( 3, "Helper connected to DLL - no signal required" );
return;
}
DPF( 3, "Signalling DDHELP that a new process has connected" );
hd.req = DDHELPREQ_NEWPID;
hd.pid = pid;
hd.lpNotify = proc;
sendRequest( &hd );
} /* SignalNewProcess */
/*
* StopWatchProcess
*
* Signal DDHELP to stop watching a process. This is called with the
* DLL lock taken, so global vars are safe
*/
void StopWatchProcess( DWORD pid, LPHELPNOTIFYPROC proc )
{
DDHELPDATA hd;
if( pid == dwHelperPid )
{
DPF( 3, "Helper connected to DLL - no signal required" );
return;
}
DPF( 3, "Signalling DDHELP to stop watching a process" );
hd.req = DDHELPREQ_STOPWATCHPID;
hd.pid = pid;
hd.lpNotify = proc;
sendRequest( &hd );
} /* SignalNewProcess */
/*
* SignalNewDriver
*
* Signal DDHELP that a new driver has been loaded. This is called with the
* DLL lock taken, so global vars are safe
*/
void SignalNewDriver( LPSTR fname, BOOL isdisp )
{
DDHELPDATA hd;
DPF( 3, "Signalling DDHELP to create a new DC" );
hd.req = DDHELPREQ_NEWDC;
hd.isdisp = isdisp;
lstrcpy( hd.fname, fname );
sendRequest( &hd );
} /* SignalNewDriver */
/*
* CreateHelperProcess
*/
BOOL CreateHelperProcess( LPDWORD ppid )
{
if( dwHelperPid == 0 )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE h;
h = OpenEvent( SYNCHRONIZE, FALSE, DDHELP_STARTUP_EVENT_NAME );
if( h == NULL )
{
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwFlags = 0;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
DPF( 3, "Creating helper process now" );
if( !CreateProcess(NULL, "ddhelp.exe", NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi) )
{
DPF( 2, "Could not create DDHELP.EXE" );
return FALSE;
}
dwHelperPid = pi.dwProcessId;
DPF( 3, "Helper rocess created" );
}
else
{
DDHELPDATA hd;
DPF( 3, "DDHELP already exists, waiting for DDHELP event" );
WaitForSingleObject( h, INFINITE );
CloseHandle( h );
DPF( 3, "Asking for DDHELP pid" );
hd.req = DDHELPREQ_RETURNHELPERPID;
sendRequest( &hd );
dwHelperPid = hd.pid;
DPF( 3, "DDHELP pid = %08lx", dwHelperPid );
}
*ppid = dwHelperPid;
return TRUE;
}
*ppid = dwHelperPid;
return FALSE;
} /* CreateHelperProcess */
#ifdef WIN95 //this is Just For Now... dsound will get the help it needs..jeffno 951206
/*
* HelperWaveOpen
*
* get the helper to load a DLL for us.
*/
DWORD HelperWaveOpen( LPVOID lphwo, DWORD dwDeviceID, LPVOID pwfx )
{
DDHELPDATA hd;
if( (lphwo != NULL) && (pwfx != NULL) )
{
hd.req = DDHELPREQ_WAVEOPEN;
hd.pData1 = lphwo;
hd.dwData1 = dwDeviceID;
hd.dwData2 = (DWORD)pwfx;
DPF( 3, "Asking DDHELP to Open Wave Device %d", dwDeviceID );
sendRequest( &hd );
return hd.dwReturn;
}
else
{
DPF( 3, "Helper Wave Open param error");
return MMSYSERR_ERROR;
}
} /* HelperWaveOpen */
/*
* HelperWaveClose
*
* get the helper to load a DLL for us.
*/
DWORD HelperWaveClose( DWORD hwo )
{
DDHELPDATA hd;
if( (hwo != 0) )
{
hd.req = DDHELPREQ_WAVECLOSE;
hd.dwData1 = hwo;
DPF( 3, "Asking DDHELP to Close Wave Device ");
sendRequest( &hd );
return hd.dwReturn;
}
else
{
DPF( 3, "Helper Wave Close param error");
return MMSYSERR_ERROR;
}
} /* HelperWaveClose */
/*
* HelperCreateTimer
*
* get the helper to load a DLL for us.
*/
DWORD HelperCreateTimer( DWORD dwResolution,
LPVOID pTimerProc,
DWORD dwInstanceData )
{
DDHELPDATA hd;
if( (dwResolution != 0) && (pTimerProc != NULL) )
{
hd.req = DDHELPREQ_CREATETIMER;
hd.pData1 = pTimerProc;
hd.dwData1 = dwResolution;
hd.dwData2 = dwInstanceData;
DPF( 3, "Asking DDHELP to Create Timer" );
sendRequest( &hd );
return hd.dwReturn;
}
else
{
DPF( 3, "Helper Wave Close param error");
return MMSYSERR_ERROR;
}
} /* HelperCreateTimer */
/*
* HelperKillTimer
*
* get the helper to load a DLL for us.
*/
DWORD HelperKillTimer( DWORD dwTimerID )
{
DDHELPDATA hd;
if( (dwTimerID != 0) )
{
hd.req = DDHELPREQ_KILLTIMER;
hd.dwData1 = dwTimerID;
DPF( 3, "Asking DDHELP to KILL Timer %X", dwTimerID );
sendRequest( &hd );
return hd.dwReturn;
}
else
{
DPF( 3, "Helper Wave Close param error");
return MMSYSERR_ERROR;
}
} /* HelperKillTimer */
/*
* HelperCreateDSMixerThread
*
* get the helper to create a mixer thread.
*/
HANDLE HelperCreateDSMixerThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
LPDWORD pdwThreadParam,
DWORD dwFlags,
LPDWORD pThreadId )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_CREATEDSMIXERTHREAD;
hd.pData1 = pfnThreadFunc;
hd.dwData1 = (DWORD)pdwThreadParam;
hd.dwData2 = dwFlags;
hd.pData2 = pThreadId;
sendRequest( &hd );
return (HANDLE)hd.dwReturn;
} /* HelperCreateDSMixerThread
/*
* HelperCreateDSFocusThread
*
* get the helper to create a sound focus thread.
*/
HANDLE HelperCreateDSFocusThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
LPDWORD pdwThreadParam,
DWORD dwFlags,
LPDWORD pThreadId )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_CREATEDSFOCUSTHREAD;
hd.pData1 = pfnThreadFunc;
hd.dwData1 = (DWORD)pdwThreadParam;
hd.dwData2 = dwFlags;
hd.pData2 = pThreadId;
sendRequest( &hd );
return (HANDLE)hd.dwReturn;
} /* HelperCreateDSFocusThread
/*
* HelperCallDSEmulatorCleanup
*
* Call the DirectSound function which cleans up MMSYSTEM handles
*/
void HelperCallDSEmulatorCleanup( LPVOID callback,
LPVOID pDirectSound )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_CALLDSCLEANUP;
hd.pData1 = callback;
hd.pData2 = pDirectSound;
sendRequest( &hd );
}
#endif //not winnt -just for now-jeffno
/*
* HelperCreateModeSetThread
*
* get the helper to load a DLL for us.
*/
BOOL HelperCreateModeSetThread(
LPVOID callback,
HANDLE *ph,
LPVOID lpdd,
DWORD hInstance )
{
DDHELPDATA hd;
HANDLE h;
char str[64];
hd.req = DDHELPREQ_CREATEMODESETTHREAD;
hd.lpModeSetNotify = callback;
hd.pData1 = lpdd;
hd.dwData1 = hInstance;
sendRequest( &hd );
wsprintf( str, DDHELP_MODESET_EVENT_NAME, hInstance );
DPF( 3, "Trying to open event \"%s\"", str );
h = OpenEvent( SYNCHRONIZE, FALSE, str );
if( h == NULL )
{
DPF( 3, "Could not open modeset event!" );
*ph = NULL;
return FALSE;
}
*ph = h;
DPF( 1, "HelperCreateModeSetThread GotEvent: %08lx", h );
return TRUE;
} /* HelperCreateModeSetThread */
/*
* HelperKillModeSetThread
*
* get the helper to load a DLL for us.
*/
void HelperKillModeSetThread( DWORD hInstance )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_KILLMODESETTHREAD;
hd.dwData1 = hInstance;
sendRequest( &hd );
} /* HelperKillModeSetThread */
#ifdef WIN95
/*
* HelperCreateDOSBoxThread
*
* get the helper to create a thread so kernel mode can notify us of DOS box
* changes.
*/
BOOL HelperCreateDOSBoxThread(
LPVOID callback,
HANDLE *ph,
LPVOID lpdd,
DWORD hInstance )
{
DDHELPDATA hd;
HANDLE h;
char str[64];
hd.req = DDHELPREQ_CREATEDOSBOXTHREAD;
hd.lpModeSetNotify = callback;
hd.pData1 = lpdd;
hd.dwData1 = hInstance;
sendRequest( &hd );
wsprintf( str, DDHELP_DOSBOX_EVENT_NAME, hInstance );
DPF( 3, "Trying to open event \"%s\"", str );
h = OpenEvent( SYNCHRONIZE, FALSE, str );
if( h == NULL )
{
DPF( 3, "Could not open DOS box event!" );
*ph = NULL;
return FALSE;
}
*ph = h;
DPF( 1, "HelperCreateDOSBoxThread GotEvent: %08lx", h );
return TRUE;
} /* HelperCreateDOSBoxThread */
/*
* HelperKillDOSBoxThread
*
* get the helper to load a DLL for us.
*/
void HelperKillDOSBoxThread( DWORD hInstance )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_KILLDOSBOXTHREAD;
hd.dwData1 = hInstance;
sendRequest( &hd );
} /* HelperKillDOSBoxThread */
#endif //!winnt
// notify dphelp.c that we have a new server on this system
DWORD HelperAddDPlayServer(DWORD port)
{
DDHELPDATA hd;
DWORD pid = GetCurrentProcessId();
memset(&hd, 0, sizeof(DDHELPDATA));
hd.req = DDHELPREQ_DPLAYADDSERVER;
hd.pid = pid;
hd. dwData1 = port;
if (sendRequest(&hd))
return (DWORD)hd.dwReturn;
else
return ((DWORD) E_FAIL);
} // HelperAddDPlayServer
// server is going away
BOOL HelperDeleteDPlayServer(void)
{
DDHELPDATA hd;
DWORD pid = GetCurrentProcessId();
hd.req = DDHELPREQ_DPLAYDELETESERVER;
hd.pid = pid;
return sendRequest(&hd);
} // HelperDeleteDPlayServer
#ifdef WIN95
/*
* Get DDHELP to load the DirectSound VXD (if it has not
* already done so) and return a handle to the VXD)
*/
HANDLE HelperGetDSVxd( void )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_GETDSVXDHANDLE;
sendRequest( &hd );
return (HANDLE) hd.dwReturn;
} /* HelperGetDSVxd */
/*
* Get DDHELP to load the DirectDraw VXD (if it has not
* already done so) and return a handle to the VXD)
*/
HANDLE HelperGetDDVxd( void )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_GETDDVXDHANDLE;
sendRequest( &hd );
return (HANDLE) hd.dwReturn;
} /* HelperGetDDVxd */
#endif /* WIN95 */
/*
* HelperSetOnDisplayChangeNotify
*
* get the helper to call us back if there is DisplayChange
* message. (This is for multi-mon topology changes.)
*/
void HelperSetOnDisplayChangeNotify( void *pfn )
{
DDHELPDATA hd;
hd.req = DDHELPREQ_NOTIFYONDISPLAYCHANGE;
hd.dwData1 = (DWORD_PTR)pfn;
sendRequest( &hd );
return;
}
HINSTANCE HelperLoadLibrary(LPCSTR pszLibraryName)
{
DDHELPDATA hd;
hd.req = DDHELPREQ_LOADLIBRARY;
hd.dwData1 = (DWORD_PTR)pszLibraryName;
sendRequest(&hd);
return (HINSTANCE)hd.dwReturn;
}
BOOL HelperFreeLibrary(HINSTANCE hInst)
{
DDHELPDATA hd;
hd.req = DDHELPREQ_FREELIBRARY;
hd.dwData1 = (DWORD_PTR)hInst;
sendRequest(&hd);
return (BOOL)hd.dwReturn;
}
void HelperAddDeviceChangeNotify(LPDEVICECHANGENOTIFYPROC lpNotify)
{
DDHELPDATA hd;
hd.req = DDHELPREQ_ADDDEVICECHANGENOTIFY;
hd.pData1 = lpNotify;
sendRequest(&hd);
}
void HelperDelDeviceChangeNotify(LPDEVICECHANGENOTIFYPROC lpNotify)
{
DDHELPDATA hd;
hd.req = DDHELPREQ_DELDEVICECHANGENOTIFY;
hd.pData1 = lpNotify;
sendRequest(&hd);
}