|
|
/******************************************************************************
Copyright (c) 1985-1998 Microsoft Corporation
Title: drvrrare.c - Installable driver code. Less common code
Version: 1.00
Date: 10-Jun-1990
Author: DAVIDDS ROBWI
------------------------------------------------------------------------------
Change log:
DATE REV DESCRIPTION ----------- ----- ----------------------------------------------------------- 28-FEB-1992 ROBINSP Port to NT 23-Apr-1992 StephenE Unicoded 22-Apr-1993 RobinSp Add NT multithread protection
Multithread design :
Uses 2 critical sections :
DriverListCritSec :
protects the list of drivers :
hInstalledDriverList - handle of global driver list cInstalledDrivers - high water mark of installed drivers
so that only 1 thread at a time has the list locked and can refer to or update it.
DriverLoadFreeCritSec
Makes sure that actual loads and frees of drivers don't overlap and that the actual loading of a driver via LoadLibrary coincides with its first message being DRV_LOAD.
This can easily happen if the DRV_OPEN from another thread can get in before the DRV_LOAD has been sent.
*****************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#define MMNOSOUND
#define MMNOWAVE
#define MMNOMIDI
#define MMNOSEQ
#define MMNOTIMER
#define MMNOJOY
#define MMNOMCI
#define NOTIMERDEV
#define NOJOYDEV
#define NOMCIDEV
#define NOSEQDEV
#define NOWAVEDEV
#define NOMIDIDEV
#define NOTASKDEV
#include <winmmi.h>
#include "drvr.h"
extern HANDLE hInstalledDriverList; // List of installed driver instances
extern int cInstalledDrivers; // High water count of installed driver instances
extern DWORD FAR PASCAL DriverProc(DWORD dwID, HDRVR hdrv, UINT msg, DWORD dw1, DWORD dw2);
/* Support for using 3.1 APIs if available */
typedef HANDLE (FAR PASCAL *OPENDRIVER31)(LPCSTR, LPCSTR, LPARAM); typedef LONG (FAR PASCAL *CLOSEDRIVER31)(HANDLE, LPARAM, LPARAM); typedef HANDLE (FAR PASCAL *GETDRIVERMODULEHANDLE31)(HANDLE); typedef LONG (FAR PASCAL *SENDDRIVERMESSAGE31)(HANDLE, UINT, LPARAM, LPARAM); typedef LONG (FAR PASCAL *DEFDRIVERPROC31)(DWORD, HANDLE, UINT, LPARAM, LPARAM);
OPENDRIVER31 lpOpenDriver; CLOSEDRIVER31 lpCloseDriver; GETDRIVERMODULEHANDLE31 lpGetDriverModuleHandle; SENDDRIVERMESSAGE31 lpSendDriverMessage; DEFDRIVERPROC31 lpDefDriverProc; #if 0
BOOL fUseWinAPI = 0; // NOTE: fUseWinAPI is not being used at present
// as we only have a partial device loading story
#endif
/***************************************************************************
strings
****************************************************************************/
#if 0
extern char far szBoot[]; extern char far szUser[]; extern char far szOpenDriver[]; extern char far szCloseDriver[]; extern char far szDrvModuleHandle[]; extern char far szSendDriverMessage[]; extern char far szDefDriverProc[]; extern char far szDriverProc[]; #endif
/***************************************************************************
* * @doc DDK * * @api LONG | DrvClose | This function closes an open driver * instance and decrements * the driver's open count. Once the driver's open count becomes zero, * the driver is unloaded. * * @parm HANDLE | hDriver | Specifies the handle of the installable * driver to close. * * @parm LPARAM | lParam1 | Specifies the first message parameter for * the DRV_CLOSE message. This data is passed directly to the driver. * * @parm LPARAM | lParam2 | Specifies the second message parameter * for DRV_CLOSE message. This data is passed directly to the driver. * * @rdesc Returns zero if the driver aborted the close; * otherwise, returns the return result from the driver.
* @xref DrvOpen * ***************************************************************************/
LRESULT APIENTRY DrvClose(HANDLE hDriver, LPARAM lParam1, LPARAM lParam2) { /* The driver will receive the following message sequence:
* * DRV_CLOSE * if DRV_CLOSE returns non-zero * if driver usage count = 1 * DRV_DISABLE * DRV_FREE */
if (fUseWinAPI) return ((*lpCloseDriver)(hDriver, lParam1, lParam2)); else return InternalCloseDriver((UINT)(UINT_PTR)hDriver, lParam1, lParam2, TRUE); }
/***************************************************************************
* * @doc DDK * * @api LONG | DrvOpen | This function opens an installable driver. * The first time a driver is opened it is loaded * and enabled. A driver must be opened before messages are sent * to it. * * @parm LPSTR | szDriverName | Specifies a far pointer to a * null-terminated character string * containing a driver filename or a keyname from a * section of the SYSTEM.INI file. * * @parm LPSTR | szSectionName | Specifies a far pointer to a * null-terminated character string containing the name of * the driver section to search. If <p szSectionName> is * not null, the specified section of the SYSTEM.INI file is * searched instead of the [Drivers] section. If * <p szSectionName> is null, the default [Drivers] section is used. * * @parm LPARAM | lParam | Specifies a message parameter to * pass to the driver procedure with the <m DRV_OPEN> message. * * @rdesc Returns a handle to the driver. * * @comm Installable drivers must export a <f DriverProc> routine of * the form: * * @cb LONG FAR PASCAL | DriverProc | This entry point receives the * messages sent to an installable driver. This entry will always * handle the system messages as a minimum set of messages. * * @parm DWORD | dwDriverIdentifier | Specifies the device driver * identifier. * * @parm HANDLE | hDriver | Specifies the device driver handle. * * @parm UINT | wMessage | Specifies the message for the device * driver. * * @parm LONG | lParm1 | Specifies message dependent data. * * @parm LONG | lParm2 | Specifies message dependent data. * * @xref DrvClose * ****************************************************************************/
HANDLE APIENTRY DrvOpen( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2) { /* The driver will receive the following message sequence:
* * if driver not loaded and can be found * DRV_LOAD * if DRV_LOAD returns non-zero * DRV_ENABLE * if driver loaded correctly * DRV_OPEN */
HDRVR hdrv;
if (fUseWinAPI) {
/*------------------------------------------------------------*\
* UNICODE: convert szDriver and szSectionName to ascii * and then call WIN31 driver \*------------------------------------------------------------*/ LPSTR aszDriver; LPSTR aszSectionName; INT lenD; INT lenS;
lenD = lstrlenW( szDriverName ) * sizeof( WCHAR ) + sizeof( WCHAR ); aszDriver = HeapAlloc( hHeap, 0, lenD ); if ( aszDriver == (LPSTR)NULL ) { return NULL; }
lenS = lstrlenW( szSectionName ) * sizeof( WCHAR ) + sizeof( WCHAR ); aszSectionName = HeapAlloc( hHeap, 0, lenS ); if ( aszSectionName == (LPSTR)NULL ) { HeapFree( hHeap, 0, aszDriver ); return NULL; }
// Unicode to Ascii
UnicodeStrToAsciiStr( (PBYTE)aszDriver, (PBYTE)aszDriver + lenD, szDriverName );
UnicodeStrToAsciiStr( (PBYTE)aszSectionName, (PBYTE)aszSectionName + lenS, szSectionName );
hdrv = (HDRVR)((*lpOpenDriver)( aszDriver, aszSectionName, lParam2 ));
HeapFree( hHeap, 0, aszDriver ); HeapFree( hHeap, 0, aszSectionName );
} else { dprintf2(("DrvOpen(%ls), Looking in Win.ini [%ls]", szDriverName, szSectionName ? szSectionName : L"NULL !!" ));
hdrv = (HDRVR)InternalOpenDriver(szDriverName, szSectionName, lParam2, TRUE); }
#if DBG
if (hdrv) { WCHAR ach[255]; static SZCODE szFormat[] = "DrvOpen(): Opened %ls (%ls)\r\n";
GetModuleFileNameW( DrvGetModuleHandle( hdrv ), ach, sizeof(ach) / sizeof(WCHAR) ); dprintf2((szFormat, szDriverName, ach)); } #endif
return (HANDLE)hdrv; }
/***************************************************************************
* * @doc DDK * * @api HANDLE | DrvGetModuleHandle | This function returns the library * module handle of the specified installable driver. * * @parm HANDLE | hDriver | Specifies the handle of the installable driver. * * @rdesc Returns the module handle of the driver specified by the * driver handle <p hDriver>. * * @comm A module handle is not the same as an installable driver handle. * ***************************************************************************/
HMODULE APIENTRY DrvGetModuleHandle(HDRVR hDriver) { LPDRIVERTABLE lpdt; HMODULE h = 0;
if (fUseWinAPI) return ((*lpGetDriverModuleHandle)(hDriver));
DrvEnter(); if (hDriver && ((int)(UINT_PTR)hDriver <= cInstalledDrivers)) { lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList); h = (HMODULE)lpdt[(UINT)(UINT_PTR)hDriver-1].hModule; GlobalUnlock(hInstalledDriverList); } DrvLeave();
return(h); }
LRESULT FAR PASCAL InternalCloseDriver(UINT hDriver, LPARAM lParam1, LPARAM lParam2, BOOL fSendDisable) { LRESULT result;
// check handle in valid range.
DrvEnter();
if ((int)hDriver > cInstalledDrivers) { DrvLeave(); return(FALSE); }
DrvLeave();
result = DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_CLOSE, lParam1, lParam2);
if (result) { InternalFreeDriver(hDriver, fSendDisable); }
return(result); }
LRESULT FAR PASCAL InternalOpenDriver( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2, BOOL fSendEnable) { DWORD_PTR hDriver; LPDRIVERTABLE lpdt; LRESULT result; WCHAR sz[128];
if (0 != (hDriver = InternalLoadDriver( szDriverName, szSectionName, sz, sizeof(sz) / sizeof(WCHAR), fSendEnable ) ) ) { /*
* Set the driver identifier to the DRV_OPEN call to the * driver handle. This will let people build helper functions * that the driver can call with a unique identifier if they * want to. */
DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList); lpdt[hDriver-1].dwDriverIdentifier = (DWORD)hDriver; GlobalUnlock(hInstalledDriverList); DrvLeave();
result = DrvSendMessage( (HANDLE)hDriver, DRV_OPEN, (LPARAM)(LPSTR)sz, lParam2); if (!result) { dprintf1(("DrvSendMessage failed, result = %8x",result)); InternalFreeDriver((UINT)hDriver, fSendEnable); } else { DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList); lpdt[hDriver-1].dwDriverIdentifier = result; GlobalUnlock(hInstalledDriverList); DrvLeave(); result = hDriver; } } else result = 0L;
return result; }
/***************************************************************************
* * @doc INTERNAL * * @api LONG | InternalLoadDriver | Loads an installable driver. If this is * the first time that the driver is opened, the driver will be loaded * and enabled. * * @parm LPSTR | szDriverName | A null-terminated character string * containing a driver filename or a keyname from the [Drivers] * section of system.ini. * * @parm LPSTR | szSectionName | A null-terminated character string * that specifies a driver section to search. If szSectionName is * not null, the specified section of system.ini is searched instead * of the [Drivers] section. If szSectionName is null, the * default [Drivers] section is used. * * @parm LPSTR | lpstrTail | caller supplied buffer to return the "tail" * of the system.ini line in. The tail is any characters that follow * the filename. * * @parm UINT | cbTail | size of supplied buffer as a character count. * * @parm BOOL | fSendEnable | TRUE if driver should be enabled * * @rdesc Returns a long whose loword is the handle to the driver and whose * high word is an error code or the module handle * * @xref InternalOpenDriver * ****************************************************************************/
LRESULT FAR PASCAL InternalLoadDriver(LPCWSTR szDriverName, LPCWSTR szSectionName, LPWSTR lpstrTail, UINT cbTail, BOOL fSendEnable) { int index; LPDRIVERTABLE lpdt; LONG result; HANDLE h; DRIVERPROC lpDriverEntryPoint;
/* The driver will receive the following message sequence:
* * if driver not loaded and can be found * DRV_LOAD * if DRV_LOAD returns non-zero and fSendEnable * DRV_ENABLE */
/* Allocate a table entry */
// This can be made more efficient by keeping a count of how many drivers
// we have loaded and how many entries there are in the table. Then when
// we should reuse an entry we would not reallocate - unlike at present.
DrvEnter(); if (!hInstalledDriverList) { h = GlobalAlloc(GHND, (DWORD)((UINT)sizeof(DRIVERTABLE))); // Note: it is valid to assume that the memory has been ZERO'ed
// ...might want to add a debug WinAssert to verify...
} else {
/* Alloc space for the next driver we will install. We may not really
* install the driver in the last entry but rather in an intermediate * entry which was freed. */
h = GlobalReAlloc(hInstalledDriverList, (DWORD)((UINT)sizeof(DRIVERTABLE)*(cInstalledDrivers+1)), GHND); // Note: it is valid to assume that the new memory has been ZERO'ed
// ...might want to add a debug WinAssert to verify...
}
if (!h) { dprintf1(("Failed to allocate space for Installed driver list")); DrvLeave(); return(0L); }
cInstalledDrivers++; hInstalledDriverList = h; lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
/* find an unused entry in the table */
for (index=0;index<cInstalledDrivers;index++) { if (lpdt[index].hModule == 0 && !lpdt[index].fBusy) break; }
if (index+1 < cInstalledDrivers) {
/* The driver went into an unused entry in the middle somewhere so
* restore table size. */
cInstalledDrivers--; }
/* Protect the entry we just allocated so that OpenDriver
* can be called at any point from now on without overriding * the entry */
lpdt[index].fBusy = 1;
GlobalUnlock(hInstalledDriverList); DrvLeave();
/*
* Make sure Loadlibrary and DRV_LOAD messages to driver are consistent */
EnterCriticalSection(&DriverLoadFreeCritSec);
h = LoadAliasedLibrary( szDriverName, szSectionName ? szSectionName : wszDrivers, wszSystemIni, lpstrTail, cbTail ); if (0 == h) { dprintf1(("Failed to LoadLibrary %ls Error is %d", szDriverName, GetLastError())); LeaveCriticalSection(&DriverLoadFreeCritSec); result = 0; goto LoadCleanUp; }
lpDriverEntryPoint = (DRIVERPROC)GetProcAddress(h, DRIVER_PROC_NAME);
if (lpDriverEntryPoint == NULL) { // Driver does not have correct entry point
dprintf1(("Cannot find entry point %ls in %ls", DRIVER_PROC_NAME, szDriverName));
FreeLibrary(h); LeaveCriticalSection(&DriverLoadFreeCritSec); result = 0L; goto LoadCleanUp; }
DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
lpdt[index].lpDriverEntryPoint = lpDriverEntryPoint;
// Set hModule here so that GetDrvrUsage() and DrvSendMessage() work
lpdt[index].hModule = (UINT_PTR)h;
GlobalUnlock(hInstalledDriverList); DrvLeave();
if (GetDrvrUsage(h) == 1) { LRESULT LoadResult;
// First instance of the driver.
LoadResult = DrvSendMessage((HANDLE)(UINT_PTR)(index+1), DRV_LOAD, 0L, 0L);
DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
if (!LoadResult) { // Driver failed load call.
lpdt[index].lpDriverEntryPoint = NULL; lpdt[index].hModule = (UINT_PTR)NULL; GlobalUnlock(hInstalledDriverList); DrvLeave(); FreeLibrary(h); LeaveCriticalSection(&DriverLoadFreeCritSec); result = 0L; goto LoadCleanUp; } lpdt[index].fFirstEntry = 1; GlobalUnlock(hInstalledDriverList); DrvLeave();
if (fSendEnable) { DrvSendMessage((HANDLE)(UINT_PTR)(index+1), DRV_ENABLE, 0L, 0L); } }
LeaveCriticalSection(&DriverLoadFreeCritSec);
result = index + 1;
LoadCleanUp: DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList); lpdt[index].fBusy = 0; GlobalUnlock(hInstalledDriverList); DrvLeave(); return(result); }
/***************************************************************************
* * @doc INTERNAL * * @api UINT | InternalFreeDriver | This function decrements the usage * count of the specified driver. When the driver usage count reaches * 0, the driver is sent a DRV_FREE message and then freed. * * @parm HANDLE | hDriver | Driver handle of the installable driver to be * freed. * * @parm BOOL | fSendDisable | TRUE if a DRV_DISABLE message should be sent * before the DRV_FREE message if the usage count reaches zero. * * @rdesc Returns current driver usage count. * * @comm Using LoadLibrary or FreeLibrary directly on a library installed * with OpenDriver will break this function. A module handle is not * the same as an installable driver handle. * * @xref CloseDriver * ***************************************************************************/
UINT FAR PASCAL InternalFreeDriver(UINT hDriver, BOOL fSendDisable) { LPDRIVERTABLE lpdt; UINT w; int index; HMODULE hModule;
/* The driver will receive the following message sequence:
* * if usage count of driver is 1 * DRV_DISABLE (normally) * DRV_FREE */
EnterCriticalSection(&DriverLoadFreeCritSec);
DrvEnter(); if ((int)hDriver > cInstalledDrivers || !hDriver) { DrvLeave(); LeaveCriticalSection(&DriverLoadFreeCritSec); return(0); }
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
/*
* If the driver usage count is 1, then send * free and disable messages. */
/*
Clear dwDriverIdentifier so that the sendmessage for DRV_OPEN and DRV_ENABLE have dwDriverIdentifier = 0 if an entry gets reused and so that the DRV_DISABLE and DRV_FREE messages below also get dwDriverIdentifier = 0. */
lpdt[hDriver-1].dwDriverIdentifier = 0; hModule = (HMODULE)lpdt[hDriver-1].hModule;
GlobalUnlock(hInstalledDriverList); DrvLeave();
w = GetDrvrUsage((HANDLE)hModule);
if (w == 1) { if (fSendDisable) DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_DISABLE, 0L, 0L); DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_FREE, 0L, 0L); } FreeLibrary(hModule);
DrvEnter(); lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
/* Only one entry for the driver in the driver list has the first
* instance flag set. This is to make it easier to handle system * messages that only need to be sent to a driver once. * * To maintain the flag, we must set the flag in one of the other * entries if we remove the driver entry with the flag set. * * Note that InternalFreeDriver returns the new usage count of * the driver so if it is zero, we know that there are no other * entries for the driver in the list and so we don't have to * do this loop. */
if (lpdt[hDriver - 1].fFirstEntry) { for (index=0;index<cInstalledDrivers;index++) if (lpdt[index].hModule == lpdt[hDriver-1].hModule && !lpdt[index].fFirstEntry) { lpdt[index].fFirstEntry = 1; break; } }
// Clear the rest of the table entry
lpdt[hDriver-1].hModule = 0; // this indicates free entry
lpdt[hDriver-1].fFirstEntry = 0; // this is also just to be tidy
lpdt[hDriver-1].lpDriverEntryPoint = 0; // this is also just to be tidy
GlobalUnlock(hInstalledDriverList); DrvLeave();
LeaveCriticalSection(&DriverLoadFreeCritSec);
return(w-1); }
#if 0
UINT GetWinVer() { WORD w = GetVersion();
return (w>>8) | (w<<8); }
#endif
#if 0
void NEAR PASCAL DrvInit(void) { HANDLE hlibUser; LPDRIVERTABLE lpdt;
/* If the window's driver interface is present then use it.
*/
DOUT(("DrvInit\r\n"));
hlibUser = GetModuleHandle(szUser);
if(lpOpenDriver = (OPENDRIVER31)GetProcAddress(hlibUser,szOpenDriver)) fUseWinAPI = TRUE; else { fUseWinAPI = FALSE; DOUT((" - No Windows Driver I/F detected. Using MMSYSTEM\r\n"));
//
// force MMSYSTEM into the driver table, without enabling it.
//
DrvEnter(); cInstalledDrivers = 0; hInstalledDriverList = GlobalAlloc(GHND|GMEM_SHARE, (DWORD)((UINT)sizeof(DRIVERTABLE)));
#if DBG
if (hInstalledDriverList == NULL) { DOUT(("no memory for driver table\r\n")); // FatalExit(-1);
return; } #endif
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
//
// NOTE! we are not setting fFirstEntry==TRUE
//
// because under windows 3.0 MMSOUND will enable/disable us
// we *dont* wan't the driver interface doing it!
//
lpdt->lpDriverEntryPoint = (DRIVERPROC)DriverProc; lpdt->hModule = ghInst; lpdt->fFirstEntry = 0;
GlobalUnlock(hInstalledDriverList); DrvLeave(); }
if (fUseWinAPI) { DOUT((" - Windows Driver I/F detected\r\n"));
if (GetWinVer() < 0x30A) DOUT(("MMSYSTEM: WARNING !!! WINDOWS DRIVER I/F BUT VERSION LESS THAN 3.1\r\n"));
// link to the relevant user APIs.
lpCloseDriver = (CLOSEDRIVER31)GetProcAddress(hlibUser, szCloseDriver); lpGetDriverModuleHandle = (GETDRIVERMODULEHANDLE31)GetProcAddress(hlibUser, szDrvModuleHandle); lpSendDriverMessage = (SENDDRIVERMESSAGE31)GetProcAddress(hlibUser, szSendDriverMessage); lpDefDriverProc = (DEFDRIVERPROC31)GetProcAddress(hlibUser, szDefDriverProc); } } #endif
#if 0
/***************************************************************************
* * @doc INTERNAL * * @api void | InternalInstallDriverChain | This function loads the * drivers specified on the Drivers= line of the [Boot] section * of system.ini. The Drivers are loaded but not opened. * * @rdesc None * ***************************************************************************/
void FAR PASCAL InternalInstallDriverChain(void) { char szBuffer[150]; BOOL bFinished; int iStart; int iEnd;
if (!fUseWinAPI) { /* Load DLL's from DRIVERS section in system.ini
*/
szBuffer[0] = TEXT('\0');
winmmGetPrivateProfileString(szBoot, /* [Boot] section */ szDrivers, /* Drivers= */ szNull, /* Default if no match */ szBuffer, /* Return buffer */ sizeof(szBuffer), szSystemIni);
if (!*szBuffer) { return; }
bFinished = FALSE; iStart = 0; while (!bFinished) { iEnd = iStart; while (szBuffer[iEnd] && (szBuffer[iEnd] != ' ') && (szBuffer[iEnd] != ',')) iEnd++;
if (szBuffer[iEnd] == NULL) bFinished = TRUE; else szBuffer[iEnd] = NULL;
/* Load and enable the driver.
*/ InternalLoadDriver(&(szBuffer[iStart]), NULL, NULL, 0, TRUE);
iStart = iEnd+1; } } } #endif
/***************************************************************************
* * @doc INTERNAL * * @api void | InternalDriverEnable | This function enables all the * currently loaded installable drivers. If the user driver i/f * has been detected, this function will do nothing. * * @rdesc None * ***************************************************************************/
void FAR PASCAL InternalDriverEnable(void) {
if (!fUseWinAPI) InternalBroadcastDriverMessage(1, DRV_ENABLE, 0L, 0L, IBDM_ONEINSTANCEONLY); }
/***************************************************************************
* * @doc INTERNAL * * @api void | InternalDriverDisable | This function disables all the * currently loaded installable drivers. If the user driver I/F * has been detected, this function will do nothing. * * * @rdesc None * ***************************************************************************/
void FAR PASCAL InternalDriverDisable(void) {
if (!fUseWinAPI) InternalBroadcastDriverMessage(0, DRV_DISABLE, 0L, 0L, IBDM_ONEINSTANCEONLY | IBDM_REVERSE); }
/***************************************************************************
* * @doc INTERNAL * * @api BOOL | TestExeFormat | This function tests if the executable * supplied is loadable as a 32-bit executable * * @parm LPWSTR | szExe | The file to test * * @rdesc BOOL | TRUE if format was OK, FALSE otherwise * ***************************************************************************/
BOOL TestExeFormat(LPWSTR szExe) { HANDLE SectionHandle; HANDLE FileHandle; PVOID BaseAddress; SIZE_T ViewSize; WCHAR ExpandedName[MAX_PATH]; LPWSTR FilePart;
//
// See if it's already loaded
//
if (GetModuleHandleW(szExe)) { return TRUE; }
//
// Search for our DLL
//
if (!SearchPathW(NULL, szExe, NULL, MAX_PATH, ExpandedName, &FilePart)) { return FALSE; }
//
// Get a handle for it
//
FileHandle = CreateFileW(ExpandedName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (FileHandle == INVALID_HANDLE_VALUE) { return FALSE; }
//
// We create and map a section for this file as an IMAGE
// to make sure it's recognized as such
//
if (!NT_SUCCESS(NtCreateSection( &SectionHandle, SECTION_ALL_ACCESS, NULL, NULL, PAGE_READONLY, SEC_IMAGE, FileHandle))) { CloseHandle(FileHandle); return FALSE; }
//
// Map it whereever it will go
//
ViewSize = 0; BaseAddress = NULL;
//
// See if the loader is happy with the format
//
if (!NT_SUCCESS(NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0L, 0L, NULL, &ViewSize, ViewShare, 0L, PAGE_READONLY))) { NtClose(SectionHandle); CloseHandle(FileHandle); return FALSE; }
NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); NtClose(SectionHandle); CloseHandle(FileHandle);
return TRUE;
}
/***************************************************************************
* * @doc INTERNAL * * @api HANDLE | LoadAliasedLibrary | This function loads the library module * contained in the specified file and returns its module handle * unless the specified name matches a keyname in the * specified section section of the specified ini file in which case * the library module in the file specified on the ini line is loaded. * * @parm LPSTR | szLibFileName | points to a null-terminated character * string containing the filename or system.ini keyname. * * @parm LPSTR | szSection | points to a null-terminated character * string containing the section name. * * @parm LPSTR | szIniFile | points to a null-terminated character * string containing the ini filename. * * @parm LPSTR | lpstrTail | caller supplied buffer to return the "tail" * of the system.ini line in. The tail is any characters that follow * the filename. * * @parm UINT | cbTail | size of supplied buffer. * * @rdesc Returns the library's module handle. * * @xref LoadLibrary * ***************************************************************************/
HANDLE LoadAliasedLibrary( LPCWSTR szLibFileName, LPCWSTR szSection, LPWSTR szIniFile, LPWSTR lpstrTail, UINT cbTail) { #define SZ_SIZE 128
#define SZ_SIZE_BYTES (SZ_SIZE * sizeof( WCHAR ))
WCHAR sz[SZ_SIZE]; LPWSTR pch; HANDLE hReturn; DWORD OldErrorMode; // OFSTRUCT of;
if (!szLibFileName || !*szLibFileName) return(NULL); // File not found
// read the filename and additional info. into sz
sz[0] = L'\0'; if (winmmGetPrivateProfileString(szSection, // ini section
szLibFileName, // key name
szLibFileName, // default if no match
sz, // return buffer
SZ_SIZE, // sizeof of return buffer
szIniFile)==0) // ini. file
{ return NULL; }
sz[SZ_SIZE - 1] = 0;
#if 1
if (0 == lstrcmpiW(sz, L"wdmaud.drv")) { if (0 != lstrcmpiW(sz, szLibFileName)) { // Squirt("LoadAliasedLibrary: [%ls:%ls]", szLibFileName, sz);
// Squirt("Should not load [%ls]", szLibFileName);
return NULL; } } #endif
//
// strip off the additional info.
//
pch = (LPWSTR)sz;
//
// at exit from loop pch pts to ch after first space or null ch
//
while (*pch) { if ( *pch == ' ' ) { *pch++ = '\0'; break; } pch++; }
//
// These lines are removed for unicode because:
// there is not a unicode version of OpenFile.
// LoadLibrary performs the same test as the one below anyway
//
// if (!GetModuleHandle( sz ) &&
// OpenFile(sz, &of, OF_EXIST|OF_READ|OF_SHARE_DENY_NONE) == -1) {
//
// return(NULL);
// }
//
// copy additional info. to lpstrTail
//
if (lpstrTail && cbTail) { while (cbTail-- && (0 != (*lpstrTail++ = *pch++))) ;
*(lpstrTail-1) = 0; }
//
// If we're running in the server check if it's a good image.
// The server bug checks if it tries to load bad images (LoadLibrary
// inconsistency).
//
// To do this we simulate the load process far enough to make
// the check that it's a valid image
//
if (WinmmRunningInServer && !TestExeFormat(sz)) { return NULL; }
//
// Disable hard error popups
//
OldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
//
// Try to load it
//
hReturn = LoadLibraryW( sz );
SetErrorMode(OldErrorMode);
return hReturn;
#undef SZ_SIZE_BYTES
#undef SZ_SIZE
}
/***************************************************************************
* * @doc INTERNAL * * @api int | GetDrvrUsage | Runs through the driver list and figures * out how many instances of this driver module handle we have. * We use this instead of GetModuleUsage so that we can have drivers * loaded as normal DLLs and as installable drivers. * * @parm HANDLE | h | Driver's module handle * * @rdesc Returns the library's driver usage count. * ***************************************************************************/
int FAR PASCAL GetDrvrUsage(HANDLE h) { LPDRIVERTABLE lpdt; int index; int count;
DrvEnter(); if (!hInstalledDriverList || !cInstalledDrivers) { DrvLeave(); return(0); }
count = 0; lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList); for (index=0;index<cInstalledDrivers;index++) { if (lpdt->hModule==(UINT_PTR)h) { count++; } lpdt++; } GlobalUnlock(hInstalledDriverList);
DrvLeave();
return(count); }
|